Skip to content

Suggest impl Fn() in return type when trying to return a closure coerced to fn() pointer #159481

Description

@estebank

Code

fn offsetter(offset: i32) -> fn(i32) -> i32 { // should have been `impl Fn(i32) -> i32`.
    |value| value + offset
    //~^ ERROR mismatched types
}

fn main() {}

Current output

error[E0308]: mismatched types
 --> src/main.rs:2:5
  |
1 | fn offsetter(offset: i32) -> fn(i32) -> i32 { // `impl Fn(i32) -> i32`.
  |                              -------------- expected `fn(i32) -> i32` because of return type
2 |     |value| value + offset
  |     ^^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure
  |
  = note: expected fn pointer `fn(i32) -> i32`
                found closure `{closure@src/main.rs:2:5: 2:12}`
note: closures can only be coerced to `fn` types if they do not capture any variables
 --> src/main.rs:2:21
  |
2 |     |value| value + offset
  |                     ^^^^^^ `offset` captured here

Desired output

error[E0308]: mismatched types
 --> src/main.rs:2:5
  |
1 | fn offsetter(offset: i32) -> fn(i32) -> i32 { // `impl Fn(i32) -> i32`.
  |                              -------------- expected `fn(i32) -> i32` because of return type
2 |     |value| value + offset
  |     ^^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure
  |
  = note: expected fn pointer `fn(i32) -> i32`
                found closure `{closure@src/main.rs:2:5: 2:12}`
note: closures can only be coerced to `fn` types if they do not capture any variables
 --> src/main.rs:2:21
  |
2 |     |value| value + offset
  |                     ^^^^^^ `offset` captured here
help: change the return type to return a type-erased closure instead
  |
1 - fn offsetter(offset: i32) -> fn(i32) -> i32 { // `impl Fn(i32) -> i32`.
1 + fn offsetter(offset: i32) -> impl Fn(i32) -> i32 { // `impl Fn(i32) -> i32`.
  |

Rationale and extra context

The distinction is not necessarily easy to understand for newcomers to the language.

Other cases

Rust Version

1.97

Anything else?

No response

Metadata

Metadata

Assignees

Labels

A-closuresArea: Closures (`|…| { … }`)A-diagnosticsArea: Messages for errors, warnings, and lintsA-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.A-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`D-lack-of-suggestionDiagnostics: Adding a (structured) suggestion would increase the quality of the diagnostic.D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.T-compilerRelevant to the compiler 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