Skip to content

"Expected type [closure@...], found fn pointer" when unnecessarily returning a closure #88097

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kpreid opened this issue Aug 17, 2021 · 2 comments · Fixed by #88147
Closed
Assignees
Labels
A-closures Area: Closures (`|…| { … }`) A-diagnostics Area: Messages for errors, warnings, and lints A-inference Area: Type inference T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@kpreid
Copy link
Contributor

kpreid commented Aug 17, 2021

Given the following code:

fn peculiar() -> impl Fn(u8) -> u8 {
    return |x| x + 1
}

The current output is:

error[E0308]: mismatched types
 --> src/lib.rs:1:36
  |
1 |   fn peculiar() -> impl Fn(u8) -> u8 {
  |  ____________________________________^
2 | |     return |x| x + 1
3 | | }
  | |_^ expected closure, found fn pointer
  |
  = note:    expected type `[closure@src/lib.rs:2:12: 2:21]`
          found fn pointer `fn(u8) -> u8`

Ideally the code would compile successfully, but if that is infeasible, it would be nice if the diagnostic contained a hint to remove the return. (It's rather head-scratching that the closure is being converted to a fn pointer even though the return type has also been resolved to be the closure type.)

The return is entirely unnecessary here, but I imagine a beginner might include it unthinkingly (as I did) and not be able to even guess that the return has anything to do with the type error.


The results are the same on stable 1.54.0, beta, and nightly.

If I modify the closure to not be coercible to a function pointer by capturing a variable, then the code compiles without error or relevant warning:

fn peculiar(y: u8) -> impl Fn(u8) -> u8 {
    return move |x| x + y
}
@kpreid kpreid added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 17, 2021
@kpreid
Copy link
Contributor Author

kpreid commented Aug 17, 2021

@rustbot label: +A-closures +A-inference

@rustbot rustbot added A-closures Area: Closures (`|…| { … }`) A-inference Area: Type inference labels Aug 17, 2021
@FabianWolff
Copy link
Contributor

Interestingly, this compiles (note the semicolon):

fn peculiar() -> impl Fn(u8) -> u8 {
    return |x| x + 1;
}

@rustbot claim

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Sep 11, 2021
Fix non-capturing closure return type coercion

Fixes rust-lang#88097. For the example given there:
```rust
fn peculiar() -> impl Fn(u8) -> u8 {
    return |x| x + 1
}
```
which incorrectly reports an error, I noticed something weird in the debug log:
```
DEBUG rustc_typeck::check::coercion coercion::try_find_coercion_lub([[email protected]:2:12: 2:21], [[email protected]:2:12: 2:21], exprs=1 exprs)
```
Apparently, `try_find_coercion_lub()` thinks that the LUB for two closure types always has to be a function pointer (which explains the `expected closure, found fn pointer` error in rust-lang#88097). There is one corner case where that isn't true, though — namely, when the two closure types are equal, in which case the trivial LUB is the type itself. This PR fixes this by inserting an explicit check for type equality in `try_find_coercion_lub()`.
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Sep 11, 2021
Fix non-capturing closure return type coercion

Fixes rust-lang#88097. For the example given there:
```rust
fn peculiar() -> impl Fn(u8) -> u8 {
    return |x| x + 1
}
```
which incorrectly reports an error, I noticed something weird in the debug log:
```
DEBUG rustc_typeck::check::coercion coercion::try_find_coercion_lub([[email protected]:2:12: 2:21], [[email protected]:2:12: 2:21], exprs=1 exprs)
```
Apparently, `try_find_coercion_lub()` thinks that the LUB for two closure types always has to be a function pointer (which explains the `expected closure, found fn pointer` error in rust-lang#88097). There is one corner case where that isn't true, though — namely, when the two closure types are equal, in which case the trivial LUB is the type itself. This PR fixes this by inserting an explicit check for type equality in `try_find_coercion_lub()`.
@bors bors closed this as completed in 94cbefb Sep 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-closures Area: Closures (`|…| { … }`) A-diagnostics Area: Messages for errors, warnings, and lints A-inference Area: Type inference T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants