Higher-ranked lifetime bounds give confusing errors

93bb447
Opened by wthrowe at 2024-09-24 22:56:43
#![allow(dead_code)]

fn x(_: &()) {}

trait HR {}
impl HR for fn(&()) {}
fn hr<T: HR>(_: T) {}

trait NotHR {}
impl<'a> NotHR for fn(&'a ()) {}
fn not_hr<T: NotHR>(_: T) {}

fn a<'a>() {
    let not_hr_func: fn(&'a ()) = x;
    let hr_func: fn(&()) = x;
    let hr_func2: for<'b> fn(&'b ()) = x;
    hr(not_hr_func);
    not_hr(hr_func);
    not_hr(hr_func2);
}

fn main() {}

gives

<anon>:17:5: 17:7 error: the trait `HR` is not implemented for the type `fn(&())` [E0277]
<anon>:17     hr(not_hr_func);
              ^~
<anon>:17:5: 17:7 help: see the detailed explanation for E0277
<anon>:17:5: 17:7 note: required by `hr`
<anon>:18:5: 18:11 error: the trait `NotHR` is not implemented for the type `fn(&())` [E0277]
<anon>:18     not_hr(hr_func);
              ^~~~~~
<anon>:18:5: 18:11 help: see the detailed explanation for E0277
<anon>:18:5: 18:11 note: required by `not_hr`
<anon>:19:5: 19:11 error: the trait `NotHR` is not implemented for the type `fn(&'b ())` [E0277]
<anon>:19     not_hr(hr_func2);
              ^~~~~~
<anon>:19:5: 19:11 help: see the detailed explanation for E0277
<anon>:19:5: 19:11 note: required by `not_hr`
error: aborting due to 3 previous errors
playpen: application terminated with error code 101

Summarizing, given the type declaration, we have the printed form:

| Declaration | Display | | --- | --- | | fn(&'a ()) | fn(&()) | | fn(&()) | fn(&()) | | for<'b> fn(&'b ()) | fn(&'b ()) |

So the non-higher-ranked type has its lifetime elided and is printed like a higher-ranked type, and higher-ranked types are sometimes printed without the quantifier but with the lifetime, looking like non-higher-ranked types.

  1. the message now seems to be as follows - would that be good enough, @wthrowe ?

        rustc 1.18.0 (03fc9d622 2017-06-06)
    error[E0277]: the trait bound `fn(&()): HR` is not satisfied
      --> <anon>:17:5
       |
    17 |     hr(not_hr_func);
       |     ^^ the trait `HR` is not implemented for `fn(&())`
       |
       = help: the following implementations were found:
    	     <fn(&()) as HR>
       = note: required by `hr`
    
    error[E0277]: the trait bound `fn(&()): NotHR` is not satisfied
      --> <anon>:18:5
       |
    18 |     not_hr(hr_func);
       |     ^^^^^^ the trait `NotHR` is not implemented for `fn(&())`
       |
       = help: the following implementations were found:
    	     <fn(&'a ()) as NotHR>
       = note: required by `not_hr`
    
    error[E0277]: the trait bound `fn(&'b ()): NotHR` is not satisfied
      --> <anon>:19:5
       |
    19 |     not_hr(hr_func2);
       |     ^^^^^^ the trait `NotHR` is not implemented for `fn(&'b ())`
       |
       = help: the following implementations were found:
    	     <fn(&'a ()) as NotHR>
       = note: required by `not_hr`
    
    error: aborting due to 3 previous errors
    

    Cyryl Płotnicki at 2017-06-28 07:00:17

  2. Triage:

    rustc: 1.32.0 errors with the same message cyplo posted

    rust version 1.33.0-beta.4 (635817b9d 2019-01-24) errors with the following:

    error[E0308]: mismatched types
      --> src/main.rs:17:5
       |
    17 |     hr(not_hr_func);
       |     ^^ one type is more general than the other
       |
       = note: expected type `HR`
                  found type `HR`
    

    rust version 1.34.0-nightly (c1c3c4e95 2019-01-29) errors with the following:

    error: implementation of `HR` is not general enough
      --> src/main.rs:17:5
       |
    17 |     hr(not_hr_func);
       |     ^^
       |
       = note: Due to a where-clause on `hr`,
       = note: `HR` would have to be implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
       = note: but `HR` is actually implemented for the type `for<'r> fn(&'r ())`
    

    memoryruins at 2019-01-30 23:31:49

  3. Current output:

    error[E0277]: the trait bound `fn(&()): HR` is not satisfied
      --> file5.rs:17:8
       |
    7  | fn hr<T: HR>(_: T) {}
       | ------------------ required by `hr`
    ...
    17 |     hr(not_hr_func);
       |        ^^^^^^^^^^^ the trait `HR` is not implemented for `fn(&())`
       |
       = help: the following implementations were found:
                 <for<'r> fn(&'r ()) as HR>
    
    error[E0277]: the trait bound `for<'r> fn(&'r ()): NotHR` is not satisfied
      --> file5.rs:18:12
       |
    11 | fn not_hr<T: NotHR>(_: T) {}
       | ------------------------- required by `not_hr`
    ...
    18 |     not_hr(hr_func);
       |            ^^^^^^^ the trait `NotHR` is not implemented for `for<'r> fn(&'r ())`
       |
       = help: the following implementations were found:
                 <fn(&'a ()) as NotHR>
    
    error[E0277]: the trait bound `for<'b> fn(&'b ()): NotHR` is not satisfied
      --> file5.rs:19:12
       |
    11 | fn not_hr<T: NotHR>(_: T) {}
       | ------------------------- required by `not_hr`
    ...
    19 |     not_hr(hr_func2);
       |            ^^^^^^^^ the trait `NotHR` is not implemented for `for<'b> fn(&'b ())`
       |
       = help: the following implementations were found:
                 <fn(&'a ()) as NotHR>
    

    The only case that doesn't refer to the signature in the same way it was written is fn(&())/for<'r> fn(&'r ()).

    Esteban Kuber at 2019-09-21 21:01:28

  4. Update, little change:

    error[E0277]: the trait bound `fn(&()): HR` is not satisfied
      --> src/main.rs:17:8
       |
    7  | fn hr<T: HR>(_: T) {}
       |          -- required by this bound in `hr`
    ...
    17 |     hr(not_hr_func);
       |        ^^^^^^^^^^^ the trait `HR` is not implemented for `fn(&())`
       |
       = help: the following implementations were found:
                 <for<'r> fn(&'r ()) as HR>
    
    error[E0277]: the trait bound `for<'r> fn(&'r ()): NotHR` is not satisfied
      --> src/main.rs:18:12
       |
    11 | fn not_hr<T: NotHR>(_: T) {}
       |              ----- required by this bound in `not_hr`
    ...
    18 |     not_hr(hr_func);
       |            ^^^^^^^ the trait `NotHR` is not implemented for `for<'r> fn(&'r ())`
       |
       = help: the following implementations were found:
                 <fn(&'a ()) as NotHR>
    
    error[E0277]: the trait bound `for<'b> fn(&'b ()): NotHR` is not satisfied
      --> src/main.rs:19:12
       |
    11 | fn not_hr<T: NotHR>(_: T) {}
       |              ----- required by this bound in `not_hr`
    ...
    19 |     not_hr(hr_func2);
       |            ^^^^^^^^ the trait `NotHR` is not implemented for `for<'b> fn(&'b ())`
       |
       = help: the following implementations were found:
                 <fn(&'a ()) as NotHR>
    

    Esteban Kuber at 2020-06-11 18:59:03

  5. Current output:

    error: implementation of `HR` is not general enough
      --> src/main.rs:17:5
       |
    17 |     hr(not_hr_func);
       |     ^^^^^^^^^^^^^^^ implementation of `HR` is not general enough
       |
       = note: `HR` would have to be implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`...
       = note: ...but `HR` is actually implemented for the type `for<'a> fn(&'a ())`
    
    error: implementation of `NotHR` is not general enough
      --> src/main.rs:18:5
       |
    18 |     not_hr(hr_func);
       |     ^^^^^^^^^^^^^^^ implementation of `NotHR` is not general enough
       |
       = note: `NotHR` would have to be implemented for the type `for<'a> fn(&'a ())`
       = note: ...but `NotHR` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
    

    Dylan DPC at 2023-05-26 11:14:10