Skip to content

Commit 3799d84

Browse files
Review
1 parent fd37906 commit 3799d84

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -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
}

tests/ui/traits/object/constrain-via-unnecessary-bound.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub trait Trait {
1313
}
1414

1515
impl Other for dyn Trait {}
16-
// `dyn Trait<Assoc = ()>` is a different "nominal type" than `dyn Traiat`.
16+
// `dyn Trait<Assoc = ()>` is a different "nominal type" than `dyn Trait`.
1717
impl Other for dyn Trait<Assoc = ()> {}
1818
//~^ WARN unnecessary associated type bound for dyn-incompatible associated type
1919

0 commit comments

Comments
 (0)