@@ -146,7 +146,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
146146
147147 let principal_trait = regular_traits. into_iter ( ) . next ( ) ;
148148
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+
150157 if let Some ( ( principal_trait, ref spans) ) = principal_trait {
151158 let principal_trait = principal_trait. map_bound ( |trait_pred| {
152159 assert_eq ! ( trait_pred. polarity, ty:: PredicatePolarity :: Positive ) ;
@@ -171,7 +178,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
171178 // FIXME(negative_bounds): Handle this correctly...
172179 let trait_ref =
173180 tcx. anonymize_bound_vars ( bound_predicate. rebind ( pred. trait_ref ) ) ;
174- needed_associated_types . extend (
181+ ordered_associated_types . extend (
175182 tcx. associated_items ( pred. trait_ref . def_id )
176183 . in_definition_order ( )
177184 // We only care about associated types.
@@ -249,15 +256,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
249256 }
250257 }
251258
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.
252265 let mut missing_assoc_types = FxIndexSet :: default ( ) ;
253- let projection_bounds: Vec < _ > = needed_associated_types
266+ let projection_bounds: Vec < _ > = ordered_associated_types
254267 . into_iter ( )
255268 . filter_map ( |key| {
256269 if let Some ( assoc) = projection_bounds. get ( & key) {
257270 Some ( * assoc)
258271 } 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.
261276 if !tcx. generics_require_sized_self ( key. 0 ) {
262277 missing_assoc_types. insert ( key) ;
263278 }
0 commit comments