rust-lang / rust-lang/rust

Closure parameter type not inferred from `Fn` bound through a `[F; 1]` wrapper

Open
#157,468 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-inference C-enhancement needs-triage T-types
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.