Function pointers for (monomorphised versions of) functions that take AsRef<Path> arguments

The point is that Fn* traits are special, because references in their signature stand in for HRTBs. Therefore this:

Fn(&Path) -> Result

is really just this:

for<'p> Fn(&'p Path) -> Result

so the fully-desugared signature of the function

fn wrapper<F: Fn(&Path) -> Result>(f: F, p: &Path) -> Result

is in fact

fn wrapper<'a, F: for<'p> Fn(&'p Path) -> Result>(f: F, p: &'a Path) -> Result

Meanwhile, when you declare an fn item like

fn operation_1<P: AsRef<Path>>(p: P) -> Result

then this is only generic (over whatever lifetime P may have); it is not a HRTB.
The type variable P thus will always be bound to a specific type (including a specific lifetime if it's a &Path) when you instantiate it.

Hence, in the following call:

wrapper(operation_1, p)

the function operation_1 will be monomorphized and instantiated with one specific type and lifetime, say &'q Path for some concrete, caller-chosen 'q, so its full type becomes:

wrapper(operation_1::<&'q Path>, p)

however, the signature of wrapper() still expects its functional argument to be higher-ranked over the lifetime! This is where the mismatch comes from.

4 Likes