(* TEST expect; *) (* Subtyping is "syntactic" *) fun (x : < x : int >) y z -> (y :> 'a), (x :> 'a), (z :> 'a);; [%%expect{| - : < x : int > -> < x : int > -> < x : int > -> < x : int > * < x : int > * < x : int > = |}];; (* - : (< x : int > as 'a) -> 'a -> 'a * 'a = *) (* Quirks of class typing. *) class ['a] c () = object method f = (new c (): int c) end and ['a] d () = object inherit ['a] c () end;; [%%expect{| class ['a] c : unit -> object constraint 'a = int method f : int c end and ['a] d : unit -> object constraint 'a = int method f : 'a c end |}];; (* class ['a] c : unit -> object constraint 'a = int method f : 'a c end *) (* and ['a] d : unit -> object constraint 'a = int method f : 'a c end *) (* 'a free in class d *) class ['a] c () = object method f (x : 'a) = () end and d () = object inherit ['a] c () end;; [%%expect{| Lines 3-5, characters 4-3: 3 | ....and d () = object 4 | inherit ['a] c () 5 | end.. Error: Some type variables are unbound in this type: class d : unit -> object method f : 'a -> unit end The method "f" has type "'a -> unit" where "'a" is unbound |}];; (* Create instance #c *) class virtual c () = object end and ['a] d () = object constraint 'a = #c method f (x : #c) = (x#x : int) end;; [%%expect{| class virtual c : unit -> object end and ['a] d : unit -> object constraint 'a = < x : int; .. > method f : 'a -> int end |}];; (* class virtual c : unit -> object end *) (* and ['a] d : *) (* unit -> object constraint 'a = < x : int; .. > method f : 'a -> int end *) class ['a] c () = object constraint 'a = int end and ['a] d () = object constraint 'a = 'b #c end;; [%%expect{| class ['a] c : unit -> object constraint 'a = int end and ['a] d : unit -> object constraint 'a = int #c end |}];; (* class ['a] c : unit -> object constraint 'a = int end and ['a] d : unit -> object constraint 'a = int #c end *) (* Class type constraint *) module F(X:sig type t end) = struct class type ['a] c = object method m: 'a -> X.t end end class ['a] c = object constraint 'a = 'a #F(Int).c end [%%expect {| module F : (X : sig type t end) -> sig class type ['a] c = object method m : 'a -> X.t end end class ['a] c : object constraint 'a = < m : 'a -> Int.t; .. > end |}] (* Self as parameter *) class ['a] c (x : 'a) = object (self : 'b) constraint 'a = 'b method f = self end;; [%%expect{| class ['a] c : 'a -> object ('a) constraint 'a = < f : 'a; .. > method f : 'a end |}];; new c;; [%%expect{| - : ('a c as 'a) -> 'a = |}];; (* class ['a] c : 'a -> object ('a) constraint 'a = < f : 'a; .. > method f : 'a end *) (* - : ('a c as 'a) -> 'a = *) class x () = object method virtual f : int end;; [%%expect{| Lines 1-3, characters 13-3: 1 | .............object 2 | method virtual f : int 3 | end.. Error: This non-virtual class has virtual methods. The following methods are virtual : "f" |}];; (* The class x should be virtual: its methods f is undefined *) (* Supplementary method g *) class virtual c ((x : 'a): < f : int >) = object (_ : 'a) end and virtual d x = object (_ : 'a) inherit c x method g = true end;; [%%expect{| Line 1, characters 49-57: 1 | class virtual c ((x : 'a): < f : int >) = object (_ : 'a) end ^^^^^^^^ Error: This pattern cannot match self: it only matches values of type "< f : int >" |}];; (* Constraint not respected *) class ['a] c () = object constraint 'a = int method f x = (x : bool c) end;; [%%expect{| Lines 1-4, characters 0-3: 1 | class ['a] c () = object 2 | constraint 'a = int 3 | method f x = (x : bool c) 4 | end.. Error: The abbreviation "c" is used with parameter(s) "bool " which are incompatible with constraint(s) "int " |}];; (* Different constraints *) class ['a, 'b] c () = object constraint 'a = int -> 'c constraint 'b = 'a * * 'c * 'd method f (x : 'a) (y : 'b) = () end;; [%%expect{| class ['a, 'b] c : unit -> object constraint 'a = int -> 'c constraint 'b = 'a * < x : 'b > * 'c * 'd method f : 'a -> 'b -> unit end |}];; class ['a, 'b] d () = object inherit ['a, 'b] c () end;; [%%expect{| class ['a, 'b] d : unit -> object constraint 'a = int -> 'd constraint 'b = 'a * (< x : 'b > as 'c) * 'd * 'e method f : (int -> 'd) -> (int -> 'd) * 'c * 'd * 'e -> unit end |}];; (* Non-generic constraint *) let x = ref [];; [%%expect{| val x : '_weak1 list ref = {contents = []} |}];; class ['a] c () = object method f = (x : 'a) end;; [%%expect{| Lines 1-3, characters 0-3: 1 | class ['a] c () = object 2 | method f = (x : 'a) 3 | end.. Error: The type of this class, "class ['a] c : unit -> object constraint 'a = '_weak1 list ref method f : 'a end", contains the non-generalizable type variable(s): "'_weak1". (see manual section 6.1.2) |}];; (* Abbreviations *) type 'a c = and 'a d = ;; [%%expect{| Line 1, characters 0-32: 1 | type 'a c = ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This recursive type is not regular. The type constructor "c" is defined as type "'a c" but it is used as "int c" after the following expansion(s): "< f : 'a c; g : 'a d >" contains "'a d", "'a d" = "< f : int c >", "< f : int c >" contains "int c" All uses need to match the definition for the recursive type to be regular. |}];; type 'a c = and 'a d = ;; [%%expect{| type 'a c = < f : 'a c; g : 'a d > and 'a d = < f : 'a c > |}];; type 'a c = and 'a d = ;; [%%expect{| type 'a c = < f : 'a c > and 'a d = < f : int c > |}];; type 'a u = < x : 'a> and 'a t = 'a t u;; [%%expect{| Line 2, characters 0-17: 2 | and 'a t = 'a t u;; ^^^^^^^^^^^^^^^^^ Error: The type abbreviation "t" is cyclic: "'a t u" contains "'a t", "'a t" = "'a t u", "'a t u" contains "'a t" |}];; (* fails since 4.04 *) type 'a u = 'a and 'a t = 'a t u;; [%%expect{| Line 2, characters 0-17: 2 | and 'a t = 'a t u;; ^^^^^^^^^^^^^^^^^ Error: The type abbreviation "t" is cyclic: "'a t" = "'a t u", "'a t u" = "'a t" |}];; type 'a u = 'a;; [%%expect{| type 'a u = 'a |}];; type t = t u * t u;; [%%expect{| Line 1, characters 0-18: 1 | type t = t u * t u;; ^^^^^^^^^^^^^^^^^^ Error: The type abbreviation "t" is cyclic: "t" = "t u * t u", "t u * t u" contains "t u", "t u" = "t" |}];; type t = as 'a;; [%%expect{| type t = < x : 'a > as 'a |}];; type 'a u = 'a;; [%%expect{| type 'a u = 'a |}];; fun (x : t) (y : 'a u) -> x = y;; [%%expect{| - : t -> t u -> bool = |}];; fun (x : t) (y : 'a u) -> y = x;; [%%expect{| - : t -> t u -> bool = |}];; (* - : t -> t u -> bool = *) (* Modules *) module M = struct class ['a, 'b] c (x: int) (y: 'b) = object constraint 'a = int -> bool val x : float list = [] val y = y method f (x : 'a) = () method g = y end end;; [%%expect{| module M : sig class ['a, 'b] c : int -> 'b -> object constraint 'a = int -> bool val x : float list val y : 'b method f : 'a -> unit method g : 'b end end |}];; module M' = (M : sig class virtual ['a, 'b] c : int -> 'b -> object constraint 'a = int -> bool val x : float list val y : 'b method f : 'a -> unit method g : 'b end end);; [%%expect{| module M' : sig class virtual ['a, 'b] c : int -> 'b -> object constraint 'a = int -> bool val x : float list val y : 'b method f : 'a -> unit method g : 'b end end |}];; class ['a, 'b] d () y = object inherit ['a, 'b] M.c 7 y end;; [%%expect{| class ['a, 'b] d : unit -> 'b -> object constraint 'a = int -> bool val x : float list val y : 'b method f : (int -> bool) -> unit method g : 'b end |}];; class ['a, 'b] e () y = object inherit ['a, 'b] M'.c 1 y end;; [%%expect{| class ['a, 'b] e : unit -> 'b -> object constraint 'a = int -> bool val x : float list val y : 'b method f : (int -> bool) -> unit method g : 'b end |}];; (new M.c 3 "a")#g;; [%%expect{| - : string = "a" |}];; (new d () 10)#g;; [%%expect{| - : int = 10 |}];; (new e () 7.1)#g;; [%%expect{| - : float = 7.1 |}];; open M;; [%%expect{| |}];; (new c 5 true)#g;; [%%expect{| - : bool = true |}];; (* #cl when cl is closed *) module M = struct class ['a] c () = object method f (x : 'a) = () end end;; [%%expect{| module M : sig class ['a] c : unit -> object method f : 'a -> unit end end |}];; module M' = (M : sig class ['a] c : unit -> object method f : 'a -> unit end end);; [%%expect{| module M' : sig class ['a] c : unit -> object method f : 'a -> unit end end |}];; fun x -> (x :> 'a #M.c);; [%%expect{| - : ('a #M.c as 'b) -> 'b = |}];; fun x -> (x :> 'a #M'.c);; [%%expect{| - : ('a #M'.c as 'b) -> 'b = |}];; class ['a] c (x : 'b #c) = object end;; [%%expect{| class ['a] c : 'a #c -> object end |}];; class ['a] c (x : 'b #c) = object end;; [%%expect{| class ['a] c : 'a #c -> object end |}];; (* Computation order *) class c () = object method f = 1 end and d () = object method f = 2 end;; [%%expect{| class c : unit -> object method f : int end and d : unit -> object method f : int end |}];; class e () = object inherit c () inherit d () end;; [%%expect{| class e : unit -> object method f : int end |}];; (new e ())#f;; [%%expect{| - : int = 2 |}];; class c () = object val x = - true val y = -. () end;; [%%expect{| Line 1, characters 30-34: 1 | class c () = object val x = - true val y = -. () end;; ^^^^ Error: The constructor "true" has type "bool" but an expression was expected of type "int" |}];; class c () = object method f = 1 method g = 1 method h = 1 end;; [%%expect{| class c : unit -> object method f : int method g : int method h : int end |}];; class d () = object method h = 2 method i = 2 method j = 2 end;; [%%expect{| class d : unit -> object method h : int method i : int method j : int end |}];; class e () = object method f = 3 inherit c () method g = 3 method i = 3 inherit d () method j = 3 end;; [%%expect{| class e : unit -> object method f : int method g : int method h : int method i : int method j : int end |}];; let e = new e ();; [%%expect{| val e : e = |}];; e#f, e#g, e#h, e#i, e#j;; [%%expect{| - : int * int * int * int * int = (1, 3, 2, 2, 3) |}];; class c a = object val x = 1 val y = 1 val z = 1 val a = a end;; [%%expect{| class c : 'a -> object val a : 'a val x : int val y : int val z : int end |}];; class d b = object val z = 2 val t = 2 val u = 2 val b = b end;; [%%expect{| class d : 'a -> object val b : 'a val t : int val u : int val z : int end |}];; class e () = object val x = 3 inherit c 5 val y = 3 val t = 3 inherit d 7 val u = 3 method x = x method y = y method z = z method t = t method u = u method a = a method b = b end;; [%%expect{| Line 3, characters 2-13: 3 | inherit c 5 ^^^^^^^^^^^ Warning 13 [instance-variable-override]: the following instance variables are overridden by the class "c": "x" Line 4, characters 6-7: 4 | val y = 3 ^ Warning 13 [instance-variable-override]: the instance variable "y" is overridden. Line 6, characters 2-13: 6 | inherit d 7 ^^^^^^^^^^^ Warning 13 [instance-variable-override]: the following instance variables are overridden by the class "d": "t" "z" Line 7, characters 6-7: 7 | val u = 3 ^ Warning 13 [instance-variable-override]: the instance variable "u" is overridden. class e : unit -> object val a : int val b : int val t : int val u : int val x : int val y : int val z : int method a : int method b : int method t : int method u : int method x : int method y : int method z : int end |}];; let e = new e ();; [%%expect{| val e : e = |}];; e#x, e#y, e#z, e#t, e#u, e#a, e#b;; [%%expect{| - : int * int * int * int * int * int * int = (1, 3, 2, 2, 3, 5, 7) |}];; class c (x : int) (y : int) = object val x = x val y = y method x = x method y = y end;; [%%expect{| class c : int -> int -> object val x : int val y : int method x : int method y : int end |}];; class d x y = object inherit c x y end;; [%%expect{| class d : int -> int -> object val x : int val y : int method x : int method y : int end |}];; let c = new c 1 2 in c#x, c#y;; [%%expect{| - : int * int = (1, 2) |}];; let d = new d 1 2 in d#x, d#y;; [%%expect{| - : int * int = (1, 2) |}];; (* Parameters which does not appear in the object type *) class ['a] c (x : 'a) = object end;; [%%expect{| class ['a] c : 'a -> object end |}];; new c;; [%%expect{| - : 'a -> 'a c = |}];; (* Private variables *) (* module type M = sig class c : unit -> object val x : int end class d : unit -> object inherit c val private x : int val x : bool end end;; [%%expect{| foo |}];; class c (x : int) = val private mutable x = x method get = x method set y = x <- y end;; [%%expect{| foo |}];; let c = new c 5;; [%%expect{| foo |}];; c#get;; [%%expect{| foo |}];; c#set 7; c#get;; [%%expect{| foo |}];; class c () = val x = 1 val y = 1 method c = x end;; [%%expect{| foo |}];; class d () = inherit c () val private x method d = x end;; [%%expect{| foo |}];; class e () = val x = 2 val y = 2 inherit d () method x = x method y = y end;; [%%expect{| foo |}];; let e = new e () in e#x, e#y, e#c, e#d;; [%%expect{| foo |}];; *) (* Forgotten variables in interfaces *) module M : sig class c : unit -> object method xc : int end end = struct class c () = object val x = 1 method xc = x end end;; [%%expect{| module M : sig class c : unit -> object method xc : int end end |}];; class d () = object val x = 2 method xd = x inherit M.c () end;; [%%expect{| class d : unit -> object val x : int method xc : int method xd : int end |}];; let d = new d () in d#xc, d#xd;; [%%expect{| - : int * int = (1, 2) |}];; class virtual ['a] matrix (sz, init : int * 'a) = object val m = Array.make_matrix sz sz init method add (mtx : 'a matrix) = (mtx#m.(0).(0) : 'a) end;; [%%expect{| Lines 1-4, characters 0-3: 1 | class virtual ['a] matrix (sz, init : int * 'a) = object 2 | val m = Array.make_matrix sz sz init 3 | method add (mtx : 'a matrix) = (mtx#m.(0).(0) : 'a) 4 | end.. Error: The abbreviation "'a matrix" expands to type "< add : 'a matrix -> 'a >" but is used with type "< m : 'a array array; .. >" |}];; class c () = object method m = new c () end;; [%%expect{| class c : unit -> object method m : c end |}];; (new c ())#m;; [%%expect{| - : c = |}];; module M = struct class c () = object method m = new c () end end;; [%%expect{| module M : sig class c : unit -> object method m : c end end |}];; (new M.c ())#m;; [%%expect{| - : M.c = |}];; type uu = A of int | B of ( as 'a);; [%%expect{| type uu = A of int | B of (< leq : 'a > as 'a) |}];; class virtual c () = object (_ : 'a) method virtual m : 'a end;; [%%expect{| class virtual c : unit -> object ('a) method virtual m : 'a end |}];; module S = (struct let f (x : #c) = x end : sig val f : (#c as 'a) -> 'a end);; [%%expect{| module S : sig val f : (#c as 'a) -> 'a end |}];; module S = (struct let f (x : #c) = x end : sig val f : #c -> #c end);; [%%expect{| Lines 1-3, characters 12-3: 1 | ............struct 2 | let f (x : #c) = x 3 | end...... Error: Signature mismatch: Modules do not match: sig val f : (#c as 'a) -> 'a end is not included in sig val f : #c -> #c end Values do not match: val f : (#c as 'a) -> 'a is not included in val f : #c -> #c The type "(#c as 'a) -> 'a" is not compatible with the type "#c -> #c" Type "#c as 'a" = "< m : 'a; .. >" is not compatible with type "#c as 'b" = "< m : 'b; .. >" Type "'a" is not compatible with type "'b" |}];; module M = struct type t = int class t () = object end end;; [%%expect{| Line 1, characters 37-38: 1 | module M = struct type t = int class t () = object end end;; ^ Error: Multiple definition of the type name "t". Names must be unique in a given structure or signature. |}];; fun x -> (x :> < m : 'a -> 'a > as 'a);; [%%expect{| - : < m : (< m : 'a > as 'b) -> 'b as 'a; .. > -> 'b = |}, Principal{| - : < m : < m : 'a > -> < m : 'a > as 'a; .. > -> (< m : 'b -> 'b > as 'b) = |}];; fun x -> (x : int -> bool :> 'a -> 'a);; [%%expect{| Line 1, characters 9-38: 1 | fun x -> (x : int -> bool :> 'a -> 'a);; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Type "int -> bool" is not a subtype of "int -> int" Type "bool" is not a subtype of "int" |}];; fun x -> (x : int -> bool :> int -> int);; [%%expect{| Line 1, characters 9-40: 1 | fun x -> (x : int -> bool :> int -> int);; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Type "int -> bool" is not a subtype of "int -> int" Type "bool" is not a subtype of "int" |}];; fun x -> (x : < > :> < .. >);; [%%expect{| - : < > -> < > = |}];; fun x -> (x : < .. > :> < >);; [%%expect{| - : < .. > -> < > = |}];; let x = ref [];; [%%expect{| val x : '_weak2 list ref = {contents = []} |}];; module F(X : sig end) = struct type t = int let _ = (x : < m : t> list ref) end;; [%%expect{| module F : (X : sig end) -> sig type t = int end |}];; x;; [%%expect{| - : < m : int > list ref = {contents = []} |}];; type 'a t;; [%%expect{| type 'a t |}];; fun (x : 'a t as 'a) -> ();; [%%expect{| Line 1, characters 17-19: 1 | fun (x : 'a t as 'a) -> ();; ^^ Error: This alias is bound to type "'a t" but is used as an instance of type "'a" The type variable "'a" occurs inside "'a t" |}];; fun (x : 'a t) -> (x : 'a); ();; [%%expect{| Line 1, characters 19-20: 1 | fun (x : 'a t) -> (x : 'a); ();; ^ Error: The value "x" has type "'a t" but an expression was expected of type "'a" The type variable "'a" occurs inside "'a t" |}];; fun ((x : 'a) | (x : 'a t)) -> ();; [%%expect{| Line 1, characters 10-12: 1 | fun ((x : 'a) | (x : 'a t)) -> ();; ^^ Error: This type "'a t" should be an instance of type "'a" The type variable "'a" occurs inside "'a t" |}];; fun ((x : 'a) | (x : 'a t)) -> ();; [%%expect{| Line 1, characters 10-12: 1 | fun ((x : 'a) | (x : 'a t)) -> ();; ^^ Error: This type "'a t" should be an instance of type "'a" The type variable "'a" occurs inside "'a t" |}];; type 'a t = < x : 'a >;; [%%expect{| type 'a t = < x : 'a > |}];; fun (x : 'a t as 'a) -> ();; [%%expect{| - : ('a t as 'a) -> unit = |}];; fun (x : 'a t) -> (x : 'a); ();; [%%expect{| Line 1, characters 18-26: 1 | fun (x : 'a t) -> (x : 'a); ();; ^^^^^^^^ Warning 10 [non-unit-statement]: this expression should have type unit. - : ('a t as 'a) t -> unit = |}];; fun ((x : 'a) | (x : 'a t)) -> ();; [%%expect{| Line 1, characters 17-18: 1 | fun ((x : 'a) | (x : 'a t)) -> ();; ^ Warning 12 [redundant-subpat]: this sub-pattern is unused. - : ('a t as 'a) -> unit = |}];; class ['a] c () = object constraint 'a = < .. > -> unit method m = (fun x -> () : 'a) end;; [%%expect{| class ['a] c : unit -> object constraint 'a = (< .. > as 'b) -> unit method m : 'b -> unit end |}];; class ['a] c () = object constraint 'a = unit -> < .. > method m (f : 'a) = f () end;; [%%expect{| class ['a] c : unit -> object constraint 'a = unit -> (< .. > as 'b) method m : 'a -> 'b end |}];; class c () = object (self) method private m = 1 method n = self#m end;; [%%expect{| class c : unit -> object method private m : int method n : int end |}];; class d () = object (self) inherit c () method o = self#m end;; [%%expect{| class d : unit -> object method private m : int method n : int method o : int end |}];; let x = new d () in x#n, x#o;; [%%expect{| - : int * int = (1, 1) |}];; class c () = object method virtual m : int method private m = 1 end;; [%%expect{| class c : unit -> object method m : int end |}];; (* Recursion (cf. PR#5291) *) class a = let _ = new b in object end and b = let _ = new a in object end;; [%%expect{| Line 1, characters 10-37: 1 | class a = let _ = new b in object end ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This kind of recursive class expression is not allowed |}];; class a = let _ = new a in object end;; [%%expect{| Line 1, characters 10-37: 1 | class a = let _ = new a in object end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This kind of recursive class expression is not allowed |}];; (* More tests about recursion in class declarations *) class a = let _x() = new a in object end;; [%%expect{| class a : object end |}];; class a = object end and b = let _x() = new a in object end;; [%%expect{| class a : object end and b : object end |}];; class a = let x() = new a in let y = x() in object end;; [%%expect{| Line 1, characters 10-54: 1 | class a = let x() = new a in let y = x() in object end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This kind of recursive class expression is not allowed |}];; class a = object end and b = let x() = new a in let y = x() in object end;; [%%expect{| Line 2, characters 8-52: 2 | and b = let x() = new a in let y = x() in object end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This kind of recursive class expression is not allowed |}];; class a = object val x = 3 val y = x + 2 end;; [%%expect{| Line 1, characters 35-36: 1 | class a = object val x = 3 val y = x + 2 end;; ^ Error: The instance variable "x" cannot be accessed from the definition of another instance variable |}];; class a = object (self) val x = self#m method m = 3 end;; [%%expect{| Line 1, characters 32-36: 1 | class a = object (self) val x = self#m method m = 3 end;; ^^^^ Error: The self variable "self" cannot be accessed from the definition of an instance variable |}];; class a = object method m = 3 end class b = object inherit a as super val x = super#m end;; [%%expect{| class a : object method m : int end Line 2, characters 44-49: 2 | class b = object inherit a as super val x = super#m end;; ^^^^^ Error: The ancestor variable "super" cannot be accessed from the definition of an instance variable |}];; (* Some more tests of class idiosyncrasies *) class c = object method private m = 3 end and d = object method o = object inherit c end end;; [%%expect {| class c : object method private m : int end and d : object method o : c end |}];; class c = object(_ : 'self) method o = object(_ : 'self) method o = assert false end end;; [%%expect {| Line 2, characters 13-58: 2 | method o = object(_ : 'self) method o = assert false end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: Cannot close type of object literal: "< o : '_weak4; .. > as '_weak3" it has been unified with the self type of a class that is not yet completely defined. |}];; class c = object method m = 1 inherit object (self) method n = self#m end end;; [%%expect {| Line 4, characters 17-23: 4 | method n = self#m ^^^^^^ Warning 17 [undeclared-virtual-method]: the virtual method "m" is not declared. class c : object method m : int method n : int end |}];; class virtual c = object (self : 'c) constraint 'c = < f : int; .. > end [%%expect {| class virtual c : object method virtual f : int end |}];; class virtual c = object (self : 'c) constraint 'c = < f : int; .. > method g = self # f end [%%expect {| class virtual c : object method virtual f : int method g : int end |}];; class [ 'a ] c = object (_ : 'a) end;; let o = object method m = 1 inherit [ < m : int > ] c end;; [%%expect {| class ['a] c : object ('a) constraint 'a = < .. > end Line 4, characters 14-25: 4 | inherit [ < m : int > ] c ^^^^^^^^^^^ Error: The type parameter "< m : int >" does not meet its constraint: it should be "< .. >" Self type cannot be unified with a closed object type |}];; class type [ 'a ] d = object method a : 'a method b : 'a end class c : ['a] d = object (self) method a = 1 method b = assert false end;; [%%expect {| class type ['a] d = object method a : 'a method b : 'a end Line 2, characters 19-73: 2 | class c : ['a] d = object (self) method a = 1 method b = assert false end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The class type object method a : int method b : 'a end is not matched by the class type ['_a] d The class type object method a : int method b : 'a end is not matched by the class type object method a : 'a method b : 'a end The method a has type "int" but is expected to have type "'a" Type "int" is not compatible with type "'a" |}];; class type ['a] ct = object ('a) end class c : [ < a : int; ..> ] ct = object method a = 3 end;; [%%expect {| class type ['a] ct = object ('a) constraint 'a = < .. > end Line 2, characters 10-31: 2 | class c : [ < a : int; ..> ] ct = object method a = 3 end;; ^^^^^^^^^^^^^^^^^^^^^ Error: This non-virtual class has undeclared virtual methods. The following methods were not declared : "a" |}];; class virtual c : [ < a : int; ..> ] ct = object method a = 3 end;; [%%expect {| class virtual c : object method virtual a : int end |}];; class c : object method m : < m : 'a > as 'a end = object (self) method m = self end;; [%%expect {| Lines 3-5, characters 8-3: 3 | ........object (self) 4 | method m = self 5 | end.. Error: The class type object ('a) method m : < m : 'a; .. > as 'a end is not matched by the class type object method m : < m : 'a > as 'a end The method m has type "< m : 'a; .. > as 'a" but is expected to have type "< m : 'b > as 'b" Type "'a" is not compatible with type "< >" |}];; class c : object method foo : < foo : int; .. > -> < foo : int> -> unit end = object method foo : 'a. (< foo : int; .. > as 'a) -> 'a -> unit = assert false end;; [%%expect {| Lines 5-7, characters 2-5: 5 | ..object 6 | method foo : 'a. (< foo : int; .. > as 'a) -> 'a -> unit = assert false 7 | end.. Error: The class type object method foo : (< foo : int; .. > as 'a) -> 'a -> unit end is not matched by the class type object method foo : < foo : int; .. > -> < foo : int > -> unit end The method foo has type "'a. (< foo : int; .. > as 'a) -> 'a -> unit" but is expected to have type "'b. (< foo : int; .. > as 'b) -> < foo : int > -> unit" Type "'c" is not compatible with type "< >" |}];; class c = (fun x -> object(_:'foo) end) 3;; [%%expect {| class c : object end |}];; class virtual c = ((fun (x : 'self -> unit) -> object(_:'self) end) (fun (_ : < a : int; .. >) -> ()) : object method virtual a : int end) [%%expect {| class virtual c : object method virtual a : int end |}];; class c = object val x = 3 method o = {< x = 4; y = 5 >} val y = 4 end;; [%%expect {| class c : object ('a) val x : int val y : int method o : 'a end |}];; class c : object('self) method m : < m : 'a; x : int; ..> -> unit as 'a end = object (_ : 'self) method m (_ : 'self) = () end;; [%%expect {| Line 2, characters 4-52: 2 | object (_ : 'self) method m (_ : 'self) = () end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: The class type object ('a) method m : (< m : 'a -> unit; .. > as 'a) -> unit end is not matched by the class type object method m : < m : 'a; x : int; .. > -> unit as 'a end The method m has type "(< m : 'a -> unit; .. > as 'a) -> unit" but is expected to have type "'b. (< m : 'c; x : int; .. > as 'b) -> unit as 'c" Type "'a" is not compatible with type "< x : int; .. >" |}];; let is_empty (x : < >) = () class c = object (self) method private foo = is_empty self end;; [%%expect {| val is_empty : < > -> unit = Line 2, characters 54-58: 2 | class c = object (self) method private foo = is_empty self end;; ^^^^ Error: The value "self" has type "< .. >" but an expression was expected of type "< >" Self type cannot be unified with a closed object type |}];; (* Warnings about private methods implicitly made public *) let has_foo (x : < foo : 'a; .. >) = () class c = object (self) method private foo = 5 initializer has_foo self end;; [%%expect {| val has_foo : < foo : 'a; .. > -> unit = Line 3, characters 10-75: 3 | class c = object (self) method private foo = 5 initializer has_foo self end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Warning 15 [implicit-public-methods]: the following private methods were made public implicitly: "foo". class c : object method foo : int end |}];; class type c = object(< foo : 'a; ..>) method private foo : int end;; [%%expect {| class type c = object method foo : int end |}];; class ['a] p = object (_ : 'a) method private foo = 5 end;; class c = [ < foo : int; .. > ] p;; [%%expect {| class ['a] p : object ('a) constraint 'a = < .. > method private foo : int end class c : object method foo : int end |}];; (* Errors for undefined methods *) class c = object method virtual foo : int end;; [%%expect {| Line 1, characters 10-45: 1 | class c = object method virtual foo : int end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This non-virtual class has virtual methods. The following methods are virtual : "foo" |}];; class type ct = object method virtual foo : int end;; [%%expect {| Line 1, characters 16-51: 1 | class type ct = object method virtual foo : int end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This non-virtual class type has virtual methods. The following methods are virtual : "foo" |}];; let o = object method virtual foo : int end;; [%%expect {| Line 1, characters 8-43: 1 | let o = object method virtual foo : int end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This object has virtual methods. The following methods are virtual : "foo" |}];; class c = object(self) initializer self#foo end;; [%%expect {| Line 1, characters 35-39: 1 | class c = object(self) initializer self#foo end;; ^^^^ Error: This expression has no method "foo" |}];; let o = object(self) initializer self#foo end;; [%%expect {| Line 1, characters 33-37: 1 | let o = object(self) initializer self#foo end;; ^^^^ Error: This expression has no method "foo" |}];; let has_foo (x : < foo : int; ..>) = () class c = object(self) initializer has_foo self end;; [%%expect {| val has_foo : < foo : int; .. > -> unit = Line 2, characters 10-51: 2 | class c = object(self) initializer has_foo self end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This non-virtual class has undeclared virtual methods. The following methods were not declared : "foo" |}];; let o = object(self) initializer has_foo self end;; [%%expect {| Line 1, characters 41-45: 1 | let o = object(self) initializer has_foo self end;; ^^^^ Error: The value "self" has type "< >" but an expression was expected of type "< foo : int; .. >" The first object type has no method "foo" |}];; class c = object(_ : < foo : int; ..>) end;; [%%expect {| Line 1, characters 10-42: 1 | class c = object(_ : < foo : int; ..>) end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This non-virtual class has undeclared virtual methods. The following methods were not declared : "foo" |}];; class type ct = object(< foo : int; ..>) end;; [%%expect {| Line 1, characters 16-44: 1 | class type ct = object(< foo : int; ..>) end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This non-virtual class type has undeclared virtual methods. The following methods were not declared : "foo" |}];; let o = object(_ : < foo : int; ..>) end;; [%%expect {| Line 1, characters 8-40: 1 | let o = object(_ : < foo : int; ..>) end;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This object has undeclared virtual methods. The following methods were not declared : "foo" |}];; (* Shadowing/overriding methods in class types *) class type c = object val x : int val x : float end;; [%%expect {| class type c = object val x : float end |}];; class type c = object val x : int val mutable x : int end;; [%%expect {| class type c = object val mutable x : int end |}];; class type c = object val mutable x : int val x : int end;; [%%expect {| class type c = object val x : int end |}];; class type virtual c = object val virtual x : int val x : int end;; [%%expect {| class type c = object val x : int end |}];; class type virtual c = object val x : int val virtual x : int end;; [%%expect {| class type c = object val x : int end |}];; class type virtual c = object val x : int val virtual x : float end;; [%%expect {| class type c = object val x : float end |}];; class c = object method virtual private test : unit method private test = () end let () = (new c)#test [%%expect {| class c : object method private test : unit end Line 6, characters 9-16: 6 | let () = (new c)#test ^^^^^^^ Error: This expression has type "c" It has no method "test" |}];; class c = object method virtual private test : unit method test = () end let () = (new c)#test [%%expect {| class c : object method test : unit end |}];; class virtual d = object method virtual private test : unit end class c = object inherit d method private test = () end let () = (new c)#test [%%expect {| class virtual d : object method private virtual test : unit end class c : object method private test : unit end Line 10, characters 9-16: 10 | let () = (new c)#test ^^^^^^^ Error: This expression has type "c" It has no method "test" |}];; class c = object inherit d method test = () end let () = (new c)#test [%%expect {| class c : object method test : unit end |}];; class foo = object method private f (b : bool) = b inherit object method f (b : bool) = b end end let _ = (new foo)#f true [%%expect {| class foo : object method f : bool -> bool end - : bool = true |}];; class c : object method virtual m : int end = object method m = 9 end [%%expect {| Lines 1-3, characters 10-3: 1 | ..........object 2 | method virtual m : int 3 | end......... Error: This non-virtual class type has virtual methods. The following methods are virtual : "m" |}];; class virtual c : object method virtual m : int end = object method m = 42 end [%%expect {| class virtual c : object method virtual m : int end |}];; class virtual cv = object method virtual m : int end class c : cv = object method m = 42 end [%%expect {| class virtual cv : object method virtual m : int end Line 5, characters 10-12: 5 | class c : cv = object ^^ Error: This non-virtual class type has virtual methods. The following methods are virtual : "m" |}];; class virtual c : cv = object method m = 41 end [%%expect {| class virtual c : cv |}];; class c = cv [%%expect {| Line 1, characters 10-12: 1 | class c = cv ^^ Error: This non-virtual class has virtual methods. The following methods are virtual : "m" |}];; class virtual c = cv [%%expect {| class virtual c : cv |}];; (** Test classes abbreviations with a recursive type *) class ['a] c = object method m: ( as 'b) -> unit = fun _ -> () end class d = ['a] c [%%expect {| class ['a] c : object method m : (< f : 'b; x : 'a > as 'b) -> unit end Line 2, characters 0-16: 2 | class d = ['a] c ^^^^^^^^^^^^^^^^ Error: Some type variables are unbound in this type: class d : ['a] c The method "m" has type "(< f : 'b; x : 'a > as 'b) -> unit" where "'a" is unbound |}]