中級のRustエラー 60問
12種類のエラーを、それぞれ複数パターンずつ収録しています。
- E0502: cannot borrow as mutable because it is also borrowed as immutable不変参照が生きている(後で使われる)間に、同じ変数を可変で借用しようとするとE0502エラーになります。Rustの借用規則は「不変参照は何個でも、可変参照は同時に1つだけ」を強制します。
- for ループで Vec を直接回すと要素がムーブされるfor x in vec のように所有権を持つVecを直接forに渡すと、内部でinto_iter()が呼ばれ各要素の所有権がムーブされます。ループの後で元のVecを使おうとするとE0382エラーになります。
- attempt to subtract with overflow パニックの原因と直し方符号なし整数(usizeなど)で0から1を引くような演算を行うと、負の値を表現できないため実行時にパニックします。Vecの長さから1を引く処理で、空のVecを渡すと典型的に発生します。
- HashMapを存在しないキーで [] 添字アクセスすると no entry found for key パニックになるHashMapに[]で添字アクセスした際、そのキーが存在しないとパニックします。存在するかどうか分からないキーを扱う場合は、getメソッドを使いOptionとして受け取る必要があります。
- move クロージャに取り込んだ値をクロージャの外で使うと E0382 になるmoveを付けたクロージャは、参照する変数の所有権を丸ごと取り込みます。取り込まれた後にクロージャの外側でその変数を使おうとするとE0382エラーになります。
- E0106: missing lifetime specifier の原因と直し方参照を返す関数で、その参照が複数の引数のどちらに由来するのかコンパイラが判断できない場合、E0106エラーになります。ライフタイム注釈を付けて、戻り値の参照がどの引数と同じ生存期間なのかを明示する必要があります。
- E0277: doesn't implement `std::fmt::Display` の原因と直し方自作の構造体を{}(Display)で出力しようとすると、Displayトレイトを実装していない限りE0277エラーになります。デバッグ目的で中身を見たいだけなら、{:?}(Debug)を使う方法もあります。
- E0072: recursive type has infinite size の原因と直し方構造体が自分自身の型を直接フィールドに持つと、サイズが無限になってしまいコンパイルエラーになります。Boxなどのポインタ経由の間接参照を挟むことで、サイズを確定させる必要があります。
- range end index out of range for slice パニックの原因と直し方配列やVecをスライスする際、範囲の終端が要素数を超えているとパニックします。スライス構文v[a..b]は、bが要素数以下であることが前提です。
- ブロック内でのシャドーイングは外側の変数に反映されないif文などのブロックの中でletを使って同じ名前の変数を再宣言(シャドーイング)すると、それはブロック内だけで有効な別の変数になります。ブロックを抜けると、外側の変数は変更されないまま残ります。
- swap_remove は要素の順序を保証しない(remove との違い)Vecのswap_removeは指定位置の要素を削除し、その穴を最後の要素で埋めるため高速ですが、要素の順序が変わります。順序を保ったまま削除したい場合はremoveを使う必要があります。
- byte index is not a char boundary パニックの原因と直し方Rustの文字列はUTF-8のバイト列として保持されており、日本語のようなマルチバイト文字の途中の位置でスライスしようとするとパニックします。文字単位で扱いたい場合はcharsなどのイテレータを使う必要があります。