Skip to content

Closure Fn* trait coercion removes other implementable Fn* traits #129381

Open
@konnorandrews

Description

@konnorandrews

I tried this code:

fn demo<F: FnOnce()>(f: F) -> F { f }

fn other<F: Fn()>(_f: F) {}

fn main() {
    let x = || ();
    other(x); 
    
    let x = demo(|| ());
    other(x); 
}

I expected to see this happen: The code to compile.

Instead, this happened: Compilation failed stating the second x does not implement Fn.

error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
  --> src/main.rs:9:18
   |
9  |     let x = demo(|| ());
   |                  ^^ this closure implements `FnOnce`, not `Fn`
10 |     other(x); 
   |     ----- - the requirement to implement `Fn` derives from here
   |     |
   |     required by a bound introduced by this call
   |
note: required by a bound in `other`
  --> src/main.rs:3:13
   |
3  | fn other<F: Fn()>(_f: F) {}
   |             ^^^^ required by this bound in `other`

playground

I would expect this to either compile fine (which means changing something about how closure coercion works) or for the diagnostic given to point at the coercion to a FnOnce for the reason why it doesn't implement the Fn trait.

Meta

rustc --version --verbose:

rustc 1.80.1 (3f5fd8dd4 2024-08-06)
binary: rustc
commit-hash: 3f5fd8dd41153bc5fdca9427e9e05be2c767ba23
commit-date: 2024-08-06
host: x86_64-unknown-linux-gnu
release: 1.80.1
LLVM version: 18.1.7

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-inferenceArea: Type inferenceC-bugCategory: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions