Skip to content

Commit

Permalink
rustc: always keep an explicit lifetime in trait objects.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Jan 28, 2017
1 parent 41553d6 commit c5befdc
Show file tree
Hide file tree
Showing 13 changed files with 137 additions and 166 deletions.
13 changes: 8 additions & 5 deletions src/librustc/hir/intravisit.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) => {
Expand Down
24 changes: 20 additions & 4 deletions src/librustc/hir/lowering.rs
Expand Up @@ -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))
Expand Down Expand Up @@ -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))
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/mod.rs
Expand Up @@ -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),
Expand Down
17 changes: 15 additions & 2 deletions src/librustc/hir/print.rs
Expand Up @@ -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[..])?;
Expand Down
12 changes: 10 additions & 2 deletions src/librustc/middle/resolve_lifetime.rs
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_incremental/calculate_svh/svh_visitor.rs
Expand Up @@ -828,7 +828,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
visit::walk_ty_param_bound(self, bounds)
}

fn visit_poly_trait_ref(&mut self, t: &'tcx PolyTraitRef, m: &'tcx TraitBoundModifier) {
fn visit_poly_trait_ref(&mut self, t: &'tcx PolyTraitRef, m: TraitBoundModifier) {
debug!("visit_poly_trait_ref: st={:?}", self.st);
SawPolyTraitRef.hash(self.st);
m.hash(self.st);
Expand Down
11 changes: 11 additions & 0 deletions src/librustc_passes/ast_validation.rs
Expand Up @@ -144,6 +144,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
});
}
TyKind::TraitObject(ref bounds) => {
let mut any_lifetime_bounds = false;
for bound in bounds {
if let RegionTyParamBound(ref lifetime) = *bound {
if any_lifetime_bounds {
span_err!(self.session, lifetime.span, E0226,
"only a single explicit lifetime bound is permitted");
break;
}
any_lifetime_bounds = true;
}
}
self.no_questions_in_bounds(bounds, "trait object types", false);
}
TyKind::ImplTrait(ref bounds) => {
Expand Down
1 change: 1 addition & 0 deletions src/librustc_passes/diagnostics.rs
Expand Up @@ -244,6 +244,7 @@ match 5u32 {
}

register_diagnostics! {
E0226, // only a single explicit lifetime bound is permitted
E0472, // asm! is unsupported on this target
E0561, // patterns aren't allowed in function pointer types
E0571, // `break` with a value in a non-`loop`-loop
Expand Down

0 comments on commit c5befdc

Please sign in to comment.