I set up a bunch of recursive modules, some of which have records inside.
I’m getting a weird error, though.
File "src/lib/ir.ml", lines 61-62, characters 6-5:
61 | ......map : Register_map.t
62 | ;................
Error: Record element types must have a representable layout.
The layout of Register_map.t is any.
But the layout of Register_map.t must be representable
because it is the type of record field map.
Eyeballing the types below, it’s clear to me what the layout of Register_map.t is because Register.t is already defined at that point.
Why does the compiler think otherwise?
and Register : sig
type t =
{ id : id
; size : int
}
[@@deriving sexp]
end =
Register
and Register_map : sig
type t = Register.t option array [@@deriving sexp]
end =
Register_map
and Register_index : sig
type t =
{ id : id
; map : Register_map.t
; map_index : int
; bit_field : Bit_field.t
}
[@@deriving sexp]
end =
Register_index
Note for the curious: this is an OxCaml-specific error (OxCaml allows to define types whose layout is not the uniform layout of regular values, but this comes with restrictions on where these types can be used).
I’m not completely sure of what is going on (the typing of recursive modules is a notoriously complex problem), but I suspect that the signature of Register_index is checked under an approximated environment, where it only knows that Register_map.t exists but not its actual representation. The error then complains that because the representation is not known, the layout isn’t either, so it cannot be used as a record field.
If you don’t actually need the recursion, I would advise against using recursive modules (not only in OxCaml, but in OCaml in general). In this case you can at least switch to individual recursive definitions instead of mutually recursive ones.
Testing locally, I was able to reproduce this error, and adding a kind annotation to the type that was complained about fixed it. So in your example, try changing Register_map like this:
and Register_map : sig
type t : value = Register.t option array [@@deriving sexp]
end
(It’s possible this won’t work, because I don’t have your complete example, but I’d be curious to have a look if not).
Another thing worth noting is that, at least in my small reproduction case, the problem goes away without the [@@deriving sexp]. I haven’t dug in to the generated code yet to see what’s going on in there.
As @vlaviron says, typechecking for recursive types and recursive modules is pretty tricky, and right now OxCaml will require kind annotations in a few cases where it seems like the compiler should be able to work it out.
Ah, after a little more investigation, I’m pretty sure this is the result of a bug that we just found very recently (credit to Ryan Tjoa for tracking it down). He made a PR to fix it on the OxCaml repository, and the fix should make its way into the next release of OxCaml.
This turns out to be a bug that is also present in typechecking of recursive modules in upstream OCaml (it’s just a little harder to hit without OxCaml’s layouts), so we’ll also be making a bug fix upstream soon.