Reputation: 95
I was looking at the Rust reference book and it states that a tuple struct is "refutable when one of its subpatterns is refutable". It also states that identifier patterns are irrefutable when "the subpattern is not specified".
Given this, if I create a tuple struct pattern with a single irrefutable identifier subpattern, I would expect the tuple struct pattern to be irrefutable as well because its subpatterns are all irrefutable.
pub fn main() {
enum Foo {
Bar(i32),
Baz(i32),
}
// Compiler says Foo::Bar(x) is a refutable pattern
// but the reference book suggests it is irrefutable
let Foo::Bar(x) = Foo::Bar(50);
}
The AST of the code above confirms that the Foo::Bar(x)
is a tuple struct pattern and the x
is an identifier pattern. I feel that the compiler is correct here, but the reference book suggests the Foo::Bar(x)
is irrefutable despite the compiler.
I understand the need for blocking refutable patterns given the multiple possible enum variants and how an if let
or similar would help here but am confused by the contradicting quotes.
Is something going on here that I am missing, or is this an issue with the reference book?
Upvotes: 3
Views: 525
Reputation: 2907
The refutability section of the Reference appears underspecified for enums (you'll see there's also no information on struct variants of enum types). The missing piece here is that the enum variant name is also a subpattern, and in an enum with two or more constructible variants, it is refutable:
// refutable
// |
// | irrefutable (with respect to variant `Bar`)
// | |
let Foo::Bar(x) = Foo::Bar(50);
I would provide a reference, but unfortunately the refutability section appears underspecified for enums... (etc.)
Upvotes: 4
Reputation: 22728
The type of Foo::Bar(50)
is Foo
, just as the type of a 4
is i32
.
Look at this:
let 4 = 4;
error[E0005]: refutable pattern in local binding: `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered
--> src/main.rs:2:9
|
2 | let 4 = 4;
| ^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `i32`
This is refutable because the type of the 4
on the tright is i32
. The value is irrelevant for refutability. It's all about the type.
And let 4 = <i32>
is refutable, because <i32>
could be a value different than 4
.
I think refutability
only talks about types, not about values.
Of course I'm not a theoretical language expert, so I might be completely off. But that's my understanding of what refutability means.
Upvotes: 5