you need the annotation not because it's ambiguous, but because the type inference fails in this case.
there are many cases where the types seem to be obvious to humans, but the type inference algorithm is not able to figure it out.
in this particular case, it's a known limitation when it comes to inferring the type of closures with higher ranked lifetimes. in fact, you don't need the full type annotation, just the argument types in the "shape" of references should be enough:
run(|x: &_, y: &mut _| d.f(x, y));
also, this particular case have a simple workaround: if you add the FnMut() bound directly, it serves a "hint" to the type checker and helps the inference, e.g.
Thanks for your reply. Indeed, the goal of the trait FDF is to be implemented for other types. Great that "shape" annotations are enough—they are much lighter. Do you know whether the next-gen type engine will eventually “solve” this? It doesn't at the moment.
Calling a trait function, especially using the non-method form, is allowed in more places like this because the trait means it knows the signature without needing a particularly-precise receiver type.