此示例无法编译:
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
,但也失败了。
答案 0 :(得分:7)
根据引入枚举命名空间的RFC 390,这个推理被认为是一个黑客,并没有更好的设计。来自RFC的替代部分:
我们可以在1.0之后通过添加&#34; fallback&#34;来实现枚举命名空间。需要解决的案例,其变体可以从他们的&#34; flat&#34;定义位置,如果该命名空间中没有其他定义冲突。在保持向后兼容性的黑客计划中,这并不是那么糟糕,但仍然明显比不必担心回退更糟糕。
在RFC 390之后没有考虑推理的官方原因是,没有人真正关心提出更改:
@netvl Java是一个有趣的案例,你只能参考&#34;裸&#34;中的变体。
FOO
语句中的表单(MyEnum.FOO
,而不是switch
)。 Rust中的情况有点复杂,因为match
允许比传统的switch
语句更强大的模式匹配。最接近的模拟可能是隐含地处理在模式中导入的所有相关内容。这似乎与此提案足够正确,它可能值得拥有自己的RFC。
(从那时起,没有人为此编写过RFC。)
但是,这样一个RFC通过的可能性很小。毕竟,您只需要在某处添加一行use nix::sys::socket::SockAddr::*
即可使其正常工作。在语言中添加一个特性需要考虑正确的规范和极端情况(例如当你use nix::sys::socket::SockAddr::Unix as Inet
时会发生什么)它可能不值得花时间。