Code
fn call<C>(f: C)
where
C: Fn(),
{
f()
}
struct FooPrinter {}
impl FooPrinter {
fn print(&self) {
println!("foo");
}
fn new() -> Self {
FooPrinter {}
}
}
fn print_foo() {
println!("foo");
}
fn main() {
// passing a normal function
call(print_foo);
// clippy lints this
call(|| print_foo());
// doesn't work
call(FooPrinter::new().print);
// fixed looks like clippy would lint this
call(|| FooPrinter::new().print());
}
Current output
error[E0615]: attempted to take value of method `print` on type `FooPrinter`
--> src/main.rs:21:28
|
21 | call(FooPrinter::new().print);
| ^^^^^ method, not a field
|
help: use parentheses to call the method
|
21 | call(FooPrinter::new().print());
| ++
For more information about this error, try `rustc --explain E0615`.
Desired output
error[E0615]: cannot use `print` on instance of type `FooPrinter` for generic
--> src/main.rs:21:28
|
21 | call(FooPrinter::new().print);
| ^^^^^ method on instance
|
help: wrap it into a closure
|
21 | call(|| FooPrinter::new().print());
| +++ ++
Rationale and extra context
As pointed out in the code example this kinda stems from the clippy lint redundant closure lint.
I had a case where I was very confused why clippy wouldn't lint this and when I removed the lamda, it gave me this error.
It also stems from a desire to have neat code and especially when the called function has many arguments, copying all the argument types into the lamda is kinda ugly. But I get why it is required for instance methods.
Other cases
a case where adding the closure actually makes the code more ugly
mod my_external_crate {
pub type AVeryVeryVeryVeryVeryVeryVeryLongType = ();
pub fn call<C>(f: C)
where
C: Fn(AVeryVeryVeryVeryVeryVeryVeryLongType, AVeryVeryVeryVeryVeryVeryVeryLongType),
{
f((), ())
}
pub struct FooPrinter {}
impl FooPrinter {
pub fn print(
&self,
_: AVeryVeryVeryVeryVeryVeryVeryLongType,
_: AVeryVeryVeryVeryVeryVeryVeryLongType,
) {
println!("foo");
}
pub fn new() -> Self {
FooPrinter {}
}
}
pub fn print_foo(
_: AVeryVeryVeryVeryVeryVeryVeryLongType,
_: AVeryVeryVeryVeryVeryVeryVeryLongType,
) {
println!("foo");
}
}
use my_external_crate::*;
fn main() {
// passing a normal function
call(print_foo);
// clippy actually does not lint this, but i think it should
call(
|x: AVeryVeryVeryVeryVeryVeryVeryLongType, y: AVeryVeryVeryVeryVeryVeryVeryLongType| {
print_foo(x, y)
},
);
// doesn't work
call(FooPrinter::new().print);
// fixed looks like clippy would lint this
call(
|x: AVeryVeryVeryVeryVeryVeryVeryLongType, y: AVeryVeryVeryVeryVeryVeryVeryLongType| {
FooPrinter::new().print(x, y)
},
);
}
Rust Version
rustc 1.97.1 (8bab26f4f 2026-07-14) (built from a source tarball) // from nixpkgs
binary: rustc
commit-hash: 8bab26f4f68e0e26f0bb7960be334d5b520ea452
commit-date: 2026-07-14
host: x86_64-unknown-linux-gnu
release: 1.97.1
LLVM version: 21.1.8
Anything else?
Sorry if my rust lingo is not on point, i still consider myself a beginner or at most intermediate in rust.
Code
Current output
Desired output
Rationale and extra context
As pointed out in the code example this kinda stems from the clippy lint redundant closure lint.
I had a case where I was very confused why clippy wouldn't lint this and when I removed the lamda, it gave me this error.
It also stems from a desire to have neat code and especially when the called function has many arguments, copying all the argument types into the lamda is kinda ugly. But I get why it is required for instance methods.
Other cases
a case where adding the closure actually makes the code more ugly
Rust Version
rustc 1.97.1 (8bab26f4f 2026-07-14) (built from a source tarball) // from nixpkgs binary: rustc commit-hash: 8bab26f4f68e0e26f0bb7960be334d5b520ea452 commit-date: 2026-07-14 host: x86_64-unknown-linux-gnu release: 1.97.1 LLVM version: 21.1.8Anything else?
Sorry if my rust lingo is not on point, i still consider myself a beginner or at most intermediate in rust.