2014-11-01 53 views
0

這(很無聊)函數編譯失敗:爲什麼Rust借用檢查器拒絕這個函數?

fn silliness(mut z: &mut int) { 
    z = &mut *z; 
} 

編譯器輸出:

$ rustc blah.rs 
blah.rs:2:5: 2:16 error: cannot assign to `z` because it is borrowed 
blah.rs:2  z = &mut *z; 
       ^~~~~~~~~~~ 
blah.rs:2:14: 2:16 note: borrow of `z` occurs here 
blah.rs:2  z = &mut *z; 
         ^~ 
error: aborting due to previous error 

在我看來,既然只有一個參考一下個Z指向在任何時間,事情應該好好地。我不明白什麼?

回答

1

這是安全的,但編譯器只是不夠聰明,還不足以理解它。下面擾動編譯罰款:

fn silliness(mut z: &mut int) { 
    let tmp = z; 
    z = &mut *tmp; 
} 

fn main() {} 

playpen

此引入-A-臨時訣竅是特別編寫遍歷數據結構的環,其你有&mut參考,例如,當一個有用的工具TreeMap使用它(let temp)爲find_mut,它使用效率循環(而不是通過遞歸顯然實現,這不需要這個技巧)。

+0

我不認爲這是關於編譯器不夠聰明。 '&mut * z' *有*使編譯器認爲'z'是唯一借用的,因爲這是防止混疊的唯一方法。否則,你將有兩個可用的和可變的引用到同一個內存位置:原始的'z'和'&mut * z'的結果。這可以被認爲是「好」的唯一原因是這種別名僅存在很短的時間。但就我而言,即使這個時間太短,也不應該讓編譯器開發者提出特別的規則來檢查短時間鋸齒的無辜。 – sellibitze 2014-11-03 15:02:26

+0

@sellibitze,它*是*不夠聰明:[#10520](https://github.com/rust-lang/rust/issues/10520)。編譯器完全可以被教會理解,重新賦值的'z'就像是臨時的(即就好像在重新分配之前「z」被「移出」一樣)。 – huon 2014-11-03 21:31:36

+0

(鋸齒髮生了很多,並且沒問題:只要只有一條路徑可用,這是編譯器執行的操作,可以使指針值相同 - 即在機器級別進行鋸齒 - 。 – huon 2014-11-03 21:34:37

相關問題