What is warning 30 for?

If I write a code like this:

type a = B of b | C of c
and b = {str: string;}
and c = {str: string; a: a};;

I get a warning:

the label str is defined in both types b and c.

But why is this bad? What kind of issues I can have if I ignore the warning?

Originally asked at the ReScript forum.

1 Like

If you have two types that defines the same label or constructor, distinguishing between the two types requires type-directed disambiguation. Since type-directed disambiguation is not sufficient in all context, this implies that the type of some functions becomes ambiguous

let str x = x.str (* what is the type of `x`? `b` or `c`)

and those functions require some explicit type annotation to remove the ambiguity:

let str (x:c) = x.str

However, in many cases it is not that painful to deal with the ambiguity, that is why the
the duplicate-definitions warning is disabled by default in recent versions of OCaml.


I thought that was the reason, but I only get the warning when the types are mutually recursive. For example this doesn’t produce a warning:

type b = {str: string;}
type c = {str: string; a: int}

So I wonder whether there some additional concerns when the types are recursive?

With mutually recursive types, the order of the type definitions is unclear, and there is no point where there is only one definition in scope. Contrarily, with a separated type definitions, you could have something like:

type t = A
let x = A
type u = A
(* ... some code that never use `A:t` *)

where it is fine to shadow A:t if it is never used again.
Thus the duplicate-definitions case is clearly always problematic without type-directed disambiguation, but the situation is slightly less clear cut with separate definitions.


Warning 30 was important before we supported type-based disambiguation, because those situations were always a mistake from the user. It became mostly irrelevant when disambiguation was added. But we took some time noticing, and only disabled it by default in OCaml 4.10 (see #9046). I believe that you can safely forget about it.