Skip to content
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

casting trait methods to FnOnce(&mut dyn Trait) is not ergonomic #68589

Open
programmerjake opened this issue Jan 28, 2020 · 4 comments
Open
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@programmerjake
Copy link
Member

In the following code, I'm trying to cast Trait::f to FnOnce(&mut dyn Trait) which should be possible, but the obvious method doesn't work. None of the combinations I tried got it to work (I could just use a lambda that called f, but that defeats the purpose).

trait Trait {
    fn f(&mut self);
}

fn g<F: FnOnce(&mut dyn Trait)>(f: F) {}

fn f() {
    g(Trait::f)
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0631]: type mismatch in function arguments
 --> src/lib.rs:8:7
  |
2 |     fn f(&mut self);
  |     ---------------- found signature of `for<'r> fn(&'r mut _) -> _`
...
5 | fn g<F: FnOnce(&mut dyn Trait)>(f: F) {}
  |    -    ---------------------- required by this bound in `g`
...
8 |     g(Trait::f)
  |       ^^^^^^^^ expected signature of `for<'r> fn(&'r mut (dyn Trait + 'r)) -> _`

error[E0271]: type mismatch resolving `for<'r> <for<'s> fn(&'s mut _) {<_ as Trait>::f} as std::ops::FnOnce<(&'r mut (dyn Trait + 'r),)>>::Output == ()`
 --> src/lib.rs:8:5
  |
5 | fn g<F: FnOnce(&mut dyn Trait)>(f: F) {}
  |    -    ---------------------- required by this bound in `g`
...
8 |     g(Trait::f)
  |     ^ expected bound lifetime parameter, found concrete lifetime

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0271`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

@programmerjake
Copy link
Member Author

I'm reporting this here because I consider it a UI bug.

@jonas-schievink jonas-schievink added A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 28, 2020
@estebank
Copy link
Contributor

You can make this work by introducing an extra type parameter: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=3b4a9c25c6acae74ef2da4bc9f137163

The error happens because Self is not dyn Trait.

@programmerjake
Copy link
Member Author

You can make this work by introducing an extra type parameter: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=3b4a9c25c6acae74ef2da4bc9f137163

The error happens because Self is not dyn Trait.

I don't think that will work for my particular usecase, since I have a dyn Trait that I pass to another function along with the particular trait method to call:

trait Trait {
    fn f(&mut self);
}

fn g<F: FnOnce(&mut dyn Trait)>(f: F, v: &mut dyn Trait) {
    f(v)
}

fn f(v: &mut dyn Trait) {
    g(Trait::f, v)
}

@estebank
Copy link
Contributor

It can work if your type param T doesn't require it to be Sized. #57744 covers guiding people in that direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants