mGCA: Make traits with type assoc consts dyn compatible...

...but require all assoc consts to be specified via bindings.
This commit is contained in:
León Orell Valerian Liehr 2026-01-21 12:53:44 +01:00
parent 838db25382
commit 8d524f096d
No known key found for this signature in database
GPG key ID: D17A07215F68E713
32 changed files with 359 additions and 146 deletions

View file

@ -56,7 +56,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
let mut user_written_bounds = Vec::new();
let mut potential_assoc_types = Vec::new();
let mut potential_assoc_items = Vec::new();
for poly_trait_ref in hir_bounds.iter() {
let result = self.lower_poly_trait_ref(
poly_trait_ref,
@ -66,7 +66,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
OverlappingAsssocItemConstraints::Forbidden,
);
if let Err(GenericArgCountMismatch { invalid_args, .. }) = result.correct {
potential_assoc_types.extend(invalid_args);
potential_assoc_items.extend(invalid_args);
}
}
@ -138,7 +138,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
// Map the projection bounds onto a key that makes it easy to remove redundant
// bounds that are constrained by supertraits of the principal def id.
// bounds that are constrained by supertraits of the principal trait.
//
// Also make sure we detect conflicting bounds from expanding a trait alias and
// also specifying it manually, like:
@ -191,13 +191,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let principal_trait = regular_traits.into_iter().next();
// 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![];
// A stable ordering of associated types & consts 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_items = vec![];
if let Some((principal_trait, ref spans)) = principal_trait {
let principal_trait = principal_trait.map_bound(|trait_pred| {
@ -223,12 +222,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// FIXME(negative_bounds): Handle this correctly...
let trait_ref =
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
ordered_associated_types.extend(
ordered_associated_items.extend(
tcx.associated_items(pred.trait_ref.def_id)
.in_definition_order()
// We only care about associated types.
.filter(|item| item.is_type())
// No RPITITs -- they're not dyn-compatible for now.
// Only associated types & consts can possibly be constrained via a binding.
.filter(|item| item.is_type() || item.is_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)),
);
@ -283,15 +282,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}
// `dyn Trait<Assoc = Foo>` desugars to (not Rust syntax) `dyn Trait where
// <Self as Trait>::Assoc = Foo`. So every `Projection` clause is an
// `Assoc = Foo` bound. `needed_associated_types` contains all associated
// types that we expect to be provided by the user, so the following loop
// removes all the associated types that have a corresponding `Projection`
// clause, either from expanding trait aliases or written by the user.
// Flag assoc item bindings that didn't really need to be specified.
for &(projection_bound, span) in projection_bounds.values() {
let def_id = projection_bound.item_def_id();
if tcx.generics_require_sized_self(def_id) {
// FIXME(mgca): Ideally we would generalize the name of this lint to sth. like
// `unused_associated_item_bindings` since this can now also trigger on *const*
// projections / assoc *const* bindings.
tcx.emit_node_span_lint(
UNUSED_ASSOCIATED_TYPE_BOUNDS,
hir_id,
@ -301,35 +298,36 @@ 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<_> = ordered_associated_types
// The user has to constrain all associated types & consts via bindings unless the
// corresponding associated item has a `where Self: Sized` clause. This can be done
// in the `dyn Trait` directly, in the supertrait bounds or behind trait aliases.
//
// Collect all associated items that weren't specified and compute the list of
// projection bounds which we'll later turn into existential ones.
//
// We intentionally keep around projections whose associated item has a `Self: Sized`
// bound in order to be able to wfcheck the RHS, allow the RHS to constrain generic
// parameters and to imply bounds.
// See also <https://github.com/rust-lang/rust/pull/140684>.
let mut missing_assoc_items = FxIndexSet::default();
let projection_bounds: Vec<_> = ordered_associated_items
.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, 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);
}
None
.filter_map(|key @ (def_id, _)| {
if let Some(&assoc) = projection_bounds.get(&key) {
return Some(assoc);
}
if !tcx.generics_require_sized_self(def_id) {
missing_assoc_items.insert(key);
}
None
})
.collect();
// If there are any associated items whose value wasn't provided, bail out with an error.
if let Err(guar) = self.check_for_required_assoc_tys(
principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
missing_assoc_types,
potential_assoc_types,
missing_assoc_items,
potential_assoc_items,
hir_bounds,
) {
return Ty::new_error(tcx, guar);

View file

@ -759,7 +759,7 @@ pub struct ImplSourceUserDefinedData<'tcx, N> {
pub nested: ThinVec<N>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
pub enum DynCompatibilityViolation {
/// `Self: Sized` declared on the trait.
SizedSelf(SmallVec<[Span; 1]>),
@ -780,11 +780,17 @@ pub enum DynCompatibilityViolation {
/// Method has something illegal.
Method(Symbol, MethodViolationCode, Span),
/// Associated const.
/// Associated constant.
AssocConst(Symbol, Span),
/// GAT
GAT(Symbol, Span),
/// Generic associated constant.
GenericAssocConst(Symbol, Span),
/// Associated constant that wasn't marked `#[type_const]`.
NonTypeAssocConst(Symbol, Span),
/// Generic associated type.
GenericAssocTy(Symbol, Span),
}
impl DynCompatibilityViolation {
@ -852,14 +858,18 @@ impl DynCompatibilityViolation {
MethodViolationCode::UndispatchableReceiver(_),
_,
) => format!("method `{name}`'s `self` parameter cannot be dispatched on").into(),
DynCompatibilityViolation::AssocConst(name, DUMMY_SP) => {
format!("it contains associated `const` `{name}`").into()
DynCompatibilityViolation::AssocConst(name, _) => {
format!("it contains associated const `{name}`").into()
}
DynCompatibilityViolation::AssocConst(..) => {
"it contains this associated `const`".into()
DynCompatibilityViolation::GenericAssocConst(name, _) => {
format!("it contains generic associated const `{name}`").into()
}
DynCompatibilityViolation::GAT(name, _) => {
format!("it contains the generic associated type `{name}`").into()
DynCompatibilityViolation::NonTypeAssocConst(name, _) => {
format!("it contains associated const `{name}` that's not marked `#[type_const]`")
.into()
}
DynCompatibilityViolation::GenericAssocTy(name, _) => {
format!("it contains generic associated type `{name}`").into()
}
}
}
@ -888,7 +898,9 @@ impl DynCompatibilityViolation {
_,
) => DynCompatibilityViolationSolution::ChangeToRefSelf(*name, *span),
DynCompatibilityViolation::AssocConst(name, _)
| DynCompatibilityViolation::GAT(name, _)
| DynCompatibilityViolation::GenericAssocConst(name, _)
| DynCompatibilityViolation::NonTypeAssocConst(name, _)
| DynCompatibilityViolation::GenericAssocTy(name, _)
| DynCompatibilityViolation::Method(name, ..) => {
DynCompatibilityViolationSolution::MoveToAnotherTrait(*name)
}
@ -905,7 +917,9 @@ impl DynCompatibilityViolation {
| DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans)
| DynCompatibilityViolation::SupertraitConst(spans) => spans.clone(),
DynCompatibilityViolation::AssocConst(_, span)
| DynCompatibilityViolation::GAT(_, span)
| DynCompatibilityViolation::GenericAssocConst(_, span)
| DynCompatibilityViolation::NonTypeAssocConst(_, span)
| DynCompatibilityViolation::GenericAssocTy(_, span)
| DynCompatibilityViolation::Method(_, _, span) => {
if *span != DUMMY_SP {
smallvec![*span]
@ -972,7 +986,7 @@ impl DynCompatibilityViolationSolution {
}
/// Reasons a method might not be dyn-compatible.
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
pub enum MethodViolationCode {
/// e.g., `fn foo()`
StaticMethod(Option<(/* add &self */ (String, Span), /* add Self: Sized */ (String, Span))>),

View file

@ -148,8 +148,9 @@ impl AssocItem {
AssocKind::Type { .. } => DefKind::AssocTy,
}
}
pub fn is_type(&self) -> bool {
matches!(self.kind, ty::AssocKind::Type { .. })
pub fn is_const(&self) -> bool {
matches!(self.kind, ty::AssocKind::Const { .. })
}
pub fn is_fn(&self) -> bool {
@ -160,6 +161,10 @@ impl AssocItem {
matches!(self.kind, ty::AssocKind::Fn { has_self: true, .. })
}
pub fn is_type(&self) -> bool {
matches!(self.kind, ty::AssocKind::Type { .. })
}
pub fn as_tag(&self) -> AssocTag {
match self.kind {
AssocKind::Const { .. } => AssocTag::Const,

View file

@ -762,8 +762,7 @@ impl<'tcx> Ty<'tcx> {
.principal_def_id()
.into_iter()
.flat_map(|principal_def_id| {
// NOTE: This should agree with `needed_associated_types` in
// dyn trait lowering, or else we'll have ICEs.
// IMPORTANT: This has to agree with HIR ty lowering of dyn trait!
elaborate::supertraits(
tcx,
ty::Binder::dummy(ty::TraitRef::identity(tcx, principal_def_id)),
@ -771,7 +770,7 @@ impl<'tcx> Ty<'tcx> {
.map(|principal| {
tcx.associated_items(principal.def_id())
.in_definition_order()
.filter(|item| item.is_type())
.filter(|item| item.is_type() || item.is_const())
.filter(|item| !item.is_impl_trait_in_trait())
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
.count()

View file

@ -7,8 +7,9 @@
use std::ops::ControlFlow;
use rustc_errors::FatalError;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem};
use rustc_hir::{self as hir, LangItem, find_attr};
use rustc_middle::query::Providers;
use rustc_middle::ty::{
self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@ -288,7 +289,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
return false; /* No Sized trait, can't require it! */
};
// Search for a predicate like `Self : Sized` amongst the trait bounds.
// Search for a predicate like `Self: Sized` amongst the trait bounds.
let predicates = tcx.predicates_of(def_id);
let predicates = predicates.instantiate_identity(tcx).predicates;
elaborate(tcx, predicates).any(|pred| match pred.kind().skip_binder() {
@ -306,24 +307,35 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
})
}
/// Returns `Some(_)` if this item makes the containing trait dyn-incompatible.
#[instrument(level = "debug", skip(tcx), ret)]
pub fn dyn_compatibility_violations_for_assoc_item(
tcx: TyCtxt<'_>,
trait_def_id: DefId,
item: ty::AssocItem,
) -> Vec<DynCompatibilityViolation> {
// Any item that has a `Self : Sized` requisite is otherwise
// exempt from the regulations.
// Any item that has a `Self: Sized` requisite is otherwise exempt from the regulations.
if tcx.generics_require_sized_self(item.def_id) {
return Vec::new();
}
let span = || item.ident(tcx).span;
match item.kind {
// Associated consts are never dyn-compatible, as they can't have `where` bounds yet at all,
// and associated const bounds in trait objects aren't a thing yet either.
ty::AssocKind::Const { name } => {
vec![DynCompatibilityViolation::AssocConst(name, item.ident(tcx).span)]
if tcx.features().min_generic_const_args() {
if !tcx.generics_of(item.def_id).is_own_empty() {
vec![DynCompatibilityViolation::GenericAssocConst(name, span())]
} else if !find_attr!(tcx.get_all_attrs(item.def_id), AttributeKind::TypeConst(_)) {
vec![DynCompatibilityViolation::NonTypeAssocConst(name, span())]
} else {
// We will permit type associated consts if they are explicitly mentioned in the
// trait object type. We can't check this here, as here we only check if it is
// guaranteed to not be possible.
Vec::new()
}
} else {
vec![DynCompatibilityViolation::AssocConst(name, span())]
}
}
ty::AssocKind::Fn { name, .. } => {
virtual_call_violations_for_method(tcx, trait_def_id, item)
@ -338,20 +350,22 @@ pub fn dyn_compatibility_violations_for_assoc_item(
(MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
}
_ => item.ident(tcx).span,
_ => span(),
};
DynCompatibilityViolation::Method(name, v, span)
})
.collect()
}
// Associated types can only be dyn-compatible if they have `Self: Sized` bounds.
ty::AssocKind::Type { .. } => {
if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() {
vec![DynCompatibilityViolation::GAT(item.name(), item.ident(tcx).span)]
ty::AssocKind::Type { data } => {
if !tcx.generics_of(item.def_id).is_own_empty()
&& let ty::AssocTypeData::Normal(name) = data
{
vec![DynCompatibilityViolation::GenericAssocTy(name, span())]
} else {
// We will permit associated types if they are explicitly mentioned in the trait object.
// We can't check this here, as here we only check if it is guaranteed to not be possible.
// We will permit associated types if they are explicitly mentioned in the trait
// object type. We can't check this here, as here we only check if it is
// guaranteed to not be possible.
Vec::new()
}
}

View file

@ -7,8 +7,6 @@ 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
}
fn main() {}

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Trait` is not dyn compatible
--> $DIR/associated-const-in-trait.rs:7:6
--> $DIR/associated-const-in-trait.rs:7:10
|
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 <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@ -11,41 +11,9 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait Trait {
| ----- this trait is not dyn compatible...
LL | const N: usize;
| ^ ...because it contains this associated `const`
| ^ ...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 <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/associated-const-in-trait.rs:4:11
|
LL | trait Trait {
| ----- this trait is not dyn compatible...
LL | const N: usize;
| ^ ...because it contains this associated `const`
= 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 <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/associated-const-in-trait.rs:4:11
|
LL | trait Trait {
| ----- this trait is not dyn compatible...
LL | const N: usize;
| ^ ...because it contains this associated `const`
= help: consider moving `N` to another trait
error: aborting due to 3 previous errors
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0038`.

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Bar` is not dyn compatible
--> $DIR/issue-48027.rs:6:6
--> $DIR/issue-48027.rs:6:10
|
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 <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait Bar {
| --- this trait is not dyn compatible...
LL | const X: usize;
| ^ ...because it contains this associated `const`
| ^ ...because it contains associated const `X`
= help: consider moving `X` to another trait
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type

View file

@ -8,7 +8,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
|
= note: the trait is not dyn compatible because it contains the generic associated type `CallRefFuture`
= note: the trait is not dyn compatible because it contains generic associated type `CallRefFuture`
error: aborting due to 1 previous error

View file

@ -0,0 +1,38 @@
// Traits with type associated consts are dyn compatible.
// Check that we allow the corresp. trait object types if all assoc consts are specified.
//@ check-pass
#![feature(min_generic_const_args)]
#![expect(incomplete_features)]
trait Trait: SuperTrait<C = 3> {
#[type_const]
const K: usize;
}
trait SuperTrait {
#[type_const]
const Q: usize;
#[type_const]
const C: usize;
}
trait Bound {
#[type_const]
const N: usize;
}
impl Bound for () {
#[type_const]
const N: usize = 10;
}
fn main() {
let _: dyn Trait<K = 1, Q = 2>;
let obj: &dyn Bound<N = 10> = &();
_ = identity(obj);
fn identity(x: &(impl ?Sized + Bound<N = 10>)) -> &(impl ?Sized + Bound<N = 10>) { x }
}

View file

@ -0,0 +1,18 @@
// Ensure that we actually enforce equality constraints found in trait object types.
#![feature(min_generic_const_args)]
#![expect(incomplete_features)]
trait Trait {
#[type_const]
const N: usize;
}
impl Trait for () {
#[type_const]
const N: usize = 1;
}
fn main() {
let _: &dyn Trait<N = 0> = &(); //~ ERROR type mismatch resolving `<() as Trait>::N == 0`
}

View file

@ -0,0 +1,13 @@
error[E0271]: type mismatch resolving `<() as Trait>::N == 0`
--> $DIR/dyn-compat-const-mismatch.rs:17:32
|
LL | let _: &dyn Trait<N = 0> = &();
| ^^^ expected `0`, found `1`
|
= note: expected constant `0`
found constant `1`
= note: required for the cast from `&()` to `&dyn Trait<N = 0>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0271`.

View file

@ -0,0 +1,16 @@
// Ensure that traits with generic associated consts (GACs) are dyn *in*compatible.
// It would be very hard to make dyn Trait with GACs sound just like with GATs.
//@ dont-require-annotations: NOTE
#![feature(min_generic_const_args, generic_const_items)]
#![expect(incomplete_features)]
trait Trait {
const POLY<T>: T;
//~^ NOTE it contains generic associated const `POLY`
}
fn main() {
let _: dyn Trait; //~ ERROR the trait `Trait` is not dyn compatible
}

View file

@ -0,0 +1,19 @@
error[E0038]: the trait `Trait` is not dyn compatible
--> $DIR/dyn-compat-generic-assoc-const.rs:15:16
|
LL | let _: dyn Trait;
| ^^^^^ `Trait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/dyn-compat-generic-assoc-const.rs:10:11
|
LL | trait Trait {
| ----- this trait is not dyn compatible...
LL | const POLY<T>: T;
| ^^^^ ...because it contains generic associated const `POLY`
= help: consider moving `POLY` to another trait
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0038`.

View file

@ -0,0 +1,20 @@
// Ensure that traits with non-type associated consts are dyn *in*compatible.
//@ dont-require-annotations: NOTE
#![feature(min_generic_const_args)]
#![expect(incomplete_features)]
trait Trait {
const K: usize;
//~^ NOTE it contains associated const `K` that's not marked `#[type_const]`
}
fn main() {
let _: dyn Trait; //~ ERROR the trait `Trait` is not dyn compatible
// Check that specifying the non-type assoc const doesn't "magically make it work".
let _: dyn Trait<K = 0>;
//~^ ERROR the trait `Trait` is not dyn compatible
//~| ERROR use of trait associated const without `#[type_const]`
}

View file

@ -0,0 +1,43 @@
error[E0038]: the trait `Trait` is not dyn compatible
--> $DIR/dyn-compat-non-type-assoc-const.rs:14:16
|
LL | let _: dyn Trait;
| ^^^^^ `Trait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/dyn-compat-non-type-assoc-const.rs:9:11
|
LL | trait Trait {
| ----- this trait is not dyn compatible...
LL | const K: usize;
| ^ ...because it contains associated const `K` that's not marked `#[type_const]`
= help: consider moving `K` to another trait
error: use of trait associated const without `#[type_const]`
--> $DIR/dyn-compat-non-type-assoc-const.rs:17:22
|
LL | let _: dyn Trait<K = 0>;
| ^^^^^
|
= note: the declaration in the trait must be marked with `#[type_const]`
error[E0038]: the trait `Trait` is not dyn compatible
--> $DIR/dyn-compat-non-type-assoc-const.rs:17:16
|
LL | let _: dyn Trait<K = 0>;
| ^^^^^^^^^^^^ `Trait` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/dyn-compat-non-type-assoc-const.rs:9:11
|
LL | trait Trait {
| ----- this trait is not dyn compatible...
LL | const K: usize;
| ^ ...because it contains associated const `K` that's not marked `#[type_const]`
= help: consider moving `K` to another trait
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0038`.

View file

@ -0,0 +1,25 @@
// Traits with type associated consts are dyn compatible. However, all associated consts must
// be specified in the corresp. trait object type (barring exceptions) similiar to associated
// types. Check that we reject code that doesn't provide the necessary bindings.
#![feature(min_generic_const_args)]
#![expect(incomplete_features)]
trait Trait {
#[type_const]
const K: usize;
}
// fn ctxt / body
fn main() {
let _: dyn Trait;
//~^ ERROR the value of the associated type `K` in `Trait` must be specified
}
// item ctxt / signature / non-body
struct Store(dyn Trait);
//~^ ERROR the value of the associated type `K` in `Trait` must be specified
// item ctxt & no wfcking (eager ty alias)
type DynTrait = dyn Trait;
//~^ ERROR the value of the associated type `K` in `Trait` must be specified

View file

@ -0,0 +1,30 @@
error[E0191]: the value of the associated type `K` in `Trait` must be specified
--> $DIR/dyn-compat-unspecified-assoc-consts.rs:20:18
|
LL | const K: usize;
| -------------- `K` defined here
...
LL | struct Store(dyn Trait);
| ^^^^^ help: specify the associated type: `Trait<K = Type>`
error[E0191]: the value of the associated type `K` in `Trait` must be specified
--> $DIR/dyn-compat-unspecified-assoc-consts.rs:24:21
|
LL | const K: usize;
| -------------- `K` defined here
...
LL | type DynTrait = dyn Trait;
| ^^^^^ help: specify the associated type: `Trait<K = Type>`
error[E0191]: the value of the associated type `K` in `Trait` must be specified
--> $DIR/dyn-compat-unspecified-assoc-consts.rs:15:16
|
LL | const K: usize;
| -------------- `K` defined here
...
LL | let _: dyn Trait;
| ^^^^^ help: specify the associated type: `Trait<K = Type>`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0191`.

View file

@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait X {
| - this trait is not dyn compatible...
LL | type Y<const N: i16>;
| ^ ...because it contains the generic associated type `Y`
| ^ ...because it contains generic associated type `Y`
= help: consider moving `Y` to another trait
error: aborting due to 1 previous error

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `Bar` is not dyn compatible
--> $DIR/associated-consts.rs:8:31
--> $DIR/associated-consts.rs:8:35
|
LL | fn make_bar<T: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 <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait Bar {
| --- this trait is not dyn compatible...
LL | const X: usize;
| ^ ...because it contains this associated `const`
| ^ ...because it contains associated const `X`
= help: consider moving `X` to another trait
error: aborting due to 1 previous error

View file

@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait Super {
| ----- this trait is not dyn compatible...
LL | type Assoc<'a>;
| ^^^^^ ...because it contains the generic associated type `Assoc`
| ^^^^^ ...because it contains generic associated type `Assoc`
= help: consider moving `Assoc` to another trait
error: aborting due to 1 previous error

View file

@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait Foo {
| --- this trait is not dyn compatible...
LL | type Bar<T>;
| ^^^ ...because it contains the generic associated type `Bar`
| ^^^ ...because it contains generic associated type `Bar`
= help: consider moving `Bar` to another trait
error: aborting due to 1 previous error

View file

@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait Tr {
| -- this trait is not dyn compatible...
LL | const N: usize;
| ^ ...because it contains this associated `const`
| ^ ...because it contains associated const `N`
= help: consider moving `N` to another trait
= help: only type `u8` implements `Tr`; consider using it directly instead.

View file

@ -18,7 +18,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
--> $DIR/supertrait-mentions-GAT.rs:4:10
|
LL | type Gat<'a>
| ^^^ ...because it contains the generic associated type `Gat`
| ^^^ ...because it contains generic associated type `Gat`
...
LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
| ---------- this trait is not dyn compatible...

View file

@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait Foo {
| --- this trait is not dyn compatible...
LL | type A<'a> where Self: 'a;
| ^ ...because it contains the generic associated type `A`
| ^ ...because it contains generic associated type `A`
= help: consider moving `A` to another trait
error[E0038]: the trait `Foo` is not dyn compatible
@ -27,7 +27,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait Foo {
| --- this trait is not dyn compatible...
LL | type A<'a> where Self: 'a;
| ^ ...because it contains the generic associated type `A`
| ^ ...because it contains generic associated type `A`
= help: consider moving `A` to another trait
error: aborting due to 2 previous errors

View file

@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait X {
| - this trait is not dyn compatible...
LL | type Y<'a>;
| ^ ...because it contains the generic associated type `Y`
| ^ ...because it contains generic associated type `Y`
= help: consider moving `Y` to another trait
error: aborting due to 1 previous error

View file

@ -27,7 +27,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | pub trait SuperTrait {
| ---------- this trait is not dyn compatible...
LL | type SubType<'a>: SubTrait where Self: 'a;
| ^^^^^^^ ...because it contains the generic associated type `SubType`
| ^^^^^^^ ...because it contains generic associated type `SubType`
= help: consider moving `SubType` to another trait
= help: only type `SuperStruct` implements `SuperTrait` within this crate; consider using it directly instead.
= note: `SuperTrait` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type

View file

@ -27,7 +27,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait CollectionFamily {
| ---------------- this trait is not dyn compatible...
LL | type Member<T>;
| ^^^^^^ ...because it contains the generic associated type `Member`
| ^^^^^^ ...because it contains generic associated type `Member`
= help: consider moving `Member` to another trait
error: aborting due to 2 previous errors

View file

@ -27,7 +27,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait MapLike<K, V> {
| ------- this trait is not dyn compatible...
LL | type VRefCont<'a>: RefCont<'a, V>
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
| ^^^^^^^^ ...because it contains generic associated type `VRefCont`
= help: consider moving `VRefCont` to another trait
error: aborting due to 2 previous errors

View file

@ -11,7 +11,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait StreamingIterator {
| ----------------- this trait is not dyn compatible...
LL | type Item<'a> where Self: 'a;
| ^^^^ ...because it contains the generic associated type `Item`
| ^^^^ ...because it contains generic associated type `Item`
= help: consider moving `Item` to another trait
error: aborting due to 1 previous error

View file

@ -141,15 +141,15 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
--> $DIR/item-privacy.rs:26:15
|
LL | const A: u8 = 0;
| ^ ...because it contains this associated `const`
| ^ ...because it contains associated const `A`
...
LL | const B: u8 = 0;
| ^ ...because it contains this associated `const`
| ^ ...because it contains associated const `B`
...
LL | pub trait C: A + B {
| - this trait is not dyn compatible...
LL | const C: u8 = 0;
| ^ ...because it contains this associated `const`
| ^ ...because it contains associated const `C`
= help: consider moving `C` to another trait
= help: consider moving `A` to another trait
= help: consider moving `B` to another trait
@ -166,15 +166,15 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
--> $DIR/item-privacy.rs:26:15
|
LL | const A: u8 = 0;
| ^ ...because it contains this associated `const`
| ^ ...because it contains associated const `A`
...
LL | const B: u8 = 0;
| ^ ...because it contains this associated `const`
| ^ ...because it contains associated const `B`
...
LL | pub trait C: A + B {
| - this trait is not dyn compatible...
LL | const C: u8 = 0;
| ^ ...because it contains this associated `const`
| ^ ...because it contains associated const `C`
= help: consider moving `C` to another trait
= help: consider moving `A` to another trait
= help: consider moving `B` to another trait

View file

@ -1,8 +1,8 @@
error[E0038]: the trait `T` is not dyn compatible
--> $DIR/issue-87495.rs:4:25
--> $DIR/issue-87495.rs:4:29
|
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 <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
@ -11,13 +11,8 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
LL | trait T {
| - this trait is not dyn compatible...
LL | const CONST: (bool, dyn T);
| ^^^^^ ...because it contains this associated `const`
| ^^^^^ ...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