Skip to content

References to closures have worse error messages when they don't implement the right Fn* trait #161327

Description

@Darksonn

Code

fn apply_and_log(
    func: impl Fn(&'static str) -> String,
    func_name: &'static str,
    input: &'static str,
) {
    println!("Calling {func_name}({input}): {}", func(input));
    println!("Calling {func_name}({input}) a second time: {}", func(input));
}

fn main() {
    let mut v = Vec::new();
    let mut accumulate = |x| {
        v.push(x);
        v.join("/")
    };
    apply_and_log(&mut accumulate, "accumulate", "red");
    apply_and_log(&mut accumulate, "accumulate", "green");
    apply_and_log(&mut accumulate, "accumulate", "blue");
}

Current output

error[E0277]: expected a `Fn(&'static str)` closure, found `&mut {closure@src/main.rs:15:26: 15:29}`
  --> src/main.rs:19:19
   |
19 |     apply_and_log(&mut accumulate, "accumulate", "red");
   |     ------------- ^^^^^^^^^^^^^^^ expected an `Fn(&'static str)` closure, found `&mut {closure@src/main.rs:15:26: 15:29}`
   |     |
   |     required by a bound introduced by this call
   |
   = help: the trait `Fn(&'static str)` is not implemented for `&mut {closure@src/main.rs:15:26: 15:29}`
note: required by a bound in `apply_and_log`
  --> src/main.rs:5:16
   |
 4 | fn apply_and_log(
   |    ------------- required by a bound in this function
 5 |     func: impl Fn(&'static str) -> String,
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `apply_and_log`
help: consider removing the leading `&`-reference
   |
19 -     apply_and_log(&mut accumulate, "accumulate", "red");
19 +     apply_and_log(accumulate, "accumulate", "red");

Desired output

error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
  --> src/main.rs:15:26
   |
15 |     let mut accumulate = |x| {
   |                          ^^^ this closure implements `FnMut`, not `Fn`
16 |         v.push(x);
   |         - closure is `FnMut` because it mutates the variable `v` here
...
19 |     apply_and_log(&mut accumulate, "accumulate", "red");
   |     ------------- --------------- the requirement to implement `Fn` derives from here
   |     |
   |     required by a bound introduced by this call
   |
note: required by a bound in `apply_and_log`
  --> src/main.rs:5:16
   |
 4 | fn apply_and_log(
   |    ------------- required by a bound in this function
 5 |     func: impl Fn(&'static str) -> String,
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `apply_and_log`

Other cases

If you remove the &mut from the closure when passing it to apply_and_log, you get the error message listed in "desired output".

 fn main() {
     let mut v = Vec::new();
     let mut accumulate = |x| {
         v.push(x);
         v.join("/")
     };
-    apply_and_log(&mut accumulate, "accumulate", "red");
-    apply_and_log(&mut accumulate, "accumulate", "green");
-    apply_and_log(&mut accumulate, "accumulate", "blue");
+    apply_and_log(accumulate, "accumulate", "red");
 }

This error message was encountered while teaching this slide of the comprehensive Rust course.

Rust Version

rustc 1.97.1 (8bab26f4f 2026-07-14)
binary: rustc
commit-hash: 8bab26f4f68e0e26f0bb7960be334d5b520ea452
commit-date: 2026-07-14
host: x86_64-unknown-linux-gnu
release: 1.97.1
LLVM version: 22.1.6

Anything else?

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions