Solution (source code)

= Solution

<Method overloading> chooses a signature using the <static types> available at the call site. The receiver `m` has <static type> `M`, whose visible overloads accept `X` and `Y`; the `Z` overload introduced only in `N` is not a candidate.

For `m.f(x)`, the argument's <static type> is `X`, so the chosen signature is `f(X)`. `N` does not override it, and the inherited `M` body runs. For `m.f(y)`, the chosen signature is `f(Y)`, and <dynamic dispatch> on the receiver chooses `N`'s override. For `m.f(z)`, both visible signatures apply, but `f(Y)` is more specific than `f(X)`. <Dynamic dispatch> again chooses `N.f(Y)`. Thus
``
f with X at M
f with Y at N
f with Y at N
``
Equivalently,
$$
\boxed{X@M,\qquad Y@N,\qquad Y@N.}
$$
The <runtime type> of every argument is `Z`, but ordinary single-receiver <dynamic dispatch> does not redo <method overloading> using that <runtime type>. This is <overload selection followed by dynamic dispatch>.