Skip to content

Mismatch reported for fn impl with HRTB lifetime without cast #112046

Open
@mqudsi

Description

type IntCallback = fn(&i32);

enum Callback {
    Int(IntCallback)
}

impl Into<Callback> for for<'a> fn(&'a i32) {
    fn into(self) -> Callback {
        Callback::Int(self)
    }
}

fn callback(_: &i32) {
}

fn main() {
    let callback: Callback = callback.into();
}

I expected to see this happen: the impl for the fn pointer should be picked up and used.

Instead, this happened:

Compiling playground v0.0.1 (/playground)
error[[E0277]](https://doc.rust-lang.org/nightly/error_codes/E0277.html): the trait bound `Callback: From<for<'a> fn(&'a i32) {callback}>` is not satisfied
  --> src/main.rs:17:39
   |
17 |     let callback: Callback = callback.into();
   |                                       ^^^^ the trait `From<for<'a> fn(&'a i32) {callback}>` is not implemented for `Callback`
   |
   = help: the trait `Into<Callback>` is implemented for fn pointer `for<'a> fn(&'a i32)`, cast using `as`
   = note: required for `for<'a> fn(&'a i32) {callback}` to implement `Into<Callback>`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (bin "playground") due to previous error

Since callback can be passed directly to a function taking IntCallback as a parameter, it should be possible for the existing From<> impl to be used directly.

This makes it extremely verbose to use generic bounds to accept a callback:

fn callback(_: &i32) {
}

fn foo<C: Into<Callback>>(c: C) {
    todo!();
}

fn main() {
    foo(callback);
}

which returns

error[[E0277]](https://doc.rust-lang.org/nightly/error_codes/E0277.html): the trait bound `Callback: From<for<'a> fn(&'a i32) {callback}>` is not satisfied
  --> src/main.rs:17:9
   |
17 |     foo(callback);
   |     --- ^^^^^^^^ the trait `From<for<'a> fn(&'a i32) {callback}>` is not implemented for `Callback`
   |     |
   |     required by a bound introduced by this call
   |
   = help: the trait `Into<Callback>` is implemented for fn pointer `for<'a> fn(&'a i32)`, cast using `as`
   = note: required for `for<'a> fn(&'a i32) {callback}` to implement `Into<Callback>`
note: required by a bound in `foo`
  --> src/main.rs:20:11
   |
20 | fn foo<C: Into<Callback>>(c: C) {
   |           ^^^^^^^^^^^^^^ required by this bound in `foo`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (bin "playground") due to previous error

Playground link: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=c367afd81fc7219e802099735acc2507

Side note: the diagnostics for this have drastically improved in the latest nightlies. The nightly build I have installed didn't give me the "cast using as" hint and instead said "type xxxx doesn't implement Foo, implemented for <same type xxxx>"

Meta

rustc --version --verbose:

 1.71.0-nightly (2023-05-27 cca7ee58110726983951)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-higher-rankedArea: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)A-lifetimesArea: Lifetimes / regionsD-confusingDiagnostics: Confusing error or lint that should be reworked.D-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.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