Rust 如何匹配包含&;的元组;mut enum并在匹配臂中使用该enum?
如何编译下面的代码?它看起来非常安全,但无法让编译器相信它是安全的 与Rust 如何匹配包含&;的元组;mut enum并在匹配臂中使用该enum?,rust,pattern-matching,borrow-checker,Rust,Pattern Matching,Borrow Checker,如何编译下面的代码?它看起来非常安全,但无法让编译器相信它是安全的 与*self匹配的版本出现错误:无法移出匹配行上的借用内容 与self匹配的版本给出:移动值的使用:*self enum Foo { Foo1(u32), Foo2(i16), } impl Foo { fn bar(&mut self, y: u32) -> (u32, &mut Foo) { match (*self, y) { (Foo
*self
匹配的版本出现错误:无法移出匹配行上的借用内容
与self
匹配的版本给出:移动值的使用:*self
enum Foo {
Foo1(u32),
Foo2(i16),
}
impl Foo {
fn bar(&mut self, y: u32) -> (u32, &mut Foo) {
match (*self, y) {
(Foo::Foo1(ref mut a), b) if (b == 5) => {
print!("is five");
*a = b + 42;
(b, self)
}
(Foo::Foo2(ref mut a), b) if (b == 5) => {
print!("is five");
*a = (b + 42) as i16;
(*a * b, self)
}
_ => {
print!("is not five!");
(y, self)
}
}
}
}
我觉得我需要一个匹配臂,如下所示,但它似乎不是有效的语法:
(ref mut f @ Foo::Foo1, b) if (b == 5) => {
print!("is five");
f.0 = b + 42;
(b, f)
}
错误[E0532]:应为单元结构/变量或常量,找到元组变量`Foo::Foo1`
-->src/main.rs:24:30
|
如果(b==5)=>{
|^^^^^^^^^^^^^^不是单位结构/变量或常量
不,这不安全。您正试图在匹配臂内引入可变别名。可变引用a
指向与self
相同的值。可以更改self
(例如*self=Foo::Foo1(99)
)这将使a
无效,因此不允许使用此代码
相反,在match
语句中可变地重新箭头self
,并让它返回元组的第一个值。由于此值没有对self
的引用,因此您可以返回self
以及match
的结果:
enum Foo {
Foo1(u32),
Foo2(u32), // changed so I don't have to figure out what casting you meant
}
impl Foo {
fn bar(&mut self, y: u32) -> (u32, &mut Foo) {
let next = match (&mut *self, y) {
(Foo::Foo1(a), b @ 5) => {
*a = b + 42;
b
}
(Foo::Foo2(a), b @ 5) => {
*a = b + 42;
*a * b
}
_ => y,
};
(next, self)
}
}
但是,像这样返回self
在这里是毫无意义的。调用者已经有一个&mut Foo
,因此您不需要“返回”。这允许简化为:
impl Foo {
fn bar(&mut self, y: u32) -> u32 {
match (self, y) {
(Foo::Foo1(a), b @ 5) => {
*a = b + 42;
b
}
(Foo::Foo2(a), b @ 5) => {
*a = b + 42;
*a * b
}
_ => y,
}
}
}
我仍然认为这是一个安全的操作,尽管编译器可能无法理解这一点
使用,借阅检查器变得更加智能。添加了显式重新借阅的原始代码将编译:
#![feature(nll)]
enum Foo {
Foo1(u32),
Foo2(u32), // changed so I don't have to figure out what casting you meant
}
impl Foo {
fn bar(&mut self, y: u32) -> (u32, &mut Foo) {
match (&mut *self, y) {
(Foo::Foo1(a), b @ 5) => {
*a = b + 42;
(b, self)
}
(Foo::Foo2(a), b @ 5) => {
*a = b + 42;
(*a * b, self)
}
_ => (y, self),
}
}
}
另见:
不,这不安全。您正试图在匹配臂内引入可变别名。可变引用
a
指向与self
相同的值。可以更改self
(例如*self=Foo::Foo1(99)
)这将使a
无效,因此不允许使用此代码
相反,在match
语句中可变地重新箭头self
,并让它返回元组的第一个值。由于此值没有对self
的引用,因此您可以返回self
以及match
的结果:
enum Foo {
Foo1(u32),
Foo2(u32), // changed so I don't have to figure out what casting you meant
}
impl Foo {
fn bar(&mut self, y: u32) -> (u32, &mut Foo) {
let next = match (&mut *self, y) {
(Foo::Foo1(a), b @ 5) => {
*a = b + 42;
b
}
(Foo::Foo2(a), b @ 5) => {
*a = b + 42;
*a * b
}
_ => y,
};
(next, self)
}
}
但是,像这样返回self
在这里是毫无意义的。调用者已经有一个&mut Foo
,因此您不需要“返回”。这允许简化为:
impl Foo {
fn bar(&mut self, y: u32) -> u32 {
match (self, y) {
(Foo::Foo1(a), b @ 5) => {
*a = b + 42;
b
}
(Foo::Foo2(a), b @ 5) => {
*a = b + 42;
*a * b
}
_ => y,
}
}
}
我仍然认为这是一个安全的操作,尽管编译器可能无法理解这一点
使用,借阅检查器变得更加智能。添加了显式重新借阅的原始代码将编译:
#![feature(nll)]
enum Foo {
Foo1(u32),
Foo2(u32), // changed so I don't have to figure out what casting you meant
}
impl Foo {
fn bar(&mut self, y: u32) -> (u32, &mut Foo) {
match (&mut *self, y) {
(Foo::Foo1(a), b @ 5) => {
*a = b + 42;
(b, self)
}
(Foo::Foo2(a), b @ 5) => {
*a = b + 42;
(*a * b, self)
}
_ => (y, self),
}
}
}
另见: