about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/ty.rs6
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs53
-rw-r--r--src/test/run-pass/region-dependent-addr-of.rs3
-rw-r--r--src/test/run-pass/region-dependent-autofn.rs22
-rw-r--r--src/test/run-pass/region-dependent-autoslice.rs23
5 files changed, 97 insertions, 10 deletions
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<ty::Region>)
+        {
+            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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}