[英]Why can't enum variants be inferred in match arms?
此示例无法编译:
extern crate nix;
use std::os::unix::io::RawFd;
fn func(fd: RawFd, buf: &mut [u8]) -> Result<(), nix::Error> {
let (size, nix_addr) = nix::sys::socket::recvfrom(
fd, buf
)?;
let addr = match nix_addr {
//nix::sys::socket::SockAddr::Inet(addr) => addr.to_std(),
Inet(addr) => addr.to_std(),
_ => panic!(),
};
Ok(())
}
fn main() {}
此版本中的错误是:
error[E0531]: unresolved tuple struct/variant `Inet`
--> match_arms.rs:14:3
|
14 | Inet(addr) => addr.to_std(),
| ^^^^
交换注释掉的Inet
线成功编译。
编译器似乎要求我指定枚举类型本身,我想它知道我在match
臂中指定的变体是合法的。 但为什么? 不能推断出枚举吗? 编译器是否有足够的信息来实现nix_addr
是一个nix::…::SocketAddr
,因此, Inet
是一个有效的变量(和一个有数据的变量)?
我为什么要出去键入整个事情,或拖动名称与一个当前范围use
?
我也试过_::Inet
,也失败了。
根据引入枚举命名空间的RFC 390 ,这个推理被认为是一个黑客,并没有更好的设计。 从RFC的替代部分:
我们可以在1.0之后通过添加“回退”案例来实现枚举命名空间,如果没有其他定义在该命名空间中发生冲突,则可以从其“平面”定义位置引用变体。 在保持向后兼容性的黑客计划中,这并不是那么糟糕, 但仍然比不必担心后备更糟糕。
在RFC 390之后没有考虑推理的官方原因是没有人真正关心提出改变:
@netvl Java是一个有趣的案例,你只能在
switch
语句中引用“裸”形式的变体(FOO
,而不是MyEnum.FOO
)。 Rust的情况有点复杂,因为match
允许比传统的switch
语句更强大的模式匹配。 最接近的模拟可能是隐含地处理在模式中导入的所有相关内容。 这似乎与这个提议足够正确, 它可能值得拥有自己的RFC。
(从那时起,没有人为此编写过RFC。)
但是,这样一个RFC通过的机会很小。 毕竟,你只需要在某处添加一行use nix::sys::socket::SockAddr::*
来使其工作。 在语言中添加一个特性需要考虑正确的规范和use nix::sys::socket::SockAddr::Unix as Inet
情况(例如,当你use nix::sys::socket::SockAddr::Unix as Inet
时会发生什么)它可能不值得花时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.