If you mean to ask about the difference between PhantomData<M> and PhantomData<fn(M) -> M>, it has to do with a fairly advanced Rust notion:
Subtyping and Variance
To take a simpler example, let's imagine that M = &'s str, so that now we "just" have a generic lifetime parameter rather than a whole generic type parameter.
Let's simplify your MetricConsumer into a newtype wrapper over a F : FnOnce(&'s str):
struct Function<'s, F : FnOnce(&'s str)> (
F,
Phantom<'s>,
);
What should Phantom<'s> be?
PhantomData<&'s str> or PhantomData<fn(&'s str)>?
Let's see why it shouldn't be PhantomData<&'s str>.
We can call this function with a caller-chosen 's thanks to the following function:
fn call<'s, F> (function: Function<'s, F>, s: &'s str)
where
F : FnOnce(&'s str),
{
(function.0)(s)
}
And now the interesting part:
-
imagine having some fn(&'s str) function, and a &'static str string
fn foo<'s> (f: fn(&'s str), s: &'static str) {
-
you happen to wrap your function into the Function wrapper struct:
let function: Function<'s, _> = Function(f, PhantomData);
-
and now you want to call it:
call::<'static, _>(
// `f: Function<'s, _>`, but the required type here is:
// `Function<'static, _>`
function,
string,
);
This ought to be fine: if the function f is able to handle an input string with a short lifetime 's, then it is sound for f to receive an input string which is valid for an even longer lifetime ('static).
That is, the type fn(&'s str) can be seen as a fn(&'static str), given that 'static : 's.
This is what we call contravariance!
Contravariance example
type F<'lifetime> = fn(&'lifetime str) verifies that
'static : 's ⟹ F<'s> : F<'static>
(the subtyping order is reversed).
This form of variance is opposite to the more classic one, covariance:
Covariance example
type F<'lifetime> = &'lifetime str verifies that
'static : 's ⟹ F<'static> : F<'s>
(the subtyping order is kept as-is)
So, when defining Phantom<'s> as PhantomData<&'s str>, Phantom<'s> is not contravariant in 's, making the Function wrapper not contravariant in 's, which makes the above foo() function fail to compile and yield:
error[E0308]: mismatched types
--> src/lib.rs:31:9
|
31 | function,
| ^^^^^^^^ lifetime mismatch
|
= note: expected type `Function<'static, fn(&str)>`
found type `Function<'s, fn(&str)>`
note: the lifetime 's as defined on the function body at 25:8...
--> src/lib.rs:25:8
|
25 | fn foo<'s> (f: fn(&'s str), string: &'static str)
| ^^
= note: ...does not necessarily outlive the static lifetime
That's why we should define Phantom<'s> as PhantomData<fn(&'s str)>: Phantom<'s> is indeed contravariant in 's, letting the Function wrapper be so. The code then compiles just fine.