(* TEST * expect *) module F(_ : sig end) : sig type t = private int end = struct type t = int end;; [%%expect{| module F : sig end -> sig type t = private int end |}] module Direct = F(struct end);; [%%expect{| module Direct : sig type t = private int end |}] module G(X : sig end) : sig type t = F(X).t end = F(X);; [%%expect{| module G : functor (X : sig end) -> sig type t = F(X).t end |}] module Indirect = G(struct end);; [%%expect{| module Indirect : sig type t = private int end |}] (* unroll_abbrev *) module Pub(_ : sig end) = struct type t = [ `Foo of t ] end;; [%%expect{| module Pub : sig end -> sig type t = [ `Foo of t ] end |}] module Priv(_ : sig end) = struct type t = private [ `Foo of t ] end;; [%%expect{| module Priv : sig end -> sig type t = private [ `Foo of t ] end |}] module DirectPub = Pub(struct end);; [%%expect{| module DirectPub : sig type t = [ `Foo of t ] end |}] module DirectPriv = Priv(struct end);; [%%expect{| module DirectPriv : sig type t = private [ `Foo of t ] end |}] module H(X : sig end) : sig type t = Pub(X).t end = Pub(X);; [%%expect{| module H : functor (X : sig end) -> sig type t = Pub(X).t end |}] module I(X : sig end) : sig type t = Priv(X).t end = Priv(X);; [%%expect{| module I : functor (X : sig end) -> sig type t = Priv(X).t end |}] module IndirectPub = H(struct end);; [%%expect{| module IndirectPub : sig type t = [ `Foo of 'a ] as 'a end |}] (* The result would be {[ type t = private [ `Foo of t ] ]} if we were unrolling the abbrev. *) module IndirectPriv = I(struct end);; [%%expect{| module IndirectPriv : sig type t end |}] (*** Test proposed by Jacques in https://github.com/ocaml/ocaml/pull/1826#discussion_r194290729 ***) (* Baseline *) type t = private [ `Bar of int | `Foo of t -> int ];; [%%expect{| type t = private [ `Bar of int | `Foo of t -> int ] |}] module M : sig type s = private [ `Bar of int | `Foo of 'a -> int ] as 'a end = struct type s = t end;; [%%expect{| Lines 3-5, characters 6-3: 3 | ......struct 4 | type s = t 5 | end.. Error: Signature mismatch: Modules do not match: sig type s = t end is not included in sig type s = private [ `Bar of int | `Foo of 'a -> int ] as 'a end Type declarations do not match: type s = t is not included in type s = private [ `Bar of int | `Foo of 'a -> int ] as 'a |}] (* nondep_type_decl + nondep_type_rec *) module Priv(_ : sig end) = struct type t = private [ `Foo of t -> int | `Bar of int ] end;; [%%expect{| module Priv : sig end -> sig type t = private [ `Bar of int | `Foo of t -> int ] end |}] module I(X : sig end) : sig type t = Priv(X).t end = Priv(X);; [%%expect{| module I : functor (X : sig end) -> sig type t = Priv(X).t end |}] module IndirectPriv = I(struct end);; [%%expect{| module IndirectPriv : sig type t end |}]