wiki

Type-directed disambiguation

also: label disambiguation, constructor disambiguation, type-based selection

OCaml's rule, since 4.01, for deciding which record type a field label or which variant a constructor belongs to when several in scope share the name: if the expected type is already known at that point, it decides; otherwise the most recently defined type with that name wins.

Two record types in one module can have a field of the same name. Before 4.01 the later definition simply shadowed the earlier one. Now the type checker uses whatever it already knows about the expression's type.

Two records with a field x.

type a = { x : int }
type b = { x : string }
let f (r : a) = r.x
let g r = r.x

What ocamlc -i infers, OCaml 5.5.1. The annotation picks a; with nothing known, the last definition wins.

val f : a -> int
val g : b -> string

“Already known” means known at that point of inference, which runs roughly left to right. A label read before anything has fixed its record's type resolves to the most recent record with that field, and the error then names a type the code never meant. Compiling with -principal makes warning 18 point out where the outcome depends on inference order.

It is also what lets code generated without types work. A ppx that writes s.address.city with only s annotated leaves the type checker to find which record each field belongs to.

see also

referenced by

further reading

  • OCaml 4.01.0 release notes (2013), which introduced type-based selection of record labels and constructors.