为什么我不能在模式匹配时使用常量,即使它实现了 PartialEq 和 Eq?
Why cant I use a constant when pattern matching even though it implements PartialEq and Eq?
我想在模式匹配时使用常量net::Ipv4Addr::LOCALHOST
过滤掉IPv4本地主机地址:
use get_if_addrs; // 0.5.3
use std::net;
fn main() -> std::io::Result<()> {
assert_eq!(
"127.0.0.1".parse::<net::Ipv4Addr>().unwrap(),
net::Ipv4Addr::LOCALHOST
);
{
let ifaces = get_if_addrs::get_if_addrs().unwrap();
for iface in ifaces {
match iface.addr {
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr {
ip: _,
netmask: _,
broadcast: None,
}) => (),
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr {
ip: net::Ipv4Addr::LOCALHOST,
netmask: _,
broadcast: _,
}) => (),
get_if_addrs::IfAddr::V4(addr) => println!("{:?}", addr),
get_if_addrs::IfAddr::V6(_) => (),
}
}
}
Ok(())
}
我收到一个错误
error: to use a constant of type `std::net::Ipv4Addr` in a pattern, `std::net::Ipv4Addr` must be annotated with `#[derive(PartialEq, Eq)]`
--> src/main.rs:19:25
|
19 | ip: net::Ipv4Addr::LOCALHOST,
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unreachable pattern
--> src/main.rs:23:17
|
23 | get_if_addrs::IfAddr::V4(addr) => println!("{:?}", addr),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unreachable_patterns)] on by default
std::net::Ipv4Addr
确实有 PartialEq
和 Eq
的实现,那么这个错误是什么意思?我该如何解决?
如错误消息所述:
must be annotated with #[derive(PartialEq, Eq)]
这是not true for Ipv4Addr
,手动实现,而不是派生。
相反,使用 比赛守卫:
use get_if_addrs; // 0.5.3
fn main() -> std::io::Result<()> {
let ifaces = get_if_addrs::get_if_addrs().unwrap();
for iface in ifaces {
match iface.addr {
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr {
broadcast: None, ..
}) => (),
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr { ip, .. }) if ip.is_loopback() => (),
get_if_addrs::IfAddr::V4(addr) => println!("{:?}", addr),
get_if_addrs::IfAddr::V6(_) => (),
}
}
Ok(())
}
你也可以考虑引入一些嵌套:
use get_if_addrs::{IfAddr, Ifv4Addr}; // 0.5.3
fn main() -> std::io::Result<()> {
let ifaces = get_if_addrs::get_if_addrs().unwrap();
for iface in ifaces {
match iface.addr {
IfAddr::V4(addr) => match addr {
Ifv4Addr {
broadcast: None, ..
} => (),
Ifv4Addr { ip, .. } if ip.is_loopback() => (),
addr => println!("{:?}", addr),
},
IfAddr::V6(_) => (),
}
}
Ok(())
}
RFC 1445 进一步解释了基本决策:
- Introduce a feature-gated attribute
#[structural_match]
which can be applied to a struct or enum T
to indicate that constants of type T
can be used within patterns.
- Have
#[derive(Eq)]
automatically apply this attribute to the struct or enum that it decorates. Automatically inserted attributes do
not require use of feature-gate.
- When expanding constants of struct or enum type into equivalent patterns, require that the struct or enum type is decorated with
#[structural_match]
. Constants of builtin types are always expanded.
The practical effect of these changes will be to prevent the use of
constants in patterns unless the type of those constants is either a
built-in type (like i32
or &str
) or a user-defined constant for which
Eq
is derived (not merely implemented).
我想在模式匹配时使用常量net::Ipv4Addr::LOCALHOST
过滤掉IPv4本地主机地址:
use get_if_addrs; // 0.5.3
use std::net;
fn main() -> std::io::Result<()> {
assert_eq!(
"127.0.0.1".parse::<net::Ipv4Addr>().unwrap(),
net::Ipv4Addr::LOCALHOST
);
{
let ifaces = get_if_addrs::get_if_addrs().unwrap();
for iface in ifaces {
match iface.addr {
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr {
ip: _,
netmask: _,
broadcast: None,
}) => (),
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr {
ip: net::Ipv4Addr::LOCALHOST,
netmask: _,
broadcast: _,
}) => (),
get_if_addrs::IfAddr::V4(addr) => println!("{:?}", addr),
get_if_addrs::IfAddr::V6(_) => (),
}
}
}
Ok(())
}
我收到一个错误
error: to use a constant of type `std::net::Ipv4Addr` in a pattern, `std::net::Ipv4Addr` must be annotated with `#[derive(PartialEq, Eq)]`
--> src/main.rs:19:25
|
19 | ip: net::Ipv4Addr::LOCALHOST,
| ^^^^^^^^^^^^^^^^^^^^^^^^
warning: unreachable pattern
--> src/main.rs:23:17
|
23 | get_if_addrs::IfAddr::V4(addr) => println!("{:?}", addr),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unreachable_patterns)] on by default
std::net::Ipv4Addr
确实有 PartialEq
和 Eq
的实现,那么这个错误是什么意思?我该如何解决?
如错误消息所述:
must be annotated with
#[derive(PartialEq, Eq)]
这是not true for Ipv4Addr
,手动实现,而不是派生。
相反,使用 比赛守卫:
use get_if_addrs; // 0.5.3
fn main() -> std::io::Result<()> {
let ifaces = get_if_addrs::get_if_addrs().unwrap();
for iface in ifaces {
match iface.addr {
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr {
broadcast: None, ..
}) => (),
get_if_addrs::IfAddr::V4(get_if_addrs::Ifv4Addr { ip, .. }) if ip.is_loopback() => (),
get_if_addrs::IfAddr::V4(addr) => println!("{:?}", addr),
get_if_addrs::IfAddr::V6(_) => (),
}
}
Ok(())
}
你也可以考虑引入一些嵌套:
use get_if_addrs::{IfAddr, Ifv4Addr}; // 0.5.3
fn main() -> std::io::Result<()> {
let ifaces = get_if_addrs::get_if_addrs().unwrap();
for iface in ifaces {
match iface.addr {
IfAddr::V4(addr) => match addr {
Ifv4Addr {
broadcast: None, ..
} => (),
Ifv4Addr { ip, .. } if ip.is_loopback() => (),
addr => println!("{:?}", addr),
},
IfAddr::V6(_) => (),
}
}
Ok(())
}
RFC 1445 进一步解释了基本决策:
- Introduce a feature-gated attribute
#[structural_match]
which can be applied to a struct or enumT
to indicate that constants of typeT
can be used within patterns.- Have
#[derive(Eq)]
automatically apply this attribute to the struct or enum that it decorates. Automatically inserted attributes do not require use of feature-gate.- When expanding constants of struct or enum type into equivalent patterns, require that the struct or enum type is decorated with
#[structural_match]
. Constants of builtin types are always expanded.The practical effect of these changes will be to prevent the use of constants in patterns unless the type of those constants is either a built-in type (like
i32
or&str
) or a user-defined constant for whichEq
is derived (not merely implemented).