前提
Rustを始めたのですが、mutable関連のコンパイルエラーが発生して詰まってしまったので、詳しい人に原因を教えてもらいたいです。
実現したいこと
- コンパイルエラーの原因を知る
発生している問題・エラーメッセージ
error[E0502]: cannot borrow `self.item` as mutable because it is also borrowed as immutable --> src/sandbox.rs:22:13 | 20 | player.play(); | ------------- immutable borrow later used here 21 | 22 | self.item.change(); | ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here ... 25 | player = self.get_next_player(); | ---------------------- immutable borrow occurs here
該当のソースコード
問題が発生する箇所から、余計なものを取り除き、エラーが起きる最小限のコードにしたものです。
(最小限にしたので無限ループになってしまいましたが、本来はbreakする箇所があります)
Rust
1struct Item {} 2impl Item { 3 fn change(&mut self) {} 4} 5 6struct Player {} 7impl Player { 8 fn play(&self) {} 9} 10 11struct Sandbox { 12 item: Item, 13 player: Player, 14} 15impl Sandbox { 16 pub fn start(&mut self) { 17 let mut player = &self.player; 18 19 while true { 20 player.play(); 21 22 // ここでコンパイルエラーが発生する 23 self.item.change(); 24 25 if true { 26 player = self.get_next_player(); 27 } 28 } 29 } 30 31 fn get_next_player(&self) -> &Player { 32 &self.player 33 } 34}
試したこと
エラーメッセージを和訳するとself.itemはimuutableとしても借用されているので、mutableとして借用できない
とのことですが、self.itemが使われている箇所は1箇所しかなく、意味が分かりませんでした。
また、以下のようにコードに色々手を加えるとエラーが起きなくなるのですが、いずれも何故そうなるのか分かりませんでした。
以下の行どれか1つを消す
- player.play();
- self.item.change();
- player = self.get_next_player();
なぜかこの3つが全て揃ってないとエラーになりません。
get_next_player() を消す
self.get_next_player()
をやめて、代わりに&self.player
にするとエラーが起きません。
if 文を消す
if文を消してplayer = self.get_next_player();
を外に出すとエラーが起きません。
playerへの代入を止める
player =
を消して、self.get_next_player();
だけにするとエラーが起きません。
追記1
その後、思い当たった仮説を追記。
そももの原因は、self.get_next_player()のところで、selfがimmutable借用された後、self.item.change()でmuttable借用されるから?
player.play()、player = self.get_next_player()を書き換えたときエラーが起きなくなるのは、Non-lexical lifetimesの機能によって、コンパイラーがplayerにselfが借用されてないと判定されている?
ただ、if文を消すとエラーにならない原因は分からない。
補足情報(FW/ツールのバージョンなど)
rustc 1.65.0 (897e37553 2022-11-02)

回答2件
あなたの回答
tips
プレビュー
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
また依頼した内容が修正された場合は、修正依頼を取り消すようにしましょう。