Implement the basic rules of RFC 599, but do not yet support custom types.

This commit is contained in:
Niko Matsakis 2015-02-11 19:45:19 -05:00
parent f5c6a23c9e
commit 80d1f14e7d
8 changed files with 275 additions and 8 deletions

View File

@ -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) => {

View File

@ -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)))
}

View File

@ -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> {

View File

@ -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() {
}

View File

@ -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() {
}

View File

@ -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() {
}

View File

@ -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() {
}

View File

@ -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() {
}