Closure parameter type not inferred from `Fn` bound through a `[F; 1]` wrapper
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.2k
- PR merge metrics
- PR metrics pending
Description
Code
This program compiles and runs — it is rustc's own UI test tests/ui/issues/issue-28181.rs:
fn bar<F>(f: F) -> usize where F: Fn([usize; 1]) -> usize {
f([2])
}
fn main() {
bar(|u| { u[0] });
}
Wrapping the f parameter in a one-element array [F; 1] (destructured in the body with let [f] = _f;) and wrapping the call-site closure in [ … ] makes inference fail:
fn bar<F>(_f: [F; 1]) -> usize where F: Fn([usize; 1]) -> usize {
let [f] = _f;
f([2])
}
fn main() {
bar([|u| { u[0] }]); // <-- error[E0282]
}
Expected
Both versions compile, because the rewritten program gives the compiler exactly the same information. The argument now has expected type [F; 1], so its single element has expected type F — still carrying the bound F: Fn([usize; 1]) -> usize. In both programs the only thing that fixes the closure parameter is that Fn bound, and it is identical in both: it determines u: [usize; 1]. The array literal adds one layer of structure but no ambiguity — the type of its sole element is unambiguously F.
Actual
The array-wrapped version is rejected:
error[E0282]: type annotations needed
--> src/main.rs:7:11
|
7 | bar([|u| { u[0] }]);
| ^ - type must be known at this point
|
help: consider giving this closure parameter an explicit type
|
7 | bar([|u: /* Type */| { u[0] }]);
| ++++++++++++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0282`.
Notes
The closest existing issue is #120677, where a closure wrapped in an Option<F> argument fails to compile because the coercion of its return type fails (E0271).
That issue notes a workaround: replacing the closure body with a call to a named function whose types are explicit. The same workaround applies here — delegating to helper, whose parameter type [usize; 1] then fixes u:
fn bar<F>(_f: [F; 1]) -> usize where F: Fn([usize; 1]) -> usize {
let [f] = _f;
f([2])
}
fn helper(u: [usize; 1]) -> usize { u[0] }
fn main() {
bar([|u| { helper(u) }]); // compiles
}
Meta
rustc 1.96.0 (ac68faa20 2026-05-25)
binary: rustc
commit-hash: ac68faa20c58cbccd01ee7208bf3b6e93a7d7f96
commit-date: 2026-05-25
host: aarch64-apple-darwin
release: 1.96.0
LLVM version: 22.1.2
Tested on stable 1.96.0 only.
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 reproduction in tests/ui/issues/issue-28181.rs and run the array-wrapped closure case with the reported rustc version. Trace closure parameter inference through the Fn bound and [F; 1] wrapper. Done means the wrapped version compiles and has a regression test covering the behavior.
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
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100