-- main
class t =
    object
    end;;

class m =
    object
        inherit t
    end;;

class b =
    object
        inherit m
    end;;

class u =
    object
        method cv (ot : t) = print_string "cv(T) in U\n" ;
        method ctv (ob : b) = print_string "ctv(B) in U\n" ;
    end;;

class d =
    object
        inherit u
        method cv ( om : m ) = print_string "cv(M) in D\n" ;
        method ctv ( om : m) = print_string "ctv(M) in D\n" ;
    end;;

let ou = new u;; let ow = new u;; let od = new d;;

let ot = new t;; let om = new m;; let ob = new b;;

let w=d;;

print_string "-- first test suite\n" ;;
ou#cv(ot);;
ou#cv(om);;
ou#cv(ob);;
ou#ctv(ot);;
ou#ctv(om);;
ou#ctv(ob);;

print_string "-- second test suite\n" ;;
od#cv(ot);;
od#cv(om);;
od#cv(ob);;
od#ctv(ot);;
od#ctv(om);;
od#ctv(ob);;

print_string "-- third test suite\n" ;;
ow#cv(ot);;
ow#cv(om);;
ow#cv(ob);;
ow#ctv(ot);;
ow#ctv(om);;
ow#ctv(ob);;
 

-- run
-- first test suite
    - : unit = ()
# cv(T) in U
    - : unit = ()
# cv(T) in U
    - : unit = ()
# cv(T) in U
    - : unit = ()
# ctv(B) in U
    - : unit = ()
# ctv(B) in U
    - : unit = ()
# ctv(B) in U
    - : unit = ()
-- second test suite
    - : unit = ()
# cv(M) in D
    - : unit = ()
# cv(M) in D
    - : unit = ()
# cv(M) in D
    - : unit = ()
# ctv(M) in D
    - : unit = ()
# ctv(M) in D
    - : unit = ()
# ctv(M) in D
    - : unit = ()
-- third test suite
    - : unit = ()
# cv(M) in D
    - : unit = ()
# cv(M) in D
    - : unit = ()
# cv(M) in D
    - : unit = ()
# ctv(M) in D
    - : unit = ()
# ctv(M) in D
    - : unit = ()
# ctv(M) in D
    - : unit = () #

//run with an attempt to have a runtime error

class m =
    object
        inherit t
        method boom () = print_string "ok\n" ;
    end;;

class d =
    object
        inherit u
        method cv ( om : m ) = begin print_string "cv(M) in D\n" ; om#boom();
        (* attempt to generate an error, calling boom() *)
        end;
        method ctv ( om : m) = print_string "ctv(M) in D\n" ;
    end;;

-- first test suite
    - : unit = ()

# cv(T) in U
    - : unit = ()

# Characters 6-8: This expression has type m = < boom : unit -> unit > but is
here used with type t = <  > Only the first object type has a method boom

# Characters 6-8: This expression has type b = < boom : unit -> unit > but is
here used with type t = <  > Only the first object type has a method boom

# Characters 7-9: This expression has type t = <  > but is here used with type
  b = < boom : unit -> unit >
Only the second object type has a method boom

# ctv(B) in U
    - : unit = ()
# ctv(B) in U
    - : unit = () #

-- second test suite
    - : unit = ()

# Characters 0-2: Unbound value od
# Characters 0-2: Unbound value od
# Characters 0-2: Unbound value od
# Characters 0-2: Unbound value od
# Characters 0-2: Unbound value od
# Characters 0-2: Unbound value od

-- third test suite
    - : unit = ()

# cv(T) in U
    - : unit = ()

# Characters 6-8: This expression has type m = < boom : unit -> unit > but is
here used with type t = <  > Only the first object type has a method boom

# Characters 6-8: This expression has type b = < boom : unit -> unit > but is
here used with type t = <  > Only the first object type has a method boom

# Characters 7-9: This expression has type t = <  > but is here used with type
  b = < boom : unit -> unit > Only the second object type has a method boom

# ctv(B) in U
    - : unit = ()
# ctv(B) in U
    - : unit = () #