Impossible de sortir de derrière la référence mutable à l'option [duplicate]

Oct 14 2020

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

2 prog-fh Oct 14 2020 at 14:16

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.