Trait Solver 6 @WaffleLapkin @BoxyUwU

Warning: this quiz is still "work-in-progress", some questions might not have good explanations (or any at all), formatting/structure/titles/etc are not final, and so on. You might want to return here on a later date.

fn func(a: &u32) {
    dbg!(a);
}

fn accepts_func(b: fn(&u32), c: &u32) {
    b(c);
}

fn main() {
    accepts_func(func as fn(_), &23);
}
Solution
error[E0308]: mismatched types
  --> examples/trait_solver_6.rs:10:18
   |
10 |     accepts_func(func as fn(_), &23);
   |     ------------ ^^^^^^^^^^^^^ one type is more general than the other
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected fn pointer `for<'a> fn(&'a u32)`
              found fn pointer `fn(_)`
note: function defined here
  --> examples/trait_solver_6.rs:5:4
   |
5  | fn accepts_func(b: fn(&u32), c: &u32) {
   |    ^^^^^^^^^^^^ -----------

For more information about this error, try `rustc --explain E0308`.
error: could not compile `code` (example "trait_solver_6") due to 1 previous error

Let's first explicitly annotate all elided lifetimes:

fn func<'a>(a: &'a u32) {
    dbg!(a);
}

fn accepts_func<'a>(b: for<'b> fn(&'b u32), c: &'a u32) {
    b(c);
}

fn main() {
    accepts_func(func as fn(_), &23);
}

func is a higher-ranked function of type for<'a> fn(&'a u32). This means it can accept any lifetime. accepts_func's first parameter b is also a higher ranked function of the same type, so it needs a function that can accept any lifetime.

But in main, we cast the higher-ranked function type to fn(_). fn(_) is inferred to not be a higher-ranked function pointer type (inferring a specific lifetime for the argument), so it is no longer valid to pass to accepts_func.

If we instead specify it as as fn(&_) it gets inferred as a higher-ranked function pointer type again and the program compiles. Specifying an inferred type as &_ is sometimes done in real programs for closure arguments to make sure the closure type is inferred to be higher-ranked.