У меня возникла проблема с выражением соответствия в моем коде, которое выдает предупреждение, когда включена защита. Я полагаю, что это предупреждение связано с нелексическими временами жизни, используемыми контролером заимствований. Моя функция возвращает непостоянную ссылку на элемент из коллекции или клон всей коллекции.
#[derive(Debug, Clone)]
enum Value {
Int(i32),
List(Vec<Value>),
}
#[derive(Debug)]
struct Error(&'static str, Value);
fn main() {
let mut value = Value::List(vec![
Value::Int(1),
Value::Int(2),
Value::Int(34),
Value::Int(12),
]);
let y = index_list(&mut value, 2);
let _ = dbg!(y);
}
fn index_list<'a>(value: &'a mut Value, idx: usize) -> Result<&'a mut Value, Error> {
match *value {
Value::List(ref mut list) if idx < list.len() => Ok(&mut list[idx]),
Value::List(_) => Err(Error("index out of range", value.clone())),
_ => Err(Error("tried to index int", value.clone())),
}
}
Он компилируется и запускается, но я получаю очень зловещее предупреждение:
warning[E0502]: cannot borrow `*value` as immutable because it is also borrowed as mutable
--> src/main.rs:25:59
|
22 | fn index_list<'a>(value: &'a mut Value, idx: usize) -> Result<&'a mut Value, Error> {
| -- lifetime `'a` defined here
23 | match *value {
24 | Value::List(ref mut list) if idx < list.len() => Ok(&mut list[idx]),
| ------------ ------------------ returning this value requires that `value.0` is borrowed for `'a`
| |
| mutable borrow occurs here
25 | Value::List(_) => Err(Error("index out of range", value.clone())),
| ^^^^^ immutable borrow occurs here
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
warning[E0502]: cannot borrow `*value` as immutable because it is also borrowed as mutable
--> src/main.rs:26:46
|
22 | fn index_list<'a>(value: &'a mut Value, idx: usize) -> Result<&'a mut Value, Error> {
| -- lifetime `'a` defined here
23 | match *value {
24 | Value::List(ref mut list) if idx < list.len() => Ok(&mut list[idx]),
| ------------ ------------------ returning this value requires that `value.0` is borrowed for `'a`
| |
| mutable borrow occurs here
25 | Value::List(_) => Err(Error("index out of range", value.clone())),
26 | _ => Err(Error("tried to index int", value.clone())),
| ^^^^^ immutable borrow occurs here
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
Я не понимаю, почему строка Err(value.clone())
требует, чтобы заем Ok(&mut ...)
все еще был активным, потому что они взаимоисключающие и оба приводят к возврату функции. Это предупреждение исчезнет, если я уберу охрану на первой руке спички, но мне нужен этот охранник, чтобы быть там. Это ошибка в системе NLL? У меня никогда не было этой проблемы со старым заемщиком. Как я могу сделать это лучше?