Reputation: 4998
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
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