2017-04-24 26 views
15

鑑於以下功能:當返回使用StdinLock的結果時,爲什麼要保留stdin的借用?

use std::io::{BufRead, stdin}; 

fn foo() -> usize { 
    let stdin = stdin(); 
    let stdinlock = stdin.lock(); 
    stdinlock 
     .lines() 
     .count() 
} 

這失敗,出現以下錯誤編譯:

error: `stdin` does not live long enough 
    --> src/main.rs:12:1 
    | 
7 |  let stdinlock = stdin.lock(); 
    |      ----- borrow occurs here 
... 
11 | } 
    |^`stdin` dropped here while still borrowed 
    | 
    = note: values in a scope are dropped in the opposite order they are created 

我覺得這是令人驚訝的,因爲消耗的鎖(通過lines)的結果不保留任何引用到原始來源。事實上,在返回之前將相同的結果分配給綁定就很好(Playground)。

fn bar() -> usize { 
    let stdin = stdin(); 
    let stdinlock = stdin.lock(); 
    let r = stdinlock 
     .lines() 
     .count(); 
    r 
} 

這表明,返回一個「消費鎖」立即導致了鎖試圖活得比鎖定的內容,多以不尋常的方式。我研究過的所有參考文獻通常都指出聲明的順序很重要,但並不知道返回的對象如何影響它們被釋放的順序。

那爲什麼前面的函數被編譯器拒絕?爲什麼鎖看似比預期更長久?

+1

哦。有趣! –

+0

@MatthieuM。原因似乎是'MutexGuard'的魔法。我僅僅根據類型做了一個簡單的複製。見[這裏](https://gist.github.com/peterjoel/f6a1e1ec29da1ee73994820f742cdb7d#file-stlocklock_problem-rs)。在破解的版本中,我使用'std'中的'MutexGuard'。在工作的版本中,我複製粘貼相同的代碼而不是使用'std'。 –

+1

有沒有人提出過錯誤報告? – Veedrac

回答

1

這似乎是編譯器中的一個錯誤。你可以讓編譯器高興通過使用一個明確的return聲明:

use std::io::{stdin, BufRead}; 

fn foo() -> usize { 
    let stdin = stdin(); 
    let stdinlock = stdin.lock(); 
    return stdinlock 
     .lines() 
     .count(); 
} 

fn main() {} 

playground

正如在評論中提到的,也有與此相關的多種鏽病問題:

1

我不能回答你的問題的爲什麼,但我可以說,當前實現非詞彙壽命的允許原始代碼進行編譯:

​​3210

Playground

1.25.0-nightly(2018-01-11 73ac5d6)

相關問題