【发布时间】:2018-01-12 01:40:44
【问题描述】:
我有一个两种情况的枚举:
#[derive(Debug)]
pub enum Enum {
Str(String),
Fields { len: u32, opt: Option<String> },
}
use Enum::*;
我想就地更新我的枚举,具体取决于它的值。这首先有效:
pub fn update(x: &mut Enum) {
match x {
&mut Str(ref mut s) => { s.push('k'); }
&mut Fields { ref mut len, ref mut opt } => { *len += 1; }
}
}
在某些情况下我想切换枚举类型:
pub fn update(x: &mut Enum) {
match x {
&mut Str(ref mut s) => { s.push('k'); }
&mut Fields { ref mut len, ref mut opt } => {
if *len < 5 {
*x = Str(String::from("default"));
} else {
*len += 1;
}
}
}
}
现在借用检查器很不高兴:
error[E0506]: cannot assign to `*x` because it is borrowed
--> src/main.rs:14:15
|
12 | &mut Fields { ref mut len, ref mut opt } => {
| ----------- borrow of `*x` occurs here
13 | if *len < 5 {
14 | *x = Str(String::from("default"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `*x` occurs here
在这种情况下,我们可以通过分配一个临时变量来解决这个问题:
pub fn update(x: &mut Enum) {
let mut update_hack: Option<Enum> = None;
match x {
&mut Str(ref mut s) => { s.push('k'); }
&mut Fields { ref mut len, ref mut opt } => {
if *len < 5 {
update_hack = Some(Str(String::from("default")));
} else {
*len += 1;
}
}
}
match update_hack {
None => {},
Some(to_return) => { *x = to_return; },
}
}
但我想使用我在update_hack 中的一些数据。
match x {
&mut Str(ref mut s) => { s.push('k'); }
&mut Fields { ref mut len, ref mut opt } => {
match opt {
&mut Some(ref s) => { update_hack = Some(Str(*s)) },
&mut None => { *len += 1 },
}
}
}
现在我们遇到了更严重的麻烦:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:16:62
|
16 | &mut Some(ref s) => { update_hack = Some(Str(*s)) },
| ^^ cannot move out of borrowed content
这次我不知道如何解决这个问题。当应该有一个干净的方法时,感觉就像我们正在堆积黑客。什么是惯用的解决方案?
【问题讨论】:
-
您的情况是否可以使用比赛后卫? play.rust-lang.org/…
-
这是个好主意。我的实际代码有几个分支,其中一些使用子字段,因此它不容易适用于该解决方案。不过也许是可能的。
标签: rust borrow-checker