From ef85338175cb322fa07846d20eec91c2800a98e6 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 17 Jun 2015 10:02:32 -0400 Subject: [PATCH] Code up the new lifetime default rules, but leave them disabled for now. --- src/librustc/metadata/tydecode.rs | 8 ++-- src/librustc/metadata/tyencode.rs | 8 ++-- src/librustc/middle/ty.rs | 6 ++- src/librustc/middle/ty_fold.rs | 3 ++ src/librustc_typeck/check/mod.rs | 6 ++- src/librustc_typeck/collect.rs | 16 +++---- src/librustc_typeck/rscope.rs | 79 ++++++++++++++++++++++++------- 7 files changed, 90 insertions(+), 36 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index a5b9e40593a83..99d27c1ba3190 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -843,15 +843,15 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) fn parse_object_lifetime_default<'a,'tcx, F>(st: &mut PState<'a,'tcx>, conv: &mut F) - -> Option + -> ty::ObjectLifetimeDefault where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId, { match next(st) { - 'n' => None, - 'a' => Some(ty::ObjectLifetimeDefault::Ambiguous), + 'a' => ty::ObjectLifetimeDefault::Ambiguous, + 'b' => ty::ObjectLifetimeDefault::BaseDefault, 's' => { let region = parse_region_(st, conv); - Some(ty::ObjectLifetimeDefault::Specific(region)) + ty::ObjectLifetimeDefault::Specific(region) } _ => panic!("parse_object_lifetime_default: bad input") } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index c078b62dd2d8a..d80316b8f489f 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -414,12 +414,12 @@ pub fn enc_type_param_def<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, - default: Option) + default: ty::ObjectLifetimeDefault) { match default { - None => mywrite!(w, "n"), - Some(ty::ObjectLifetimeDefault::Ambiguous) => mywrite!(w, "a"), - Some(ty::ObjectLifetimeDefault::Specific(r)) => { + ty::ObjectLifetimeDefault::Ambiguous => mywrite!(w, "a"), + ty::ObjectLifetimeDefault::BaseDefault => mywrite!(w, "b"), + ty::ObjectLifetimeDefault::Specific(r) => { mywrite!(w, "s"); enc_region(w, cx, r); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 91a038813b868..d5372d77005d3 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2245,6 +2245,9 @@ pub enum ObjectLifetimeDefault { /// `T:'a` constraints are found. Ambiguous, + /// Use the base default, typically 'static, but in a fn body it is a fresh variable + BaseDefault, + /// Use the given region as the default. Specific(Region), } @@ -2256,7 +2259,7 @@ pub struct TypeParameterDef<'tcx> { pub space: subst::ParamSpace, pub index: u32, pub default: Option>, - pub object_lifetime_default: Option, + pub object_lifetime_default: ObjectLifetimeDefault, } #[derive(RustcEncodable, RustcDecodable, Clone, Debug)] @@ -7328,6 +7331,7 @@ impl<'tcx> fmt::Debug for ObjectLifetimeDefault { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ObjectLifetimeDefault::Ambiguous => write!(f, "Ambiguous"), + ObjectLifetimeDefault::BaseDefault => format!("BaseDefault"), ObjectLifetimeDefault::Specific(ref r) => write!(f, "{:?}", r), } } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 284d26b3cd6d7..6bae1b68ed421 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -369,6 +369,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ObjectLifetimeDefault { ty::ObjectLifetimeDefault::Ambiguous => ty::ObjectLifetimeDefault::Ambiguous, + ty::ObjectLifetimeDefault::BaseDefault => + ty::ObjectLifetimeDefault::BaseDefault, + ty::ObjectLifetimeDefault::Specific(r) => ty::ObjectLifetimeDefault::Specific(r.fold_with(folder)), } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c6975982c8747..05166fa6134cf 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1779,6 +1779,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> { fn object_lifetime_default(&self, span: Span) -> Option { + Some(self.base_object_lifetime_default(span)) + } + + fn base_object_lifetime_default(&self, span: Span) -> ty::Region { // RFC #599 specifies that object lifetime defaults take // precedence over other defaults. But within a fn body we // don't have a *default* region, rather we use inference to @@ -1786,7 +1790,7 @@ impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> { // (and anyway, within a fn body the right region may not even // be something the user can write explicitly, since it might // be some expression). - Some(self.infcx().next_region_var(infer::MiscVariable(span))) + self.infcx().next_region_var(infer::MiscVariable(span)) } fn anon_regions(&self, span: Span, count: usize) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 5161c84e4b1a6..e170808ad07d6 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1532,8 +1532,7 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let object_lifetime_default_reprs: String = scheme.generics.types.iter() .map(|t| match t.object_lifetime_default { - Some(ty::ObjectLifetimeDefault::Specific(r)) => - r.to_string(), + ty::ObjectLifetimeDefault::Specific(r) => r.to_string(), d => format!("{:?}", d), }) .collect::>() @@ -1637,7 +1636,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, name: special_idents::type_self.name, def_id: local_def(param_id), default: None, - object_lifetime_default: None, + object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault, }; ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone()); @@ -1928,7 +1927,7 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, param_id: ast::NodeId, param_bounds: &[ast::TyParamBound], where_clause: &ast::WhereClause) - -> Option + -> ty::ObjectLifetimeDefault { let inline_bounds = from_bounds(ccx, param_bounds); let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates); @@ -1936,11 +1935,12 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, .chain(where_bounds) .collect(); return if all_bounds.len() > 1 { - Some(ty::ObjectLifetimeDefault::Ambiguous) + ty::ObjectLifetimeDefault::Ambiguous + } else if all_bounds.len() == 0 { + ty::ObjectLifetimeDefault::BaseDefault } else { - all_bounds.into_iter() - .next() - .map(ty::ObjectLifetimeDefault::Specific) + ty::ObjectLifetimeDefault::Specific( + all_bounds.into_iter().next().unwrap()) }; fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, diff --git a/src/librustc_typeck/rscope.rs b/src/librustc_typeck/rscope.rs index b416026ba0134..89f118a717977 100644 --- a/src/librustc_typeck/rscope.rs +++ b/src/librustc_typeck/rscope.rs @@ -45,6 +45,13 @@ pub trait RegionScope { /// be derived from the object traits, what should we use? If /// `None` is returned, an explicit annotation is required. fn object_lifetime_default(&self, span: Span) -> Option; + + /// The "base" default is the initial default for a scope. This is + /// 'static except for in fn bodies, where it is a fresh inference + /// variable. You shouldn't call this except for as part of + /// computing `object_lifetime_default` (in particular, in legacy + /// modes, it may not be relevant). + fn base_object_lifetime_default(&self, span: Span) -> ty::Region; } // A scope in which all regions must be explicitly named. This is used @@ -53,16 +60,20 @@ pub trait RegionScope { pub struct ExplicitRscope; impl RegionScope for ExplicitRscope { - fn object_lifetime_default(&self, _span: Span) -> Option { - Some(ty::ReStatic) - } - fn anon_regions(&self, _span: Span, _count: usize) -> Result, Option>> { Err(None) } + + fn object_lifetime_default(&self, span: Span) -> Option { + Some(self.base_object_lifetime_default(span)) + } + + fn base_object_lifetime_default(&self, _span: Span) -> ty::Region { + ty::ReStatic + } } // Same as `ExplicitRscope`, but provides some extra information for diagnostics @@ -75,10 +86,6 @@ impl UnelidableRscope { } impl RegionScope for UnelidableRscope { - fn object_lifetime_default(&self, _span: Span) -> Option { - Some(ty::ReStatic) - } - fn anon_regions(&self, _span: Span, _count: usize) @@ -86,6 +93,14 @@ impl RegionScope for UnelidableRscope { let UnelidableRscope(ref v) = *self; Err(v.clone()) } + + fn object_lifetime_default(&self, span: Span) -> Option { + Some(self.base_object_lifetime_default(span)) + } + + fn base_object_lifetime_default(&self, _span: Span) -> ty::Region { + ty::ReStatic + } } // A scope in which omitted anonymous region defaults to @@ -103,11 +118,15 @@ impl ElidableRscope { } impl RegionScope for ElidableRscope { - fn object_lifetime_default(&self, _span: Span) -> Option { + fn object_lifetime_default(&self, span: Span) -> Option { // Per RFC #599, object-lifetimes default to 'static unless // overridden by context, and this takes precedence over // lifetime elision. - Some(ty::ReStatic) + Some(self.base_object_lifetime_default(span)) + } + + fn base_object_lifetime_default(&self, _span: Span) -> ty::Region { + ty::ReStatic } fn anon_regions(&self, @@ -140,11 +159,15 @@ impl BindingRscope { } impl RegionScope for BindingRscope { - fn object_lifetime_default(&self, _span: Span) -> Option { + fn object_lifetime_default(&self, span: Span) -> Option { // Per RFC #599, object-lifetimes default to 'static unless // overridden by context, and this takes precedence over the - // binding defaults. - Some(ty::ReStatic) + // binding defaults in a fn signature. + Some(self.base_object_lifetime_default(span)) + } + + fn base_object_lifetime_default(&self, _span: Span) -> ty::Region { + ty::ReStatic } fn anon_regions(&self, @@ -159,12 +182,12 @@ 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, + default: ty::ObjectLifetimeDefault, } impl<'r> ObjectLifetimeDefaultRscope<'r> { pub fn new(base_scope: &'r (RegionScope+'r), - default: Option) + default: ty::ObjectLifetimeDefault) -> ObjectLifetimeDefaultRscope<'r> { ObjectLifetimeDefaultRscope { @@ -177,9 +200,25 @@ impl<'r> ObjectLifetimeDefaultRscope<'r> { impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> { fn object_lifetime_default(&self, span: Span) -> Option { match self.default { - None => self.base_scope.object_lifetime_default(span), - Some(ty::ObjectLifetimeDefault::Ambiguous) => None, - Some(ty::ObjectLifetimeDefault::Specific(r)) => Some(r), + ty::ObjectLifetimeDefault::Ambiguous => + None, + + ty::ObjectLifetimeDefault::BaseDefault => + if false { // this will become the behavior in Rust 1.3 + Some(self.base_object_lifetime_default(span)) + } else { + self.base_scope.object_lifetime_default(span) + }, + + ty::ObjectLifetimeDefault::Specific(r) => + Some(r), + } + } + + fn base_object_lifetime_default(&self, span: Span) -> ty::Region { + assert!(false, "this code should not execute until Rust 1.3"); + self.base_scope.base_object_lifetime_default(span) + } } } @@ -210,6 +249,10 @@ impl<'r> RegionScope for ShiftedRscope<'r> { .map(|r| ty_fold::shift_region(r, 1)) } + fn base_object_lifetime_default(&self, span: Span) -> ty::Region { + ty_fold::shift_region(self.base_scope.base_object_lifetime_default(span), 1) + } + fn anon_regions(&self, span: Span, count: usize)