E0382
error[E0382]: use of moved value: `s1`
ヒープに割り当てられた値(String や Vec など)を別の変数に代入すると、所有権は新しい変数に移動します。元の変数はなくなります——その後は使用できません。これは Rust の所有権システムが use-after-free バグをコンパイル時に排除するものです。
❌ Broken
let s1 = String::from("hello");
let s2 = s1; // s1 moves into s2
println!("{}", s1); // ❌ E0382: s1 was moved✅ Fixed
let s1 = String::from("hello");
let s2 = s1.clone(); // deep copy — both stay valid
println!("{} {}", s1, s2); // ✅
// Or borrow instead of moving:
let s2 = &s1;
println!("{} {}", s1, s2); // ✅💡 Tip: プリミティブ型(i32、bool、char、f64)は Copy を実装しており、自動的に複製されます。ヒープ型(String、Vec、Box)は移動します。
E0502
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
Rust は多数の共有(&)参照か、ひとつの排他的(&mut)参照を許可します——同時には不可。アクティブな不変借用がある場合、不変借用が終わるまで可変借用を取ることができません。このルールはデータ競合をその構造上排除します。
❌ Broken
let mut v = vec![1, 2, 3];
let first = &v[0]; // immutable borrow
v.push(4); // ❌ E0502: mutable borrow while immutable exists
println!("{}", first);✅ Fixed
let mut v = vec![1, 2, 3];
let first = v[0]; // copy the value out (i32 is Copy)
v.push(4); // ✅ no active borrow
println!("{}", first);
// Or restructure scope:
let mut v = vec![1, 2, 3];
{
let first = &v[0];
println!("{}", first);
} // first's borrow ends here
v.push(4); // ✅💡 Tip: 借用チェッカーは保守的です。戦っている場合は、println を前に移動する、借用の代わりに値をコピーする、または .clone() を使ってみてください。
E0499
error[E0499]: cannot borrow `v` as mutable more than once at a time
可変参照(&mut)は同時にひとつしか存在できません。これはシングルスレッドコードのデータ競合を防ぎ、Rust の並行性保証を機能させる基本的なルールです。
❌ Broken
let mut v = vec![1, 2, 3];
let a = &mut v;
let b = &mut v; // ❌ E0499: second mutable borrow
a.push(4);
b.push(5);
✅ Fixed
let mut v = vec![1, 2, 3];
{
let a = &mut v;
a.push(4);
} // a's borrow ends here
let b = &mut v; // ✅ now safe
b.push(5);💡 Tip: スコープ {} を使って可変借用の生存期間を制限しましょう。実際にはこのエラーは、変更が順次行われるようにロジックを再構成することを意味することが多いです。
E0308
error[E0308]: mismatched types
expected `i32`, found `&i32`
コンパイラが推論または期待する型が、提供した型と一致しません。イテレータで反復する場合(イテレータは参照を生成する)、関数が値の代わりに () を返す場合、または符号付き/符号なし整数を混在させる場合に非常によく見られます。
❌ Broken
// Trailing semicolon returns () instead of i32:
fn double(n: i32) -> i32 {
n * 2; // ❌ E0308: returns () not i32
}
// Iterator reference confusion:
let nums = vec![1, 2, 3];
let sum: i32 = nums.iter().sum(); // needs type annotation✅ Fixed
fn double(n: i32) -> i32 {
n * 2 // ✅ no semicolon — expression returned
}
// Dereference in closures when iterating:
let nums = vec![1, 2, 3];
let doubled: Vec<i32> = nums.iter().map(|&x| x * 2).collect();
// ^ dereference the &i32💡 Tip: 関数の最後の行の末尾のセミコロンは、戻り型を () に静かに変えてしまいます。これは Rust での初心者の最も多い間違いです。
E0277
error[E0277]: `MyType` doesn't implement `std::fmt::Display`
型が必要なトレイトを実装していません。{} フォーマットを Display なしで使おうとした場合、PartialOrd なしで型を比較しようとした場合、または特定のトレイトを必要とするメソッドを呼び出した場合に最もよく発生します。
❌ Broken
struct Point { x: i32, y: i32 }
let p = Point { x: 1, y: 2 };
println!("{}", p); // ❌ E0277: Point doesn't implement Display
println!("{:?}", p); // also fails — needs Debug✅ Fixed
#[derive(Debug)]
struct Point { x: i32, y: i32 }
let p = Point { x: 1, y: 2 };
println!("{:?}", p); // ✅ Debug via #[derive(Debug)]
// Implement Display manually for custom formatting:
use std::fmt;
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
println!("{}", p); // ✅💡 Tip: {:?} 印刷には #[derive(Debug)] を追加してください。{} 印刷には std::fmt::Display を手動で実装してください。ほとんどの欠けている境界は Debug、Display、Clone、PartialEq、または PartialOrd です。
E0106
error[E0106]: missing lifetime specifier
expected named lifetime parameter
関数が参照を返し、複数の参照パラメータを持つ場合、Rust は出力参照がどの入力から来るかを推論できません。ライフタイムアノテーションで教える必要があります。
❌ Broken
// Compiler doesn't know if the return borrows from x or y:
fn longest(x: &str, y: &str) -> &str { // ❌ E0106
if x.len() > y.len() { x } else { y }
}✅ Fixed
// 'a says: output lives no longer than the shorter input
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { // ✅
if x.len() > y.len() { x } else { y }
}
// Single input → no annotation needed (elision rule):
fn first_word(s: &str) -> &str { // ✅ lifetime elided
let bytes = s.as_bytes();
for (i, &b) in bytes.iter().enumerate() {
if b == b' ' { return &s[..i]; }
}
&s[..]
}💡 Tip: ライフタイムアノテーションは制約であり、期間ではありません。'a は「出力は入力より長く生きられない」を意味します。ほとんどのライフタイムは推論されます(省略)。コンパイラが関係を把握できない場合にのみ明示的なものが必要です。
E0596
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
mut で宣言されていない変数を変更しようとしました。Rust では変数はデフォルトで不変です——コンパイラはこれを強制するため、意図しない変更はコンパイル時に検出されます。
❌ Broken
let x = 5;
x = 10; // ❌ E0596: x is immutable
let v = vec![1, 2, 3];
v.push(4); // ❌ E0596: v is immutable
✅ Fixed
let mut x = 5; // ✅ mut makes it mutable
x = 10;
let mut v = vec![1, 2, 3];
v.push(4); // ✅
💡 Tip: let の後に mut を追加してください。変数が実際に変化する必要がある場合にのみ mut を追加しましょう——デフォルトの不変性はバグを捕捉し、コードを推論しやすくします。
E0384
error[E0384]: cannot assign twice to immutable variable `x`
E0596 に似ていますが、メソッド呼び出しではなく 2 回目の代入によって発生します。変数が mut なしで宣言されましたが、再代入しようとしました。
❌ Broken
let x = 5;
x = 10; // ❌ E0384
✅ Fixed
let mut x = 5;
x = 10; // ✅
// Shadowing is another option if you want to "replace" the variable:
let x = 5;
let x = 10; // ✅ shadowing — creates a new binding named x
💡 Tip: シャドーイング(let x = ...)と変更(mut x = ...)は似ていますが異なります:シャドーイングは新しい変数を作成し(型を変更できる)、変更は同じバインディングを変更します。
E0507
error[E0507]: cannot move out of `*s` which is behind a shared reference
参照から値を移動しようとしました。&T を通じて所有権を取ることはできません——参照はデータを所有していません。
❌ Broken
fn print_name(s: &String) {
let owned = *s; // ❌ E0507: can't move out of &String
println!("{}", owned);
}✅ Fixed
fn print_name(s: &String) {
let owned = s.clone(); // ✅ clone the data
println!("{}", owned);
}
// Or just use the reference directly:
fn print_name(s: &String) {
println!("{}", s); // ✅ no need to own it
}💡 Tip: 値を読むだけでよい場合は、参照を直接使ってください。所有されたコピーが必要な場合は .clone() を呼び出してください。所有権が必要な場合は、パラメータを &T ではなく T を取るように変更してください。
E0004
error[E0004]: non-exhaustive patterns: `None` not covered
match 式はすべての可能なケースを処理しなければなりません。バリアントが未処理の場合、コードはコンパイルされません。これにより、未処理のケースがクラッシュを引き起こすランタイムバグのクラス全体が排除されます。
❌ Broken
let opt: Option<i32> = Some(42);
match opt {
Some(n) => println!("{}", n),
// ❌ E0004: None not covered
}✅ Fixed
match opt {
Some(n) => println!("{}", n),
None => println!("nothing"), // ✅ exhaustive
}
// Use _ as a catch-all:
match opt {
Some(n) => println!("{}", n),
_ => {}, // ✅ handles everything else
}
// Or use if let for a single case:
if let Some(n) = opt {
println!("{}", n); // ✅ no else needed
}💡 Tip: コンパイラはどのバリアントが欠けているかを正確に教えてくれます。_ はキャッチオール。if let はひとつのパターンだけを扱う場合の省略形です。
E0072
error[E0072]: recursive type `List` has infinite size
各バリアントが直接自身を含む再帰型は、割り当てに無限のメモリが必要になります。Rust はコンパイル時にすべての型のサイズを知る必要があります。解決策は Box を通じた間接参照です。Box は既知のポインタサイズを持ちます。
❌ Broken
enum List {
Cons(i32, List), // ❌ E0072: infinite size
Nil,
}✅ Fixed
enum List {
Cons(i32, Box<List>), // ✅ Box has fixed pointer size (8 bytes)
Nil,
}
let list = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));💡 Tip: Box<T> は最もシンプルなヒープポインタです。T に関わらず固定サイズ(1 ポインタ幅)を持ち、再帰的なサイズ計算を断ち切ります。
E0716
error[E0716]: temporary value dropped while borrowed
一時的な値を作成し、それへの参照を取り、その一時的な値が参照が使われる前にドロップされました。参照はダングリングになります——解放されたメモリを指してしまいます。
❌ Broken
let s: &str = &String::from("hello")
.to_uppercase(); // ❌ E0716: temporary dropped
// Also common with chains:
let name = get_user().name; // if get_user() returns a temp✅ Fixed
// Bind the temporary to a variable first:
let upper = String::from("hello").to_uppercase();
let s: &str = &upper; // ✅ upper lives long enough
println!("{}", s);💡 Tip: このエラーが出たら、中間値を保持する変数を導入してください。let バインディングのライフタイムはブロックの終わりまで延びます。
E0515
error[E0515]: cannot return value referencing local variable `local`
ローカル変数への参照を返そうとしました。関数が返るとき、ローカル変数はドロップされ、ダングリング参照が残ります。Rust はこれをコンパイル時に防ぎます。
❌ Broken
fn get_greeting() -> &str {
let s = String::from("hello");
&s // ❌ E0515: s is dropped when function returns
}✅ Fixed
// Return an owned value:
fn get_greeting() -> String {
String::from("hello") // ✅ caller owns it
}
// Or return a &'static str literal:
fn get_greeting() -> &'static str {
"hello" // ✅ lives for the entire program
}💡 Tip: 参照を返す必要がある場合、それは関数の入力(パラメータからの借用)から来るか、'static でなければなりません。迷った場合は、所有された型(String、Vec など)を返してください。
E0369
error[E0369]: binary operation `>` cannot be applied to type `T`
ジェネリック型 T に演算子を使いましたが、T にはその演算子が存在することを要求するトレイト境界がありません。ジェネリックコードは型がサポートする演算について明示的でなければなりません。
❌ Broken
fn largest<T>(list: &[T]) -> &T {
let mut biggest = &list[0];
for item in list {
if item > biggest { // ❌ E0369: T doesn't implement PartialOrd
biggest = item;
}
}
biggest
}✅ Fixed
fn largest<T: PartialOrd>(list: &[T]) -> &T { // ✅ add bound
let mut biggest = &list[0];
for item in list {
if item > biggest {
biggest = item;
}
}
biggest
}💡 Tip: E0369 が出た場合、エラーメッセージが必要なトレイトを教えてくれます:比較には PartialOrd、+ には Add、{} には Display など。境界として追加してください:<T: TraitName>。
E0428
error[E0428]: the name `connect` is defined multiple times
同じスコープ内で 2 つのアイテム(関数、構造体、型など)を同じ名前で定義しました。Rust はこれを許可しません——名前はモジュール内で一意でなければなりません。
❌ Broken
fn connect() -> String { "tcp".into() }
fn connect() -> String { "udp".into() } // ❌ E0428: duplicate✅ Fixed
fn connect_tcp() -> String { "tcp".into() }
fn connect_udp() -> String { "udp".into() } // ✅ unique names
// Or use a parameter:
fn connect(protocol: &str) -> String { protocol.into() }💡 Tip: これは use 文が競合する名前をインポートする場合にも発生します。as を使って名前を変更してください:use std::io::Error as IoError;
E0061
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
関数のシグネチャが宣言する数より多いまたは少ない引数で関数を呼び出しました。Rust はデフォルトパラメータや可変長引数関数(println! などのマクロを除く)をサポートしていません。
❌ Broken
fn add(a: i32, b: i32) -> i32 { a + b }
add(1, 2, 3); // ❌ E0061: 3 args, expected 2
add(1); // ❌ E0061: 1 arg, expected 2✅ Fixed
add(1, 2); // ✅
// For optional parameters, use Option:
fn greet(name: &str, title: Option<&str>) {
match title {
Some(t) => println!("{} {}", t, name),
None => println!("{}", name),
}
}
greet("Alice", None);
greet("Bob", Some("Dr."));💡 Tip: Rust にはデフォルトパラメータがありません。省略可能な値には Option<T> を、多くの省略可能フィールドを持つ関数にはビルダー構造体を使ってください。
E0433
error[E0433]: failed to resolve: use of undeclared crate or module `HashMap`
スコープ内にない型や関数を使いました。プレリュード以外の標準ライブラリ型(HashMap、BTreeMap、BufReader など)には明示的な use 文が必要です。
❌ Broken
let mut map = HashMap::new(); // ❌ E0433: HashMap not in scope
✅ Fixed
use std::collections::HashMap;
let mut map = HashMap::new(); // ✅
// Common imports:
use std::collections::{HashMap, HashSet, BTreeMap};
use std::io::{self, BufRead, Write};
use std::fmt;💡 Tip: Rust のプレリュードは一般的な型(Vec、String、Option、Result など)を自動的にインポートします。それ以外はすべて明示的な use が必要です。Rust Analyzer が正しい use パスを提案してくれます。
error: expected `;`, found `let`
error: expected expression, found keyword `fn`
構文エラー——パーサーが予期しないものを見つけました。通常は、セミコロンの欠落、閉じられていない区切り文字、キーワードのタイポ、または式の誤配置です。
❌ Broken
fn main() {
let x = 5 // ❌ missing semicolon
let y = 10;
fn inner() {} // ❌ nested fn needs to be at statement level
x + y // if this is a statement, not a return, add ;
}✅ Fixed
fn main() {
let x = 5; // ✅ semicolon added
let y = 10;
fn helper() {} // ✅ nested fn is valid in Rust
println!("{}", x + y);
}💡 Tip: Rust のエラーメッセージはほぼ常に正しい行を指します。セミコロンエラーがおかしいと感じたら、前の行を確認してください——前の文の ; の欠落がパーサーを奇妙な状態にします。
error[E0275]: overflow evaluating the requirement `Box<T>: Sized`
コンパイラがトレイト境界を証明しようとして無限ループに陥りました。最もよくある原因は、再帰的なトレイト実装、または自身を必要とするトレイトを実装しようとする型です。
❌ Broken
// Generic function calling itself with an incompatible bound:
fn process<T: Clone>(x: T) {
process(x.clone()); // infinite recursion in type inference
}✅ Fixed
// Add a base case or restructure logic:
fn process(x: String) {
if x.is_empty() { return; }
process(x[1..].to_string());
}💡 Tip: このエラーはほぼ常に再帰型またはトレイト境界のループを指します。トレイト制約を単純化するか、明示的な型パラメータを追加してください。
error[E0425]: cannot find value `x` in this scope
現在のスコープに存在しない変数を参照しました。よくある原因:変数名のタイポ、終了した内側のブロックで宣言された変数、ループの外でループ変数を使用。
❌ Broken
{
let x = 5;
}
println!("{}", x); // ❌ x is out of scope
for i in 0..10 { }
println!("{}", i); // ❌ i only lives inside the for loop✅ Fixed
let x = 5; // declare outside the block
{
println!("{}", x); // ✅ x is in scope
}
println!("{}", x); // ✅ still in scope
// Save the last loop value explicitly:
let mut last = 0;
for i in 0..10 { last = i; }
println!("{}", last); // ✅💡 Tip: Rust のスコープはブロックベースです。変数は宣言された場所から囲むブロックの終わりまでしか存在しません。より広いスコープが必要な場合は、宣言を上に移動してください。
🦀
始める準備はできましたか?
26 の無料インタラクティブチャレンジ。インストール不要。アカウント不要ですぐ開始。
Rust を学び始める →