rust match in match: "spurious" 简单枚举的非详尽错误:如何 "propagate" 枚举变量类型知识?
rust match in match: "spurious" non exhaustive error on simple enums: how to "propagate" the enum variable-kind knowledge?
我遇到了一个有趣的虚假“比赛中的比赛”非详尽生锈错误。做个简单的小例子(当然生产案例更有意思):
pub enum SomeEnum {
Possibility1,
Possibility2,
Possibility3
}
pub fn do_something(some: &SomeEnum){
match some {
SomeEnum::Possibility1 => println!("this is possibility 1"),
something_else => {
println!("this is not possibility 1");
match something_else {
SomeEnum::Possibility2 => println!("but this is 2"),
SomeEnum::Possibility3 => println!("but this is 3")
}
}
}
}
编译不通过,报错:
error[E0004]: non-exhaustive patterns: `&Possibility1` not covered
--> src/main.rs:13:19
|
1 | / pub enum SomeEnum {
2 | | Possibility1,
| | ------------ not covered
3 | | Possibility2,
4 | | Possibility3
5 | | }
| |_- `SomeEnum` defined here
...
13 | match something_else {
| ^^^^^^^^^^^^^^ pattern `&Possibility1` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
= note: the matched value is of type `&SomeEnum`
我理解这个错误,我知道如何“粗暴地”修复它(类似于 添加一个:
_ => unreachable!();
例如分支)。
不过,我觉得这很可悲:编译器足够聪明,在第一次匹配时就知道 something_else
是 Possibility2
或 Possibility3
类型,而折腾把这些知识写下来?
因此我的问题是:是否有一种简单、惯用的方法可以强制 Rust 将这种知识从外部匹配“传播”到内部匹配,这样我就可以在不粗暴地匹配所有输入的情况下抑制错误?同样,在这个简单的例子中,_
匹配看起来很简单,但在一些更复杂的代码中,我希望编译器帮助我检查我的逻辑是否正确,这不符合使用 _
匹配所有过滤器。
Still, I feel this is very sad: the compiler is smart enough at the first match to know that the something_else is either of kind Possibility2 or Possibility3
不是,真的。从语义上讲,它只是一个接一个地尝试每个匹配臂,然后取第一个。
My question is therefore: is there a simple, idiomatic way to force rust to "propagate" this kind knowledge from the outer match to the inner match
没有。 rustc 在类型级别(主要)的原因,就其而言 something_else
是一个 SomeEnum
,而 SomeEnum
有一个 SomeEnum::Possibility1
。如果你想要一个子枚举,你必须提供一个。
如果 RFC 2593 Enum Variant Types(或像 OCaml 风格的多态变体这样的替代方案)再次被提交 并被接受 ,并实施。但除此之外,您必须在您的枚举上“手动”实现它。
我所说的“手工完成”是指将您想要的语义手动编码为附加枚举,例如
pub enum SomeEnum {
Possibility1,
Possibility2,
Possibility3
}
enum IsOne { One, Other(Sub23) }
enum Sub23 {
Sub2,
Sub3
}
impl SomeEnum {
fn is_one(&self) -> IsOne {
match self {
Self::Possibility1 => IsOne::One,
Self::Possibility2 => IsOne::Other(Sub23::Sub2),
Self::Possibility3 => IsOne::Other(Sub23::Sub3),
}
}
}
pub fn do_something(some: &SomeEnum){
match some.is_one() {
IsOne::One => println!("this is possibility 1"),
IsOne::Other(sub) => {
println!("this is not possibility 1");
match sub {
Sub23::Sub2 => println!("but this is 2"),
Sub23::Sub3 => println!("but this is 3")
}
}
}
}
我遇到了一个有趣的虚假“比赛中的比赛”非详尽生锈错误。做个简单的小例子(当然生产案例更有意思):
pub enum SomeEnum {
Possibility1,
Possibility2,
Possibility3
}
pub fn do_something(some: &SomeEnum){
match some {
SomeEnum::Possibility1 => println!("this is possibility 1"),
something_else => {
println!("this is not possibility 1");
match something_else {
SomeEnum::Possibility2 => println!("but this is 2"),
SomeEnum::Possibility3 => println!("but this is 3")
}
}
}
}
编译不通过,报错:
error[E0004]: non-exhaustive patterns: `&Possibility1` not covered
--> src/main.rs:13:19
|
1 | / pub enum SomeEnum {
2 | | Possibility1,
| | ------------ not covered
3 | | Possibility2,
4 | | Possibility3
5 | | }
| |_- `SomeEnum` defined here
...
13 | match something_else {
| ^^^^^^^^^^^^^^ pattern `&Possibility1` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
= note: the matched value is of type `&SomeEnum`
我理解这个错误,我知道如何“粗暴地”修复它(类似于
_ => unreachable!();
例如分支)。
不过,我觉得这很可悲:编译器足够聪明,在第一次匹配时就知道 something_else
是 Possibility2
或 Possibility3
类型,而折腾把这些知识写下来?
因此我的问题是:是否有一种简单、惯用的方法可以强制 Rust 将这种知识从外部匹配“传播”到内部匹配,这样我就可以在不粗暴地匹配所有输入的情况下抑制错误?同样,在这个简单的例子中,_
匹配看起来很简单,但在一些更复杂的代码中,我希望编译器帮助我检查我的逻辑是否正确,这不符合使用 _
匹配所有过滤器。
Still, I feel this is very sad: the compiler is smart enough at the first match to know that the something_else is either of kind Possibility2 or Possibility3
不是,真的。从语义上讲,它只是一个接一个地尝试每个匹配臂,然后取第一个。
My question is therefore: is there a simple, idiomatic way to force rust to "propagate" this kind knowledge from the outer match to the inner match
没有。 rustc 在类型级别(主要)的原因,就其而言 something_else
是一个 SomeEnum
,而 SomeEnum
有一个 SomeEnum::Possibility1
。如果你想要一个子枚举,你必须提供一个。
如果 RFC 2593 Enum Variant Types(或像 OCaml 风格的多态变体这样的替代方案)再次被提交 并被接受 ,并实施。但除此之外,您必须在您的枚举上“手动”实现它。
我所说的“手工完成”是指将您想要的语义手动编码为附加枚举,例如
pub enum SomeEnum {
Possibility1,
Possibility2,
Possibility3
}
enum IsOne { One, Other(Sub23) }
enum Sub23 {
Sub2,
Sub3
}
impl SomeEnum {
fn is_one(&self) -> IsOne {
match self {
Self::Possibility1 => IsOne::One,
Self::Possibility2 => IsOne::Other(Sub23::Sub2),
Self::Possibility3 => IsOne::Other(Sub23::Sub3),
}
}
}
pub fn do_something(some: &SomeEnum){
match some.is_one() {
IsOne::One => println!("this is possibility 1"),
IsOne::Other(sub) => {
println!("this is not possibility 1");
match sub {
Sub23::Sub2 => println!("but this is 2"),
Sub23::Sub3 => println!("but this is 3")
}
}
}
}