Skip to content

'Expected <function pointer>, found <function item>' diagnostic could explicitly suggest casting #132648

Closed
@clubby789

Description

@clubby789

Code

fn foo() -> usize {
    0
}

fn bar() -> usize {
    1
}

fn main() {
    let _x: Vec<(&str, fn() -> usize)> = [("foo", foo)].into_iter().collect();
}

Current output

error[E0277]: a value of type `Vec<(&str, fn() -> usize)>` cannot be built from an iterator over elements of type `(&str, fn() -> usize {foo})`
    --> src/main.rs:10:69
     |
10   |     let _x: Vec<(&str, fn() -> usize)> = [("foo", foo)].into_iter().collect();
     |                                                                     ^^^^^^^ value of type `Vec<(&str, fn() -> usize)>` cannot be built from `std::iter::Iterator<Item=(&str, fn() -> usize {foo})>`
     |
     = help: the trait `FromIterator<(&str, fn() -> usize {foo})>` is not implemented for `Vec<(&str, fn() -> usize)>`
     = help: the trait `FromIterator<(&str, fn() -> usize)>` is implemented for `Vec<(&str, fn() -> usize)>`
     = help: for that trait implementation, expected `fn() -> usize`, found `fn() -> usize {foo}`

Desired output

error[E0277]: a value of type `Vec<(&str, fn() -> usize)>` cannot be built from an iterator over elements of type `(&str, fn() -> usize {foo})`
    --> src/main.rs:10:69
     |
10   |     let _x: Vec<(&str, fn() -> usize)> = [("foo", foo)].into_iter().collect();
     |                                                                     ^^^^^^^ value of type `Vec<(&str, fn() -> usize)>` cannot be built from `std::iter::Iterator<Item=(&str, fn() -> usize {foo})>`
     |
     = help: the trait `FromIterator<(&str, fn() -> usize {foo})>` is not implemented for `Vec<(&str, fn() -> usize)>`
     = help: the trait `FromIterator<(&str, fn() -> usize)>` is implemented for `Vec<(&str, fn() -> usize)>`
     = help: for that trait implementation, expected `fn() -> usize`, found `fn() -> usize {foo}`
     = help: consider casting the fn item to a fn pointer using `as fn() -> usize`

Rationale and extra context

If we add a second entry in the array, we get a type check error suggesting this:

  --> src/main.rs:10:65
   |
10 |     let _x: Vec<(&str, fn() -> usize)> = [("foo", foo), ("bar", bar)].into_iter().collect();
   |                                                                 ^^^ expected fn item, found a different fn item
   |
   = note: expected fn item `fn() -> _ {foo}`
              found fn item `fn() -> _ {bar}`
   = note: different fn items have unique types, even if their signatures are the same
   = help: consider casting both fn items to fn pointers using `as fn() -> usize`

This can lead to a confusing diagnostic if one is not aware of the distinction between fn items and pointers

Other cases

No response

Rust Version

$ rustc 1.84.0-nightly (662180b 2024-10-20)
binary: rustc
commit-hash: 662180b
commit-date: 2024-10-20
host: x86_64-unknown-linux-gnu
release: 1.84.0-nightly
LLVM version: 19.1.1

Anything else?

No response

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsD-confusingDiagnostics: Confusing error or lint that should be reworked.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