Error: this open statement shadows the label name (which is later used)


Me again.

I’m encountering a compiler warning of “this open statement shadows the label name (which is later used)”.

It’s supposedly caused by opening a module to which my working module already has visibility. This I understand, but I don’t get this error in every module, even though the visibility should be the same.

Further, adding “!” after the open statement removes the warning. I can’t find explanations of the exclamation point on statements anywhere in the docs. Is this only Reason or also OCaml?


The warning and the syntax are both originally from OCaml. The warning means that you have an already-defined identifier name, then you’re opening a module which also contains the identifier name, which is shadowing the original one. This can lead to subtle bugs so I would always look at why there is shadowing happening in the first place. Try to narrow down the scope of the module open as much as possible (which is a best practice in OCaml/Reason). open! should be an absolute last resort.



I discovered why the error wasn’t being thrown for the other module. The shadowing wasn’t technically occurring. Is there any other place where the ! is used? It’s a strange piece of one-off syntax otherwise.


I’m still not quite grasping why what I’m doing counts as shadowing.

module Staff = {
  type role =
    | Delivery
    | Sales
    | Other;
  type member = {
    name: string,

module NewStaff = {
    open Staff;
    let newRole = Delivery;
    let newEmployee: member = {name: "Fred", role: Other};

The open Staff line throws the shadow error only if newEmployee is included. Why?


I don’t remember off-hand if ! is syntactically used like that anywhere else. I do agree that it feels somewhat out of place.

Regarding your example, I’m actually not seeing any compiler warning when I try it in the Reason playground. I am able to reproduce the warning with the following code:

module A = {
  type a = {name: string};

module B = {
  type b = {name: string};
  open A; // Warning 45: this open statement shadows the label name (which is later used)
  let b1 = {name: ""}; // Actually has type A.a

As you can see, this is happening because different record types use the same label names. This can lead to quite a lot of confusion, hence it’s almost always better to avoid fully opening modules to access their record labels and constructors. Instead, it’s better to prefix only a single field of the record when you want to pinpoint its exact module and type, e.g. let a1 = { ""};


Bah. Found it. Much earlier in my huge monolith of phutzcode I had used the label name “name.” That was the problem.