@@ -172,7 +172,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
172172
173173 let principal_trait = regular_traits. into_iter ( ) . next ( ) ;
174174
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+
176183 if let Some ( ( principal_trait, ref spans) ) = principal_trait {
177184 let principal_trait = principal_trait. map_bound ( |trait_pred| {
178185 assert_eq ! ( trait_pred. polarity, ty:: PredicatePolarity :: Positive ) ;
@@ -197,7 +204,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
197204 // FIXME(negative_bounds): Handle this correctly...
198205 let trait_ref =
199206 tcx. anonymize_bound_vars ( bound_predicate. rebind ( pred. trait_ref ) ) ;
200- needed_associated_types . extend (
207+ ordered_associated_types . extend (
201208 tcx. associated_items ( pred. trait_ref . def_id )
202209 . in_definition_order ( )
203210 // We only care about associated types.
@@ -275,15 +282,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
275282 }
276283 }
277284
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.
278291 let mut missing_assoc_types = FxIndexSet :: default ( ) ;
279- let projection_bounds: Vec < _ > = needed_associated_types
292+ let projection_bounds: Vec < _ > = ordered_associated_types
280293 . into_iter ( )
281294 . filter_map ( |key| {
282295 if let Some ( assoc) = projection_bounds. get ( & key) {
283296 Some ( * assoc)
284297 } 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.
287302 if !tcx. generics_require_sized_self ( key. 0 ) {
288303 missing_assoc_types. insert ( key) ;
289304 }
0 commit comments