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.xlet 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 -> intval 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
- ppxA preprocessor that rewrites the OCaml syntax tree between parsing and type checking. Derivers generate code from type declarations tagged [@@deriving name]; extension points expand nodes written [%name payload]. Neither sees any types.
- Polymorphic variantA variant whose constructors, called tags and written with a backquote, exist independently of any type declaration. Their types are sets of tags with bounds: [> `A] means at least `A, [< `A | `B] at most those two, and unification works out unions and intersections of those sets.
referenced by
further reading
- OCaml 4.01.0 release notes (2013), which introduced type-based selection of record labels and constructors.