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;
@@ -58,9 +58,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
58
58
}
59
59
}
60
60
61
- let ( trait_bounds , mut projection_bounds ) =
61
+ let ( elaborated_trait_bounds , elaborated_projection_bounds ) =
62
62
traits:: expand_trait_aliases ( tcx, user_written_bounds. iter ( ) . copied ( ) ) ;
63
- let ( regular_traits, mut auto_traits) : ( Vec < _ > , Vec < _ > ) = trait_bounds
63
+ let ( regular_traits, mut auto_traits) : ( Vec < _ > , Vec < _ > ) = elaborated_trait_bounds
64
64
. into_iter ( )
65
65
. partition ( |( trait_ref, _) | !tcx. trait_is_auto ( trait_ref. def_id ( ) ) ) ;
66
66
@@ -103,37 +103,89 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
103
103
}
104
104
}
105
105
106
+ // Map the projection bounds onto a key that makes it easy to remove redundant
107
+ // bounds that are constrained by supertraits of the principal def id.
108
+ //
109
+ // Also make sure we detect conflicting bounds from expanding a trait alias and
110
+ // also specifying it manually, like:
111
+ // ```
112
+ // type Alias = Trait<Assoc = i32>;
113
+ // let _: &dyn Alias<Assoc = u32> = /* ... */;
114
+ // ```
115
+ let mut projection_bounds = FxIndexMap :: default ( ) ;
116
+ for ( proj, proj_span) in elaborated_projection_bounds {
117
+ let key = (
118
+ proj. skip_binder ( ) . projection_term . def_id ,
119
+ tcx. anonymize_bound_vars (
120
+ proj. map_bound ( |proj| proj. projection_term . trait_ref ( tcx) ) ,
121
+ ) ,
122
+ ) ;
123
+ if let Some ( ( old_proj, old_proj_span) ) =
124
+ projection_bounds. insert ( key, ( proj, proj_span) )
125
+ && tcx. anonymize_bound_vars ( proj) != tcx. anonymize_bound_vars ( old_proj)
126
+ {
127
+ let item = tcx. item_name ( proj. item_def_id ( ) ) ;
128
+ self . dcx ( )
129
+ . struct_span_err (
130
+ span,
131
+ format ! (
132
+ "conflicting associated type bounds for `{item}` when \
133
+ expanding trait alias"
134
+ ) ,
135
+ )
136
+ . with_span_label (
137
+ old_proj_span,
138
+ format ! ( "`{item}` is specified to be `{}` here" , old_proj. term( ) ) ,
139
+ )
140
+ . with_span_label (
141
+ proj_span,
142
+ format ! ( "`{item}` is specified to be `{}` here" , proj. term( ) ) ,
143
+ )
144
+ . emit ( ) ;
145
+ }
146
+ }
147
+
106
148
let principal_trait = regular_traits. into_iter ( ) . next ( ) ;
107
149
108
- let mut needed_associated_types = FxIndexSet :: default ( ) ;
109
- if let Some ( ( principal_trait, spans) ) = & principal_trait {
110
- let pred: ty:: Predicate < ' tcx > = ( * principal_trait) . upcast ( tcx) ;
111
- for ClauseWithSupertraitSpan { pred, supertrait_span } in traits:: elaborate (
150
+ let mut needed_associated_types = vec ! [ ] ;
151
+ if let Some ( ( principal_trait, ref spans) ) = principal_trait {
152
+ let principal_trait = principal_trait. map_bound ( |trait_pred| {
153
+ assert_eq ! ( trait_pred. polarity, ty:: PredicatePolarity :: Positive ) ;
154
+ trait_pred. trait_ref
155
+ } ) ;
156
+
157
+ for ClauseWithSupertraitSpan { clause, supertrait_span } in traits:: elaborate (
112
158
tcx,
113
- [ ClauseWithSupertraitSpan :: new ( pred, * spans. last ( ) . unwrap ( ) ) ] ,
159
+ [ ClauseWithSupertraitSpan :: new (
160
+ ty:: TraitRef :: identity ( tcx, principal_trait. def_id ( ) ) . upcast ( tcx) ,
161
+ * spans. last ( ) . unwrap ( ) ,
162
+ ) ] ,
114
163
)
115
164
. filter_only_self ( )
116
165
{
117
- debug ! ( "observing object predicate `{pred:?}`" ) ;
166
+ let clause = clause. instantiate_supertrait ( tcx, principal_trait) ;
167
+ debug ! ( "observing object predicate `{clause:?}`" ) ;
118
168
119
- let bound_predicate = pred . kind ( ) ;
169
+ let bound_predicate = clause . kind ( ) ;
120
170
match bound_predicate. skip_binder ( ) {
121
- ty:: PredicateKind :: Clause ( ty :: ClauseKind :: Trait ( pred) ) => {
171
+ ty:: ClauseKind :: Trait ( pred) => {
122
172
// FIXME(negative_bounds): Handle this correctly...
123
173
let trait_ref =
124
174
tcx. anonymize_bound_vars ( bound_predicate. rebind ( pred. trait_ref ) ) ;
125
175
needed_associated_types. extend (
126
- tcx. associated_items ( trait_ref. def_id ( ) )
176
+ tcx. associated_items ( pred . trait_ref . def_id )
127
177
. in_definition_order ( )
178
+ // We only care about associated types.
128
179
. filter ( |item| item. kind == ty:: AssocKind :: Type )
180
+ // No RPITITs -- even with `async_fn_in_dyn_trait`, they are implicit.
129
181
. filter ( |item| !item. is_impl_trait_in_trait ( ) )
130
182
// If the associated type has a `where Self: Sized` bound,
131
183
// we do not need to constrain the associated type.
132
184
. filter ( |item| !tcx. generics_require_sized_self ( item. def_id ) )
133
185
. map ( |item| ( item. def_id , trait_ref) ) ,
134
186
) ;
135
187
}
136
- ty:: PredicateKind :: Clause ( ty :: ClauseKind :: Projection ( pred) ) => {
188
+ ty:: ClauseKind :: Projection ( pred) => {
137
189
let pred = bound_predicate. rebind ( pred) ;
138
190
// A `Self` within the original bound will be instantiated with a
139
191
// `trait_object_dummy_self`, so check for that.
@@ -161,8 +213,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
161
213
// `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
162
214
// the discussion in #56288 for alternatives.
163
215
if !references_self {
164
- // Include projections defined on supertraits.
165
- projection_bounds. push ( ( pred, supertrait_span) ) ;
216
+ let key = (
217
+ pred. skip_binder ( ) . projection_term . def_id ,
218
+ tcx. anonymize_bound_vars (
219
+ pred. map_bound ( |proj| proj. projection_term . trait_ref ( tcx) ) ,
220
+ ) ,
221
+ ) ;
222
+ if !projection_bounds. contains_key ( & key) {
223
+ projection_bounds. insert ( key, ( pred, supertrait_span) ) ;
224
+ }
166
225
}
167
226
168
227
self . check_elaborated_projection_mentions_input_lifetimes (
@@ -182,12 +241,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
182
241
// types that we expect to be provided by the user, so the following loop
183
242
// removes all the associated types that have a corresponding `Projection`
184
243
// clause, either from expanding trait aliases or written by the user.
185
- for & ( projection_bound, span) in & projection_bounds {
244
+ for & ( projection_bound, span) in projection_bounds. values ( ) {
186
245
let def_id = projection_bound. item_def_id ( ) ;
187
- let trait_ref = tcx. anonymize_bound_vars (
188
- projection_bound. map_bound ( |p| p. projection_term . trait_ref ( tcx) ) ,
189
- ) ;
190
- needed_associated_types. swap_remove ( & ( def_id, trait_ref) ) ;
191
246
if tcx. generics_require_sized_self ( def_id) {
192
247
tcx. emit_node_span_lint (
193
248
UNUSED_ASSOCIATED_TYPE_BOUNDS ,
@@ -198,9 +253,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
198
253
}
199
254
}
200
255
256
+ let mut missing_assoc_types = FxIndexSet :: default ( ) ;
257
+ let projection_bounds: Vec < _ > = needed_associated_types
258
+ . into_iter ( )
259
+ . filter_map ( |key| {
260
+ if let Some ( assoc) = projection_bounds. get ( & key) {
261
+ Some ( * assoc)
262
+ } else {
263
+ missing_assoc_types. insert ( key) ;
264
+ None
265
+ }
266
+ } )
267
+ . collect ( ) ;
268
+
201
269
if let Err ( guar) = self . check_for_required_assoc_tys (
202
270
principal_trait. as_ref ( ) . map_or ( smallvec ! [ ] , |( _, spans) | spans. clone ( ) ) ,
203
- needed_associated_types ,
271
+ missing_assoc_types ,
204
272
potential_assoc_types,
205
273
hir_bounds,
206
274
) {
@@ -266,7 +334,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
266
334
} )
267
335
} ) ;
268
336
269
- let existential_projections = projection_bounds. iter ( ) . map ( |( bound, _) | {
337
+ let existential_projections = projection_bounds. into_iter ( ) . map ( |( bound, _) | {
270
338
bound. map_bound ( |mut b| {
271
339
assert_eq ! ( b. projection_term. self_ty( ) , dummy_self) ;
272
340
@@ -291,12 +359,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
291
359
} )
292
360
} ) ;
293
361
294
- let auto_trait_predicates = auto_traits. into_iter ( ) . map ( |( trait_pred, _) | {
295
- assert_eq ! ( trait_pred. polarity( ) , ty:: PredicatePolarity :: Positive ) ;
296
- assert_eq ! ( trait_pred. self_ty( ) . skip_binder( ) , dummy_self) ;
362
+ let mut auto_trait_predicates: Vec < _ > = auto_traits
363
+ . into_iter ( )
364
+ . map ( |( trait_pred, _) | {
365
+ assert_eq ! ( trait_pred. polarity( ) , ty:: PredicatePolarity :: Positive ) ;
366
+ assert_eq ! ( trait_pred. self_ty( ) . skip_binder( ) , dummy_self) ;
297
367
298
- ty:: Binder :: dummy ( ty:: ExistentialPredicate :: AutoTrait ( trait_pred. def_id ( ) ) )
299
- } ) ;
368
+ ty:: Binder :: dummy ( ty:: ExistentialPredicate :: AutoTrait ( trait_pred. def_id ( ) ) )
369
+ } )
370
+ . collect ( ) ;
371
+ auto_trait_predicates. dedup ( ) ;
300
372
301
373
// N.b. principal, projections, auto traits
302
374
// FIXME: This is actually wrong with multiple principals in regards to symbol mangling
@@ -306,7 +378,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
306
378
. chain ( auto_trait_predicates)
307
379
. collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
308
380
v. sort_by ( |a, b| a. skip_binder ( ) . stable_cmp ( tcx, & b. skip_binder ( ) ) ) ;
309
- v. dedup ( ) ;
310
381
let existential_predicates = tcx. mk_poly_existential_predicates ( & v) ;
311
382
312
383
// Use explicitly-specified region bound, unless the bound is missing.
0 commit comments