@@ -3,15 +3,14 @@ use rustc_errors::codes::*;
3
3
use rustc_errors:: struct_span_code_err;
4
4
use rustc_hir as hir;
5
5
use rustc_hir:: def:: { DefKind , Res } ;
6
- use rustc_hir:: def_id:: DefId ;
7
6
use rustc_lint_defs:: builtin:: UNUSED_ASSOCIATED_TYPE_BOUNDS ;
8
7
use rustc_middle:: span_bug;
9
8
use rustc_middle:: ty:: fold:: BottomUpFolder ;
10
9
use rustc_middle:: ty:: {
11
10
self , DynKind , ExistentialPredicateStableCmpExt as _, Ty , TyCtxt , TypeFoldable ,
12
11
TypeVisitableExt , Upcast ,
13
12
} ;
14
- use rustc_span:: { ErrorGuaranteed , Span } ;
13
+ use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span } ;
15
14
use rustc_trait_selection:: error_reporting:: traits:: report_dyn_incompatibility;
16
15
use rustc_trait_selection:: traits:: { self , hir_ty_lowering_dyn_compatibility_violations} ;
17
16
use rustc_type_ir:: elaborate:: ClauseWithSupertraitSpan ;
@@ -62,7 +61,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
62
61
}
63
62
64
63
let mut trait_bounds = vec ! [ ] ;
65
- let mut projection_bounds = vec ! [ ] ;
64
+ let mut projection_bounds = FxIndexMap :: default ( ) ;
66
65
for ( pred, span) in bounds. clauses ( ) {
67
66
let bound_pred = pred. kind ( ) ;
68
67
match bound_pred. skip_binder ( ) {
@@ -71,7 +70,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
71
70
trait_bounds. push ( ( bound_pred. rebind ( trait_pred. trait_ref ) , span) ) ;
72
71
}
73
72
ty:: ClauseKind :: Projection ( proj) => {
74
- 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) ) ;
75
75
}
76
76
ty:: ClauseKind :: TypeOutlives ( _) => {
77
77
// Do nothing, we deal with regions separately
@@ -88,8 +88,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
88
88
89
89
// Expand trait aliases recursively and check that only one regular (non-auto) trait
90
90
// is used and no 'maybe' bounds are used.
91
- let expanded_traits =
92
- 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
+ ) ;
93
97
94
98
let ( mut auto_traits, regular_traits) : ( Vec < _ > , Vec < _ > ) =
95
99
expanded_traits. partition ( |i| tcx. trait_is_auto ( i. trait_ref ( ) . def_id ( ) ) ) ;
@@ -128,12 +132,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
128
132
}
129
133
}
130
134
131
- let mut associated_types : FxIndexMap < Span , FxIndexSet < DefId > > = FxIndexMap :: default ( ) ;
135
+ let mut needed_associated_types = FxIndexSet :: default ( ) ;
132
136
137
+ let principal_span = regular_traits. first ( ) . map_or ( DUMMY_SP , |info| info. bottom ( ) . 1 ) ;
133
138
let regular_traits_refs_spans = trait_bounds
134
139
. into_iter ( )
135
140
. filter ( |( trait_ref, _) | !tcx. trait_is_auto ( trait_ref. def_id ( ) ) ) ;
136
141
142
+ let mut implied_projection_bounds = vec ! [ ] ;
137
143
for ( base_trait_ref, original_span) in regular_traits_refs_spans {
138
144
let base_pred: ty:: Predicate < ' tcx > = base_trait_ref. upcast ( tcx) ;
139
145
for ClauseWithSupertraitSpan { pred, supertrait_span } in
@@ -145,17 +151,28 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
145
151
let bound_predicate = pred. kind ( ) ;
146
152
match bound_predicate. skip_binder ( ) {
147
153
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) => {
148
- let pred = bound_predicate. rebind ( pred) ;
149
- associated_types. entry ( original_span) . or_default ( ) . extend (
150
- tcx. associated_items ( pred. def_id ( ) )
154
+ // FIXME(negative_bounds): Handle this correctly...
155
+ let trait_ref =
156
+ tcx. anonymize_bound_vars ( bound_predicate. rebind ( pred. trait_ref ) ) ;
157
+ needed_associated_types. extend (
158
+ tcx. associated_items ( trait_ref. def_id ( ) )
151
159
. in_definition_order ( )
152
160
. filter ( |item| item. kind == ty:: AssocKind :: Type )
153
161
. filter ( |item| !item. is_impl_trait_in_trait ( ) )
154
- . map ( |item| item. def_id ) ,
162
+ // If the associated type has a `where Self: Sized` bound,
163
+ // we do not need to constrain the associated type.
164
+ . filter ( |item| !tcx. generics_require_sized_self ( item. def_id ) )
165
+ . map ( |item| ( item. def_id , trait_ref) ) ,
155
166
) ;
156
167
}
157
168
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( pred) ) => {
158
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
+
159
176
// A `Self` within the original bound will be instantiated with a
160
177
// `trait_object_dummy_self`, so check for that.
161
178
let references_self = match pred. skip_binder ( ) . term . unpack ( ) {
@@ -182,8 +199,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
182
199
// `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
183
200
// the discussion in #56288 for alternatives.
184
201
if !references_self {
185
- // Include projections defined on supertraits.
186
- projection_bounds. push ( ( pred, original_span) ) ;
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
+ }
187
209
}
188
210
189
211
self . check_elaborated_projection_mentions_input_lifetimes (
@@ -201,26 +223,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
201
223
// So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
202
224
// types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
203
225
// corresponding `Projection` clause
204
- for def_ids in associated_types. values_mut ( ) {
205
- for ( projection_bound, span) in & projection_bounds {
206
- let def_id = projection_bound. projection_def_id ( ) ;
207
- def_ids. swap_remove ( & def_id) ;
208
- if tcx. generics_require_sized_self ( def_id) {
209
- tcx. emit_node_span_lint (
210
- UNUSED_ASSOCIATED_TYPE_BOUNDS ,
211
- hir_id,
212
- * span,
213
- crate :: errors:: UnusedAssociatedTypeBounds { span : * span } ,
214
- ) ;
215
- }
226
+ for ( projection_bound, span) in projection_bounds. values ( ) {
227
+ let def_id = projection_bound. projection_def_id ( ) ;
228
+ let trait_ref = tcx. anonymize_bound_vars (
229
+ projection_bound. map_bound ( |p| p. projection_term . trait_ref ( tcx) ) ,
230
+ ) ;
231
+ needed_associated_types. swap_remove ( & ( def_id, trait_ref) ) ;
232
+ if tcx. generics_require_sized_self ( def_id) {
233
+ tcx. emit_node_span_lint (
234
+ UNUSED_ASSOCIATED_TYPE_BOUNDS ,
235
+ hir_id,
236
+ * span,
237
+ crate :: errors:: UnusedAssociatedTypeBounds { span : * span } ,
238
+ ) ;
216
239
}
217
- // If the associated type has a `where Self: Sized` bound, we do not need to constrain the associated
218
- // type in the `dyn Trait`.
219
- def_ids. retain ( |def_id| !tcx. generics_require_sized_self ( def_id) ) ;
240
+ }
241
+ for projection_bound in & implied_projection_bounds {
242
+ let def_id = projection_bound. projection_def_id ( ) ;
243
+ let trait_ref = tcx. anonymize_bound_vars (
244
+ projection_bound. map_bound ( |p| p. projection_term . trait_ref ( tcx) ) ,
245
+ ) ;
246
+ needed_associated_types. swap_remove ( & ( def_id, trait_ref) ) ;
220
247
}
221
248
222
249
self . complain_about_missing_assoc_tys (
223
- associated_types,
250
+ principal_span,
251
+ needed_associated_types,
224
252
potential_assoc_types,
225
253
hir_trait_bounds,
226
254
) ;
@@ -302,7 +330,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
302
330
} )
303
331
} ) ;
304
332
305
- let existential_projections = projection_bounds. iter ( ) . map ( |( bound, _) | {
333
+ let existential_projections = projection_bounds. values ( ) . map ( |( bound, _) | {
306
334
bound. map_bound ( |mut b| {
307
335
assert_eq ! ( b. projection_term. self_ty( ) , dummy_self) ;
308
336
0 commit comments