问题描述
考虑以下片段:
use std::fmt;
enum TestEnum {
StructMem {value: i32,is_valid: bool},RandoMem,}
impl fmt::display for TestEnum {
fn fmt(&self,f: &mut fmt::Formatter<'_>) -> fmt::Result {
use TestEnum::*;
match self {
StructMem {value,is_valid} => {
if *is_valid { // Why dereference is_valid ?
write!(f,"f")?
}
write!(f,"{:?}",value)
}
RandoMem => {
f.write_str("Random")
}
}
}
}
为什么我需要在 is_valid
语句中取消引用 if
?
编辑:这个问题 What is the syntax to match on a reference to an enum? 似乎在处理类似的情况,但答案都集中在解决特定问题(不涉及结构)上,而不是解释所有权/绑定语义。
解决方法
这不是特定于 match
或 enum
而是由于 fmt()
的签名,它将 self
作为参考(&self
代替self
,如果所有权已被取得)。
因此,match self
已经引用了 TestEnum
的借用实例,并且匹配臂 StructMem {value,is_valid}
通过引用(&i32
和 &bool
)。这就是为什么 is_valid
最终成为 &bool
而不是 bool
。
当您对引用进行模式匹配并对其进行解构时,您只能获得内部成员的引用,否则您会将内部成员从不可变的引用中移出,这将违反 Rust 的所有权规则。这是一个更简单的例子:
struct Container(Vec<i32>);
fn get_inner_vec(c: &Container) -> &Vec<i32> {
// v MUST BE a reference
// otherwise this destructing would somehow be moving the Vec
// outside of an immutable borrow of Container
let Container(v) = c;
v
}