lambda.xy.x
lambda.xy.x

Reputation: 4998

What is the meaning of Warning 40: this record ... contains fields that are not visible in the current scope

Please consider the following code:

module A =
  struct
    type r = { i : int; s: string }
  end

module B =
  struct
    type r = { i : int; s : string }
  end


let f (x : A.r) : B.r = match x with
    { i; s } -> { i = 2*i; s = "" }

Two modules define exactly the same record. A function f converts an A record to a B record. The warning is already emitted during compilation, but also visible interactively. On the ocaml cli, it seems that a call to f does the intended thing:

# let x = f { i = 5; s = "ab" };;
Characters 10-29:
  let x = f { i = 5; s = "ab" };;
            ^^^^^^^^^^^^^^^^^^^
Warning 40: this record of type Shadow.A.r contains fields that are 
not visible in the current scope: i s.
They will not be selected if the type becomes unknown.
val x : Shadow.B.r = {Shadow.B.i = 10; s = ""}

I found a blog posting on lexifi.com which explains the problem and some common solutions. What i don't understand is the actual error message:

Upvotes: 15

Views: 3128

Answers (1)

gsg
gsg

Reputation: 9377

The type of the record is known in this case because you provided annotations. If you removed the annotations, the type would become unknown and the meaning of the code might change.

The philosophy of OCaml is that adding and removing type annotations should not affect the meaning of a program, so a warning is produced.

You can avoid this warning by bringing the relevant field into scope. Doing this for a field that is defined within a module A entails either opening A to bring its contents into scope, or qualifying the name of field with the module. For example:

module A = struct ... end

let test r = r.A.field

let test2 r = let open A in r.field

open A 

let test3 r = r.field

Upvotes: 17

Related Questions