rust - 如何对包含 &mut 枚举的元组进行模式匹配并在匹配臂中使用该枚举?
问题描述
如何编译下面的代码?它看起来非常安全,但无法说服编译器它是安全的。
版本匹配*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
,因此不允许使用此代码。
相反,在语句中可变地重新借用 并让它返回元组的第一个值。由于此值没有对 的引用,因此您可以返回以下结果:self
match
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),
}
}
}
也可以看看:
推荐阅读
- python - 获取用户输入的方程
- typescript - 使用 @nestjs/mongoose 时,如何将实例/静态方法添加到 Mongoose 模式?(打字稿问题)
- sql - 如果其中一项与 where 不匹配,则返回空的递归 mysql
- angularjs - 如何添加电子商务?
- python - Tensorflow 数据增强 - 如何将新图像添加到数据集中
- azure - Azure 默认 NSG 不阻止 Internet 流量
- wordpress - 如何使用 WP_Query 按多个元键排序?
- r - 计算分箱数据的相对百分比
- sql - 仅当第一个不存在时,如何在一个列中搜索一个值并在另一列中搜索相同的值?
- react-native - Agora React-native 功能组件实现