Code up the new lifetime default rules, but leave them disabled
for now.
This commit is contained in:
parent
f027bdc1c8
commit
ef85338175
7 changed files with 90 additions and 36 deletions
|
|
@ -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>
|
||||
-> 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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<ty::ObjectLifetimeDefault>)
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Ty<'tcx>>,
|
||||
pub object_lifetime_default: Option<ObjectLifetimeDefault>,
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<ty::Region> {
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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::<Vec<String>>()
|
||||
|
|
@ -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>
|
||||
-> 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>,
|
||||
|
|
|
|||
|
|
@ -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<ty::Region>;
|
||||
|
||||
/// 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<ty::Region> {
|
||||
Some(ty::ReStatic)
|
||||
}
|
||||
|
||||
fn anon_regions(&self,
|
||||
_span: Span,
|
||||
_count: usize)
|
||||
-> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
|
||||
Err(None)
|
||||
}
|
||||
|
||||
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
|
||||
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<ty::Region> {
|
||||
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<ty::Region> {
|
||||
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<ty::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
|
||||
// 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<ty::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)
|
||||
// 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<ty::ObjectLifetimeDefault>,
|
||||
default: ty::ObjectLifetimeDefault,
|
||||
}
|
||||
|
||||
impl<'r> ObjectLifetimeDefaultRscope<'r> {
|
||||
pub fn new(base_scope: &'r (RegionScope+'r),
|
||||
default: Option<ty::ObjectLifetimeDefault>)
|
||||
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<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),
|
||||
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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue