2017-07-22 6 views
4

以下の2つの関数try_drain_*が同じ動作をするとは思っていませんが、2番目が問題なく実行されても最初のコンパイルは失敗します。なぜ借用チェッカーはインライン式を拒否しますが、分割フォームを受け入れますか?

struct Container { 
    map: RefCell<HashMap<i32, i32>>, 
} 

impl Container { 
    fn try_drain_inline(&self) { 
     self.map.borrow_mut().drain(); 
    } 

    fn try_drain_broken_down(&self) { 
     let mut guard = self.map.borrow_mut(); 
     guard.drain(); 
    } 
} 

ボローチェッカーを約try_drain_inlineon the playgroundを文句:

error[E0597]: borrowed value does not live long enough 
    --> src/main.rs:15:5 
    | 
14 |   self.map.borrow_mut().drain(); 
    |   ---------------------  ^temporary value dropped here while still borrowed 
    |   | 
    |   temporary value created here 
    | 
    = note: values in a scope are dropped in the opposite order they are created 

それはtry_drain_broken_downと罰金であるのに対し。

作成した一時的なデータが破棄される順序に問題があるようです。一時的なものを「手動で」実体化することで、状況が改善されます。

なぜ、借用チェッカーがインラインフォームを拒否し、崩壊したものを受け入れるのですか?


注:インラインバージョンは、次のコードと同等ですので

fn try_pop(&self) -> Option<i32> { 
    let mut guard = self.map.borrow_mut(); 
    let mut drain = guard.drain(); 
    drain.next().map(|(_, t)| t) 
} 
+1

おそらく関連しています:https://stackoverflow.com/questions/43590162/when-returning-the-outcome-of-consuming-a-stdinlock-why-was-the-borrow-to-stdin; https://github.com/rust-lang/rust/issues/21114 –

+0

これはおそらくこれに関連します:http://smallcultfollowing.com/babysteps/blog/2017/07/11/non-lexical-lifetimes-draft -rfc-and-prototype-available / – Boiethios

答えて

2

:私の実際のコードは、2つの中間変数を必要try_pop機能です

fn try_drain_inline_broken_down(&self) { 
    { // Implicit block around the whole expression 
     let mut guard = self.map.borrow_mut(); 
     guard.drain() // No semicolon here 
    };     // The semicolon is here 
} 

このように書かれると、drainによって返される値がlブロックから返されるのに十分な長さですが、ブロックの最後までしか存在しないguardへの参照を保持します。

壊れたバージョンでは、drainによって返される値はセミコロンまでしか残らず、guardはブロックの最後まで存在するので、すべてが問題ありません。

関連する問題