1
- use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
1
+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
2
2
use rustc_errors:: codes:: * ;
3
3
use rustc_errors:: struct_span_code_err;
4
4
use rustc_hir as hir;
@@ -61,7 +61,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
61
61
}
62
62
63
63
let mut trait_bounds = vec ! [ ] ;
64
- let mut projection_bounds = vec ! [ ] ;
64
+ let mut projection_bounds = FxIndexMap :: default ( ) ;
65
65
for ( pred, span) in bounds. clauses ( ) {
66
66
let bound_pred = pred. kind ( ) ;
67
67
match bound_pred. skip_binder ( ) {
@@ -70,7 +70,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
70
70
trait_bounds. push ( ( bound_pred. rebind ( trait_pred. trait_ref ) , span) ) ;
71
71
}
72
72
ty:: ClauseKind :: Projection ( proj) => {
73
- projection_bounds. push ( ( bound_pred. rebind ( proj) , span) ) ;
73
+ let anon = tcx. anonymize_bound_vars ( bound_pred. rebind ( proj) ) ;
74
+ projection_bounds. insert ( anon, ( bound_pred. rebind ( proj) , span) ) ;
74
75
}
75
76
ty:: ClauseKind :: TypeOutlives ( _) => {
76
77
// Do nothing, we deal with regions separately
@@ -87,8 +88,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
87
88
88
89
// Expand trait aliases recursively and check that only one regular (non-auto) trait
89
90
// is used and no 'maybe' bounds are used.
90
- let expanded_traits =
91
- traits:: expand_trait_aliases ( tcx, trait_bounds. iter ( ) . map ( |& ( a, b) | ( a, b) ) ) ;
91
+ let mut trait_alias_projection_bounds = FxIndexSet :: default ( ) ;
92
+ let expanded_traits = traits:: expand_trait_aliases (
93
+ tcx,
94
+ & mut trait_alias_projection_bounds,
95
+ trait_bounds. iter ( ) . map ( |& ( a, b) | ( a, b) ) ,
96
+ ) ;
92
97
93
98
let ( mut auto_traits, regular_traits) : ( Vec < _ > , Vec < _ > ) =
94
99
expanded_traits. partition ( |i| tcx. trait_is_auto ( i. trait_ref ( ) . def_id ( ) ) ) ;
@@ -162,6 +167,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
162
167
}
163
168
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( pred) ) => {
164
169
let pred = bound_predicate. rebind ( pred) ;
170
+
171
+ let pred_key = tcx. anonymize_bound_vars ( pred) ;
172
+ if !trait_alias_projection_bounds. contains ( & pred_key) {
173
+ projection_bounds. shift_remove ( & pred_key) ;
174
+ }
175
+
165
176
// A `Self` within the original bound will be instantiated with a
166
177
// `trait_object_dummy_self`, so check for that.
167
178
let references_self = match pred. skip_binder ( ) . term . unpack ( ) {
@@ -188,8 +199,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
188
199
// `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
189
200
// the discussion in #56288 for alternatives.
190
201
if !references_self {
191
- // Include projections defined on supertraits.
192
- implied_projection_bounds. push ( pred) ;
202
+ if trait_alias_projection_bounds. contains ( & pred_key) {
203
+ // Include projections defined on supertraits.
204
+ projection_bounds. insert ( pred_key, ( pred, supertrait_span) ) ;
205
+ } else {
206
+ // Include projections defined on supertraits.
207
+ implied_projection_bounds. push ( pred) ;
208
+ }
193
209
}
194
210
195
211
self . check_elaborated_projection_mentions_input_lifetimes (
@@ -207,7 +223,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
207
223
// So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
208
224
// types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
209
225
// corresponding `Projection` clause
210
- for ( projection_bound, span) in & projection_bounds {
226
+ for ( projection_bound, span) in projection_bounds. values ( ) {
211
227
let def_id = projection_bound. projection_def_id ( ) ;
212
228
let trait_ref = tcx. anonymize_bound_vars (
213
229
projection_bound. map_bound ( |p| p. projection_term . trait_ref ( tcx) ) ,
@@ -314,7 +330,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
314
330
} )
315
331
} ) ;
316
332
317
- let existential_projections = projection_bounds. iter ( ) . map ( |( bound, _) | {
333
+ let existential_projections = projection_bounds. values ( ) . map ( |( bound, _) | {
318
334
bound. map_bound ( |mut b| {
319
335
assert_eq ! ( b. projection_term. self_ty( ) , dummy_self) ;
320
336
0 commit comments