diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2015-02-11 19:45:19 -0500 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2015-02-16 10:55:37 -0500 |
| commit | 80d1f14e7d54291773bf208e30c1ff4555f2178d (patch) | |
| tree | 617612255fb1cc0e4fc5ad8b17832c43647a7a4a | |
| parent | f5c6a23c9e4676964ea2dd0b2523cc2ae696da4b (diff) | |
| download | rust-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.rs | 8 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 6 | ||||
| -rw-r--r-- | src/librustc_typeck/rscope.rs | 53 | ||||
| -rw-r--r-- | src/test/run-pass/object-lifetime-default-default-to-static.rs | 42 | ||||
| -rw-r--r-- | src/test/run-pass/object-lifetime-default-from-rptr-box.rs | 42 | ||||
| -rw-r--r-- | src/test/run-pass/object-lifetime-default-from-rptr-mut.rs | 43 | ||||
| -rw-r--r-- | src/test/run-pass/object-lifetime-default-from-rptr-struct.rs | 46 | ||||
| -rw-r--r-- | src/test/run-pass/object-lifetime-default-from-rptr.rs | 43 |
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() { +} |
