Skip to content

Upstream‐breaking changes

Zesen Qian edited this page Apr 25, 2025 · 4 revisions

This is a list of things in our compiler that cause a file that builds in the upstream compiler to fail in our compiler. We plan to guard those behaviors behind compiler flags to make our compiler upstream-compatible by default.

Modes

  • module type of M zaps modalities in M to the strongest. If this module type is later used to constrain another module (containing values of weaker modalities), error will occur. For example, the following will be rejected, since module type of M has a portable modality on foo, but N doesn't.
module M = struct
  let foo x = x
end

module N : module type of M = struct
  let bar = ref "hello"
  let foo x = ignore !bar; x
end 

This is bad code style and should be fixed by spelling out the correct module type of the other module, or more conveniently by overriding the value declarations of the corresponding overriding value definitions:

module M = struct
  let foo x = x
end

module N : sig
  include module type of M

  ... (* overriding declarations *)
end = struct
  include M
  
  ... (* overriding definitions, correspondingly *)
end 
  • mli-less files are zapped to strongest modalities and will cause similar issues.
  • The inferred interface printed by the compiler when passed -i are not affected: it tries to avoid printing modalities if possible.
Clone this wiki locally