-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot use associated type as type of associated const #46969
Comments
This exact issue just occured to @CryZe and me when trying to use associated constants to create a constant struct in a library with user-provided data (without const fns) (actual use case: playground). A minimized examples is this (playground): use std::marker::PhantomData;
trait Const {
type T;
const VAL: Self::T;
}
struct MakeTuple<U>(PhantomData<U>);
impl<U: Const + Sized> Const for MakeTuple<U> {
type T = (U::T, U::T);
const VAL: Self::T = (U::VAL, U::VAL);
} Error: error[E0277]: the trait bound `U: std::marker::Sized` is not satisfied
--> src/main.rs:11:5
|
11 | const VAL: Self::T = (U::VAL, U::VAL);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `U` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `U`
= help: consider adding a `where U: std::marker::Sized` bound
= note: required because of the requirements on the impl of `Const` for `MakeTuple<U>`
error[E0277]: the trait bound `U: Const` is not satisfied
--> src/main.rs:11:5
|
11 | const VAL: Self::T = (U::VAL, U::VAL);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Const` is not implemented for `U`
|
= help: consider adding a `where U: Const` bound
= note: required because of the requirements on the impl of `Const` for `MakeTuple<U>` The interesting thing is that even though both bounds are specified, the compiler doesn't seem to take them into account. Edit: The issue is not using a trait with an associated type and const as generic bound. Instead the problem is implementing a trait with an associated type and const in general: playground |
I ran into the same problem. It's also in 1.26 stable. Here's a further minimized example (play): trait EmptyTrait {}
trait Const {
type T;
const VAL: Self::T;
}
impl<U: EmptyTrait + std::marker::Sized> Const for U
{
type T = u32;
const VAL: u32 = 5;
} We can also use the type parameter in the trait rather than the type (play): trait EmptyTrait {}
trait Const<U> {
type T;
const VAL: Self::T;
}
impl<U: EmptyTrait + Sized> Const<U> for () {
type T = u32;
const VAL: Self::T = 5;
} Both code fragments give an error saying that in the blanket impl, Rust cannot figure out that
Note that in both cases, if you remove the The problem goes away if you declare the type of I'm not familiar with the compiler internals, but my hypothesis is that associated types and constants depending on a type parameter are not evaluated properly in the constant expression evaluator. In this case, it's associated types that do not reduce well: I feel there are a couple of different issues in the same spirit:
|
Copying over my minimal example from #53908 as another data point (playground): use std::marker::PhantomData;
pub trait FromPest: Sized {
type Rule;
const RULE: Self::Rule;
}
impl<T> FromPest for PhantomData<T>
where
T: FromPest,
{
type Rule = T::Rule;
const RULE: T::Rule = T::RULE;
} Here I've added a |
cc rust-lang/rust#46969 The reason that the PhantomData approach doesn't work Not that the generic EOI does either
Bonus: fixes PestDeconstructor::discard to _actually_ skip the drop This does reduce runtime guarantees, as it doesn't only drop EOI, but hey, it makes it work. With the fix for rust-lang/rust#46969, we should be able to use PhantomData to mark ignored pairs.
All of these cases now compile, except for the original report, which has a type error:
Current output:
The correct code would be
The outstanding work would be providing a suggestion explaining what "consider constraining the associated type |
…rrors Suggest constraining assoc types in more cases Fix rust-lang#46969. ``` error[E0308]: mismatched types --> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:12:21 | LL | const N: C::M = 4u8; | ^^^ expected associated type, found `u8` | = note: expected associated type `<C as O>::M` found type `u8` help: consider constraining the associated type `<C as O>::M` to `u8` | LL | impl<C: O<M = u8>> U<C> for u16 { | ++++++++ ```
Rollup merge of rust-lang#116865 - estebank:issue-46969, r=compiler-errors Suggest constraining assoc types in more cases Fix rust-lang#46969. ``` error[E0308]: mismatched types --> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:12:21 | LL | const N: C::M = 4u8; | ^^^ expected associated type, found `u8` | = note: expected associated type `<C as O>::M` found type `u8` help: consider constraining the associated type `<C as O>::M` to `u8` | LL | impl<C: O<M = u8>> U<C> for u16 { | ++++++++ ```
Repro:
This caused E0277 "the trait bound is not satisfied" error:
The error doesn't make sense because
C
is obviouslySized
. It seems the associated const type is evaluated before the generic bounds are added, causing this error.Changing both
A::M
andC::M
tou8
makes the error go away.Reproducible on all 3 versions on playground (1.23.0, 1.24.0-beta, 1.25.0-nightly).
The text was updated successfully, but these errors were encountered: