Haven’t watched through the relevant section fully yet, but if avoiding confusion is the main goal, a diagnostic that suggests adding an as fn(…) -> …
cast might be enough. Furthermore, such a diagnostic could be a good first step anyway in evaluating how reliably the compiler can detect cases like this where coercing to a function pointer type makes a trait bound work, and how reliably the right function pointer type can be inferred… etc.
One additional point of confusion is how function types are written. for<'r> fn(&'r [Guess]) -> String {guess}
does hardly indicate clearly enough that “this type is not the same as for<'r> fn(&'r [Guess]) -> String
”, even though probably half the time you’ll run into this in error messages, it’ll be absolutely crucial for you to understand that you don’t have a function pointer type.
Maybe it should look more like closure types, something like
[function item `guess`: for<'r> fn(&'r [Guess]) -> String]
while we’re at it, closure types could probably benefit from having a visible signature, too, so something like
[closure@src/lib.rs(112:40 - 112:69): for<'r> fn(&'r [Guess]) -> String]
for a non-capturing closure, and something like
[closure@src/lib.rs(112:40 - 112:69): for<'r> Fn(&'r [Guess]) -> String]
or
[closure@src/lib.rs(112:40 - 112:69): for<'r> FnMut(&'r [Guess]) -> String]
or
[closure@src/lib.rs(112:40 - 112:69): for<'r> FnOnce(&'r [Guess]) -> String]
for capturing closures, depending on what the most general function trait they implement is.