rustc: always keep an explicit lifetime in trait objects.

This commit is contained in:
Eduard-Mihai Burtescu 2017-01-24 17:17:06 +02:00
parent 41553d6fbc
commit c5befdc630
13 changed files with 137 additions and 166 deletions

View file

@ -301,7 +301,7 @@ pub trait Visitor<'v> : Sized {
fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
walk_ty_param_bound(self, bounds)
}
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: TraitBoundModifier) {
walk_poly_trait_ref(self, t, m)
}
fn visit_variant_data(&mut self,
@ -421,7 +421,7 @@ pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v
pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
trait_ref: &'v PolyTraitRef,
_modifier: &'v TraitBoundModifier)
_modifier: TraitBoundModifier)
where V: Visitor<'v>
{
walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
@ -566,8 +566,11 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
visitor.visit_ty(ty);
visitor.visit_nested_body(length)
}
TyTraitObject(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
TyTraitObject(ref bounds, ref lifetime) => {
for bound in bounds {
visitor.visit_poly_trait_ref(bound, TraitBoundModifier::None);
}
visitor.visit_lifetime(lifetime);
}
TyImplTrait(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
@ -695,7 +698,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) {
match *bound {
TraitTyParamBound(ref typ, ref modifier) => {
TraitTyParamBound(ref typ, modifier) => {
visitor.visit_poly_trait_ref(typ, modifier);
}
RegionTyParamBound(ref lifetime) => {

View file

@ -360,7 +360,23 @@ impl<'a> LoweringContext<'a> {
hir::TyTypeof(self.record_body(expr, None))
}
TyKind::TraitObject(ref bounds) => {
hir::TyTraitObject(self.lower_bounds(bounds))
let mut lifetime_bound = None;
let bounds = bounds.iter().filter_map(|bound| {
match *bound {
TraitTyParamBound(ref ty, TraitBoundModifier::None) => {
Some(self.lower_poly_trait_ref(ty))
}
TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
RegionTyParamBound(ref lifetime) => {
lifetime_bound = Some(self.lower_lifetime(lifetime));
None
}
}
}).collect();
let lifetime_bound = lifetime_bound.unwrap_or_else(|| {
self.elided_lifetime(t.span)
});
hir::TyTraitObject(bounds, lifetime_bound)
}
TyKind::ImplTrait(ref bounds) => {
hir::TyImplTrait(self.lower_bounds(bounds))
@ -2361,20 +2377,20 @@ impl<'a> LoweringContext<'a> {
hir::QPath::Resolved(None, path) => {
// Turn trait object paths into `TyTraitObject` instead.
if let Def::Trait(_) = path.def {
let principal = hir::TraitTyParamBound(hir::PolyTraitRef {
let principal = hir::PolyTraitRef {
bound_lifetimes: hir_vec![],
trait_ref: hir::TraitRef {
path: path.and_then(|path| path),
ref_id: id,
},
span,
}, hir::TraitBoundModifier::None);
};
// The original ID is taken by the `PolyTraitRef`,
// so the `Ty` itself needs a different one.
id = self.next_id();
hir::TyTraitObject(hir_vec![principal])
hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span))
} else {
hir::TyPath(hir::QPath::Resolved(None, path))
}

View file

@ -1205,7 +1205,7 @@ pub enum Ty_ {
TyPath(QPath),
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TyTraitObject(TyParamBounds),
TyTraitObject(HirVec<PolyTraitRef>, Lifetime),
/// An `impl Bound1 + Bound2 + Bound3` type
/// where `Bound` is a trait or a lifetime.
TyImplTrait(TyParamBounds),

View file

@ -416,8 +416,21 @@ impl<'a> State<'a> {
hir::TyPath(ref qpath) => {
self.print_qpath(qpath, false)?
}
hir::TyTraitObject(ref bounds) => {
self.print_bounds("", &bounds[..])?;
hir::TyTraitObject(ref bounds, ref lifetime) => {
let mut first = true;
for bound in bounds {
self.nbsp()?;
if first {
first = false;
} else {
self.word_space("+")?;
}
self.print_poly_trait_ref(bound)?;
}
if !lifetime.is_elided() {
self.word_space("+")?;
self.print_lifetime(lifetime)?;
}
}
hir::TyImplTrait(ref bounds) => {
self.print_bounds("impl ", &bounds[..])?;

View file

@ -322,6 +322,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
intravisit::walk_ty(this, ty);
});
}
hir::TyTraitObject(ref bounds, ref lifetime) => {
for bound in bounds {
self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
}
if !lifetime.is_elided() {
self.visit_lifetime(lifetime);
}
}
_ => {
intravisit::walk_ty(self, ty)
}
@ -441,7 +449,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fn visit_poly_trait_ref(&mut self,
trait_ref: &'tcx hir::PolyTraitRef,
_modifier: &'tcx hir::TraitBoundModifier) {
_modifier: hir::TraitBoundModifier) {
debug!("visit_poly_trait_ref trait_ref={:?}", trait_ref);
if !self.trait_ref_hack || !trait_ref.bound_lifetimes.is_empty() {
@ -962,7 +970,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
fn visit_poly_trait_ref(&mut self,
trait_ref: &hir::PolyTraitRef,
modifier: &hir::TraitBoundModifier) {
modifier: hir::TraitBoundModifier) {
self.binder_depth += 1;
intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
self.binder_depth -= 1;