Impossible de sortir de derrière la référence mutable à l'option [duplicate]
J'ai une structure:
struct Foo<'a> {
parent: Option<&'a mut Foo<'a>>,
value: i32,
}
impl<'a> Foo<'a> {
fn bar(&mut self) {
if let Some(&mut parent) = self.parent {
parent.bar();
} else {
self.value = 1;
}
}
}
Mais j'obtiens l'erreur:
error[E0507]: cannot move out of `*self.parent.0` which is behind a mutable reference
--> src/lib.rs:8:36
|
8 | if let Some(&mut parent) = self.parent {
| ------ ^^^^^^^^^^^ help: consider borrowing here: `&self.parent`
| |
| data moved here
| move occurs because `parent` has type `Foo<'_>`, which does not implement the `Copy` trait
error[E0596]: cannot borrow `parent` as mutable, as it is not declared as mutable
--> src/lib.rs:9:13
|
8 | if let Some(&mut parent) = self.parent {
| ------ help: consider changing this to be mutable: `mut parent`
9 | parent.bar();
| ^^^^^^ cannot borrow as mutable
J'ai essayé de nombreuses variantes de cette ligne et je n'arrive pas à la faire fonctionner. Comment puis-je faire ceci?
Réponses
Dans votre if letdéclaration, vous essayez de déstructurer self.parentpour obtenir parent, et même obtenir le Foo(lui-même, en tant que valeur) qui se trouve derrière la référence stockée.
Vous devez ajouter un niveau supplémentaire d'indirection pour référencer le &mut Fooqui peut exister ou non, sans le supprimer du Options'il existe.
if let Some(ref mut parent) = self.parent {
ou
if let Some(parent) = self.parent.as_mut() {
La parentliaison que vous obtenez dans les deux cas est de type &mut &'a mut Foo<'a>, donc le déréférencement automatique se produit lors de l'appel parent.bar().
nb: j'utilise comme rappel « refsur le côté gauche de =est similaire à &sur le côté droit », mais ici nous voulons ajouter l' & intérieur du Option, donc l'utilisation de .as_ref()ou en .as_mut()fonction de la mutabilité attendue.