(* TEST * expect *) (* cannot_alias.ml *) module Termsig = struct module Term0 = struct module type S = sig module Id : sig end end end module Term = struct module type S = sig module Term0 : Term0.S module T = Term0 end end end;; [%%expect{| module Termsig : sig module Term0 : sig module type S = sig module Id : sig end end end module Term : sig module type S = sig module Term0 : Term0.S module T = Term0 end end end |}] module Make1 (T' : Termsig.Term.S) = struct module T = struct include T'.T let u = 1 end end;; [%%expect{| module Make1 : functor (T' : sig module Term0 : Termsig.Term0.S module T : sig module Id : sig end end end) -> sig module T : sig module Id : sig end val u : int end end |}] module Make2 (T' : Termsig.Term.S) = struct module T = struct include T'.T module Id2 = Id let u = 1 end end;; [%%expect{| module Make2 : functor (T' : sig module Term0 : Termsig.Term0.S module T : sig module Id : sig end end end) -> sig module T : sig module Id : sig end module Id2 = Id val u : int end end |}] module Make3 (T' : Termsig.Term.S) = struct module T = struct include T'.T module Id2 = Id let u = 1 let u = 1 end end;; [%%expect{| module Make3 : functor (T' : sig module Term0 : Termsig.Term0.S module T : sig module Id : sig end end end) -> sig module T : sig module Id : sig end module Id2 = Id val u : int end end |}] (* cannot_alias2.ml *) module type S = sig module Term0 : sig module Id : sig end end module T = Term0 end;; module Make1 (T' : S) = struct module Id = T'.T.Id module Id2 = Id end;; [%%expect{| module type S = sig module Term0 : sig module Id : sig end end module T = Term0 end module Make1 : functor (T' : sig module Term0 : sig module Id : sig end end module T : sig module Id : sig end end end) -> sig module Id : sig end module Id2 = Id end |}] module Make2 (T' : S) : sig module Id : sig end module Id2 = Id end with module Id := T'.Term0.Id = struct module Id = T'.T.Id module Id2 = Id end;; [%%expect{| Lines 2-5, characters 57-3: 2 | .........................................................struct 3 | module Id = T'.T.Id 4 | module Id2 = Id 5 | end.. Error: Signature mismatch: Modules do not match: sig module Id : sig end module Id2 = Id end is not included in sig module Id2 = T'.Term0.Id end In module Id2: Module T'.Term0.Id cannot be aliased |}] module Make3 (T' : S) = struct module T = struct module Id = T'.T.Id module Id2 = Id let u = 1 let u = 1 end end;; [%%expect{| module Make3 : functor (T' : sig module Term0 : sig module Id : sig end end module T : sig module Id : sig end end end) -> sig module T : sig module Id : sig end module Id2 = Id val u : int end end |}] (* unsoundness if Make1 returned an Id.x field *) module M = Make1 (struct module Term0 = struct module Id = struct let x = "a" end end module T = Term0 end);; M.Id.x;; [%%expect{| module M : sig module Id : sig end module Id2 = Id end Line 3, characters 0-6: 3 | M.Id.x;; ^^^^^^ Error: Unbound value M.Id.x |}] (* cannot_alias3.ml *) module MkT(X : sig end) = struct type t end module type S = sig module Term0 : sig module Id : sig end end module T = Term0 type t = MkT(T).t end;; module Make1 (T' : S) = struct module Id = T'.T.Id module Id2 = Id type t = T'.t end;; module IS = struct module Term0 = struct module Id = struct let x = "a" end end module T = Term0 type t = MkT(T).t end;; module M = Make1(IS);; [%%expect{| module MkT : functor (X : sig end) -> sig type t end module type S = sig module Term0 : sig module Id : sig end end module T = Term0 type t = MkT(T).t end module Make1 : functor (T' : sig module Term0 : sig module Id : sig end end module T : sig module Id : sig end end type t = MkT(T).t end) -> sig module Id : sig end module Id2 = Id type t = T'.t end module IS : sig module Term0 : sig module Id : sig val x : string end end module T = Term0 type t = MkT(T).t end module M : sig module Id : sig end module Id2 = Id type t = IS.t end |}] (* cannot_alias4.ml *) (* Can be used to break module abstraction *) (* Still sound ? *) (* It seems to only work if Term0 and Term contain identical types *) (* It may also be possible to do the same thing using Mtype.nondep_supertype anyway *) type (_,_) eq = Eq : ('a,'a) eq module MkT(X : Set.OrderedType) = Set.Make(X) module type S = sig module Term0 : Set.OrderedType with type t = int module T = Term0 type t = E of (MkT(T).t,MkT(T).t) eq type u = t = E of (MkT(Term0).t,MkT(T).t) eq end;; module F(X:S) = X;; module rec M : S = M;; module M' = F(M);; module type S' = module type of M';; module Asc = struct type t = int let compare x y = x - y end;; module Desc = struct type t = int let compare x y = y - x end;; module rec M1 : S' with module Term0 := Asc and module T := Desc = M1;; (* And now we have a witness of MkT(Asc).t = MkT(Desc).t ... *) let (E eq : M1.u) = (E Eq : M1.t);; [%%expect{| type (_, _) eq = Eq : ('a, 'a) eq module MkT : functor (X : Set.OrderedType) -> sig type elt = X.t type t = Set.Make(X).t val empty : t val is_empty : t -> bool val mem : elt -> t -> bool val add : elt -> t -> t val singleton : elt -> t val remove : elt -> t -> t val union : t -> t -> t val inter : t -> t -> t val disjoint : t -> t -> bool val diff : t -> t -> t val compare : t -> t -> int val equal : t -> t -> bool val subset : t -> t -> bool val iter : (elt -> unit) -> t -> unit val map : (elt -> elt) -> t -> t val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a val for_all : (elt -> bool) -> t -> bool val exists : (elt -> bool) -> t -> bool val filter : (elt -> bool) -> t -> t val filter_map : (elt -> elt option) -> t -> t val partition : (elt -> bool) -> t -> t * t val cardinal : t -> int val elements : t -> elt list val min_elt : t -> elt val min_elt_opt : t -> elt option val max_elt : t -> elt val max_elt_opt : t -> elt option val choose : t -> elt val choose_opt : t -> elt option val split : elt -> t -> t * bool * t val find : elt -> t -> elt val find_opt : elt -> t -> elt option val find_first : (elt -> bool) -> t -> elt val find_first_opt : (elt -> bool) -> t -> elt option val find_last : (elt -> bool) -> t -> elt val find_last_opt : (elt -> bool) -> t -> elt option val of_list : elt list -> t val to_seq_from : elt -> t -> elt Seq.t val to_seq : t -> elt Seq.t val to_rev_seq : t -> elt Seq.t val add_seq : elt Seq.t -> t -> t val of_seq : elt Seq.t -> t end module type S = sig module Term0 : sig type t = int val compare : t -> t -> int end module T = Term0 type t = E of (MkT(T).t, MkT(T).t) eq type u = t = E of (MkT(Term0).t, MkT(T).t) eq end module F : functor (X : sig module Term0 : sig type t = int val compare : t -> t -> int end module T : sig type t = int val compare : t -> t -> int end type t = E of (MkT(T).t, MkT(T).t) eq type u = t = E of (MkT(Term0).t, MkT(T).t) eq end) -> sig module Term0 : sig type t = int val compare : t -> t -> int end module T : sig type t = int val compare : t -> t -> int end type t = X.t = E of (MkT(T).t, MkT(T).t) eq type u = t = E of (MkT(Term0).t, MkT(T).t) eq end module rec M : S module M' : sig module Term0 : sig type t = int val compare : t -> t -> int end module T : sig type t = int val compare : t -> t -> int end type t = M.t = E of (MkT(T).t, MkT(T).t) eq type u = t = E of (MkT(Term0).t, MkT(T).t) eq end module type S' = sig module Term0 : sig type t = int val compare : t -> t -> int end module T : sig type t = int val compare : t -> t -> int end type t = M.t = E of (MkT(T).t, MkT(T).t) eq type u = t = E of (MkT(Term0).t, MkT(T).t) eq end module Asc : sig type t = int val compare : int -> int -> int end module Desc : sig type t = int val compare : int -> int -> int end Line 15, characters 0-69: 15 | module rec M1 : S' with module Term0 := Asc and module T := Desc = M1;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This variant or record definition does not match that of type M.t Constructors do not match: E of (MkT(M.T).t, MkT(M.T).t) eq is not compatible with: E of (MkT(Desc).t, MkT(Desc).t) eq The types are not equal. |}]