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

Confusing 'type mismatch' error when using function pointer as fn trait #73457

Open
Aaron1011 opened this issue Jun 17, 2020 · 3 comments
Open
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related D-confusing Diagnostics: Confusing error or lint that should be reworked. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Aaron1011
Copy link
Member

Aaron1011 commented Jun 17, 2020

The following code:

struct MyType;

fn parse_header<T, F: FnOnce(&MyType) -> T>(parse: F) -> T {
    panic!()
}

fn make_it(val: &MyType) -> &MyType { panic!() }

pub fn from_url<'a>() -> &'a MyType {
    parse_header(make_it)
}

fn main() {}

gives this error:

error[E0271]: type mismatch resolving `for<'r> <for<'s> fn(&'s MyType) -> &'s MyType {make_it} as std::ops::FnOnce<(&'r MyType,)>>::Output == _`
  --> src/main.rs:10:5
   |
3  | fn parse_header<T, F: FnOnce(&MyType) -> T>(parse: F) -> T {
   |                                          - required by this bound in `parse_header`
...
10 |     parse_header(make_it)
   |     ^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime

There are several issues with this error:

  • The 'type mismatch' message contains several pieces of 'internal' rust syntax (multiple consecutive for<> binders, the weird {make_it} syntax for function pointers, and an inference variable).
  • We call the return type T a 'bound', even though it's clearly not a bound.
  • We give an confusing 'expected bound lifetime parameter, found concrete lifetime' message, which doesn't really explain what's going on
  • We don't point at make_it, even though it's part of the issue.

This was minimized from code posted by @rvolosatovs.

@Aaron1011 Aaron1011 added A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: lifetime related T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. D-confusing Diagnostics: Confusing error or lint that should be reworked. labels Jun 17, 2020
@estebank
Copy link
Contributor

  • The 'type mismatch' message contains several pieces of 'internal' rust syntax (multiple consecutive for<> binders, the weird {make_it} syntax for function pointers, and an inference variable).

We can probably improve this error quite dramatically by addressing cases involving closures specifically.

  • We call the return type T a 'bound', even though it's clearly not a bound.

It is a bound, it's the Output bound in Fn(Output=T), which is sugared as Fn() -> T. We do need to make that clearer (by maybe not talking about it being a bound).

  • We don't point at make_it, even though it's part of the issue.

In E0308 we point at the parameter when possible using some hacky inference that could also be leveraged here.

@Aaron1011
Copy link
Member Author

We can probably improve this error quite dramatically by addressing cases involving closures specifically.

What makes this case tricky is that we never actually create a closure - the function pointer is used directly as F

@estebank
Copy link
Contributor

estebank commented Sep 1, 2020

Current output:

error: implementation of `std::ops::FnOnce` is not general enough
   --> src/main.rs:10:5
    |
10  |       parse_header(make_it)
    |       ^^^^^^^^^^^^ implementation of `std::ops::FnOnce` is not general enough
    |
    = note: `std::ops::FnOnce<(&'0 MyType,)>` would have to be implemented for the type `for<'r> fn(&'r MyType) -> &'r MyType {make_it}`, for some specific lifetime `'0`...
    = note: ...but `std::ops::FnOnce<(&MyType,)>` is actually implemented for the type `for<'r> fn(&'r MyType) -> &'r MyType {make_it}`

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 A-lifetimes Area: lifetime related D-confusing Diagnostics: Confusing error or lint that should be reworked. 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

2 participants