error[E0282]: type annotations needed

error[E0282]: type annotations needed for `Xxx`

型推論が失敗した場合について。

基礎知識

型推論

型推論とは、型を明示せず周辺コードから推論する機能である。

例えば、以下の二行は同じ意味になる。


let a: bool = true;
let a = true;

これにより、冗長な型の記述がなくなる。代わりに、周辺コードが複雑だと型が一目では判別できなくなる。しかし、傾向としては長所が短所を上回る。また、最近は IDE が省略された型をすぐに調べてくれる。

型推論の守備範囲

推論時にコードのどの範囲まで調べるかは言語により差がある。

2026 年現在の多くの言語 (C#, Java, TypeScript など) では文を追わない。そのため、変数型の型推論では右辺のみから型が決まる。この方法は非常に分かりやすいが、推論できる箇所が少ない。

一方、Rust では文を追いながら型情報が補完されていく。例えば以下では、変数 vec の型は宣言から Vec<_> と推論され、push の呼出から Vec<i32> と推論される。


fn main() {
    let mut vec = Vec::new();
    vec.push(42);
    assert_eq!(vec.pop(), Some(42));
}

パターン

パターン A

基本形

型推論のための情報が不足しているパターン。

サンプル


fn main() {
    let val = MyType(None);
    assert!(val.0.is_none());
}

struct MyType<T>(Option<T>);

error[E0282]: type annotations needed for `MyType<_>`
 --> src\main.rs:2:9
  |
2 |     let val = MyType(None);
  |         ^^^            ---- type must be known at this point
  |
help: consider giving `val` an explicit type, where the type for type parameter `T` is specified
  |
2 |     let val: MyType<T> = MyType(None);
  |            +++++++++++

解決策 1

エラーメッセージにもあるが、変数宣言で型を明示すればよい。


fn main() {
    let val: MyType<i32> = MyType(None);
    assert!(val.0.is_none());
}

struct MyType<T>(Option<T>);

解決策 2

値の生成時に型を明示する方法もある。


fn main() {
    let val = MyType::<i32>(None);
    assert!(val.0.is_none());
}

struct MyType<T>(Option<T>);

パターン B

トレイトの選択

推論中の型を引数に、適用可能なトレイトを複数の候補から探る事はできない。

なぜなら、これをするとトレイトの候補や組合せが膨大な数になる場合がある。

そして、これは以下のサンプルであげるような少し意外な結果をもたらす。

サンプル 1

以下では、42 との比較で xi32 型だと分かりそうだが、これはエラーになる。なぜなら、== 演算子のためには Eq トレイトが必要になる。しかし、Eq トレイトには i32 のための実装だけでなく、他の型のための実装も存在する。


fn main() {
	let x = "42".parse().unwrap();
    assert!(x == 42);
}

error[E0284]: type annotations needed
 --> src\main.rs:2:9
  |
2 |     let x = "42".parse().unwrap();
  |         ^        ----- type must be known at this point
  |
  = note: cannot satisfy `<_ as FromStr>::Err == _`
help: consider giving `x` an explicit type
  |
2 |     let x: /* Type */ = "42".parse().unwrap();
  |          ++++++++++++

サンプル 2

以下では、extend の呼出により vec_dstvec_src が同じ型だと分かりそうだが、これはエラーになる。なぜなら、VecExtend の実装には、impl<T, A> Extend<T> for Vec<T, A>impl<'a, T, A> Extend<&'a T> for Vec<T, A> の二種類がある。


fn main() {
    let mut vec_dst = Vec::<i32>::new();
    let vec_src = Vec::new();
    vec_dst.extend(vec_src);
}

error[E0282]: type annotations needed for `Vec<_>`
 --> src\main.rs:3:9
  |
3 |     let vec_src = Vec::new();
  |         ^^^^^^^   ---------- type must be known at this point
  |
help: consider giving `vec_src` an explicit type, where the type for type parameter `T` is specified
  |
3 |     let vec_src: Vec<T> = Vec::new();
  |                ++++++++

解決策

基本形と同じ解決策がどちらのサンプルにも使える。

他にも、トレイトのメソッド呼出を完全修飾記法に変更してもよい。