Overloaded call inferred to be through Fn when only FnOnce works

2ca09b4
Opened by june at 2023-09-28 04:19:29

Repro: https://is.gd/AbO8K4

A wrapper around a closure F implements FnOnce, FnMut and Fn where F does. However, when the wrapper is created with a closure which implements only FnOnce, and then the wrapper is called, the compiler expects the closure to implement FnMut or Fn.

rustc 1.15.0-nightly (daf8c1dfc 2016-12-05)
binary: rustc
commit-hash: daf8c1dfce3b448fc581cc319f64632ec22bd0e1
commit-date: 2016-12-05
host: x86_64-apple-darwin
release: 1.15.0-nightly
LLVM version: 3.9

cc @eddyb (discussed on IRC)

  1. cc @nikomatsakis @nagisa Is this one of the closure inference cases where the current algorithm is suboptimal? AFAICT the wrong trait is inferred at the callsite and it's not changed later, or even if it's changed to FnOnce there might be some obligation left around.

    Error for posterity:

    error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
      --> <anon>:31:26
       |
    31 |     let f = Wrapper { f: || foo };
       |                          ^^^^^^
       |
    note: the requirement to implement `Fn` derives from here
      --> <anon>:32:5
       |
    32 |     f();
       |     ^^^
    

    Eduard-Mihai Burtescu at 2016-12-11 19:42:12

  2. Looks like this also applies to closures only implementing FnMut and the compiler wants it to be Fn: https://is.gd/7U8lK6

    june at 2016-12-11 19:43:01

  3. triage: P-medium

    Niko Matsakis at 2016-12-22 21:41:42

  4. I'll try to investigate.

    Niko Matsakis at 2016-12-22 21:41:58

  5. Perhaps related to #26186 ?

    Jake Goulding at 2017-09-28 15:04:27

  6. Triage: Doesn't seem like it, because this still reproduces even though https://github.com/rust-lang/rust/issues/26186 is fixed.

    Martin Nordholts at 2023-09-28 04:19:29