2016-12-16 8 views
12

ここでは何が起こっていますか(playground)?関数の引数でも変更可能として借用されているため、不変として借用することはできません。

struct Number { 
    num: i32 
} 

impl Number { 
    fn set(&mut self, new_num: i32) { 
     self.num = new_num; 
    } 
    fn get(&self) -> i32 { 
     self.num 
    } 
} 

fn main() { 
    let mut n = Number{ num: 0 }; 
    n.set(n.get() + 1); 
} 

は、このエラーを与える:

error[E0502]: cannot borrow `n` as immutable because it is also borrowed as mutable 
    --> <anon>:17:11 
    | 
17 |  n.set(n.get() + 1); 
    |  - ^  - mutable borrow ends here 
    |  |  | 
    |  |  immutable borrow occurs here 
    |  mutable borrow occurs here 

は、しかし、あなたは、単にそれが動作これまでコード変更する場合:私のものに

fn main() { 
    let mut n = Number{ num: 0 }; 
    let tmp = n.get() + 1; 
    n.set(tmp); 
} 

をまったく同じに見える - 私は意味、私が期待します前者は編集時に後者に変換される。次のレベルアップ関数呼び出しを評価する前に、すべての関数パラメータを評価していませんか?

+0

借用確認プロセスの詳細については、こちらをご覧ください(https://github.com/rust-lang/rust/tree/master/src/librustc_borrowck/borrowck)。 – ljedrz

+1

回避策として[unborrow macro](https://github.com/durka/unborrow)があり、[reddit](https://www.reddit.com/r/rust/comments/575tc7)に関するディスカッションがあります。/why_does_rust_not_allow_disjoint_mutable_borrows /) – wimh

+0

ああ、ありがとうwimh! – Timmmm

答えて

11

このライン:

n.set(n.get() + 1); 

Number::set(&mut n, n.get() + 1); 

に脱糖されたエラーメッセージは、今もう少し明確にするかもしれません:

error[E0502]: cannot borrow `n` as immutable because it is also borrowed as mutable 
    --> <anon>:18:25 
    | 
18 |  Number::set(&mut n, n.get() + 1); 
    |      -^  - mutable borrow ends here 
    |      | | 
    |      | immutable borrow occurs here 
    |      mutable borrow occurs here 

錆が左から右へ引数を評価として、そのコードは次のようになります。

let arg1 = &mut n; 
let arg2 = n.get() + 1; 
Number::set(arg1, arg2); 

何が間違っているのは明らかです。最初の2行をスワップしてこれを修正しますが、Rustはそのような制御フロー解析を行いません。

これはbug #6268として最初に作成されました。現在はRFC 811に統合されています。

1.25.0夜間2018-01-13以降は、possible to use non-lexical lifetimesです。夜間の錆にあなたの例を実行し、#![feature(nll)]を使用してNLL機能ゲートを有効にする場合は、それはwill now compile without an errorです。

関連する問題