mGCA: Make traits with type assoc consts dyn compatible...
...but require all assoc consts to be specified via bindings.
This commit is contained in:
parent
838db25382
commit
8d524f096d
32 changed files with 359 additions and 146 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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))>),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
|
|
@ -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`
|
||||
}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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]`
|
||||
}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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...
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue