Skip to content

Commit c5befdc

Browse files
committed
rustc: always keep an explicit lifetime in trait objects.
1 parent 41553d6 commit c5befdc

File tree

13 files changed

+137
-166
lines changed

13 files changed

+137
-166
lines changed

src/librustc/hir/intravisit.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ pub trait Visitor<'v> : Sized {
301301
fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
302302
walk_ty_param_bound(self, bounds)
303303
}
304-
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
304+
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: TraitBoundModifier) {
305305
walk_poly_trait_ref(self, t, m)
306306
}
307307
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
421421

422422
pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
423423
trait_ref: &'v PolyTraitRef,
424-
_modifier: &'v TraitBoundModifier)
424+
_modifier: TraitBoundModifier)
425425
where V: Visitor<'v>
426426
{
427427
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) {
566566
visitor.visit_ty(ty);
567567
visitor.visit_nested_body(length)
568568
}
569-
TyTraitObject(ref bounds) => {
570-
walk_list!(visitor, visit_ty_param_bound, bounds);
569+
TyTraitObject(ref bounds, ref lifetime) => {
570+
for bound in bounds {
571+
visitor.visit_poly_trait_ref(bound, TraitBoundModifier::None);
572+
}
573+
visitor.visit_lifetime(lifetime);
571574
}
572575
TyImplTrait(ref bounds) => {
573576
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
695698

696699
pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) {
697700
match *bound {
698-
TraitTyParamBound(ref typ, ref modifier) => {
701+
TraitTyParamBound(ref typ, modifier) => {
699702
visitor.visit_poly_trait_ref(typ, modifier);
700703
}
701704
RegionTyParamBound(ref lifetime) => {

src/librustc/hir/lowering.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,23 @@ impl<'a> LoweringContext<'a> {
360360
hir::TyTypeof(self.record_body(expr, None))
361361
}
362362
TyKind::TraitObject(ref bounds) => {
363-
hir::TyTraitObject(self.lower_bounds(bounds))
363+
let mut lifetime_bound = None;
364+
let bounds = bounds.iter().filter_map(|bound| {
365+
match *bound {
366+
TraitTyParamBound(ref ty, TraitBoundModifier::None) => {
367+
Some(self.lower_poly_trait_ref(ty))
368+
}
369+
TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
370+
RegionTyParamBound(ref lifetime) => {
371+
lifetime_bound = Some(self.lower_lifetime(lifetime));
372+
None
373+
}
374+
}
375+
}).collect();
376+
let lifetime_bound = lifetime_bound.unwrap_or_else(|| {
377+
self.elided_lifetime(t.span)
378+
});
379+
hir::TyTraitObject(bounds, lifetime_bound)
364380
}
365381
TyKind::ImplTrait(ref bounds) => {
366382
hir::TyImplTrait(self.lower_bounds(bounds))
@@ -2361,20 +2377,20 @@ impl<'a> LoweringContext<'a> {
23612377
hir::QPath::Resolved(None, path) => {
23622378
// Turn trait object paths into `TyTraitObject` instead.
23632379
if let Def::Trait(_) = path.def {
2364-
let principal = hir::TraitTyParamBound(hir::PolyTraitRef {
2380+
let principal = hir::PolyTraitRef {
23652381
bound_lifetimes: hir_vec![],
23662382
trait_ref: hir::TraitRef {
23672383
path: path.and_then(|path| path),
23682384
ref_id: id,
23692385
},
23702386
span,
2371-
}, hir::TraitBoundModifier::None);
2387+
};
23722388

23732389
// The original ID is taken by the `PolyTraitRef`,
23742390
// so the `Ty` itself needs a different one.
23752391
id = self.next_id();
23762392

2377-
hir::TyTraitObject(hir_vec![principal])
2393+
hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span))
23782394
} else {
23792395
hir::TyPath(hir::QPath::Resolved(None, path))
23802396
}

src/librustc/hir/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1205,7 +1205,7 @@ pub enum Ty_ {
12051205
TyPath(QPath),
12061206
/// A trait object type `Bound1 + Bound2 + Bound3`
12071207
/// where `Bound` is a trait or a lifetime.
1208-
TyTraitObject(TyParamBounds),
1208+
TyTraitObject(HirVec<PolyTraitRef>, Lifetime),
12091209
/// An `impl Bound1 + Bound2 + Bound3` type
12101210
/// where `Bound` is a trait or a lifetime.
12111211
TyImplTrait(TyParamBounds),

src/librustc/hir/print.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,21 @@ impl<'a> State<'a> {
416416
hir::TyPath(ref qpath) => {
417417
self.print_qpath(qpath, false)?
418418
}
419-
hir::TyTraitObject(ref bounds) => {
420-
self.print_bounds("", &bounds[..])?;
419+
hir::TyTraitObject(ref bounds, ref lifetime) => {
420+
let mut first = true;
421+
for bound in bounds {
422+
self.nbsp()?;
423+
if first {
424+
first = false;
425+
} else {
426+
self.word_space("+")?;
427+
}
428+
self.print_poly_trait_ref(bound)?;
429+
}
430+
if !lifetime.is_elided() {
431+
self.word_space("+")?;
432+
self.print_lifetime(lifetime)?;
433+
}
421434
}
422435
hir::TyImplTrait(ref bounds) => {
423436
self.print_bounds("impl ", &bounds[..])?;

src/librustc/middle/resolve_lifetime.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
322322
intravisit::walk_ty(this, ty);
323323
});
324324
}
325+
hir::TyTraitObject(ref bounds, ref lifetime) => {
326+
for bound in bounds {
327+
self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
328+
}
329+
if !lifetime.is_elided() {
330+
self.visit_lifetime(lifetime);
331+
}
332+
}
325333
_ => {
326334
intravisit::walk_ty(self, ty)
327335
}
@@ -441,7 +449,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
441449

442450
fn visit_poly_trait_ref(&mut self,
443451
trait_ref: &'tcx hir::PolyTraitRef,
444-
_modifier: &'tcx hir::TraitBoundModifier) {
452+
_modifier: hir::TraitBoundModifier) {
445453
debug!("visit_poly_trait_ref trait_ref={:?}", trait_ref);
446454

447455
if !self.trait_ref_hack || !trait_ref.bound_lifetimes.is_empty() {
@@ -962,7 +970,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
962970

963971
fn visit_poly_trait_ref(&mut self,
964972
trait_ref: &hir::PolyTraitRef,
965-
modifier: &hir::TraitBoundModifier) {
973+
modifier: hir::TraitBoundModifier) {
966974
self.binder_depth += 1;
967975
intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
968976
self.binder_depth -= 1;

src/librustc_incremental/calculate_svh/svh_visitor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
828828
visit::walk_ty_param_bound(self, bounds)
829829
}
830830

831-
fn visit_poly_trait_ref(&mut self, t: &'tcx PolyTraitRef, m: &'tcx TraitBoundModifier) {
831+
fn visit_poly_trait_ref(&mut self, t: &'tcx PolyTraitRef, m: TraitBoundModifier) {
832832
debug!("visit_poly_trait_ref: st={:?}", self.st);
833833
SawPolyTraitRef.hash(self.st);
834834
m.hash(self.st);

src/librustc_passes/ast_validation.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
144144
});
145145
}
146146
TyKind::TraitObject(ref bounds) => {
147+
let mut any_lifetime_bounds = false;
148+
for bound in bounds {
149+
if let RegionTyParamBound(ref lifetime) = *bound {
150+
if any_lifetime_bounds {
151+
span_err!(self.session, lifetime.span, E0226,
152+
"only a single explicit lifetime bound is permitted");
153+
break;
154+
}
155+
any_lifetime_bounds = true;
156+
}
157+
}
147158
self.no_questions_in_bounds(bounds, "trait object types", false);
148159
}
149160
TyKind::ImplTrait(ref bounds) => {

src/librustc_passes/diagnostics.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ match 5u32 {
244244
}
245245

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

0 commit comments

Comments
 (0)