Skip to content

Commit

Permalink
Auto merge of #22230 - nikomatsakis:object-lifetime-defaults-2, r=pnk…
Browse files Browse the repository at this point in the history
…felix

Implement rules described in rust-lang/rfcs#599.

Fixes #22211.

~~Based atop PR #22182, so the first few commits (up to and including "Pacify the mercilous nrc") have already been reviewed.~~
  • Loading branch information
bors committed Feb 16, 2015
2 parents e4e7aa2 + 503e15b commit 81bce52
Show file tree
Hide file tree
Showing 53 changed files with 1,264 additions and 272 deletions.
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 @@ -1628,7 +1628,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 @@ -1762,6 +1762,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 @@ -1770,6 +1785,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 @@ -5884,42 +5900,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 @@ -7390,3 +7377,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

0 comments on commit 81bce52

Please sign in to comment.