-
Notifications
You must be signed in to change notification settings - Fork 14.1k
Description
Imagine you have the following (cf. https://docs.rs/imply-hack, and/or https://docs.rs/implied-bounds):
// 0.
mod implied_bounds {
pub trait ImpliedPredicate<X: ?Sized> : HasAssociatedImpls<X, Impls = X> {}
pub trait HasAssociatedImpls<X: ?Sized> { type Impls: ?Sized; }
impl<T: ?Sized, X: ?Sized> ImpliedPredicate<X> for T {}
impl<T: ?Sized, X: ?Sized> HasAssociatedImpls<X> for T { type Impls = X; }
}
use implied_bounds::ImpliedPredicate;
trait SomeBound {}
// 1.
trait HasImpliedBoundOnSelf
:
ImpliedPredicate<Self ,Impls: SomeBound> // <- the specific bound does not matter
{}
// 2. HEREIN LIES THE ISSUE
trait HasAssocWithImplyingBoundSuperTrait {
// ERROR, missing `SomeBound` on `Self::Assoc`.
type Assoc: HasImpliedBoundOnSelf;
}I expected to see this happen: trait declarations (with no "bad" impls) to be allowed.
Instead, this happened: the trait HasAssocWithImplyingBoundSuperTrait definition is rejected.
error[E0277]: the trait bound `<Self as HasAssocWithImplyingBoundSuperTrait>::Assoc: SomeBound` is not satisfied
--> <source>:21:17
|
21 | type Assoc: HasImpliedBoundOnSelf; // <- ERROR, missing `Send` on `Self::Assoc`.
| ^^^^^^^^^^^^^^^^^^^^^ the trait `SomeBound` is not implemented for `<Self as HasAssocWithImplyingBoundSuperTrait>::Assoc`
|
note: required by a bound in `HasImpliedBoundOnSelf`
--> <source>:16:35
|
14 | trait HasImpliedBoundOnSelf
| --------------------- required by a bound in this trait
15 | :
16 | ImpliedPredicate<Self ,Impls: SomeBound> // <- the specific bound does not matter
| ^^^^^^^^^ required by this bound in `HasImpliedBoundOnSelf`
help: consider further restricting the associated type
|
20 | trait HasAssocWithImplyingBoundSuperTrait where <Self as HasAssocWithImplyingBoundSuperTrait>::Assoc: SomeBound {
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++Meta
rustc --version --verbose: This happens since 1.79.0 (permalink), when the assoc type bounds got stabilized, all the way to current nightly:
1.93.0-nightly 2025-12-04 b33119ffdd483969934b
@rustbot label +A-trait-system +F-associated_type_bounds
Rationale
Click to see
As to some rationale behind the odd pattern (e.g., rather than a mere super-trait on Self in this instance): https://docs.rs/named-generics-bundle.
There, I want a trait to imply certain non-dyn-safe bounds such as Clone (to work around non-perfect derives later on with type-level-only generics), but I also want the trait, or a close version thereof, to be dyn-safe.
I achieve this by doing the following:
trait TargetTrait<Helper = Self>: ImpliedPredicate<Helper ,Impls: Clone> {
type Assoc : …;
// …
}This way:
dyn TargetTrait<(), …>is well-formed;X: TargetTraitentails: Clone.
From there, I can do the following:
impl<Dyn : ?Sized + TargetTrait<()>> TargetTrait for PhantomData<Dyn> {
type Assoc = Dyn::Assoc;
}
// So that `PhantomData<dyn TargetTrait<(), Assoc = …>> : TargetTrait`!Final, ergonomic touch:
macro_rules! TargetTrait {( $($assoc:tt)* ) => (
::core::marker::PhantomData<
dyn TargetTrait<(), $($assoc)*>
>
)}And we get the final result:
fn some_api<T: TargetTrait>() {
let _: T::SomeAssoc; // It Works!
}
some_api::<TargetTrait![SomeAssoc = …]>() // Named generic params!But doing all this runs into issues the moment someone does:
trait AnotherTrait {
type Assoc: TargetTrait; // <- Error, `Self::Assoc : Clone` is not fulfilled!
}which is what this very issue is about.