@@ -146,7 +146,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
146
146
147
147
let principal_trait = regular_traits. into_iter ( ) . next ( ) ;
148
148
149
- let mut needed_associated_types = vec ! [ ] ;
149
+ // A stable ordering of associated types from the principal trait and all its
150
+ // supertraits. We use this to ensure that different substitutions of a trait
151
+ // don't result in `dyn Trait` types with different projections lists, which
152
+ // can be unsound: <https://github.com/rust-lang/rust/pull/136458>.
153
+ // We achieve a stable ordering by walking over the unsubstituted principal
154
+ // trait ref.
155
+ let mut ordered_associated_types = vec ! [ ] ;
156
+
150
157
if let Some ( ( principal_trait, ref spans) ) = principal_trait {
151
158
let principal_trait = principal_trait. map_bound ( |trait_pred| {
152
159
assert_eq ! ( trait_pred. polarity, ty:: PredicatePolarity :: Positive ) ;
@@ -171,7 +178,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
171
178
// FIXME(negative_bounds): Handle this correctly...
172
179
let trait_ref =
173
180
tcx. anonymize_bound_vars ( bound_predicate. rebind ( pred. trait_ref ) ) ;
174
- needed_associated_types . extend (
181
+ ordered_associated_types . extend (
175
182
tcx. associated_items ( pred. trait_ref . def_id )
176
183
. in_definition_order ( )
177
184
// We only care about associated types.
@@ -249,15 +256,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
249
256
}
250
257
}
251
258
259
+ // We compute the list of projection bounds taking the ordered associated types,
260
+ // and check if there was an entry in the collected `projection_bounds`. Those
261
+ // are computed by first taking the user-written associated types, then elaborating
262
+ // the principal trait ref, and only using those if there was no user-written.
263
+ // See note below about how we handle missing associated types with `Self: Sized`,
264
+ // which are not required to be provided, but are still used if they are provided.
252
265
let mut missing_assoc_types = FxIndexSet :: default ( ) ;
253
- let projection_bounds: Vec < _ > = needed_associated_types
266
+ let projection_bounds: Vec < _ > = ordered_associated_types
254
267
. into_iter ( )
255
268
. filter_map ( |key| {
256
269
if let Some ( assoc) = projection_bounds. get ( & key) {
257
270
Some ( * assoc)
258
271
} else {
259
- // If the associated type has a `where Self: Sized` bound,
260
- // we do not need to constrain the associated type.
272
+ // If the associated type has a `where Self: Sized` bound, then
273
+ // we do not need to provide the associated type. This results in
274
+ // a `dyn Trait` type that has a different number of projection
275
+ // bounds, which may lead to type mismatches.
261
276
if !tcx. generics_require_sized_self ( key. 0 ) {
262
277
missing_assoc_types. insert ( key) ;
263
278
}
0 commit comments