(* TEST * expect *) module Exp = struct type _ t = | IntLit : int -> int t | BoolLit : bool -> bool t | Pair : 'a t * 'b t -> ('a * 'b) t | App : ('a -> 'b) t * 'a t -> 'b t | Abs : ('a -> 'b) -> ('a -> 'b) t let rec eval : type s . s t -> s = function | IntLit x -> x | BoolLit y -> y | Pair (x,y) -> (eval x,eval y) | App (f,a) -> (eval f) (eval a) | Abs f -> f let discern : type a. a t -> _ = function IntLit _ -> 1 | BoolLit _ -> 2 | Pair _ -> 3 | App _ -> 4 | Abs _ -> 5 end ;; [%%expect{| module Exp : sig type _ t = IntLit : int -> int t | BoolLit : bool -> bool t | Pair : 'a t * 'b t -> ('a * 'b) t | App : ('a -> 'b) t * 'a t -> 'b t | Abs : ('a -> 'b) -> ('a -> 'b) t val eval : 's t -> 's val discern : 'a t -> int end |}];; module List = struct type zero type _ t = | Nil : zero t | Cons : 'a * 'b t -> ('a * 'b) t let head = function | Cons (a,b) -> a let tail = function | Cons (a,b) -> b let rec length : type a . a t -> int = function | Nil -> 0 | Cons (a,b) -> length b end ;; [%%expect{| module List : sig type zero type _ t = Nil : zero t | Cons : 'a * 'b t -> ('a * 'b) t val head : ('a * 'b) t -> 'a val tail : ('a * 'b) t -> 'b t val length : 'a t -> int end |}];; module Nonexhaustive = struct type 'a u = | C1 : int -> int u | C2 : bool -> bool u type 'a v = | C1 : int -> int v let unexhaustive : type s . s u -> s = function | C2 x -> x module M : sig type t type u end = struct type t = int type u = bool end type 'a t = | Foo : M.t -> M.t t | Bar : M.u -> M.u t let same_type : type s . s t * s t -> bool = function | Foo _ , Foo _ -> true | Bar _, Bar _ -> true end ;; [%%expect{| Lines 11-12, characters 6-19: 11 | ......function 12 | | C2 x -> x Warning 8 [partial-match]: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: C1 _ Lines 24-26, characters 6-30: 24 | ......function 25 | | Foo _ , Foo _ -> true 26 | | Bar _, Bar _ -> true Warning 8 [partial-match]: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (Foo _, Bar _) module Nonexhaustive : sig type 'a u = C1 : int -> int u | C2 : bool -> bool u type 'a v = C1 : int -> int v val unexhaustive : 's u -> 's module M : sig type t type u end type 'a t = Foo : M.t -> M.t t | Bar : M.u -> M.u t val same_type : 's t * 's t -> bool end |}];; module Exhaustive = struct type t = int type u = bool type 'a v = | Foo : t -> t v | Bar : u -> u v let same_type : type s . s v * s v -> bool = function | Foo _ , Foo _ -> true | Bar _, Bar _ -> true end ;; [%%expect{| module Exhaustive : sig type t = int type u = bool type 'a v = Foo : t -> t v | Bar : u -> u v val same_type : 's v * 's v -> bool end |}];; module PR6862 = struct class c (Some x) = object method x : int = x end type _ opt = Just : 'a -> 'a opt | Nothing : 'a opt class d (Just x) = object method x : int = x end end;; [%%expect{| Line 2, characters 10-18: 2 | class c (Some x) = object method x : int = x end ^^^^^^^^ Warning 8 [partial-match]: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: None Line 4, characters 10-18: 4 | class d (Just x) = object method x : int = x end ^^^^^^^^ Warning 8 [partial-match]: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Nothing module PR6862 : sig class c : int option -> object method x : int end type _ opt = Just : 'a -> 'a opt | Nothing : 'a opt class d : int opt -> object method x : int end end |}];; module Exhaustive2 = struct type _ t = Int : int t let f (x : bool t option) = match x with None -> () end;; [%%expect{| module Exhaustive2 : sig type _ t = Int : int t val f : bool t option -> unit end |}];; module PR6220 = struct type 'a t = I : int t | F : float t let f : int t -> int = function I -> 1 let g : int t -> int = function I -> 1 | _ -> 2 (* warn *) end;; [%%expect{| Line 4, characters 43-44: 4 | let g : int t -> int = function I -> 1 | _ -> 2 (* warn *) ^ Warning 56 [unreachable-case]: this match case is unreachable. Consider replacing it with a refutation case ' -> .' module PR6220 : sig type 'a t = I : int t | F : float t val f : int t -> int val g : int t -> int end |}];; module PR6403 = struct type (_, _) eq = Refl : ('a, 'a) eq type empty = { bottom : 'a . 'a } type ('a, 'b) sum = Left of 'a | Right of 'b let notequal : ((int, bool) eq, empty) sum -> empty = function | Right empty -> empty end;; [%%expect{| module PR6403 : sig type (_, _) eq = Refl : ('a, 'a) eq type empty = { bottom : 'a. 'a; } type ('a, 'b) sum = Left of 'a | Right of 'b val notequal : ((int, bool) eq, empty) sum -> empty end |}];; module PR6437 = struct type ('a, 'b) ctx = | Nil : (unit, unit) ctx | Cons : ('a, 'b) ctx -> ('a * unit, 'b * unit) ctx type 'a var = | O : ('a * unit) var | S : 'a var -> ('a * unit) var let rec f : type g1 g2. (g1, g2) ctx * g1 var -> g2 var = function | Cons g, O -> O | Cons g, S n -> S (f (g, n)) | _ -> . (*| Nil, _ -> (assert false) *) (* warns, but shouldn't *) end;; [%%expect{| module PR6437 : sig type ('a, 'b) ctx = Nil : (unit, unit) ctx | Cons : ('a, 'b) ctx -> ('a * unit, 'b * unit) ctx type 'a var = O : ('a * unit) var | S : 'a var -> ('a * unit) var val f : ('g1, 'g2) ctx * 'g1 var -> 'g2 var end |}];; module PR6801 = struct type _ value = | String : string -> string value | Float : float -> float value | Any let print_string_value (x : string value) = match x with | String s -> print_endline s (* warn : Any *) end;; [%%expect{| Lines 8-9, characters 4-33: 8 | ....match x with 9 | | String s -> print_endline s................. Warning 8 [partial-match]: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: Any module PR6801 : sig type _ value = String : string -> string value | Float : float -> float value | Any val print_string_value : string value -> unit end |}];; module Existential_escape = struct type _ t = C : int -> int t type u = D : 'a t -> u let eval (D x) = x end ;; [%%expect{| Line 5, characters 21-22: 5 | let eval (D x) = x ^ Error: This expression has type $D_'a t but an expression was expected of type 'a The type constructor $D_'a would escape its scope |}];; module Rectype = struct type (_,_) t = C : ('a,'a) t let f : type s. (s, s*s) t -> unit = fun C -> () (* here s = s*s! *) end ;; [%%expect{| module Rectype : sig type (_, _) t = C : ('a, 'a) t val f : ('s, 's * 's) t -> unit end |}];; module Or_patterns = struct type _ t = | IntLit : int -> int t | BoolLit : bool -> bool t let rec eval : type s . s t -> unit = function | (IntLit _ | BoolLit _) -> () end ;; [%%expect{| module Or_patterns : sig type _ t = IntLit : int -> int t | BoolLit : bool -> bool t val eval : 's t -> unit end |}];; module Polymorphic_variants = struct type _ t = | IntLit : int -> int t | BoolLit : bool -> bool t let rec eval : type s . [`A] * s t -> unit = function | `A, IntLit _ -> () | `A, BoolLit _ -> () end ;; [%%expect{| module Polymorphic_variants : sig type _ t = IntLit : int -> int t | BoolLit : bool -> bool t val eval : [ `A ] * 's t -> unit end |}];; module Propagation = struct type _ t = IntLit : int -> int t | BoolLit : bool -> bool t let check : type s. s t -> s = function | IntLit n -> n | BoolLit b -> b let check : type s. s t -> s = fun x -> let r = match x with | IntLit n -> (n : s ) | BoolLit b -> b in r end ;; [%%expect{| Lines 11-13, characters 12-20: 11 | ............match x with 12 | | IntLit n -> (n : s ) 13 | | BoolLit b -> b Warning 18 [not-principal]: The return type of this pattern-matching is ambiguous. Please add a type annotation, as the choice of `s' is not principal. module Propagation : sig type _ t = IntLit : int -> int t | BoolLit : bool -> bool t val check : 's t -> 's end |}, Principal{| Line 13, characters 19-20: 13 | | BoolLit b -> b ^ Error: This expression has type bool but an expression was expected of type s |}];; module Normal_constrs = struct type a = A type b = B let f = function A -> 1 | B -> 2 end;; [%%expect{| Line 5, characters 28-29: 5 | let f = function A -> 1 | B -> 2 ^ Error: This variant pattern is expected to have type a The constructor B does not belong to type a |}];; module PR6849 = struct type 'a t = Foo : int t let f : int -> int = function Foo -> 5 end;; [%%expect{| Line 5, characters 6-9: 5 | Foo -> 5 ^^^ Error: This pattern matches values of type 'a t but a pattern was expected which matches values of type int |}];; type _ t = Int : int t ;; let ky x y = ignore (x = y); x ;; let test : type a. a t -> a = function Int -> ky (1 : a) 1 ;; [%%expect{| type _ t = Int : int t val ky : 'a -> 'a -> 'a = val test : 'a t -> 'a = |}];; let test : type a. a t -> _ = function Int -> 1 (* ok *) ;; [%%expect{| val test : 'a t -> int = |}];; let test : type a. a t -> _ = function Int -> ky (1 : a) 1 (* fails *) ;; [%%expect{| Line 2, characters 18-30: 2 | function Int -> ky (1 : a) 1 (* fails *) ^^^^^^^^^^^^ Error: This expression has type a = int but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation |}];; let test : type a. a t -> a = fun x -> let r = match x with Int -> ky (1 : a) 1 (* fails *) in r ;; [%%expect{| Line 2, characters 30-42: 2 | let r = match x with Int -> ky (1 : a) 1 (* fails *) ^^^^^^^^^^^^ Error: This expression has type a = int but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation |}];; let test : type a. a t -> a = fun x -> let r = match x with Int -> ky 1 (1 : a) (* fails *) in r ;; [%%expect{| Line 2, characters 30-42: 2 | let r = match x with Int -> ky 1 (1 : a) (* fails *) ^^^^^^^^^^^^ Error: This expression has type a = int but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation |}];; let test (type a) x = let r = match (x : a t) with Int -> ky 1 1 in r ;; [%%expect{| val test : 'a t -> int = |}];; let test : type a. a t -> a = fun x -> let r = match x with Int -> (1 : a) (* ok! *) in r ;; [%%expect{| val test : 'a t -> 'a = |}];; let test : type a. a t -> _ = fun x -> let r = match x with Int -> 1 (* ok! *) in r ;; [%%expect{| val test : 'a t -> int = |}];; let test : type a. a t -> a = fun x -> let r : a = match x with Int -> 1 in r (* ok *) ;; [%%expect{| val test : 'a t -> 'a = |}];; let test2 : type a. a t -> a option = fun x -> let r = ref None in begin match x with Int -> r := Some (1 : a) end; !r (* ok *) ;; [%%expect{| val test2 : 'a t -> 'a option = |}];; let test2 : type a. a t -> a option = fun x -> let r : a option ref = ref None in begin match x with Int -> r := Some 1 end; !r (* ok *) ;; [%%expect{| val test2 : 'a t -> 'a option = |}];; let test2 : type a. a t -> a option = fun x -> let r : a option ref = ref None in let u = ref None in begin match x with Int -> r := Some 1; u := !r end; !u ;; (* ok (u non-ambiguous) *) [%%expect{| val test2 : 'a t -> 'a option = |}];; let test2 : type a. a t -> a option = fun x -> let r : a option ref = ref None in let u = ref None in begin match x with Int -> u := Some 1; r := !u end; !u ;; (* fails because u : (int | a) option ref *) [%%expect{| Line 4, characters 46-48: 4 | begin match x with Int -> u := Some 1; r := !u end; ^^ Error: This expression has type int option but an expression was expected of type a option Type int is not compatible with type a = int This instance of int is ambiguous: it would escape the scope of its equation |}];; let test2 : type a. a t -> a option = fun x -> let u = ref None in let r : a option ref = ref None in begin match x with Int -> r := Some 1; u := !r end; !u ;; (* ok *) [%%expect{| val test2 : 'a t -> 'a option = |}];; let test2 : type a. a t -> a option = fun x -> let u = ref None in let a = let r : a option ref = ref None in begin match x with Int -> r := Some 1; u := !r end; !u in a ;; (* ok *) [%%expect{| val test2 : 'a t -> 'a option = |}];; let either = ky let we_y1x (type a) (x : a) (v : a t) = match v with Int -> let y = either 1 x in y ;; (* fail *) [%%expect{| val either : 'a -> 'a -> 'a = Line 3, characters 44-45: 3 | match v with Int -> let y = either 1 x in y ^ Error: This expression has type a = int but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation |}];; (* Effect of external consraints *) let f (type a) (x : a t) y = ignore (y : a); let r = match x with Int -> (y : a) in (* ok *) r ;; [%%expect{| val f : 'a t -> 'a -> 'a = |}];; let f (type a) (x : a t) y = let r = match x with Int -> (y : a) in ignore (y : a); (* ok *) r ;; [%%expect{| val f : 'a t -> 'a -> 'a = |}];; let f (type a) (x : a t) y = ignore (y : a); let r = match x with Int -> y in (* ok *) r ;; [%%expect{| val f : 'a t -> 'a -> 'a = |}];; let f (type a) (x : a t) y = let r = match x with Int -> y in ignore (y : a); (* ok *) r ;; [%%expect{| val f : 'a t -> 'a -> 'a = |}];; let f (type a) (x : a t) (y : a) = match x with Int -> y (* returns 'a *) ;; [%%expect{| val f : 'a t -> 'a -> 'a = |}];; (* Combination with local modules *) let f (type a) (x : a t) y = match x with Int -> let module M = struct type b = a let z = (y : b) end in M.z ;; (* fails because of aliasing... *) [%%expect{| Line 3, characters 46-47: 3 | let module M = struct type b = a let z = (y : b) end ^ Error: This expression has type a = int but an expression was expected of type b = int This instance of int is ambiguous: it would escape the scope of its equation |}];; let f (type a) (x : a t) y = match x with Int -> let module M = struct type b = int let z = (y : b) end in M.z ;; (* ok *) [%%expect{| val f : 'a t -> int -> int = |}];; (* Objects and variants *) type _ h = | Has_m : h | Has_b : h let f : type a. a h -> a = function | Has_m -> object method m = 1 end | Has_b -> object method b = true end ;; [%%expect{| type _ h = Has_m : < m : int > h | Has_b : < b : bool > h val f : 'a h -> 'a = |}];; type _ j = | Has_A : [`A of int] j | Has_B : [`B of bool] j let f : type a. a j -> a = function | Has_A -> `A 1 | Has_B -> `B true ;; [%%expect{| type _ j = Has_A : [ `A of int ] j | Has_B : [ `B of bool ] j val f : 'a j -> 'a = |}];; type (_,_) eq = Eq : ('a,'a) eq ;; let f : type a b. (a,b) eq -> ( as 'c) -> ( as 'c) = fun Eq o -> o ;; (* fail *) [%%expect{| type (_, _) eq = Eq : ('a, 'a) eq Lines 3-4, characters 4-15: 3 | ....f : type a b. (a,b) eq -> ( as 'c) -> ( as 'c) = 4 | fun Eq o -> o Error: The universal type variable 'b cannot be generalized: it is already bound to another variable. |}];; let f : type a b. (a,b) eq -> -> = fun Eq o -> o ;; (* fail *) [%%expect{| Line 2, characters 14-15: 2 | fun Eq o -> o ^ Error: This expression has type < m : a; .. > but an expression was expected of type < m : b; .. > Type a is not compatible with type b = a This instance of a is ambiguous: it would escape the scope of its equation |}];; let f (type a) (type b) (eq : (a,b) eq) (o : ) : = match eq with Eq -> o ;; (* should fail *) [%%expect{| Line 2, characters 22-23: 2 | match eq with Eq -> o ;; (* should fail *) ^ Error: This expression has type < m : a; .. > but an expression was expected of type < m : b; .. > Type a is not compatible with type b = a This instance of a is ambiguous: it would escape the scope of its equation |}];; let f : type a b. (a,b) eq -> -> = fun Eq o -> o ;; (* ok *) [%%expect{| val f : ('a, 'b) eq -> < m : 'a > -> < m : 'b > = |}];; let int_of_bool : (bool,int) eq = Obj.magic Eq;; let x = object method m = true end;; let y = (x, f int_of_bool x);; let f : type a. (a, int) eq -> -> bool = fun Eq o -> ignore (o : ); o#m = 3 ;; (* should be ok *) [%%expect{| val int_of_bool : (bool, int) eq = Eq val x : < m : bool > = val y : < m : bool > * < m : int > = (, ) val f : ('a, int) eq -> < m : 'a > -> bool = |}];; let f : type a b. (a,b) eq -> < m : a; .. > -> < m : b > = fun eq o -> ignore (o : < m : a >); let r : < m : b > = match eq with Eq -> o in (* fail with principal *) r;; [%%expect{| val f : ('a, 'b) eq -> < m : 'a > -> < m : 'b > = |}, Principal{| Line 4, characters 44-45: 4 | let r : < m : b > = match eq with Eq -> o in (* fail with principal *) ^ Error: This expression has type < m : a > but an expression was expected of type < m : b > Type a is not compatible with type b = a This instance of a is ambiguous: it would escape the scope of its equation |}];; let f : type a b. (a,b) eq -> < m : a; .. > -> < m : b > = fun eq o -> let r : < m : b > = match eq with Eq -> o in (* fail *) ignore (o : < m : a >); r;; [%%expect{| Line 3, characters 44-45: 3 | let r : < m : b > = match eq with Eq -> o in (* fail *) ^ Error: This expression has type < m : a; .. > but an expression was expected of type < m : b > Type a is not compatible with type b = a This instance of a is ambiguous: it would escape the scope of its equation |}];; let f : type a b. (a,b) eq -> [> `A of a] -> [> `A of b] = fun Eq o -> o ;; (* fail *) [%%expect{| Line 2, characters 14-15: 2 | fun Eq o -> o ;; (* fail *) ^ Error: This expression has type [> `A of a ] but an expression was expected of type [> `A of b ] Type a is not compatible with type b = a This instance of a is ambiguous: it would escape the scope of its equation |}, Principal{| Line 2, characters 9-15: 2 | fun Eq o -> o ;; (* fail *) ^^^^^^ Error: This expression has type ([> `A of b ] as 'a) -> 'a but an expression was expected of type [> `A of a ] -> [> `A of b ] Types for tag `A are incompatible |}];; let f (type a b) (eq : (a,b) eq) (v : [> `A of a]) : [> `A of b] = match eq with Eq -> v ;; (* should fail *) [%%expect{| Line 2, characters 22-23: 2 | match eq with Eq -> v ;; (* should fail *) ^ Error: This expression has type [> `A of a ] but an expression was expected of type [> `A of b ] Type a is not compatible with type b = a This instance of a is ambiguous: it would escape the scope of its equation |}];; let f : type a b. (a,b) eq -> [< `A of a | `B] -> [< `A of b | `B] = fun Eq o -> o ;; (* fail *) [%%expect{| Lines 1-2, characters 4-15: 1 | ....f : type a b. (a,b) eq -> [< `A of a | `B] -> [< `A of b | `B] = 2 | fun Eq o -> o.............. Error: This definition has type 'c. ('d, 'c) eq -> ([< `A of 'c & 'f & 'd | `B ] as 'e) -> 'e which is less general than 'a 'b. ('a, 'b) eq -> ([< `A of 'b & 'h | `B ] as 'g) -> 'g |}];; let f : type a b. (a,b) eq -> [`A of a | `B] -> [`A of b | `B] = fun Eq o -> o ;; (* ok *) [%%expect{| val f : ('a, 'b) eq -> [ `A of 'a | `B ] -> [ `A of 'b | `B ] = |}];; let f : type a. (a, int) eq -> [`A of a] -> bool = fun Eq v -> match v with `A 1 -> true | _ -> false ;; (* ok *) [%%expect{| val f : ('a, int) eq -> [ `A of 'a ] -> bool = |}];; let f : type a b. (a,b) eq -> [> `A of a | `B] -> [`A of b | `B] = fun eq o -> ignore (o : [< `A of a | `B]); let r : [`A of b | `B] = match eq with Eq -> o in (* fail with principal *) r;; [%%expect{| val f : ('a, 'b) eq -> [ `A of 'a | `B ] -> [ `A of 'b | `B ] = |}, Principal{| Line 4, characters 49-50: 4 | let r : [`A of b | `B] = match eq with Eq -> o in (* fail with principal *) ^ Error: This expression has type [ `A of a | `B ] but an expression was expected of type [ `A of b | `B ] Type a is not compatible with type b = a This instance of a is ambiguous: it would escape the scope of its equation |}];; let f : type a b. (a,b) eq -> [> `A of a | `B] -> [`A of b | `B] = fun eq o -> let r : [`A of b | `B] = match eq with Eq -> o in (* fail *) ignore (o : [< `A of a | `B]); r;; [%%expect{| Line 3, characters 49-50: 3 | let r : [`A of b | `B] = match eq with Eq -> o in (* fail *) ^ Error: This expression has type [> `A of a | `B ] but an expression was expected of type [ `A of b | `B ] Type a is not compatible with type b = a This instance of a is ambiguous: it would escape the scope of its equation |}];; (* Pattern matching *) type 'a t = A of int | B of bool | C of float | D of 'a type _ ty = | TE : 'a ty -> 'a array ty | TA : int ty | TB : bool ty | TC : float ty | TD : string -> bool ty let f : type a. a ty -> a t -> int = fun x y -> match x, y with | _, A z -> z | _, B z -> if z then 1 else 2 | _, C z -> truncate z | TE TC, D [|1.0|] -> 14 | TA, D 0 -> -1 | TA, D z -> z | TD "bye", D false -> 13 | TD "hello", D true -> 12 (* | TB, D z -> if z then 1 else 2 *) | TC, D z -> truncate z | _, D _ -> 0 ;; [%%expect{| type 'a t = A of int | B of bool | C of float | D of 'a type _ ty = TE : 'a ty -> 'a array ty | TA : int ty | TB : bool ty | TC : float ty | TD : string -> bool ty val f : 'a ty -> 'a t -> int = |}];; let f : type a. a ty -> a t -> int = fun x y -> match x, y with | _, A z -> z | _, B z -> if z then 1 else 2 | _, C z -> truncate z | TE TC, D [|1.0|] -> 14 | TA, D 0 -> -1 | TA, D z -> z ;; (* warn *) [%%expect{| Lines 2-8, characters 2-16: 2 | ..match x, y with 3 | | _, A z -> z 4 | | _, B z -> if z then 1 else 2 5 | | _, C z -> truncate z 6 | | TE TC, D [|1.0|] -> 14 7 | | TA, D 0 -> -1 8 | | TA, D z -> z Warning 8 [partial-match]: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: (TE TC, D [| 0. |]) val f : 'a ty -> 'a t -> int = |}];; let f : type a. a ty -> a t -> int = fun x y -> match y, x with | A z, _ -> z | B z, _ -> if z then 1 else 2 | C z, _ -> truncate z | D [|1.0|], TE TC -> 14 | D 0, TA -> -1 | D z, TA -> z ;; (* fail *) [%%expect{| Line 6, characters 6-13: 6 | | D [|1.0|], TE TC -> 14 ^^^^^^^ Error: This pattern matches values of type 'a array but a pattern was expected which matches values of type a |}];; type ('a,'b) pair = {right:'a; left:'b} let f : type a. a ty -> a t -> int = fun x y -> match {left=x; right=y} with | {left=_; right=A z} -> z | {left=_; right=B z} -> if z then 1 else 2 | {left=_; right=C z} -> truncate z | {left=TE TC; right=D [|1.0|]} -> 14 | {left=TA; right=D 0} -> -1 | {left=TA; right=D z} -> z ;; (* fail *) [%%expect{| type ('a, 'b) pair = { right : 'a; left : 'b; } Line 8, characters 25-32: 8 | | {left=TE TC; right=D [|1.0|]} -> 14 ^^^^^^^ Error: This pattern matches values of type 'a array but a pattern was expected which matches values of type a |}];; type ('a,'b) pair = {left:'a; right:'b} let f : type a. a ty -> a t -> int = fun x y -> match {left=x; right=y} with | {left=_; right=A z} -> z | {left=_; right=B z} -> if z then 1 else 2 | {left=_; right=C z} -> truncate z | {left=TE TC; right=D [|1.0|]} -> 14 | {left=TA; right=D 0} -> -1 | {left=TA; right=D z} -> z ;; (* ok *) [%%expect{| type ('a, 'b) pair = { left : 'a; right : 'b; } Lines 4-10, characters 2-29: 4 | ..match {left=x; right=y} with 5 | | {left=_; right=A z} -> z 6 | | {left=_; right=B z} -> if z then 1 else 2 7 | | {left=_; right=C z} -> truncate z 8 | | {left=TE TC; right=D [|1.0|]} -> 14 9 | | {left=TA; right=D 0} -> -1 10 | | {left=TA; right=D z} -> z Warning 8 [partial-match]: this pattern-matching is not exhaustive. Here is an example of a case that is not matched: {left=TE TC; right=D [| 0. |]} val f : 'a ty -> 'a t -> int = |}];; (* Injectivity *) module M : sig type 'a t val eq : ('a t, 'b t) eq end = struct type 'a t = int let eq = Eq end ;; let f : type a b. (a M.t, b M.t) eq -> (a, b) eq = function Eq -> Eq (* fail *) ;; [%%expect{| module M : sig type 'a t val eq : ('a t, 'b t) eq end Line 6, characters 17-19: 6 | function Eq -> Eq (* fail *) ^^ Error: This expression has type (a, a) eq but an expression was expected of type (a, b) eq Type a is not compatible with type b |}];; let f : type a b. (a M.t * a, b M.t * b) eq -> (a, b) eq = function Eq -> Eq (* ok *) ;; [%%expect{| val f : ('a M.t * 'a, 'b M.t * 'b) eq -> ('a, 'b) eq = |}];; let f : type a b. (a * a M.t, b * b M.t) eq -> (a, b) eq = function Eq -> Eq (* ok *) ;; [%%expect{| val f : ('a * 'a M.t, 'b * 'b M.t) eq -> ('a, 'b) eq = |}];; (* Applications of polymorphic variants *) type _ t = | V1 : [`A | `B] t | V2 : [`C | `D] t let f : type a. a t -> a = function | V1 -> `A | V2 -> `C ;; f V1;; [%%expect{| type _ t = V1 : [ `A | `B ] t | V2 : [ `C | `D ] t val f : 'a t -> 'a = - : [ `A | `B ] = `A |}];; (* PR#5425 and PR#5427 *) type _ int_foo = | IF_constr : int_foo type _ int_bar = | IB_constr : int_bar ;; let g (type t) (x:t) (e : t int_foo) (e' : t int_bar) = let IF_constr, IB_constr = e, e' in (x:) ;; [%%expect{| type _ int_foo = IF_constr : < foo : int; .. > int_foo type _ int_bar = IB_constr : < bar : int; .. > int_bar Line 10, characters 3-4: 10 | (x:) ^ Error: This expression has type t = < foo : int; .. > but an expression was expected of type < foo : int > Type $0 = < bar : int; .. > is not compatible with type < > The second object type has no method bar |}];; let g (type t) (x:t) (e : t int_foo) (e' : t int_bar) = let IF_constr, IB_constr = e, e' in (x:) ;; [%%expect{| Line 3, characters 3-4: 3 | (x:) ^ Error: This expression has type t = < foo : int; .. > but an expression was expected of type < bar : int; foo : int > Type $0 = < bar : int; .. > is not compatible with type < bar : int > The first object type has an abstract row, it cannot be closed |}];; let g (type t) (x:t) (e : t int_foo) (e' : t int_bar) = let IF_constr, IB_constr = e, e' in (x:) ;; [%%expect{| Line 3, characters 2-26: 3 | (x:) ^^^^^^^^^^^^^^^^^^^^^^^^ Error: This expression has type < bar : int; foo : int; .. > but an expression was expected of type 'a The type constructor $1 would escape its scope |}];; let g (type t) (x:t) (e : t int_foo) (e' : t int_bar) : t = let IF_constr, IB_constr = e, e' in (x:) ;; [%%expect{| val g : 't -> 't int_foo -> 't int_bar -> 't = |}];; let g (type t) (x:t) (e : t int_foo) (e' : t int_bar) = let IF_constr, IB_constr = e, e' in x, x#foo, x#bar ;; [%%expect{| val g : 't -> 't int_foo -> 't int_bar -> 't * int * int = |}];; (* PR#5554 *) type 'a ty = Int : int -> int ty;; let f : type a. a ty -> a = fun x -> match x with Int y -> y;; let g : type a. a ty -> a = let () = () in fun x -> match x with Int y -> y;; [%%expect{| type 'a ty = Int : int -> int ty val f : 'a ty -> 'a = val g : 'a ty -> 'a = |}];; (* Printing of anonymous variables *) module M = struct type _ t = int end;; module M = struct type _ t = T : int t end;; module N = M;; [%%expect{| module M : sig type _ t = int end module M : sig type _ t = T : int t end module N = M |}];; (* Principality *) (* adding a useless equation should not break inference *) let f : type a b. (a,b) eq -> (a,int) eq -> a -> b -> _ = fun ab aint a b -> let Eq = ab in let x = let Eq = aint in if true then a else b in ignore x ;; (* ok *) [%%expect{| val f : ('a, 'b) eq -> ('a, int) eq -> 'a -> 'b -> unit = |}];; let f : type a b. (a,b) eq -> (b,int) eq -> a -> b -> _ = fun ab bint a b -> let Eq = ab in let x = let Eq = bint in if true then a else b in ignore x ;; (* ok *) [%%expect{| val f : ('a, 'b) eq -> ('b, int) eq -> 'a -> 'b -> unit = |}];; let f : type a b. (a,b) eq -> (a,int) eq -> a -> b -> _ = fun ab aint a b -> let Eq = aint in let x = let Eq = ab in if true then a else b in ignore x ;; (* ok *) [%%expect{| Line 5, characters 24-25: 5 | if true then a else b ^ Error: This expression has type b = int but an expression was expected of type a = int Type b = int is not compatible with type int This instance of int is ambiguous: it would escape the scope of its equation |}];; let f : type a b. (a,b) eq -> (b,int) eq -> a -> b -> _ = fun ab bint a b -> let Eq = bint in let x = let Eq = ab in if true then a else b in ignore x ;; (* ok *) [%%expect{| Line 5, characters 24-25: 5 | if true then a else b ^ Error: This expression has type b = int but an expression was expected of type a = int Type int is not compatible with type a = int This instance of int is ambiguous: it would escape the scope of its equation |}];; let f (type a b c) (b : bool) (w1 : (a,b) eq) (w2 : (a,int) eq) (x : a) (y : b) = let Eq = w1 in let Eq = w2 in if b then x else y ;; [%%expect{| Line 4, characters 19-20: 4 | if b then x else y ^ Error: This expression has type b = int but an expression was expected of type a = int Type a = int is not compatible with type a = int This instance of int is ambiguous: it would escape the scope of its equation |}];; let f (type a b c) (b : bool) (w1 : (a,b) eq) (w2 : (a,int) eq) (x : a) (y : b) = let Eq = w1 in let Eq = w2 in if b then y else x [%%expect{| Line 4, characters 19-20: 4 | if b then y else x ^ Error: This expression has type a = int but an expression was expected of type b = int This instance of int is ambiguous: it would escape the scope of its equation |}];;