gpt4 book ai didi

rust - 如何模式匹配包含 &mut 枚举的元组并在匹配臂中使用枚举?

转载 作者:行者123 更新时间:2023-11-29 08:26:52 25 4
gpt4 key购买 nike

下面的代码如何编译?它看起来非常安全,但无法让编译器相信它是安全的。

匹配*self的版本报错:cannot move out of borrowed content on the line of the match

匹配 self 的版本给出:use of moved value: *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)
}
error[E0532]: expected unit struct/variant or constant, found tuple variant `Foo::Foo1`
--> src/main.rs:24:30
|
24 | (ref mut f @ Foo::Foo1, b) if (b == 5) => {
| ^^^^^^^^^ not a unit struct/variant or constant

最佳答案

不,这不安全。您正试图在匹配臂中引入可变别名。可变引用 a 指向与 self 相同的值。可以更改 self(例如 *self = Foo::Foo1(99)),这将使 a 无效,因此此代码是不允许的。

相反,可变地重新借用 selfmatch 语句中并让它返回元组的第一个值。由于此值没有对 self 的引用,因此您可以使用 match 的结果返回 self:

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,
}
}
}

I would still say it is a safe operation, although the compiler may not be able to understand that

non-lexical lifetimes ,借用检查器变得更加智能。添加显式重新借用的原始代码编译:

#![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),
}
}
}

另见:

关于rust - 如何模式匹配包含 &mut 枚举的元组并在匹配臂中使用枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51329458/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com