Skip to content

Commit 783b713

Browse files
author
Alexander Regueiro
committed
Addressed more points raised in review.
1 parent 2009662 commit 783b713

12 files changed

+452
-185
lines changed

src/librustc/traits/util.rs

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,8 @@ struct PredicateSet<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
5151
}
5252

5353
impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
54-
fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PredicateSet<'a, 'gcx, 'tcx> {
55-
PredicateSet { tcx: tcx, set: Default::default() }
56-
}
57-
58-
fn contains(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
59-
// See the `insert` method for why we use `anonymize_predicate` here.
60-
self.set.contains(&anonymize_predicate(self.tcx, pred))
54+
fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self {
55+
Self { tcx: tcx, set: Default::default() }
6156
}
6257

6358
fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
@@ -73,11 +68,6 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> {
7368
// regions before we throw things into the underlying set.
7469
self.set.insert(anonymize_predicate(self.tcx, pred))
7570
}
76-
77-
fn remove(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
78-
// See the `insert` method for why we use `anonymize_predicate` here.
79-
self.set.remove(&anonymize_predicate(self.tcx, pred))
80-
}
8171
}
8272

8373
impl<'a, 'gcx, 'tcx, T: AsRef<ty::Predicate<'tcx>>> Extend<T> for PredicateSet<'a, 'gcx, 'tcx> {
@@ -135,7 +125,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
135125
FilterToTraits::new(self)
136126
}
137127

138-
fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
128+
fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) {
139129
let tcx = self.visited.tcx;
140130
match *predicate {
141131
ty::Predicate::Trait(ref data) => {
@@ -153,7 +143,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
153143
// This is necessary to prevent infinite recursion in some
154144
// cases. One common case is when people define
155145
// `trait Sized: Sized { }` rather than `trait Sized { }`.
156-
predicates.retain(|p| self.visited.insert(p));
146+
predicates.retain(|pred| self.visited.insert(pred));
157147

158148
self.stack.extend(predicates);
159149
}
@@ -251,15 +241,12 @@ impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> {
251241

252242
fn next(&mut self) -> Option<ty::Predicate<'tcx>> {
253243
// Extract next item from top-most stack frame, if any.
254-
let next_predicate = match self.stack.pop() {
255-
Some(predicate) => predicate,
256-
None => {
257-
// No more stack frames. Done.
258-
return None;
259-
}
260-
};
261-
self.push(&next_predicate);
262-
return Some(next_predicate);
244+
if let Some(pred) = self.stack.pop() {
245+
self.elaborate(&pred);
246+
Some(pred)
247+
} else {
248+
None
249+
}
263250
}
264251
}
265252

@@ -294,31 +281,29 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>,
294281
/// Expansion is done via a DFS (depth-first search), and the `visited` field
295282
/// is used to avoid cycles.
296283
pub struct TraitAliasExpander<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
284+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
297285
stack: Vec<TraitAliasExpansionInfo<'tcx>>,
298-
/// The set of predicates visited from the root directly to the current point in the
299-
/// expansion tree (only containing trait aliases).
300-
visited: PredicateSet<'a, 'gcx, 'tcx>,
301286
}
302287

303288
/// Stores information about the expansion of a trait via a path of zero or more trait aliases.
304289
#[derive(Debug, Clone)]
305290
pub struct TraitAliasExpansionInfo<'tcx> {
306-
pub items: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>,
291+
pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>,
307292
}
308293

309294
impl<'tcx> TraitAliasExpansionInfo<'tcx> {
310295
fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
311296
Self {
312-
items: smallvec![(trait_ref, span)]
297+
path: smallvec![(trait_ref, span)]
313298
}
314299
}
315300

316-
fn push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
317-
let mut items = self.items.clone();
318-
items.push((trait_ref, span));
301+
fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
302+
let mut path = self.path.clone();
303+
path.push((trait_ref, span));
319304

320305
Self {
321-
items
306+
path
322307
}
323308
}
324309

@@ -327,11 +312,11 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
327312
}
328313

329314
pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
330-
self.items.last().unwrap()
315+
self.path.last().unwrap()
331316
}
332317

333318
pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
334-
self.items.first().unwrap()
319+
self.path.first().unwrap()
335320
}
336321
}
337322

@@ -340,21 +325,25 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
340325
pub trait TraitAliasExpansionInfoDignosticBuilder {
341326
fn label_with_exp_info<'tcx>(&mut self,
342327
info: &TraitAliasExpansionInfo<'tcx>,
343-
top_label: &str
328+
top_label: &str,
329+
use_desc: &str
344330
) -> &mut Self;
345331
}
346332

347333
impl<'a> TraitAliasExpansionInfoDignosticBuilder for DiagnosticBuilder<'a> {
348334
fn label_with_exp_info<'tcx>(&mut self,
349335
info: &TraitAliasExpansionInfo<'tcx>,
350-
top_label: &str
336+
top_label: &str,
337+
use_desc: &str
351338
) -> &mut Self {
352339
self.span_label(info.top().1, top_label);
353-
if info.items.len() > 1 {
354-
for (_, sp) in info.items[1..(info.items.len() - 1)].iter().rev() {
355-
self.span_label(*sp, "referenced here");
340+
if info.path.len() > 1 {
341+
for (_, sp) in info.path.iter().rev().skip(1).take(info.path.len() - 2) {
342+
self.span_label(*sp, format!("referenced here ({})", use_desc));
356343
}
357344
}
345+
self.span_label(info.bottom().1,
346+
format!("trait alias used in trait object type ({})", use_desc));
358347
self
359348
}
360349
}
@@ -367,7 +356,7 @@ pub fn expand_trait_aliases<'cx, 'gcx, 'tcx>(
367356
.into_iter()
368357
.map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span))
369358
.collect();
370-
TraitAliasExpander { stack: items, visited: PredicateSet::new(tcx) }
359+
TraitAliasExpander { tcx, stack: items }
371360
}
372361

373362
impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> {
@@ -376,23 +365,25 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> {
376365
/// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a
377366
/// trait alias.
378367
/// The return value indicates whether `item` should be yielded to the user.
379-
fn push(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
380-
let tcx = self.visited.tcx;
368+
fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
369+
let tcx = self.tcx;
381370
let trait_ref = item.trait_ref();
382371
let pred = trait_ref.to_predicate();
383372

384373
debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
385374

386-
// Don't recurse unless this bound is a trait alias and isn't currently in the DFS stack of
387-
// already-visited predicates.
375+
// Don't recurse if this bound is not a trait alias.
388376
let is_alias = tcx.is_trait_alias(trait_ref.def_id());
389-
if !is_alias || self.visited.contains(&pred) {
390-
return !is_alias;
377+
if !is_alias {
378+
return true;
391379
}
392380

393-
// Remove the current predicate from the stack of already-visited ones, since we're doing
394-
// a DFS.
395-
self.visited.remove(&pred);
381+
// Don't recurse if this trait alias is already on the stack for the DFS search.
382+
let anon_pred = anonymize_predicate(tcx, &pred);
383+
if item.path.iter().rev().skip(1)
384+
.any(|(tr, _)| anonymize_predicate(tcx, &tr.to_predicate()) == anon_pred) {
385+
return false;
386+
}
396387

397388
// Get components of trait alias.
398389
let predicates = tcx.super_predicates_of(trait_ref.def_id());
@@ -403,16 +394,13 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> {
403394
.filter_map(|(pred, span)| {
404395
pred.subst_supertrait(tcx, &trait_ref)
405396
.to_opt_poly_trait_ref()
406-
.map(|trait_ref| item.push(trait_ref, *span))
397+
.map(|trait_ref| item.clone_and_push(trait_ref, *span))
407398
})
408399
.collect();
409400
debug!("expand_trait_aliases: items={:?}", items);
410401

411402
self.stack.extend(items);
412403

413-
// Record predicate into set of already-visited.
414-
self.visited.insert(&pred);
415-
416404
false
417405
}
418406
}
@@ -426,7 +414,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for TraitAliasExpander<'cx, 'gcx, 'tcx> {
426414

427415
fn next(&mut self) -> Option<TraitAliasExpansionInfo<'tcx>> {
428416
while let Some(item) = self.stack.pop() {
429-
if self.push(&item) {
417+
if self.expand(&item) {
430418
return Some(item);
431419
}
432420
}

src/librustc_typeck/astconv.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -648,14 +648,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
648648
// careful!
649649
if default_needs_object_self(param) {
650650
struct_span_err!(tcx.sess, span, E0393,
651-
"the type parameter `{}` must be explicitly \
652-
specified",
653-
param.name)
654-
.span_label(span,
655-
format!("missing reference to `{}`", param.name))
656-
.note(&format!("because of the default `Self` reference, \
657-
type parameters must be specified on object \
658-
types"))
651+
"the type parameter `{}` must be explicitly specified",
652+
param.name
653+
)
654+
.span_label(span, format!(
655+
"missing reference to `{}`", param.name))
656+
.note(&format!(
657+
"because of the default `Self` reference, type parameters \
658+
must be specified on object types"))
659659
.emit();
660660
tcx.types.err.into()
661661
} else {
@@ -987,20 +987,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
987987
);
988988
potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten());
989989
(trait_ref, trait_bound.span)
990-
}).collect();
990+
})
991+
.collect();
991992

992993
// Expand trait aliases recursively and check that only one regular (non-auto) trait
993994
// is used and no 'maybe' bounds are used.
994995
let expanded_traits = traits::expand_trait_aliases(tcx, bound_trait_refs.clone());
995996
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
996997
expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
997998
if regular_traits.len() > 1 {
998-
let extra_trait = &regular_traits[1];
999-
struct_span_err!(tcx.sess, extra_trait.bottom().1, E0225,
999+
let first_trait = &regular_traits[0];
1000+
let additional_trait = &regular_traits[1];
1001+
struct_span_err!(tcx.sess, additional_trait.bottom().1, E0225,
10001002
"only auto traits can be used as additional traits in a trait object"
10011003
)
1002-
.label_with_exp_info(extra_trait, "additional non-auto trait")
1003-
.span_label(regular_traits[0].top().1, "first non-auto trait")
1004+
.label_with_exp_info(additional_trait, "additional non-auto trait",
1005+
"additional use")
1006+
.label_with_exp_info(first_trait, "first non-auto trait",
1007+
"first use")
10041008
.emit();
10051009
}
10061010

src/test/ui/bad/bad-sized.stderr

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
22
--> $DIR/bad-sized.rs:4:24
33
|
44
LL | let x: Vec<Trait + Sized> = Vec::new();
5-
| ----- ^^^^^ additional non-auto trait
6-
| |
5+
| ----- ^^^^^
6+
| | |
7+
| | additional non-auto trait
8+
| | trait alias used in trait object type (additional use)
79
| first non-auto trait
10+
| trait alias used in trait object type (first use)
811

912
error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
1013
--> $DIR/bad-sized.rs:4:12

src/test/ui/error-codes/E0225.stderr

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
error[E0225]: only auto traits can be used as additional traits in a trait object
2-
--> $DIR/E0225.rs:6:32
2+
--> $DIR/E0225.rs:6:36
33
|
4-
LL | let _: Box<std::io::Read + std::io::Write>;
5-
| ------------- ^^^^^^^^^^^^^^ additional non-auto trait
6-
| |
7-
| first non-auto trait
4+
LL | let _: Box<dyn std::io::Read + std::io::Write>;
5+
| ------------- ^^^^^^^^^^^^^^
6+
| | |
7+
| | additional non-auto trait
8+
| | trait alias used in trait object type (additional use)
9+
| first non-auto trait
10+
| trait alias used in trait object type (first use)
811

912
error[E0225]: only auto traits can be used as additional traits in a trait object
10-
--> $DIR/E0225.rs:8:16
13+
--> $DIR/E0225.rs:8:20
1114
|
1215
LL | trait Foo = std::io::Read + std::io::Write;
1316
| ------------- -------------- additional non-auto trait
1417
| |
1518
| first non-auto trait
1619
...
17-
LL | let _: Box<Foo>;
18-
| ^^^
20+
LL | let _: Box<dyn Foo>;
21+
| ^^^
22+
| |
23+
| trait alias used in trait object type (additional use)
24+
| trait alias used in trait object type (first use)
1925

2026
error: aborting due to 2 previous errors
2127

src/test/ui/issues/issue-22560.stderr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,16 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
1818
--> $DIR/issue-22560.rs:6:13
1919
|
2020
LL | type Test = Add +
21-
| --- first non-auto trait
21+
| ---
22+
| |
23+
| first non-auto trait
24+
| trait alias used in trait object type (first use)
2225
...
2326
LL | Sub;
24-
| ^^^ additional non-auto trait
27+
| ^^^
28+
| |
29+
| additional non-auto trait
30+
| trait alias used in trait object type (additional use)
2531

2632
error[E0191]: the value of the associated types `Output` (from the trait `std::ops::Add`), `Output` (from the trait `std::ops::Sub`) must be specified
2733
--> $DIR/issue-22560.rs:3:13

src/test/ui/issues/issue-32963.stderr

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
22
--> $DIR/issue-32963.rs:8:25
33
|
44
LL | size_of_copy::<Misc+Copy>();
5-
| ---- ^^^^ additional non-auto trait
6-
| |
5+
| ---- ^^^^
6+
| | |
7+
| | additional non-auto trait
8+
| | trait alias used in trait object type (additional use)
79
| first non-auto trait
10+
| trait alias used in trait object type (first use)
811

912
error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied
1013
--> $DIR/issue-32963.rs:8:5

0 commit comments

Comments
 (0)