Skip to content

Rust Error E0107: Wrong Number of Generic Arguments (Takes N but M Were Supplied)

E0107 means the number of types inside <...> doesn’t match what the type or function expects. Result wants two (Result<T, E>), HashMap wants two (HashMap<K, V>), Option and Vec want one. Give one too few or one too many and rustc says something like enum takes 2 generic arguments but 1 generic argument was supplied, with “struct”, “enum”, “type alias”, “function” or “method” at the front. It’s one of the friendliest errors: rustc tells you both numbers, and the fix is to add or remove a type. It’s part of the compiler errors guide.

error[E0107]: enum takes 2 generic arguments but 1 generic argument was supplied
--> src/main.rs:1:29
|
1 | fn parse_age(text: &str) -> Result<u32> { // ❌ `Result` needs two types
| ^^^^^^ --- supplied 1 generic argument
| |
| expected 2 generic arguments
|
help: add missing generic argument
|
1 | fn parse_age(text: &str) -> Result<u32, E> { // ❌ `Result` needs two types
| +++

This is the program that produces it:

fn parse_age(text: &str) -> Result<u32> { // ❌ `Result` needs two types
text.trim().parse()
}
fn main() {
for input in ["42", "forty"] {
match parse_age(input) {
Ok(age) => println!("age: {}", age),
Err(e) => println!("error: {}", e),
}
}
}

rustc points at line 1 twice:

  1. The ^^^^^^ under Result: “expected 2 generic arguments”. Result is an enum with two type parameters: T for the success value and E for the error.
  2. The --- under u32: “supplied 1 generic argument”. You only gave T.
  3. The help: adds a placeholder E. It’s a hint about where the type goes, not the type itself: you replace E with the real error type.

Generic arguments are like the blanks on a form. A Result form has two blanks, “if it works:” and “if it fails:”. Fill in only one, and the clerk hands it back.

This is a very common one if you’ve read code that writes Result<u32> with one type. That code wasn’t wrong: it used a type alias like io::Result<T> or anyhow::Result<T>, which fills in the error type for you. The plain Result from the prelude has no such shortcut.

A generic type isn’t a complete type until every parameter has a value. Result<u32, E> with an unknown E doesn’t say how big the value is or what an error looks like, so Rust can’t compile code that uses it. Rust could try to guess the missing type from the function body, but it deliberately never infers types in a function signature. Signatures are the contract other code relies on, so they must be written out in full.

Some parameters do have defaults. HashMap<K, V, S = RandomState> has a third parameter for the hasher, which is why rustc says “at least 2” for a HashMap. Defaults can only fill in from the end, and only where the type’s author added one. See Generics and Result.

Choose this most of the time. Find out what the missing parameter should be and write it. For parse(), the error type of a number that fails to parse is std::num::ParseIntError:

use std::num::ParseIntError;
fn parse_age(text: &str) -> Result<u32, ParseIntError> {
text.trim().parse()
}
fn main() {
for input in ["42", "forty"] {
match parse_age(input) {
Ok(age) => println!("age: {}", age),
Err(e) => println!("error: {}", e),
}
}
}

Output:

age: 42
error: invalid digit found in string
▶ Try it Yourself

Not sure which error type it is? Check the docs of the function whose error you return. The same fix works for HashMap<String>: say what the values are, as in HashMap<String, u32>. See HashMaps and Custom Errors.

Fix 2: Use the one-type alias you meant, like io::Result

Section titled “Fix 2: Use the one-type alias you meant, like io::Result”

Choose this when you work with files, the network or stdin, or when you saw Result<T> in someone else’s code. std::io::Result<T> is short for Result<T, std::io::Error>. Import the module and write io::Result:

use std::fs;
use std::io;
fn read_config(path: &str) -> io::Result<String> {
fs::read_to_string(path)
}
fn main() {
match read_config("missing-config.toml") {
Ok(text) => println!("{}", text),
Err(e) => println!("could not read config: {}", e),
}
}

Output:

could not read config: No such file or directory (os error 2)
▶ Try it Yourself

Apps that use the anyhow crate write anyhow::Result<T> the same way. The opposite mistake is also E0107: io::Result<String, io::Error> gives type alias takes 1 generic argument but 2 generic arguments were supplied, because the alias already contains the error type. Drop the second one. See File I/O and anyhow and thiserror.

Fix 3: Make your function generic, or name the types

Section titled “Fix 3: Make your function generic, or name the types”

Choose this when the type is your own generic struct and you wrote just its name. rustc says missing generics for struct `Pair` :

error[E0107]: missing generics for struct `Pair`
--> src/main.rs:6:13
|
6 | fn show(p: &Pair) { // ❌ which `K` and `V`?
| ^^^^ expected 2 generic arguments
|
note: struct defined here, with 2 generic parameters: `K`, `V`
--> src/main.rs:1:8
|
1 | struct Pair<K, V> {
| ^^^^ - -
help: add missing generic arguments
|
6 | fn show(p: &Pair<K, V>) { // ❌ which `K` and `V`?
| ++++++

The broken program:

struct Pair<K, V> {
key: K,
value: V,
}
fn show(p: &Pair) { // ❌ which `K` and `V`?
println!("{} = {}", p.key, p.value);
}
fn main() {
show(&Pair { key: "volume", value: 7 });
show(&Pair { key: "theme", value: "dark" });
}

The help: writes Pair<K, V>, but K and V don’t exist in show yet, so you also have to declare them. Since show is called with two different kinds of Pair, make it generic, with the bounds it needs to print:

use std::fmt::Display;
struct Pair<K, V> {
key: K,
value: V,
}
fn show<K: Display, V: Display>(p: &Pair<K, V>) {
println!("{} = {}", p.key, p.value);
}
fn main() {
show(&Pair { key: "volume", value: 7 });
show(&Pair { key: "theme", value: "dark" });
}

Output:

volume = 7
theme = dark
▶ Try it Yourself

If the function only ever handles one kind, name the types instead: fn show(p: &Pair<&str, u32>). The same goes for impl Pair { ... }, which needs impl<K, V> Pair<K, V> { ... }. See Generics.

Choose this when rustc says “but 2 generic arguments were supplied” and wants fewer. It often happens with the turbofish ::<> on a function call:

error[E0107]: function takes 1 generic argument but 2 generic arguments were supplied
--> src/main.rs:13:20
|
13 | println!("{}", largest::<i32, i32>(&scores)); // ❌ one type too many
| ^^^^^^^ ----- help: remove the unnecessary generic argument
| |
| expected 1 generic argument
|
note: function defined here, with 1 generic parameter: `T`
--> src/main.rs:1:4
|
1 | fn largest<T: PartialOrd + Copy>(items: &[T]) -> T {
| ^^^^^^^ -

The broken program:

fn largest<T: PartialOrd + Copy>(items: &[T]) -> T {
let mut best = items[0];
for &item in items {
if item > best {
best = item;
}
}
best
}
fn main() {
let scores = [72, 95, 88];
println!("{}", largest::<i32, i32>(&scores)); // ❌ one type too many
}

largest has one parameter, T, so it takes one type. Write largest::<i32>(...), or leave the turbofish out completely, since Rust can tell T from the argument:

fn largest<T: PartialOrd + Copy>(items: &[T]) -> T {
let mut best = items[0];
for &item in items {
if item > best {
best = item;
}
}
best
}
fn main() {
let scores = [72, 95, 88];
println!("{}", largest(&scores));
println!("{}", largest::<f64>(&[1.5, 0.5]));
}

Output:

95
1.5
▶ Try it Yourself

The note: is the most useful line here: it shows the definition and lists its parameters, so you can count them yourself.

HashMap<String> with only the key. rustc says struct takes at least 2 generic arguments but 1 generic argument was supplied. Fix: HashMap<String, u32>, or write HashMap::new() and let Rust infer both from the first insert. See HashMaps.

Your own struct with two type parameters, given one. let p: Pair<&str> = ... gives struct takes 2 generic arguments but 1 generic argument was supplied. Fix: Pair<&str, i32>, or Pair<_, _> to let Rust fill both in. Option<i32, i32> is the opposite: enum takes 1 generic argument but 2 generic arguments were supplied. If you wanted two values, use a tuple, Option<(i32, i32)>.

Lifetimes count too. A struct Excerpt<'a> written as Excerpt<'a, 'a> gives struct takes 1 lifetime argument but 2 lifetime arguments were supplied. Fix: one lifetime per parameter in the definition. See Lifetimes. A method that isn’t generic at all, like .into::<String>(), gives method takes 0 generic arguments but 1 generic argument was supplied; write let s: String = x.into(); instead (see E0283).

One surprise: Vec<i32, i32> is not E0107. Vec has a second, unstable parameter for the memory allocator, so you get E0658 (allocator_api) and a few other errors instead. The fix is the same: Vec<i32>, or Vec<(i32, i32)> for pairs.

  • E0061: the same mistake with normal arguments, a function that takes N arguments but M were supplied.
  • E0106: missing lifetime specifier, when a reference in a type needs a 'a.
  • E0252: two use lines import the same name; an E0107 often follows when Result means fmt::Result.
  • E0283: type annotations needed, the right fix when .into::<T>() gives E0107.
  • E0401: an inner function uses the outer function’s generic T.
  • All compiler errors: the full list of error pages.

Quick check

1. fn load() -> Result<String> gives E0107. Which return type fixes it for a function that reads a file?

2. Why does rustc say at least 2 generic arguments for HashMap?

3. fn show(p: &Pair) gives `missing generics for struct Pair , and show is called with different kinds of Pair`. What's the fix?

Score: 0 / 3