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.