Skip to content
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

Rewrite E0158 error-code docs for clarity #105744

Merged
merged 1 commit into from
Dec 16, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 34 additions & 19 deletions compiler/rustc_error_codes/src/error_codes/E0158.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,53 @@
An associated const has been referenced in a pattern.
An associated `const`, `const` parameter or `static` has been referenced
in a pattern.

Erroneous code example:

```compile_fail,E0158
enum EFoo { A, B, C, D }
enum Foo {
One,
Two
}

trait Foo {
const X: EFoo;
trait Bar {
const X: Foo;
}

fn test<A: Foo>(arg: EFoo) {
fn test<A: Bar>(arg: Foo) {
match arg {
A::X => { // error!
println!("A::X");
}
A::X => println!("A::X"), // error: E0158: associated consts cannot be
// referenced in patterns
Foo::Two => println!("Two")
}
}
```

`const` and `static` mean different things. A `const` is a compile-time
constant, an alias for a literal value. This property means you can match it
directly within a pattern.
Associated `const`s cannot be referenced in patterns because it is impossible
for the compiler to prove exhaustiveness (that some pattern will always match).
Take the above example, because Rust does type checking in the *generic*
method, not the *monomorphized* specific instance. So because `Bar` could have
theoretically infinite implementations, there's no way to always be sure that
`A::X` is `Foo::One`. So this code must be rejected. Even if code can be
proven exhaustive by a programmer, the compiler cannot currently prove this.

The `static` keyword, on the other hand, guarantees a fixed location in memory.
This does not always mean that the value is constant. For example, a global
mutex can be declared `static` as well.
The same holds true of `const` parameters and `static`s.

If you want to match against a `static`, consider using a guard instead:
If you want to match against an associated `const`, `const` parameter or
`static` consider using a guard instead:

```
static FORTY_TWO: i32 = 42;
trait Trait {
const X: char;
}

static FOO: char = 'j';

match Some(42) {
Some(x) if x == FORTY_TWO => {}
_ => {}
fn test<A: Trait, const Y: char>(arg: char) {
match arg {
c if c == A::X => println!("A::X"),
c if c == Y => println!("Y"),
c if c == FOO => println!("FOO"),
_ => ()
}
}
```