diff options
| author | Michael Goulet <michael@errs.io> | 2025-05-07 16:55:21 +0000 |
|---|---|---|
| committer | Pietro Albini <pietro@pietroalbini.org> | 2025-05-09 18:12:13 +0200 |
| commit | d800540c12f6da4f2006ff2b13ea64a6883857bf (patch) | |
| tree | 1804e77836e03d19ee5c8e59530397e1a0674bc5 | |
| parent | 2f71d0a243f31f346f868808f8ff5892a8ff8279 (diff) | |
| download | rust-d800540c12f6da4f2006ff2b13ea64a6883857bf.tar.gz rust-d800540c12f6da4f2006ff2b13ea64a6883857bf.zip | |
Review
| -rw-r--r-- | compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs | 25 | ||||
| -rw-r--r-- | tests/ui/traits/object/constrain-via-unnecessary-bound.rs | 2 |
2 files changed, 21 insertions, 6 deletions
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 19f80751d05..8be8ea1cc1c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -146,7 +146,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let principal_trait = regular_traits.into_iter().next(); - let mut needed_associated_types = vec![]; + // A stable ordering of associated types from the principal trait and all its + // supertraits. We use this to ensure that different substitutions of a trait + // don't result in `dyn Trait` types with different projections lists, which + // can be unsound: <https://github.com/rust-lang/rust/pull/136458>. + // We achieve a stable ordering by walking over the unsubstituted principal + // trait ref. + let mut ordered_associated_types = vec![]; + if let Some((principal_trait, ref spans)) = principal_trait { let principal_trait = principal_trait.map_bound(|trait_pred| { assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive); @@ -171,7 +178,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // FIXME(negative_bounds): Handle this correctly... let trait_ref = tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref)); - needed_associated_types.extend( + ordered_associated_types.extend( tcx.associated_items(pred.trait_ref.def_id) .in_definition_order() // We only care about associated types. @@ -249,15 +256,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } + // We compute the list of projection bounds taking the ordered associated types, + // and check if there was an entry in the collected `projection_bounds`. Those + // are computed by first taking the user-written associated types, then elaborating + // the principal trait ref, and only using those if there was no user-written. + // See note below about how we handle missing associated types with `Self: Sized`, + // which are not required to be provided, but are still used if they are provided. let mut missing_assoc_types = FxIndexSet::default(); - let projection_bounds: Vec<_> = needed_associated_types + let projection_bounds: Vec<_> = ordered_associated_types .into_iter() .filter_map(|key| { if let Some(assoc) = projection_bounds.get(&key) { Some(*assoc) } else { - // If the associated type has a `where Self: Sized` bound, - // we do not need to constrain the associated type. + // If the associated type has a `where Self: Sized` bound, then + // we do not need to provide the associated type. This results in + // a `dyn Trait` type that has a different number of projection + // bounds, which may lead to type mismatches. if !tcx.generics_require_sized_self(key.0) { missing_assoc_types.insert(key); } diff --git a/tests/ui/traits/object/constrain-via-unnecessary-bound.rs b/tests/ui/traits/object/constrain-via-unnecessary-bound.rs index 5534471fb27..4640d6b3ed5 100644 --- a/tests/ui/traits/object/constrain-via-unnecessary-bound.rs +++ b/tests/ui/traits/object/constrain-via-unnecessary-bound.rs @@ -13,7 +13,7 @@ pub trait Trait { } impl Other for dyn Trait {} -// `dyn Trait<Assoc = ()>` is a different "nominal type" than `dyn Traiat`. +// `dyn Trait<Assoc = ()>` is a different "nominal type" than `dyn Trait`. impl Other for dyn Trait<Assoc = ()> {} //~^ WARN unnecessary associated type bound for dyn-incompatible associated type |
