Borrow Checker 1 @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: &'static u32) {
    dbg!(a);
}

fn accepts_func(f: fn(&u32), data: &u32) {
    f(data);
}

fn main() {
    //  &'static u32 can be shortened to any
    // lifetime borrow so func should be fine
    accepts_func(func, &274);
}
Solution
error[E0308]: mismatched types
  --> examples/borrowck_1.rs:12:18
   |
12 |     accepts_func(func, &274);
   |     ------------ ^^^^ one type is more general than the other
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected fn pointer `for<'a> fn(&'a _)`
                 found fn item `fn(&'static _) {func}`
note: function defined here
  --> examples/borrowck_1.rs:5:4
   |
5  | fn accepts_func(f: fn(&u32), data: &u32) {
   |    ^^^^^^^^^^^^ -----------

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

Elided lifetimes in function pointers use "for all", so fn(&u32) in accepts_func is the same as for<'a> fn(&'a u32). In other words accepts_func requires a function that can be called with a reference with any lifetime.

Notably func can't be called with any lifetime — it can only be called with 'static, causing the error.

Note that normally it's okay to shorten lifetimes, i.e. coerce &'big _ to &'small _. However, in function pointers it's different, you can coerce fn(&'small _) to fn(&'big _) but not the other way around. This is because when you call fn(&'big _) the argument can be coerced to &'small _. This is also commonly known as functions being contravariant in respect to their arguments. You can learn more about variance in the Subtyping and Variance chapter of the nomicon.