RustエラーE0317の修正:代入式におけるelse句の不足への対処

beginner🦀 Rust2026-06-06| Rust (全バージョン), Cargo, Linux, macOS, または Windows

Error Message

error[E0317]: if may be missing an else clause
#rust#構文#if-else##

コーディングの障壁深夜の作業中にロジックを整理していて、簡単な条件分岐を使って値を代入しようとしたとします。簡潔な1行で済むはずが、Rustコンパイラは次のような鋭いエラーメッセージであなたの手を止めます。

error[E0317]: if may be missing an else clause
  --> src/main.rs:5:13
   |
5  |       let x = if condition {
   |  ____________^ 
6  | |         10
7  | |     };
   | |_____^ expected (), found i32
   |
   = note: `if` expressions without `else` evaluate to `()`
   = help: add an `else` block that evaluates to the expected type

PythonやJavaScriptのような言語では、変数を未定義のままにしてスルーされるかもしれませんが、Rustは実行時のクラッシュを防ぐために明示性を求めます。

エラーの原因Rustでは、ifを単なる文ではなくとして扱います。つまり、値を返さなければなりません。let x = if ...のように、ifを使って変数に結果を代入する場合、コンパイラはあらゆる可能性においてxに有効な値が渡されることを保証しようとします。

elseブランチを省略すると、Rustは暗黙的にユニット型である()を返します。これにより、即座に型の不一致が発生します。ifブロックが32ビット整数(i32)を返しているのに、隠れたelseが何も返さない場合、コンパイラは変数に対して単一で一貫した型を割り当てることができません。

ステップ別の修正方法#### 1. フォールバック用のelse句を追加するデフォルト値を提供することが最も直接的な解決策です。すべての実行パスが同じデータ型を返す必要があります。

// ❌ E0317を発生させる
let is_active = true;
let speed = if is_active {
    100
}; // エラー: () が期待されていますが、i32 が見つかりました

// ✅ フォールバックを追加して修正
let speed = if is_active {
    100
} else {
    0
};

2. デフォルト値で初期化するelseブロックが冗長に感じられることもあります。その場合は、まず可変変数を初期化します。これにより、ifは代入式ではなく、単純な制御フロー文になります。

let mut retry_count = 0; // 標準のデフォルト値
if failure_detected {
    retry_count = 5;
} // ifブロックを使って変数の型を定義していないため、エラーは発生しません

3. 複雑なロジックにはmatchを使用する3つ以上の条件を扱う場合は、matchブロックの方が圧倒的に読みやすくなります。すべてのケースを網羅することを強制されるため、if/elseと同じ安全性が得られます。

let connection_state = "loading";
let code = match connection_state {
    "active" => 200,
    "loading" => 102,
    _ => 500, // すべてに一致する「else」と同等のもの
};

特殊なケース:Optionを使用する論理的なデフォルト値が存在しない場合は、結果をOptionでラップします。これにより、値が欠落している可能性があることをプログラムの他の部分に明示的に伝えることができます。

let user_id = if user_found {
    Some(1024)
} else {
    None
};

修正の確認コンパイラのチェックを実行して、エラーが解消されたことを確認します。

cargo check

修正が成功すればE0317は消えます。さらに、フォールバック値が期待通りに動作することを確認するために、簡単なユニットテストを追加してロジックを検証することもできます。

#[test]
fn test_speed_default() {
    let is_active = false;
    let val = if is_active { 100 } else { 0 };
    assert_eq!(val, 0);
}

トラブルシューティングのヒント- サイレント・セミコロン: ifブロックの中に誤ってセミコロンを置いていないか確認してください。{ 10 }は整数を返しますが、{ 10; }()を返します。この微妙な違いは、型エラーのよくある原因です。- 厳密な型一致: 両方のブランチが全く同じ型を返すようにしてください。一方のブランチでi32を返し、もう一方でu32を返すと、別のエラー(E0308)が発生します。- リターンロジック: Rustのブロックにおいて、セミコロンのない最後の式が戻り値として機能することを忘れないでください。これによりifによる代入が強力になりますが、完全な一貫性が求められます。

Related Error Notes