Skip to content

Unsatisfied trait bound on fn item should suggest as fn() if it is satisfied for fn pointer #99922

Closed
@CAD97

Description

@CAD97

Given the following code: [playground]

trait Trait {}
impl Trait for fn() {}
fn take(_: impl Trait) {}

fn f() {}
fn main() {
    take(f);
}

The current output is:

error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): the trait bound `fn() {f}: Trait` is not satisfied
 --> src/main.rs:7:10
  |
7 |     take(f);
  |     ---- ^ the trait `Trait` is not implemented for `fn() {f}`
  |     |
  |     required by a bound introduced by this call
  |
  = help: the trait `Trait` is implemented for `fn()`
note: required by a bound in `take`
 --> src/main.rs:3:17
  |
3 | fn take(_: impl Trait) {}
  |                 ^^^^^ required by this bound in `take`

Ideally the output should look like:

error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): the trait bound `fn() {f}: Trait` is not satisfied
 --> src/main.rs:7:10
  |
7 |     take(f);
  |     ---- ^ the trait `Trait` is not implemented for fn item `fn() {f}`
  |     |
  |     required by a bound introduced by this call
  |
  = help: the trait `Trait` is implemented for fn pointer `fn()`
note: required by a bound in `take`
 --> src/main.rs:3:17
  |
3 | fn take(_: impl Trait) {}
  |                 ^^^^^ required by this bound in `take`
  |
help: Convert the fn item to a fn pointer with `as`
  |
7 |     take(f as fn());
  |           ++++++++
A more involved diagnostic example:

[playground]

trait Trait {}
impl<A: PartialEq> Trait for A {}
fn take(_: impl Trait) {}

fn f() {}
fn main() {
    take(f);
}

The current output is:

error[[E0277]](https://doc.rust-lang.org/nightly/error-index.html#E0277): can't compare `fn() {f}` with `fn() {f}`
 --> src/main.rs:7:10
  |
7 |     take(f);
  |     ---- ^ no implementation for `fn() {f} == fn() {f}`
  |     |
  |     required by a bound introduced by this call
  |
  = help: the trait `PartialEq` is not implemented for `fn() {f}`
  = help: the following other types implement trait `PartialEq<Rhs>`:
            extern "C" fn() -> Ret
            extern "C" fn(A, B) -> Ret
            extern "C" fn(A, B, ...) -> Ret
            extern "C" fn(A, B, C) -> Ret
            extern "C" fn(A, B, C, ...) -> Ret
            extern "C" fn(A, B, C, D) -> Ret
            extern "C" fn(A, B, C, D, ...) -> Ret
            extern "C" fn(A, B, C, D, E) -> Ret
          and 68 others
note: required because of the requirements on the impl of `Trait` for `fn() {f}`
 --> src/main.rs:2:20
  |
2 | impl<A: PartialEq> Trait for A {}
  |                    ^^^^^     ^
note: required by a bound in `take`
 --> src/main.rs:3:17
  |
3 | fn take(_: impl Trait) {}
  |                 ^^^^^ required by this bound in `take`

Ideally the output should look like:

error[[E0277]](https://doc.rust-lang.org/nightly/error-index.html#E0277): can't compare `fn() {f}` with `fn() {f}`
 --> src/main.rs:7:10
  |
7 |     take(f);
  |     ---- ^ no implementation for `fn() {f} == fn() {f}`
  |     |
  |     required by a bound introduced by this call
  |
  = help: the trait `PartialEq` is not implemented for fn item `fn() {f}`
  = help: the trait `PartialEq` is implemented for fn pointer `fn()`
note: required because of the requirements on the impl of `Trait` for `fn() {f}`
 --> src/main.rs:2:20
  |
2 | impl<A: PartialEq> Trait for A {}
  |                    ^^^^^     ^
note: required by a bound in `take`
 --> src/main.rs:3:17
  |
3 | fn take(_: impl Trait) {}
  |                 ^^^^^ required by this bound in `take`
  |
help: Convert the fn item to a fn pointer with `as`
  |
7 |     take(f as fn());
  |           ++++++++

(bonus side effect: hiding the giant list of explicit variadic fn pointer impls)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-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