ocaml/testsuite/tests/typing-modules/generative.ml

99 lines
2.9 KiB
OCaml

(* TEST
* expect
*)
(* Using generative functors *)
(* Without type *)
module type S = sig val x : int end;;
let v = (module struct let x = 3 end : S);;
module F() = (val v);; (* ok *)
module G (X : sig end) : S = F ();; (* ok *)
module H (X : sig end) = (val v);; (* ok *)
[%%expect{|
module type S = sig val x : int end
val v : (module S) = <module>
module F : functor () -> S
module G : functor (X : sig end) -> S
module H : functor (X : sig end) -> S
|}];;
(* With type *)
module type S = sig type t val x : t end;;
let v = (module struct type t = int let x = 3 end : S);;
module F() = (val v);; (* ok *)
[%%expect{|
module type S = sig type t val x : t end
val v : (module S) = <module>
module F : functor () -> S
|}];;
module G (X : sig end) : S = F ();; (* fail *)
[%%expect{|
Line 1, characters 29-33:
1 | module G (X : sig end) : S = F ();; (* fail *)
^^^^
Error: This expression creates fresh types.
It is not allowed inside applicative functors.
|}];;
module H() = F();; (* ok *)
[%%expect{|
module H : functor () -> S
|}];;
(* Alias *)
module U = struct end;;
module M = F(struct end);; (* ok *)
[%%expect{|
module U : sig end
module M : S
|}];;
module M = F(U);; (* fail *)
[%%expect{|
Line 1, characters 11-12:
1 | module M = F(U);; (* fail *)
^
Error: This is a generative functor. It can only be applied to ()
|}];;
(* Cannot coerce between applicative and generative *)
module F1 (X : sig end) = struct end;;
module F2 : functor () -> sig end = F1;; (* fail *)
[%%expect{|
module F1 : functor (X : sig end) -> sig end
Line 2, characters 36-38:
2 | module F2 : functor () -> sig end = F1;; (* fail *)
^^
Error: Signature mismatch:
Modules do not match:
functor (X : sig end) -> sig end
is not included in
functor () -> sig end
|}];;
module F3 () = struct end;;
module F4 : functor (X : sig end) -> sig end = F3;; (* fail *)
[%%expect{|
module F3 : functor () -> sig end
Line 2, characters 47-49:
2 | module F4 : functor (X : sig end) -> sig end = F3;; (* fail *)
^^
Error: Signature mismatch:
Modules do not match:
functor () -> sig end
is not included in
functor (X : sig end) -> sig end
|}];;
(* tests for shortened functor notation () *)
module X (X: sig end) (Y: sig end) = functor (Z: sig end) -> struct end;;
module Y = functor (X: sig end) (Y:sig end) -> functor (Z: sig end) ->
struct end;;
module Z = functor (_: sig end) (_:sig end) (_: sig end) -> struct end;;
module GZ : functor (X: sig end) () (Z: sig end) -> sig end
= functor (X: sig end) () (Z: sig end) -> struct end;;
[%%expect{|
module X : functor (X : sig end) (Y : sig end) (Z : sig end) -> sig end
module Y : functor (X : sig end) (Y : sig end) (Z : sig end) -> sig end
module Z : sig end -> sig end -> sig end -> sig end
module GZ : functor (X : sig end) () (Z : sig end) -> sig end
|}];;