@@ -172,7 +172,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
172
172
173
173
let principal_trait = regular_traits. into_iter ( ) . next ( ) ;
174
174
175
- let mut needed_associated_types = vec ! [ ] ;
175
+ // A stable ordering of associated types from the principal trait and all its
176
+ // supertraits. We use this to ensure that different substitutions of a trait
177
+ // don't result in `dyn Trait` types with different projections lists, which
178
+ // can be unsound: <https://github.com/rust-lang/rust/pull/136458>.
179
+ // We achieve a stable ordering by walking over the unsubstituted principal
180
+ // trait ref.
181
+ let mut ordered_associated_types = vec ! [ ] ;
182
+
176
183
if let Some ( ( principal_trait, ref spans) ) = principal_trait {
177
184
let principal_trait = principal_trait. map_bound ( |trait_pred| {
178
185
assert_eq ! ( trait_pred. polarity, ty:: PredicatePolarity :: Positive ) ;
@@ -197,7 +204,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
197
204
// FIXME(negative_bounds): Handle this correctly...
198
205
let trait_ref =
199
206
tcx. anonymize_bound_vars ( bound_predicate. rebind ( pred. trait_ref ) ) ;
200
- needed_associated_types . extend (
207
+ ordered_associated_types . extend (
201
208
tcx. associated_items ( pred. trait_ref . def_id )
202
209
. in_definition_order ( )
203
210
// We only care about associated types.
@@ -275,15 +282,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
275
282
}
276
283
}
277
284
285
+ // We compute the list of projection bounds taking the ordered associated types,
286
+ // and check if there was an entry in the collected `projection_bounds`. Those
287
+ // are computed by first taking the user-written associated types, then elaborating
288
+ // the principal trait ref, and only using those if there was no user-written.
289
+ // See note below about how we handle missing associated types with `Self: Sized`,
290
+ // which are not required to be provided, but are still used if they are provided.
278
291
let mut missing_assoc_types = FxIndexSet :: default ( ) ;
279
- let projection_bounds: Vec < _ > = needed_associated_types
292
+ let projection_bounds: Vec < _ > = ordered_associated_types
280
293
. into_iter ( )
281
294
. filter_map ( |key| {
282
295
if let Some ( assoc) = projection_bounds. get ( & key) {
283
296
Some ( * assoc)
284
297
} else {
285
- // If the associated type has a `where Self: Sized` bound,
286
- // we do not need to constrain the associated type.
298
+ // If the associated type has a `where Self: Sized` bound, then
299
+ // we do not need to provide the associated type. This results in
300
+ // a `dyn Trait` type that has a different number of projection
301
+ // bounds, which may lead to type mismatches.
287
302
if !tcx. generics_require_sized_self ( key. 0 ) {
288
303
missing_assoc_types. insert ( key) ;
289
304
}
0 commit comments