-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Description
The following code compiles on nightly (playground):
#![feature(exhaustive_patterns, never_type)]
enum Either<A, B> {
A(A),
B(Wrapper<B>),
}
struct Wrapper<T>(T);
fn foo() -> Either<(), !> {
Either::A(())
}
fn main() {
let Either::A(()) = foo();
}But if the wrapper type is moved into a module to make the field private, then it does not: (playground):
#![feature(exhaustive_patterns, never_type)]
mod inner {
pub struct Wrapper<T>(T);
}
enum Either<A, B> {
A(A),
B(inner::Wrapper<B>),
}
fn foo() -> Either<(), !> {
Either::A(())
}
fn main() {
let Either::A(()) = foo();
}error[E0005]: refutable pattern in local binding: `Either::B(_)` not covered
--> src/main.rs:17:9
|
17 | let Either::A(()) = foo();
| ^^^^^^^^^^^^^ pattern `Either::B(_)` 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: `Either<(), !>` defined here
--> src/main.rs:9:5
|
7 | enum Either<A, B> {
| ------
8 | A(A),
9 | B(inner::Wrapper<B>),
| ^ not covered
= note: the matched value is of type `Either<(), !>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
17 | if let Either::A(()) = foo() { todo!() }
| ++ ~~~~~~~~~~~
Making the field pub makes it compile again.
Is this expected? I suppose I could understand if it is; the private fields could change to make Wrapper<!> actually be constructable and therefore make the pattern refutable. But if that's the case, then I think the compiler should point this out, like note: the pattern is currently irrefutable, but the type contains private fields which may change in the future to make the pattern refutable.
If indeed this is expected, is there any way for me as a library author to somehow convince the compiler that I will never change the fields to make the type constructable? I want users of my library to be able to elide match arms when I give them an Either<A, !>.
@rustbot label +T-compiler +F-never_type +D-confusing +requires-nightly +S-bug-has-mcve