"implementation of `Fn` is not general enough" on some conditions when using closures
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Hello rust team!
I crossed the following compiler error.
There is a lifetime elision problem on closures on some specific conditions
- they accept as input a struct with a lifetime
- they are transmited to a function accepting multiple of them as generics
Quite hard to explain with words, so here is the simplified example:
The code:
pub struct InodeMapper;
pub struct ValueCreatorParams<'a> {
pub child_name: &'a u32,
}
impl InodeMapper {
pub fn batch_insert<F, G>(
&self,
f1: F,
f2: G
)
where
F: for <'a> Fn(ValueCreatorParams<'a>) -> u32,
G: for <'b> Fn(ValueCreatorParams<'b>) -> i32
{
todo!()
}
}
fn test_batch_insert_large_entries_varying_depths() {
let mapper = InodeMapper{};
let f1 = |_| 1;
let f2 = |_| 2;
// *** ERROR ON FOLLOWING LINE ***
mapper.batch_insert(f1, f2);
}
The error
implementation of `Fn` is not general enough
closure with signature `fn(test::ValueCreatorParams<'2>) -> u32` must implement `Fn<(test::ValueCreatorParams<'1>,)>`, for any lifetime `'1`...
...but it actually implements `Fn<(test::ValueCreatorParams<'2>,)>`, for some specific lifetime `'2`rustc[Click for full compiler diagnostic](rust-analyzer-diagnostics-view:/diagnostic%20message%20[4]?4#file:///home/alogani/Coding/easy_fuser/src/types/test.rs)
implementation of `FnOnce` is not general enough
closure with signature `fn(test::ValueCreatorParams<'2>) -> u32` must implement `FnOnce<(test::ValueCreatorParams<'1>,)>`, for any lifetime `'1`...
...but it actually implements `FnOnce<(test::ValueCreatorParams<'2>,)>`, for some specific lifetime `'2`rustc[Click for full compiler diagnostic](rust-analyzer-diagnostics-view:/diagnostic%20message%20[5]?5#file:///home/alogani/Coding/easy_fuser/src/types/test.rs)
The solution:
Fully qualify the types of the closure arguments (for both)!
fn test_batch_insert_large_entries_varying_depths() {
let mapper = InodeMapper{};
let f1 = |_: ValueCreatorParams| 1;
let f2 = |_: ValueCreatorParams| 2;
mapper.batch_insert(f1, f2);
}
And now it works like a charm !
Meta
rustc --version --verbose:
rustc 1.82.0 (f6e511eec 2024-10-15)
binary: rustc
commit-hash: f6e511eec7342f59a25f7c0534f1dbea00d01b14
commit-date: 2024-10-15
host: x86_64-unknown-linux-gnu
release: 1.82.0
LLVM version: 19.1.1
## Suggestions
Obviously, it has a solution, but I fill the bug report, because:
- this is a situation where I don't understand why the compiler can't infer the lifetime. (Maybe there is a reason a good reason and it shall not be corrected? To be honest, I am not sure to understand the intrinsics)
- the error is not explicit (it took me several hours to isolate correctly the cause of the problem in my more complex codebase, I thought the problem were on signatures of the receiving function). So is there an improvement possible on compiler message ? Especially the compiler don't say how it infers a different lifetime for the two closures to help resolve the problem.
Thanks!
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.
Research direction
Start with the minimized Rust example in the issue and reproduce it using rustc 1.82.0, comparing the inferred closure signatures with the explicitly typed version. Investigate whether the behavior is expected and whether the reported Fn/FnOnce diagnostics can be made clearer; done means a documented compiler conclusion, regression test, or diagnostic improvement.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100