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,38 +102,87 @@ 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
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
111
157
traits:: elaborate ( tcx, [ ClauseWithSupertraitSpan :: new (
112
- pred ,
158
+ ty :: TraitRef :: identity ( tcx , principal_trait . def_id ( ) ) . upcast ( tcx ) ,
113
159
* spans. last ( ) . unwrap ( ) ,
114
160
) ] )
115
161
. filter_only_self ( )
116
162
{
117
- debug ! ( "observing object predicate `{pred:?}`" ) ;
163
+ let clause = clause. instantiate_supertrait ( tcx, principal_trait) ;
164
+ debug ! ( "observing object predicate `{clause:?}`" ) ;
118
165
119
- let bound_predicate = pred . kind ( ) ;
166
+ let bound_predicate = clause . kind ( ) ;
120
167
match bound_predicate. skip_binder ( ) {
121
- ty:: PredicateKind :: Clause ( ty :: ClauseKind :: Trait ( pred) ) => {
168
+ ty:: ClauseKind :: Trait ( pred) => {
122
169
// FIXME(negative_bounds): Handle this correctly...
123
170
let trait_ref =
124
171
tcx. anonymize_bound_vars ( bound_predicate. rebind ( pred. trait_ref ) ) ;
125
172
needed_associated_types. extend (
126
- tcx. associated_items ( trait_ref. def_id ( ) )
173
+ tcx. associated_items ( pred . trait_ref . def_id )
127
174
. in_definition_order ( )
175
+ // We only care about associated types.
128
176
. filter ( |item| item. kind == ty:: AssocKind :: Type )
177
+ // No RPITITs -- even with `async_fn_in_dyn_trait`, they are implicit.
129
178
. filter ( |item| !item. is_impl_trait_in_trait ( ) )
130
179
// If the associated type has a `where Self: Sized` bound,
131
180
// we do not need to constrain the associated type.
132
181
. filter ( |item| !tcx. generics_require_sized_self ( item. def_id ) )
133
182
. map ( |item| ( item. def_id , trait_ref) ) ,
134
183
) ;
135
184
}
136
- ty:: PredicateKind :: Clause ( ty :: ClauseKind :: Projection ( pred) ) => {
185
+ ty:: ClauseKind :: Projection ( pred) => {
137
186
let pred = bound_predicate. rebind ( pred) ;
138
187
// A `Self` within the original bound will be instantiated with a
139
188
// `trait_object_dummy_self`, so check for that.
@@ -161,8 +210,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
161
210
// `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
162
211
// the discussion in #56288 for alternatives.
163
212
if !references_self {
164
- // Include projections defined on supertraits.
165
- projection_bounds. push ( ( pred, supertrait_span) ) ;
213
+ let key = (
214
+ pred. skip_binder ( ) . projection_term . def_id ,
215
+ tcx. anonymize_bound_vars (
216
+ pred. map_bound ( |proj| proj. projection_term . trait_ref ( tcx) ) ,
217
+ ) ,
218
+ ) ;
219
+ if !projection_bounds. contains_key ( & key) {
220
+ projection_bounds. insert ( key, ( pred, supertrait_span) ) ;
221
+ }
166
222
}
167
223
168
224
self . check_elaborated_projection_mentions_input_lifetimes (
@@ -182,12 +238,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
182
238
// types that we expect to be provided by the user, so the following loop
183
239
// removes all the associated types that have a corresponding `Projection`
184
240
// clause, either from expanding trait aliases or written by the user.
185
- for & ( projection_bound, span) in & projection_bounds {
241
+ for & ( projection_bound, span) in projection_bounds. values ( ) {
186
242
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
243
if tcx. generics_require_sized_self ( def_id) {
192
244
tcx. emit_node_span_lint (
193
245
UNUSED_ASSOCIATED_TYPE_BOUNDS ,
@@ -198,9 +250,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
198
250
}
199
251
}
200
252
253
+ let mut missing_assoc_types = FxIndexSet :: default ( ) ;
254
+ let projection_bounds: Vec < _ > = needed_associated_types
255
+ . into_iter ( )
256
+ . filter_map ( |key| {
257
+ if let Some ( assoc) = projection_bounds. get ( & key) {
258
+ Some ( * assoc)
259
+ } else {
260
+ missing_assoc_types. insert ( key) ;
261
+ None
262
+ }
263
+ } )
264
+ . collect ( ) ;
265
+
201
266
if let Err ( guar) = self . check_for_required_assoc_tys (
202
267
principal_trait. as_ref ( ) . map_or ( smallvec ! [ ] , |( _, spans) | spans. clone ( ) ) ,
203
- needed_associated_types ,
268
+ missing_assoc_types ,
204
269
potential_assoc_types,
205
270
hir_bounds,
206
271
) {
@@ -266,7 +331,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
266
331
} )
267
332
} ) ;
268
333
269
- let existential_projections = projection_bounds. iter ( ) . map ( |( bound, _) | {
334
+ let existential_projections = projection_bounds. into_iter ( ) . map ( |( bound, _) | {
270
335
bound. map_bound ( |mut b| {
271
336
assert_eq ! ( b. projection_term. self_ty( ) , dummy_self) ;
272
337
@@ -291,12 +356,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
291
356
} )
292
357
} ) ;
293
358
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) ;
359
+ let mut auto_trait_predicates: Vec < _ > = auto_traits
360
+ . into_iter ( )
361
+ . map ( |( trait_pred, _) | {
362
+ assert_eq ! ( trait_pred. polarity( ) , ty:: PredicatePolarity :: Positive ) ;
363
+ assert_eq ! ( trait_pred. self_ty( ) . skip_binder( ) , dummy_self) ;
297
364
298
- ty:: Binder :: dummy ( ty:: ExistentialPredicate :: AutoTrait ( trait_pred. def_id ( ) ) )
299
- } ) ;
365
+ ty:: Binder :: dummy ( ty:: ExistentialPredicate :: AutoTrait ( trait_pred. def_id ( ) ) )
366
+ } )
367
+ . collect ( ) ;
368
+ auto_trait_predicates. dedup ( ) ;
300
369
301
370
// N.b. principal, projections, auto traits
302
371
// FIXME: This is actually wrong with multiple principals in regards to symbol mangling
@@ -306,7 +375,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
306
375
. chain ( auto_trait_predicates)
307
376
. collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
308
377
v. sort_by ( |a, b| a. skip_binder ( ) . stable_cmp ( tcx, & b. skip_binder ( ) ) ) ;
309
- v. dedup ( ) ;
310
378
let existential_predicates = tcx. mk_poly_existential_predicates ( & v) ;
311
379
312
380
// Use explicitly-specified region bound, unless the bound is missing.
0 commit comments