unhelpful error when giving an instance method to a generic function requiring a function
@Yogeshwaran-Projects is already working on this.
Since Sep 2, 2026.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.