Add a rule that enum discriminants may not use generic parameters#2206
Add a rule that enum discriminants may not use generic parameters#2206ehuss wants to merge 1 commit intorust-lang:masterfrom
Conversation
This is implemented in the compiler with the diagnostic [`ParamInEnumDiscriminant`](https://github.com/rust-lang/rust/blob/3b1b0ef4d80d3117924d91352c8b6ca528708b3c/compiler/rustc_resolve/src/errors.rs#L651-L661) and [`NoConstantGenericsReason::IsEnumDiscriminant`](https://github.com/rust-lang/rust/blob/3b1b0ef4d80d3117924d91352c8b6ca528708b3c/compiler/rustc_resolve/src/late.rs#L160-L168).
| ``` | ||
|
|
||
| r[items.enum.discriminant.restrictions.generics] | ||
| Explicit enum discriminants may not use generic parameters from the enclosing enum. |
There was a problem hiding this comment.
from the enclosing enum.
What about from anywhere else? Playground says that you also can't use from an enclosing item either
fn demo<const N: u32>() {
enum Foo {
Bar = N,
}
}though it does also have an unhelpful suggestion to
help: try introducing a local generic parameter here
|
2 | enum Foo<N> {
| +++
which then leads to
- same "can't use generic parameters from outer item" error
- with a new suggestion
help: try introducing a local generic parameter here
|
2 | enum Foo<N, N> {
| ++
- and also an error
type parameter `N` is never used
I suggest
| Explicit enum discriminants may not use generic parameters from the enclosing enum. | |
| Explicit enum discriminants may not use generic parameters. |
There was a problem hiding this comment.
The restriction that generic parameters are not in scope within items in a function body is covered by items.generics.syntax.scope.
The reason it uses the "enclosing enum" terminology is because generic parameters defined within the enum discriminant initializer may be used, as in:
enum E {
V1 = {
const fn f<T>(x: T) -> T { x }
f::<isize>(123)
}
}I didn't want to risk potential confusion around that.
There was a problem hiding this comment.
But the actual discriminant of f::<isize>(123) is not based on any generic parameter, just the invocation of a constant function that happens to be generic, same as
const fn f<T>(x: T) -> T { x }
enum E {
V1 = {
f::<isize>(123)
}
}what about
Explicit enum discriminants may not use generic parameters. Note that they may still invoke generic functions.
or something like that?
This is implemented in the compiler with the diagnostic
ParamInEnumDiscriminantandNoConstantGenericsReason::IsEnumDiscriminant.