Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object lifetime defaults (RFC 599) #22230

Merged
merged 8 commits into from
Feb 16, 2015
20 changes: 19 additions & 1 deletion src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,14 +824,32 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
assert_eq!(next(st), '|');
let bounds = parse_bounds_(st, conv);
let default = parse_opt(st, |st| parse_ty_(st, conv));
let object_lifetime_default = parse_object_lifetime_default(st, conv);

ty::TypeParameterDef {
name: name,
def_id: def_id,
space: space,
index: index,
bounds: bounds,
default: default
default: default,
object_lifetime_default: object_lifetime_default,
}
}

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),
's' => {
let region = parse_region_(st, conv);
Some(ty::ObjectLifetimeDefault::Specific(region))
}
_ => panic!("parse_object_lifetime_default: bad input")
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,21 @@ pub fn enc_type_param_def<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tc
v.space.to_uint(), v.index);
enc_bounds(w, cx, &v.bounds);
enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
enc_object_lifetime_default(w, cx, v.object_lifetime_default);
}

fn enc_object_lifetime_default<'a, 'tcx>(w: &mut SeekableMemWriter,
cx: &ctxt<'a, 'tcx>,
default: Option<ty::ObjectLifetimeDefault>)
{
match default {
None => mywrite!(w, "n"),
Some(ty::ObjectLifetimeDefault::Ambiguous) => mywrite!(w, "a"),
Some(ty::ObjectLifetimeDefault::Specific(r)) => {
mywrite!(w, "s");
enc_region(w, cx, r);
}
}
}

pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/infer/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
infer::RelateRegionParamBound(span) => {
self.tcx.sess.span_err(
span,
"declared lifetime bound not satisfied");
"lifetime bound not satisfied");
note_and_explain_region(
self.tcx,
"lifetime parameter instantiated with ",
Expand Down Expand Up @@ -1629,7 +1629,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
self.tcx.sess.span_note(
span,
&format!("...so that the type `{}` \
will meet the declared lifetime bounds",
will meet its required lifetime bounds",
self.ty_to_string(t))[]);
}
infer::RelateDefaultParamBound(span, t) => {
Expand Down
56 changes: 26 additions & 30 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1758,6 +1758,21 @@ impl fmt::Debug for IntVarValue {
}
}

/// Default region to use for the bound of objects that are
/// supplied as the value for this type parameter. This is derived
/// from `T:'a` annotations appearing in the type definition. If
/// this is `None`, then the default is inherited from the
/// surrounding context. See RFC #599 for details.
#[derive(Copy, Clone, Debug)]
pub enum ObjectLifetimeDefault {
/// Require an explicit annotation. Occurs when multiple
/// `T:'a` constraints are found.
Ambiguous,

/// Use the given region as the default.
Specific(Region),
}

#[derive(Clone, Debug)]
pub struct TypeParameterDef<'tcx> {
pub name: ast::Name,
Expand All @@ -1766,6 +1781,7 @@ pub struct TypeParameterDef<'tcx> {
pub index: u32,
pub bounds: ParamBounds<'tcx>,
pub default: Option<Ty<'tcx>>,
pub object_lifetime_default: Option<ObjectLifetimeDefault>,
}

#[derive(RustcEncodable, RustcDecodable, Clone, Debug)]
Expand Down Expand Up @@ -5880,42 +5896,13 @@ pub fn each_bound_trait_and_supertraits<'tcx, F>(tcx: &ctxt<'tcx>,
return true;
}

pub fn object_region_bounds<'tcx>(
tcx: &ctxt<'tcx>,
opt_principal: Option<&PolyTraitRef<'tcx>>, // None for closures
others: BuiltinBounds)
-> Vec<ty::Region>
{
// Since we don't actually *know* the self type for an object,
// this "open(err)" serves as a kind of dummy standin -- basically
// a skolemized type.
let open_ty = ty::mk_infer(tcx, FreshTy(0));

let opt_trait_ref = opt_principal.map_or(Vec::new(), |principal| {
// Note that we preserve the overall binding levels here.
assert!(!open_ty.has_escaping_regions());
let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty));
vec!(ty::Binder(Rc::new(ty::TraitRef::new(principal.0.def_id, substs))))
});

let param_bounds = ty::ParamBounds {
region_bounds: Vec::new(),
builtin_bounds: others,
trait_bounds: opt_trait_ref,
projection_bounds: Vec::new(), // not relevant to computing region bounds
};

let predicates = ty::predicates(tcx, open_ty, &param_bounds);
ty::required_region_bounds(tcx, open_ty, predicates)
}

/// Given a set of predicates that apply to an object type, returns
/// the region bounds that the (erased) `Self` type must
/// outlive. Precisely *because* the `Self` type is erased, the
/// parameter `erased_self_ty` must be supplied to indicate what type
/// has been used to represent `Self` in the predicates
/// themselves. This should really be a unique type; `FreshTy(0)` is a
/// popular choice (see `object_region_bounds` above).
/// popular choice.
///
/// Requires that trait definitions have been processed so that we can
/// elaborate predicates and walk supertraits.
Expand Down Expand Up @@ -7386,3 +7373,12 @@ impl<'a, 'tcx> Repr<'tcx> for ParameterEnvironment<'a, 'tcx> {
self.caller_bounds.repr(tcx))
}
}

impl<'tcx> Repr<'tcx> for ObjectLifetimeDefault {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
match *self {
ObjectLifetimeDefault::Ambiguous => format!("Ambiguous"),
ObjectLifetimeDefault::Specific(ref r) => r.repr(tcx),
}
}
}
13 changes: 13 additions & 0 deletions src/librustc/middle/ty_fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,19 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
index: self.index,
bounds: self.bounds.fold_with(folder),
default: self.default.fold_with(folder),
object_lifetime_default: self.object_lifetime_default.fold_with(folder),
}
}
}

impl<'tcx> TypeFoldable<'tcx> for ty::ObjectLifetimeDefault {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ObjectLifetimeDefault {
match *self {
ty::ObjectLifetimeDefault::Ambiguous =>
ty::ObjectLifetimeDefault::Ambiguous,

ty::ObjectLifetimeDefault::Specific(r) =>
ty::ObjectLifetimeDefault::Specific(r.fold_with(folder)),
}
}
}
Expand Down
Loading