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