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.