Rust Error E0057: This Function Takes N Arguments but M Were Supplied (Closures)
E0057 means you called a closure with the wrong number of arguments: too few or too many. It’s the closure version of E0061, and the message reads almost the same. The fix is usually quick: look at the closure’s |...| and pass one value per parameter. This page also covers two close relatives you’ll meet with iterators, E0593 and E0631, because they come from the same mix-up. For the other errors in this series, see Rust compiler errors.
The error message
Section titled “The error message”error[E0057]: this function takes 2 arguments but 1 argument was supplied --> src/main.rs:3:17 |3 | let total = add(1); // ❌ add wants two numbers | ^^^--- argument #2 of type `i32` is missing |note: closure defined here --> src/main.rs:2:15 |2 | let add = |a: i32, b: i32| a + b; | ^^^^^^^^^^^^^^^^help: provide the argument |3 | let total = add(1, /* i32 */); // ❌ add wants two numbers | +++++++++++This is the program that produces it:
fn main() { let add = |a: i32, b: i32| a + b; let total = add(1); // ❌ add wants two numbers println!("{total}");}Too many arguments gives the same code, with an “unexpected argument” label and a “remove the extra argument” help:
error[E0057]: this function takes 1 argument but 2 arguments were supplied --> src/main.rs:3:5 |3 | greet("Ferris", "Corro"); | ^^^^^ ------- unexpected argument #2 of type `&'static str` |note: closure defined hereWhat it means
Section titled “What it means”Read the message like the one for functions: the first line counts (the closure takes 2, you gave 1), the label under your call names the missing or extra argument, and help: shows where it goes. /* i32 */ is only a placeholder comment telling you the type. Put a real value there.
E0057 or E0061? The first line is the same. The note: tells them apart:
closure defined here: you called a closure. That’s E0057.callable defined here: you called a genericfwith a bound likeF: Fn(i32). Also E0057.function defined here: a normalfn, a method, or a function pointer (let f: fn(i32, i32) -> i32 = add;). That’s E0061.
Either way, the fix is the same: match the call to the parameter list.
Why Rust does this
Section titled “Why Rust does this”A closure’s parameter list is as fixed as a function’s. |a: i32, b: i32| takes exactly two i32s, every time. There are no default arguments and no “pass fewer if you like”. Even when you leave out the types, rustc works them out from the closure’s body and its first use, and from then on they’re locked in.
Under the hood, a closure implements one of the Fn traits with a fixed list of argument types, like Fn(i32, i32) -> i32. The compiler checks every call against that list, so a call with the wrong count never reaches your running program. How closures and their parameters work is covered in Closures and Closure traits.
How to fix it
Section titled “How to fix it”Fix 1: Match the call to the closure’s parameters
Section titled “Fix 1: Match the call to the closure’s parameters”Choose this almost every time. Jump to the note: location, count the parameters between the pipes |...|, and pass one value for each. If you have more values than parameters, call the closure more than once:
fn main() { let add = |a: i32, b: i32| a + b; let greet = |name: &str| println!("Hello, {name}!");
let total = add(1, 2); println!("{total}");
greet("Ferris"); greet("Corro"); // one call per name}Output:
3Hello, Ferris!Hello, Corro!If the closure really should take a different number of values, change the closure instead. That’s fine too, as long as every call agrees with it.
Fix 2: Tuples: one tuple is one argument
Section titled “Fix 2: Tuples: one tuple is one argument”Choose this when tuples are involved. |(name, score)| and |name, score| look alike, but they are different closures. The first takes one argument, a tuple, and unpacks it. The second takes two arguments.
Calling a tuple closure with two values gives E0057, and rustc suggests adding the parentheses:
error[E0057]: function takes 1 argument but 2 arguments were supplied --> src/main.rs:3:5 |3 | show("Ferris", 90); | ^^^^ |note: closure parameter defined herehelp: wrap these arguments in parentheses to construct a tuple |3 | show(("Ferris", 90)); | + +The opposite mistake happens all the time with iterators. zip, enumerate and map iteration hand your closure one tuple per item. Writing .map(|name, score| ...) gives a different code, E0593:
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments --> src/main.rs:7:10 |7 | .map(|name, score| format!("{name}: {score}")) | ^^^ ------------- takes 2 distinct arguments | | | expected closure that takes a single 2-tuple as argument |help: change the closure to accept a tuple instead of individual arguments |7 - .map(|name, score| format!("{name}: {score}"))7 + .map(|(name, score)| format!("{name}: {score}"))Both have the same fix: put the parentheses where the tuple is.
fn main() { let names = vec!["Ferris", "Corro"]; let scores = vec![90, 75];
// zip gives one (name, score) tuple per item: unpack it in the parameter list let lines: Vec<String> = names .iter() .zip(scores.iter()) .map(|(name, score)| format!("{name}: {score}")) .collect(); println!("{:?}", lines);
// a closure that takes a tuple is called with one tuple let show = |(name, score): (&str, i32)| println!("{name} scored {score}"); show(("Ferris", 90));}Output:
["Ferris: 90", "Corro: 75"]Ferris scored 90The same goes for .enumerate().map(|(i, item)| ...) and map.iter().for_each(|(key, value)| ...). See Iterators and Tuples.
Fix 3: Adapt with a wrapper closure
Section titled “Fix 3: Adapt with a wrapper closure”Choose this when you pass a function or closure to another function (a “higher-order function”) and the parameter counts don’t line up. Here apply wants something that takes one i32, but add takes two. That gives E0593 again:
error[E0593]: function is expected to take 1 argument, but it takes 2 arguments --> src/main.rs:10:26 | 5 | fn add(a: i32, b: i32) -> i32 { | ----------------------------- takes 2 arguments...10 | println!("{}", apply(add, 5)); | ----- ^^^ expected function that takes 1 argument | | | required by a bound introduced by this callDon’t change add. Wrap it in a small closure that has the shape apply expects and fills in the missing value itself:
fn apply<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 { f(x)}
fn add(a: i32, b: i32) -> i32 { a + b}
fn main() { let bonus = 10; // takes 1 argument, calls add with 2 println!("{}", apply(|x| add(x, bonus), 5));
// takes 1 tuple, calls add with its two parts let pairs = vec![(1, 2), (3, 4)]; let sums: Vec<i32> = pairs.into_iter().map(|(a, b)| add(a, b)).collect(); println!("{:?}", sums);}Output:
15[3, 7]The wrapper borrows bonus from the surrounding code, which is exactly what closures are good at. Passing a function by name (apply(double, 5)) works only when its parameters already match. See Closure traits.
Where you’ll usually see it
Section titled “Where you’ll usually see it”Inside a generic function. fn call_twice<F: Fn(i32)>(f: F) that calls f(2, 3) gives E0057 with note: callable defined here, pointing at Fn(i32). The bound is the parameter list. Fix: call f(2), or change the bound to Fn(i32, i32) if you really need two values (then every caller’s closure must take two).
Boxed closures. let f: Box<dyn Fn(i32, i32) -> i32> = Box::new(|a, b| a + b); then f(1) gives E0057 with note: implementation defined here. Fix: pass both values, f(1, 2).
Sorting. v.sort_by(|a| a.cmp(a)) gives E0593, “closure is expected to take 2 arguments, but it takes 1 argument”. sort_by compares two items at a time. Fix: v.sort_by(|a, b| a.cmp(b)). See Sorting.
Right count, wrong type. nums.iter().map(|x: i32| x * 2) gives E0631, “type mismatch in closure arguments”, because .iter() hands out &i32. rustc’s help suggests |x: &i32|. Simplest fix: drop the annotation, |x| x * 2.
Unpacking something that isn’t a tuple. v.iter().map(|(a, b)| a + b) on a plain Vec<i32> gives E0308, “expected integer, found (_, _)”. Fix: only use |(a, b)| when the items really are pairs.
Related errors
Section titled “Related errors”- E0061: wrong number of arguments: the same message for normal functions, methods and function pointers.
- E0308: mismatched types: the count is right, but an argument (or a tuple pattern) has the wrong type.
- E0373: closure may outlive the current function: another common closure error, about captured variables in threads and returned closures.
- E0599: no method found: can show up next to E0631, because a closure with the wrong signature breaks the rest of an iterator chain.
- E0593: closure takes 2 distinct arguments: a closure or function passed with the wrong number of parameters.
- E0631: type mismatch in closure arguments: the right number of parameters, but the wrong type.
- All compiler errors: the full list of error pages.
Quick check
Section titled “Quick check”Quick check
1. let double = |x: i32| x * 2; is called as double(2, 3). What does rustc report?
2. names.iter().zip(ages.iter()).map(|n, a| ...) doesn't compile. What is the fix?
3. Both E0057 and E0061 say this function takes 2 arguments but 1 argument was supplied. How can you tell you called a closure?
Score: 0 / 3
Read more
Section titled “Read more”- E0057 — Rust error codes index: the official explanation of this error.
- Closures — The Rust Book: closure syntax, type inference for parameters, and the
Fntraits. - Closures — Rust by Example: short runnable examples of closures, including passing them to functions.
std::ops::Fn— standard library docs: howFn(i32) -> i32bounds describe a closure’s parameters.- E0593 — Rust error codes index: the official explanation of the closure-passed-with-the-wrong-arity error.