about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-02-11 19:45:19 -0500
committerNiko Matsakis <niko@alum.mit.edu>2015-02-16 10:55:37 -0500
commit80d1f14e7d54291773bf208e30c1ff4555f2178d (patch)
tree617612255fb1cc0e4fc5ad8b17832c43647a7a4a
parentf5c6a23c9e4676964ea2dd0b2523cc2ae696da4b (diff)
downloadrust-80d1f14e7d54291773bf208e30c1ff4555f2178d.tar.gz
rust-80d1f14e7d54291773bf208e30c1ff4555f2178d.zip
Implement the basic rules of RFC 599, but do not yet support custom types.
-rw-r--r--src/librustc_typeck/astconv.rs8
-rw-r--r--src/librustc_typeck/check/mod.rs6
-rw-r--r--src/librustc_typeck/rscope.rs53
-rw-r--r--src/test/run-pass/object-lifetime-default-default-to-static.rs42
-rw-r--r--src/test/run-pass/object-lifetime-default-from-rptr-box.rs42
-rw-r--r--src/test/run-pass/object-lifetime-default-from-rptr-mut.rs43
-rw-r--r--src/test/run-pass/object-lifetime-default-from-rptr-struct.rs46
-rw-r--r--src/test/run-pass/object-lifetime-default-from-rptr.rs43
8 files changed, 275 insertions, 8 deletions
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index ac892e64861..754ca643971 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -56,7 +56,7 @@ use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
 use middle::traits;
 use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
 use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
-             ShiftedRscope, BindingRscope};
+             ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
 use TypeAndSubsts;
 use util::common::{ErrorReported, FN_OUTPUT_NAME};
 use util::nodemap::DefIdMap;
@@ -1084,7 +1084,11 @@ pub fn ast_ty_to_ty<'tcx>(
             ast::TyRptr(ref region, ref mt) => {
                 let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
                 debug!("ty_rptr r={}", r.repr(this.tcx()));
-                let t = ast_ty_to_ty(this, rscope, &*mt.ty);
+                let rscope1 =
+                    &ObjectLifetimeDefaultRscope::new(
+                        rscope,
+                        Some(ty::ObjectLifetimeDefault::Specific(r)));
+                let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
                 ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
             }
             ast::TyTup(ref fields) => {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 874bd40ab9f..4c1fd7ea854 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1891,6 +1891,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
+        // TODO. RFC #599 specifies that object lifetime defaults take
+        // precedence over other defaults. *However,* within a fn
+        // body, we typically use inference to allow users to elide
+        // lifetimes whenever they like, and then just infer it to
+        // whatever it must be. So I interpret that as applying only
+        // to fn sigs.
         Some(self.infcx().next_region_var(infer::MiscVariable(span)))
     }
 
diff --git a/src/librustc_typeck/rscope.rs b/src/librustc_typeck/rscope.rs
index c53fe91dc43..b591209a638 100644
--- a/src/librustc_typeck/rscope.rs
+++ b/src/librustc_typeck/rscope.rs
@@ -45,7 +45,7 @@ pub struct ExplicitRscope;
 
 impl RegionScope for ExplicitRscope {
     fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
-        None
+        Some(ty::ReStatic)
     }
 
     fn anon_regions(&self,
@@ -67,7 +67,7 @@ impl UnelidableRscope {
 
 impl RegionScope for UnelidableRscope {
     fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
-        None
+        Some(ty::ReStatic)
     }
 
     fn anon_regions(&self,
@@ -95,7 +95,10 @@ impl ElidableRscope {
 
 impl RegionScope for ElidableRscope {
     fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
-        Some(self.default)
+        // Per RFC #599, object-lifetimes default to 'static unless
+        // overridden by context, and this takes precedence over
+        // lifetime elision.
+        Some(ty::ReStatic)
     }
 
     fn anon_regions(&self,
@@ -128,9 +131,11 @@ impl BindingRscope {
 }
 
 impl RegionScope for BindingRscope {
-    fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region>
-    {
-        Some(self.next_region())
+    fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
+        // Per RFC #599, object-lifetimes default to 'static unless
+        // overridden by context, and this takes precedence over the
+        // binding defaults.
+        Some(ty::ReStatic)
     }
 
     fn anon_regions(&self,
@@ -142,6 +147,42 @@ impl RegionScope for BindingRscope {
     }
 }
 
+/// A scope which overrides the default object lifetime but has no other effect.
+pub struct ObjectLifetimeDefaultRscope<'r> {
+    base_scope: &'r (RegionScope+'r),
+    default: Option<ty::ObjectLifetimeDefault>,
+}
+
+impl<'r> ObjectLifetimeDefaultRscope<'r> {
+    pub fn new(base_scope: &'r (RegionScope+'r),
+               default: Option<ty::ObjectLifetimeDefault>)
+               -> ObjectLifetimeDefaultRscope<'r>
+    {
+        ObjectLifetimeDefaultRscope {
+            base_scope: base_scope,
+            default: default,
+        }
+    }
+}
+
+impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
+    fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
+        match self.default {
+            None => self.base_scope.object_lifetime_default(span),
+            Some(ty::ObjectLifetimeDefault::Ambiguous) => None,
+            Some(ty::ObjectLifetimeDefault::Specific(r)) => Some(r),
+        }
+    }
+
+    fn anon_regions(&self,
+                    span: Span,
+                    count: uint)
+                    -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
+    {
+        self.base_scope.anon_regions(span, count)
+    }
+}
+
 /// A scope which simply shifts the Debruijn index of other scopes
 /// to account for binding levels.
 pub struct ShiftedRscope<'r> {
diff --git a/src/test/run-pass/object-lifetime-default-default-to-static.rs b/src/test/run-pass/object-lifetime-default-default-to-static.rs
new file mode 100644
index 00000000000..c385a0195b6
--- /dev/null
+++ b/src/test/run-pass/object-lifetime-default-default-to-static.rs
@@ -0,0 +1,42 @@
+// Copyright 2015 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 that `Box<Test>` is equivalent to `Box<Test+'static>`, both in
+// fields and fn arguments.
+
+#![allow(dead_code)]
+
+trait Test {
+    fn foo(&self) { }
+}
+
+struct SomeStruct {
+    t: Box<Test>,
+    u: Box<Test+'static>,
+}
+
+fn a(t: Box<Test>, mut ss: SomeStruct) {
+    ss.t = t;
+}
+
+fn b(t: Box<Test+'static>, mut ss: SomeStruct) {
+    ss.t = t;
+}
+
+fn c(t: Box<Test>, mut ss: SomeStruct) {
+    ss.u = t;
+}
+
+fn d(t: Box<Test+'static>, mut ss: SomeStruct) {
+    ss.u = t;
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/object-lifetime-default-from-rptr-box.rs b/src/test/run-pass/object-lifetime-default-from-rptr-box.rs
new file mode 100644
index 00000000000..825800e1d44
--- /dev/null
+++ b/src/test/run-pass/object-lifetime-default-from-rptr-box.rs
@@ -0,0 +1,42 @@
+// Copyright 2015 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 that the lifetime from the enclosing `&` is "inherited"
+// through the `Box` struct.
+
+#![allow(dead_code)]
+
+trait Test {
+    fn foo(&self) { }
+}
+
+struct SomeStruct<'a> {
+    t: &'a Box<Test>,
+    u: &'a Box<Test+'a>,
+}
+
+fn a<'a>(t: &'a Box<Test>, mut ss: SomeStruct<'a>) {
+    ss.t = t;
+}
+
+fn b<'a>(t: &'a Box<Test>, mut ss: SomeStruct<'a>) {
+    ss.u = t;
+}
+
+fn c<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
+    ss.t = t;
+}
+
+fn d<'a>(t: &'a Box<Test+'a>, mut ss: SomeStruct<'a>) {
+    ss.u = t;
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/object-lifetime-default-from-rptr-mut.rs b/src/test/run-pass/object-lifetime-default-from-rptr-mut.rs
new file mode 100644
index 00000000000..0f34d945c8f
--- /dev/null
+++ b/src/test/run-pass/object-lifetime-default-from-rptr-mut.rs
@@ -0,0 +1,43 @@
+// Copyright 2015 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 that the lifetime of the enclosing `&` is used for the object
+// lifetime bound.
+
+#![allow(dead_code)]
+
+trait Test {
+    fn foo(&self) { }
+}
+
+struct SomeStruct<'a> {
+    t: &'a mut Test,
+    u: &'a mut (Test+'a),
+}
+
+fn a<'a>(t: &'a mut Test, mut ss: SomeStruct<'a>) {
+    ss.t = t;
+}
+
+fn b<'a>(t: &'a mut Test, mut ss: SomeStruct<'a>) {
+    ss.u = t;
+}
+
+fn c<'a>(t: &'a mut (Test+'a), mut ss: SomeStruct<'a>) {
+    ss.t = t;
+}
+
+fn d<'a>(t: &'a mut (Test+'a), mut ss: SomeStruct<'a>) {
+    ss.u = t;
+}
+
+
+fn main() {
+}
diff --git a/src/test/run-pass/object-lifetime-default-from-rptr-struct.rs b/src/test/run-pass/object-lifetime-default-from-rptr-struct.rs
new file mode 100644
index 00000000000..9d5dac536f1
--- /dev/null
+++ b/src/test/run-pass/object-lifetime-default-from-rptr-struct.rs
@@ -0,0 +1,46 @@
+// Copyright 2015 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 that the lifetime from the enclosing `&` is "inherited"
+// through the `MyBox` struct.
+
+#![allow(dead_code)]
+
+trait Test {
+    fn foo(&self) { }
+}
+
+struct SomeStruct<'a> {
+    t: &'a MyBox<Test>,
+    u: &'a MyBox<Test+'a>,
+}
+
+struct MyBox<T:?Sized> {
+    b: Box<T>
+}
+
+fn a<'a>(t: &'a MyBox<Test>, mut ss: SomeStruct<'a>) {
+    ss.t = t;
+}
+
+fn b<'a>(t: &'a MyBox<Test>, mut ss: SomeStruct<'a>) {
+    ss.u = t;
+}
+
+fn c<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
+    ss.t = t;
+}
+
+fn d<'a>(t: &'a MyBox<Test+'a>, mut ss: SomeStruct<'a>) {
+    ss.u = t;
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/object-lifetime-default-from-rptr.rs b/src/test/run-pass/object-lifetime-default-from-rptr.rs
new file mode 100644
index 00000000000..b7a28a5c524
--- /dev/null
+++ b/src/test/run-pass/object-lifetime-default-from-rptr.rs
@@ -0,0 +1,43 @@
+// Copyright 2015 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 that the lifetime of the enclosing `&` is used for the object
+// lifetime bound.
+
+#![allow(dead_code)]
+
+trait Test {
+    fn foo(&self) { }
+}
+
+struct SomeStruct<'a> {
+    t: &'a Test,
+    u: &'a (Test+'a),
+}
+
+fn a<'a>(t: &'a Test, mut ss: SomeStruct<'a>) {
+    ss.t = t;
+}
+
+fn b<'a>(t: &'a Test, mut ss: SomeStruct<'a>) {
+    ss.u = t;
+}
+
+fn c<'a>(t: &'a (Test+'a), mut ss: SomeStruct<'a>) {
+    ss.t = t;
+}
+
+fn d<'a>(t: &'a (Test+'a), mut ss: SomeStruct<'a>) {
+    ss.u = t;
+}
+
+
+fn main() {
+}