Skip to content

Commit d800540

Browse files
compiler-errorspietroalbini
authored andcommitted
Review
1 parent 2f71d0a commit d800540

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
@@ -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
}

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)