From f8bce56b3966c8784060ce875a51f65d18ac659b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 11 Mar 2026 19:39:47 +0100 Subject: [PATCH] Don't look for non-type-level assoc consts when checking trait object types --- .../src/hir_ty_lowering/dyn_trait.rs | 5 ++- compiler/rustc_middle/src/ty/assoc.rs | 4 +- compiler/rustc_middle/src/ty/sty.rs | 2 +- .../cfi/typeid/itanium_cxx_abi/transform.rs | 2 +- .../associated-const-in-trait.rs | 2 + .../associated-const-in-trait.stderr | 38 +++++++++++++++++-- tests/ui/associated-item/issue-48027.stderr | 4 +- .../associated-consts.stderr | 4 +- tests/ui/type-alias/lack-of-wfcheck.rs | 27 +++++++++++++ tests/ui/wf/issue-87495.stderr | 9 ++++- 10 files changed, 82 insertions(+), 15 deletions(-) create mode 100644 tests/ui/type-alias/lack-of-wfcheck.rs diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 7b8e09943df71..515cca6ac1c16 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -230,8 +230,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ordered_associated_items.extend( tcx.associated_items(pred.trait_ref.def_id) .in_definition_order() - // Only associated types & consts can possibly be constrained via a binding. - .filter(|item| item.is_type() || item.is_const()) + // Only associated types & type consts can possibly be + // constrained in a trait object type via a binding. + .filter(|item| item.is_type() || item.is_type_const()) // Traits with RPITITs are simply not dyn compatible (for now). .filter(|item| !item.is_impl_trait_in_trait()) .map(|item| (item.def_id, trait_ref)), diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 4cc255cba6358..cabe8514ae4be 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -137,8 +137,8 @@ impl AssocItem { self.kind.as_def_kind() } - pub fn is_const(&self) -> bool { - matches!(self.kind, ty::AssocKind::Const { .. }) + pub fn is_type_const(&self) -> bool { + matches!(self.kind, ty::AssocKind::Const { is_type_const: true, .. }) } pub fn is_fn(&self) -> bool { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index b449b8f1a406c..780b57c470f36 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -753,7 +753,7 @@ impl<'tcx> Ty<'tcx> { .map(|principal| { tcx.associated_items(principal.def_id()) .in_definition_order() - .filter(|item| item.is_type() || item.is_const()) + .filter(|item| item.is_type() || item.is_type_const()) .filter(|item| !item.is_impl_trait_in_trait()) .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .count() diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 90b489258360f..5691ed1469276 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -239,7 +239,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc .flat_map(|super_poly_trait_ref| { tcx.associated_items(super_poly_trait_ref.def_id()) .in_definition_order() - .filter(|item| item.is_type() || item.is_const()) + .filter(|item| item.is_type() || item.is_type_const()) .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .map(move |assoc_item| { super_poly_trait_ref.map_bound(|super_trait_ref| { diff --git a/tests/ui/associated-consts/associated-const-in-trait.rs b/tests/ui/associated-consts/associated-const-in-trait.rs index 6b0b43feb109c..da68a0fa97c82 100644 --- a/tests/ui/associated-consts/associated-const-in-trait.rs +++ b/tests/ui/associated-consts/associated-const-in-trait.rs @@ -7,6 +7,8 @@ trait Trait { impl dyn Trait { //~^ ERROR the trait `Trait` is not dyn compatible [E0038] const fn n() -> usize { Self::N } + //~^ ERROR the trait `Trait` is not dyn compatible [E0038] + //~| ERROR the trait `Trait` is not dyn compatible [E0038] } fn main() {} diff --git a/tests/ui/associated-consts/associated-const-in-trait.stderr b/tests/ui/associated-consts/associated-const-in-trait.stderr index fb4a55110b4e8..4085f8c990785 100644 --- a/tests/ui/associated-consts/associated-const-in-trait.stderr +++ b/tests/ui/associated-consts/associated-const-in-trait.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Trait` is not dyn compatible - --> $DIR/associated-const-in-trait.rs:7:10 + --> $DIR/associated-const-in-trait.rs:7:6 | LL | impl dyn Trait { - | ^^^^^ `Trait` is not dyn compatible + | ^^^^^^^^^ `Trait` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit @@ -14,6 +14,38 @@ LL | const N: usize; | ^ ...because it contains associated const `N` = help: consider moving `N` to another trait -error: aborting due to 1 previous error +error[E0038]: the trait `Trait` is not dyn compatible + --> $DIR/associated-const-in-trait.rs:9:29 + | +LL | const fn n() -> usize { Self::N } + | ^^^^ `Trait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/associated-const-in-trait.rs:4:11 + | +LL | trait Trait { + | ----- this trait is not dyn compatible... +LL | const N: usize; + | ^ ...because it contains associated const `N` + = help: consider moving `N` to another trait + +error[E0038]: the trait `Trait` is not dyn compatible + --> $DIR/associated-const-in-trait.rs:9:29 + | +LL | const fn n() -> usize { Self::N } + | ^^^^^^^ `Trait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/associated-const-in-trait.rs:4:11 + | +LL | trait Trait { + | ----- this trait is not dyn compatible... +LL | const N: usize; + | ^ ...because it contains associated const `N` + = help: consider moving `N` to another trait + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/associated-item/issue-48027.stderr b/tests/ui/associated-item/issue-48027.stderr index 7abcabc1c79d8..978c377d438ac 100644 --- a/tests/ui/associated-item/issue-48027.stderr +++ b/tests/ui/associated-item/issue-48027.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/issue-48027.rs:6:10 + --> $DIR/issue-48027.rs:6:6 | LL | impl dyn Bar {} - | ^^^ `Bar` is not dyn compatible + | ^^^^^^^ `Bar` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/dyn-compatibility/associated-consts.stderr b/tests/ui/dyn-compatibility/associated-consts.stderr index a92557ea7b8bd..11d02dd2904c8 100644 --- a/tests/ui/dyn-compatibility/associated-consts.stderr +++ b/tests/ui/dyn-compatibility/associated-consts.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `Bar` is not dyn compatible - --> $DIR/associated-consts.rs:8:35 + --> $DIR/associated-consts.rs:8:31 | LL | fn make_bar(t: &T) -> &dyn Bar { - | ^^^ `Bar` is not dyn compatible + | ^^^^^^^ `Bar` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit diff --git a/tests/ui/type-alias/lack-of-wfcheck.rs b/tests/ui/type-alias/lack-of-wfcheck.rs new file mode 100644 index 0000000000000..91fbee8d3f198 --- /dev/null +++ b/tests/ui/type-alias/lack-of-wfcheck.rs @@ -0,0 +1,27 @@ +// Demonstrate that we don't check the definition site of (eager) type aliases for well-formedness. +// +// Listed below are ill-formed type system entities which we don't reject since they appear inside +// the definition of (eager) type aliases. These type aliases are intentionally not referenced from +// anywhere to prevent the eagerly expanded / instantiated aliased types from getting wfchecked +// since that's not what we're testing here. + +//@ check-pass + +type UnsatTraitBound0 = [str]; // `str: Sized` unsatisfied +type UnsatTraitBound1> = T; // `str: Sized` unsatisfied +type UnsatOutlivesBound<'a> = &'static &'a (); // `'a: 'static` unsatisfied + +type Diverging = [(); panic!()]; // `panic!()` diverging + +type DynIncompat0 = dyn Sized; // `Sized` axiomatically dyn incompatible +// issue: +type DynIncompat1 = dyn HasAssocConst; // dyn incompatible due to (non-type-level) assoc const + +// * dyn incompatible due to GAT +// * `'a: 'static`, `String: Copy` and `[u8]: Sized` unsatisfied, `loop {}` diverging +type Several<'a> = dyn HasGenericAssocType = [u8]>; + +trait HasAssocConst { const N: usize; } +trait HasGenericAssocType { type Type<'a: 'static, T: Copy, const N: usize>; } + +fn main() {} diff --git a/tests/ui/wf/issue-87495.stderr b/tests/ui/wf/issue-87495.stderr index 49651e8d6c05c..42e3e2608d732 100644 --- a/tests/ui/wf/issue-87495.stderr +++ b/tests/ui/wf/issue-87495.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `T` is not dyn compatible - --> $DIR/issue-87495.rs:4:29 + --> $DIR/issue-87495.rs:4:25 | LL | const CONST: (bool, dyn T); - | ^ `T` is not dyn compatible + | ^^^^^ `T` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit @@ -13,6 +13,11 @@ LL | trait T { LL | const CONST: (bool, dyn T); | ^^^^^ ...because it contains associated const `CONST` = help: consider moving `CONST` to another trait +help: you might have meant to use `Self` to refer to the implementing type + | +LL - const CONST: (bool, dyn T); +LL + const CONST: (bool, Self); + | error: aborting due to 1 previous error