2017-02-09 15 views
0

私は数日前に錆コードを書き始めましたが、ちょうど借りチェッカーとの最初の遭遇がありました。理解している/していないと闘う錆借りチェッカー

#[derive(Clone, Eq, Debug, PartialEq)] 
pub struct Vm<'a> { 
    instructions: Rc<InstructionSequence>, 
    pc: usize, 
    stack: Vec<Value<'a>>, 
    frames: Vec<Frame<'a>>, 
} 

impl<'a> Vm<'a> { 
    pub fn run(&'a mut self) { 
     loop { 
      let instruction = self.instructions.get(self.pc).unwrap(); 

      match instruction { 
       &Instruction::Push(ref value) => { 
        let top_activation = &mut self.frames.last_mut().unwrap().activation; 
        self.stack.push(Vm::literal_to_value(value, top_activation)) 
       }, 

       _ =>() 
      }; 
     }; 
    } 
} 

full code here

錆は私に次のエラーを与える:

error[E0499]: cannot borrow `self.frames` as mutable more than once at a time 
    --> src/vm.rs:157:47 
    | 
157 |      let top_activation = &mut self.frames.last_mut().unwrap().activation; 
    |            ^^^^^^^^^^^ 
    |            | 
    |            second mutable borrow occurs here 
    |            first mutable borrow occurs here 
... 
181 |  } 
    |  - first borrow ends here 

error[E0499]: cannot borrow `self.frames` as mutable more than once at a time 
    --> src/vm.rs:157:47 
    | 
157 |      let top_activation = &mut self.frames.last_mut().unwrap().activation; 
    |            ^^^^^^^^^^^ 
    |            | 
    |            second mutable borrow occurs here 
    |            first mutable borrow occurs here 
... 
181 |  } 
    |  - first borrow ends here 

error: aborting due to 2 previous errors 

それが二回借りなっている理由私は理解していません。どうしたの?

+3

私は 'InstructionSequence'、' Value'、 'Frame'と' literal_to_value'の定義がなくても問題を再現できないので、MCVEが必要です...あなたの問題をRust Playgroundで分離し、そこにリンクがある質問。それとは別に、一般的には '&self'の' struct' *と*に同じ生涯を持たないべきです。それは非常に悪い考えであり、 'struct'がそれ自身のメンバへの参照を格納しようとするときにのみ起こります... [それは不可能です](http://stackoverflow.com/questions/26349778/how-cani-構造体としての兄弟という参照を提供する)。 –

+0

'&mut'の借りは、次のループの繰り返しまで参照が生きているので、しばしばそれ自身と衝突します。 –

答えて

1

スタックにプッシュする値は、self.framesに変更可能な借用を有効にします。 2回目のループの繰り返しでは、まだ借用は有効なので、self.framesにもう一度借りることはできません。あなたのコードを変更することができるように

Vm::literal_to_value

ではなく、不変の参照を取るために、アクティベーションオブジェクトへの変更可能な参照を必要としない:

runコンパイルを行いますが、その後、あなたのテストがコンパイルに失敗
match instruction { 
    &Instruction::Push(ref value) => { 
     let top_activation = &self.frames.last().unwrap().activation; 
     self.stack.push(Vm::literal_to_value(value, top_activation)) 
    }, 
    _ =>() 
}; 

pub fn run(&'a mut self) 

あなたはVmの寿命パラメータでselfの寿命をリンクしている:このシグネチャでためです。本来、selfのタイプは&'a mut Vm<'a>です。 は、そのフィールドの1つの中で変更可能な借用を維持しているとRustに伝えます。この場合、'aが2回発生します。これは不変の借りではなく、変更可能な借用です。したがってrunを呼び出すと、Vmオブジェクトは自身を「ロック」します。つまり、runに電話した後は、Vmで何もできません。結論はyou can't have a field in a struct that is a reference to a value that is owned by the same structです。

+0

これは何が起こっているのか、良い説明です、ありがとう!また、私のプログラムは、私がやろうとしていたような静的な寿命を許していないことも理解しました。アクティベーションを変更する必要があるので、私は 'Rc ' – gmalette

関連する問題