OK, let me make one adjustment, inspired by Scala 3’s nice error messages:
File "./test.ml", line 6, characters 23-25:
6 | let error = f Ax Ax Ax Ax
^^
Error: expected type
v
But got
Ax : u
Regarding type-directed disambiguation–in the case of a straight-up type mismatch, disambiguation doesn’t matter any more. There’s nothing to disambiguate when the candidate types are {t,s,u} but the required type is v. So we might as well fall back to the old algorithm for inferring the type. It will at least make it clear to the reader that Ax is definitely a mismatching type.