How to fix error E0282: type annotations needed
Short answer: a piece of code leaves a type with nothing to pin it to — an empty Vec::new(),
a parse() call, a bare collect() — and more than one type would make the code compile, so the
compiler refuses to pick. The message headline is always type annotations needed; the code in
front of it is E0282, E0283 or E0284 depending on which piece was underdetermined. The fix is the
same everywhere: name one concrete type, either on the binding (let v: Vec<i32> = ...) or on the
call itself ("42".parse::<u32>()). Unlike E0308,
where two known types disagree, E0282 is the absence of a type at all: the compiler is not
rejecting what you wrote, it is asking which type you meant.
The error
Section titled “The error”The everyday version: a collection starts empty, so its element type comes from nowhere.
fn main() { let v = Vec::new(); println!("{:?}", v);}Compiling that with cargo build prints:
error[E0282]: type annotations needed for `Vec<_>` --> src/main.rs:2:9 |2 | let v = Vec::new(); | ^ ---------- type must be known at this point |help: consider giving `v` an explicit type, where the type for type parameter `T` is specified |2 | let v: Vec<T> = Vec::new(); | ++++++++
For more information about this error, try `rustc --explain E0282`.The headline says the problem in one line: type annotations needed for `Vec<_>` . A Vec<T>
holds elements of type T, and nothing so far says what T is. Printing with {:?} needs the
element type to implement Debug — thousands of types do — so the print is not a clue either.
When several types would all make the code work, Rust does not guess. It stops and asks.
Fix one: annotate the binding
Section titled “Fix one: annotate the binding”fn main() { let mut v: Vec<i32> = Vec::new(); v.push(1); v.push(2); println!("{:?}", v);}This prints:
[1, 2]The : Vec<i32> after the name is the whole fix. Type inference in Rust flows in both directions —
from the value to the binding and from the binding to the value — so one annotation anywhere in the
chain settles it. Nothing changes at run time; the annotation is checked at compile time and then
erased.
Usually you do not even need it, because real use pins the type on its own:
fn main() { let mut v = Vec::new(); v.push(1); println!("{:?}", v);}This prints:
[1]push(1) makes the element type i32, and the whole Vec knows what it is from that moment. The
error only bites when the collection is printed, returned, or passed along before anything was put
in it. (String::new() never shows this error, because String already names its contents — the
annotation is needed exactly when the type has an unspoken parameter: Vec<T>, HashMap<K, V>,
HashSet<T>.)
The same message on a conversion: parse
Section titled “The same message on a conversion: parse”Second shape. parse turns a string into a number — or an IpAddr, or any type that implements
FromStr. That “any type” is the problem:
fn main() { let guess = "42".parse().expect("not a number"); println!("{guess}");}Compiling that with cargo build prints:
error[E0284]: type annotations needed --> src/main.rs:2:9 | 2 | let guess = "42".parse().expect("not a number"); | ^^^^^ ----- type must be known at this point | = note: cannot satisfy `<_ as FromStr>::Err == _` = note: the type must also implement `FromStr`note: required by a bound in `core::str::<impl str>::parse` --> /Users/rango/.rustup/toolchains/1.99.0-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/str/mod.rs:2782:21 |2782 | pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> { | ^^^^^^^ required by this bound in `core::str::<impl str>::parse`help: consider giving `guess` an explicit type | 2 | let guess: /* Type */ = "42".parse().expect("not a number"); | ++++++++++++
For more information about this error, try `rustc --explain E0284`.The headline is the same type annotations needed — this time with the code E0284. The note says
what could not be worked out: cannot satisfy `<_ as FromStr>::Err == _` . In words: parse is
declared as fn parse<F: FromStr>(&self) -> Result<F, F::Err>, so choosing the output type also
chooses the error type, and nothing in the rest of main chooses either. Printing the value does
not pin it down — almost every type implements Display.
Annotate the binding:
fn main() { let guess: u32 = "42".parse().expect("not a number"); println!("{guess}");}This prints:
42Or put the type on the call, with the turbofish syntax — ::<T> after the method name:
fn main() { let guess = "42".parse::<u32>().expect("not a number"); println!("{guess}");}This prints the same 42. Both fixes say the same thing; pick whichever reads better where you
are. The turbofish earns its keep when the binding has no natural place for a type — in a match
arm, a function argument, a chained expression — or when you want the type visible right where the
conversion happens.
collect(): any container will do
Section titled “collect(): any container will do”Third shape, and the most surprising one. collect() turns an iterator into a collection — but
“collection” is not one type:
fn main() { let evens = (0..10).filter(|n| n % 2 == 0).collect(); println!("{:?}", evens);}Compiling that with cargo build prints:
error[E0283]: type annotations needed --> src/main.rs:2:9 | 2 | let evens = (0..10).filter(|n| n % 2 == 0).collect(); | ^^^^^ ------- type must be known at this point | = note: the type must implement `FromIterator<i32>`note: required by a bound in `collect` --> /Users/rango/.rustup/toolchains/1.99.0-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2073:19 |2073 | fn collect<B: FromIterator<Self::Item>>(self) -> B | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`help: consider giving `evens` an explicit type | 2 | let evens: Vec<_> = (0..10).filter(|n| n % 2 == 0).collect(); | ++++++++
For more information about this error, try `rustc --explain E0283`.Again type annotations needed, now with the code E0283. The iterator’s items are i32 — that
part is known. What is unknown is the container: the same expression can produce a Vec<i32>, a
VecDeque<i32>, a HashSet<i32>, and more, because collect is generic over everything that
implements FromIterator. One expression, many valid results — the compiler will not choose for
you. Note that the compiler’s own suggestion is exactly the fix:
fn main() { let evens: Vec<i32> = (0..10).filter(|n| n % 2 == 0).collect(); println!("{:?}", evens);}This prints:
[0, 2, 4, 6, 8]Or put the container on the call:
fn main() { let evens = (0..10).filter(|n| n % 2 == 0).collect::<Vec<i32>>(); println!("{:?}", evens);}This prints the same list. A middle form is common when the element type is already obvious and
only the container needs naming: Vec<_> means “a Vec, of whatever the iterator produces” —
let evens: Vec<_> = ...collect(); compiles just the same, and the _ is filled in from the
iterator.
Three codes, one message
Section titled “Three codes, one message”The same headline travels under three codes, and the difference is where the missing type was sitting:
- E0282 — the value’s own type parameter is open:
type annotations needed for `Vec<_>`. Thehelp:points at the binding. - E0283 — a trait bound could be satisfied by several impls:
the type must implement `FromIterator<i32>`. Thehelp:suggests a type annotation that names the container. - E0284 — an associated type in the chain is unresolved:
cannot satisfy `<_ as FromStr>::Err == _`.
Searching for any of the three lands on the same fix: give the compiler one concrete type. The
note: lines name the constraint that could not be satisfied; read them if the fix is not obvious,
because they say exactly which choice was left open.
Not this error
Section titled “Not this error”- mismatched types — E0308, two types that were both known and disagree. E0282 is the opposite situation: not enough is known to disagree.
- the trait bound is not satisfied — E0277.
Happens after you fix this one if the type you named does not actually support the operation —
parsing into a type with no
FromStrimpl, for instance.