From fd8f56efab638baa9d6028ce9e02f66a576cfea1 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 3 Apr 2013 05:24:30 -0700 Subject: [PATCH] Link lifetimes of autoslice'd vectors (Issue #3184) Fixes #5739. --- src/librustc/middle/ty.rs | 6 +-- src/librustc/middle/typeck/check/regionck.rs | 53 ++++++++++++++++--- src/test/run-pass/region-dependent-addr-of.rs | 3 ++ src/test/run-pass/region-dependent-autofn.rs | 22 ++++++++ .../run-pass/region-dependent-autoslice.rs | 23 ++++++++ 5 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 src/test/run-pass/region-dependent-autofn.rs create mode 100644 src/test/run-pass/region-dependent-autoslice.rs diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b20678ac092..c29029de351 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -197,13 +197,13 @@ pub enum AutoRefKind { /// Convert from T to &T AutoPtr, - /// Convert from @[]/~[] to &[] (or str) + /// Convert from @[]/~[]/&[] to &[] (or str) AutoBorrowVec, - /// Convert from @[]/~[] to &&[] (or str) + /// Convert from @[]/~[]/&[] to &&[] (or str) AutoBorrowVecRef, - /// Convert from @fn()/~fn() to &fn() + /// Convert from @fn()/~fn()/&fn() to &fn() AutoBorrowFn } diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index dfc5f218d67..833dbff89a0 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -494,8 +494,8 @@ pub mod guarantor { * inferencer would not know of this dependency and thus it might * infer the lifetime of L2 to be greater than L1 (issue #3148). * - * There are a number of troublesome scenarios in the test - * `region-dependent-addr-of.rs`, but here is one example: + * There are a number of troublesome scenarios in the tests + * `region-dependent-*.rs`, but here is one example: * * struct Foo { i: int } * struct Bar { foo: Foo } @@ -583,8 +583,35 @@ pub mod guarantor { let mut expr_ct = categorize_unadjusted(rcx, expr); expr_ct = apply_autoderefs( rcx, expr, autoderefs, expr_ct); - for expr_ct.cat.guarantor.each |g| { - infallibly_mk_subr(rcx, true, expr.span, autoref.region, *g); + + match autoref.kind { + ty::AutoPtr => { + // In this case, we are implicitly adding an `&`. + maybe_make_subregion(rcx, expr, autoref.region, + expr_ct.cat.guarantor); + } + + ty::AutoBorrowVec | + ty::AutoBorrowVecRef | + ty::AutoBorrowFn => { + // In each of these cases, what is being borrowed is + // not the (autoderef'd) expr itself but rather the + // contents of the autoderef'd expression (i.e., what + // the pointer points at). + maybe_make_subregion(rcx, expr, autoref.region, + guarantor_of_deref(&expr_ct.cat)); + } + } + + fn maybe_make_subregion( + rcx: @mut Rcx, + expr: @ast::expr, + sub_region: ty::Region, + sup_region: Option) + { + for sup_region.each |r| { + infallibly_mk_subr(rcx, true, expr.span, sub_region, *r); + } } } @@ -813,19 +840,31 @@ pub mod guarantor { fn pointer_categorize(ty: ty::t) -> PointerCategorization { match ty::get(ty).sty { - ty::ty_rptr(r, _) | ty::ty_evec(_, ty::vstore_slice(r)) | + ty::ty_rptr(r, _) | + ty::ty_evec(_, ty::vstore_slice(r)) | ty::ty_estr(ty::vstore_slice(r)) => { BorrowedPointer(r) } - ty::ty_uniq(*) | ty::ty_estr(ty::vstore_uniq) | + ty::ty_uniq(*) | + ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) => { OwnedPointer } - ty::ty_box(*) | ty::ty_ptr(*) | + ty::ty_box(*) | + ty::ty_ptr(*) | ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => { OtherPointer } + ty::ty_closure(ref closure_ty) => { + match closure_ty.sigil { + ast::BorrowedSigil => BorrowedPointer(closure_ty.region), + ast::OwnedSigil => OwnedPointer, + + // NOTE This is...not quite right. Deduce a test etc. + ast::ManagedSigil => OtherPointer, + } + } _ => { NotPointer } diff --git a/src/test/run-pass/region-dependent-addr-of.rs b/src/test/run-pass/region-dependent-addr-of.rs index 42784200b66..dd33f7f1e30 100644 --- a/src/test/run-pass/region-dependent-addr-of.rs +++ b/src/test/run-pass/region-dependent-addr-of.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test lifetimes are linked properly when we create dependent region pointers. +// Issue #3148. + struct A { value: B } diff --git a/src/test/run-pass/region-dependent-autofn.rs b/src/test/run-pass/region-dependent-autofn.rs new file mode 100644 index 00000000000..82d4115d66d --- /dev/null +++ b/src/test/run-pass/region-dependent-autofn.rs @@ -0,0 +1,22 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test lifetimes are linked properly when we autoslice a vector. +// Issue #3148. + +fn subslice<'r>(v: &'r fn()) -> &'r fn() { v } + +fn both<'r>(v: &'r fn()) -> &'r fn() { + subslice(subslice(v)) +} + +fn main() { + both(main); +} diff --git a/src/test/run-pass/region-dependent-autoslice.rs b/src/test/run-pass/region-dependent-autoslice.rs new file mode 100644 index 00000000000..10c2988fc9f --- /dev/null +++ b/src/test/run-pass/region-dependent-autoslice.rs @@ -0,0 +1,23 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test lifetimes are linked properly when we autoslice a vector. +// Issue #3148. + +fn subslice1<'r>(v: &'r [uint]) -> &'r [uint] { v } + +fn both<'r>(v: &'r [uint]) -> &'r [uint] { + subslice1(subslice1(v)) +} + +fn main() { + let v = ~[1,2,3]; + both(v); +}