summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--VERSION2
-rw-r--r--testsuite/tests/typing-gadts/test.ml71
-rw-r--r--testsuite/tests/typing-gadts/test.ml.principal.reference32
-rw-r--r--testsuite/tests/typing-gadts/test.ml.reference43
-rw-r--r--typing/parmatch.ml17
-rw-r--r--typing/printtyp.ml2
-rw-r--r--typing/typecore.ml67
7 files changed, 199 insertions, 35 deletions
diff --git a/VERSION b/VERSION
index ed7b65316..2a00aa0c2 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-3.13.0-gadt (2010-10-22)
+3.13.0-gadt (2011-06-15)
# The version string is the first line of this file.
# It must be in the format described in stdlib/sys.mli
diff --git a/testsuite/tests/typing-gadts/test.ml b/testsuite/tests/typing-gadts/test.ml
index a3de7ae6f..e79361acf 100644
--- a/testsuite/tests/typing-gadts/test.ml
+++ b/testsuite/tests/typing-gadts/test.ml
@@ -237,3 +237,74 @@ let f (type a) (x : a t) y =
let f (type a) (x : a t) (y : a) =
match x with Int -> y
;;
+
+(* 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
+;;
+
+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 *)
+
+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 *)
+
+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 *)
+
+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
+;; (* warn *)
diff --git a/testsuite/tests/typing-gadts/test.ml.principal.reference b/testsuite/tests/typing-gadts/test.ml.principal.reference
index fae7dca83..6db24e1a5 100644
--- a/testsuite/tests/typing-gadts/test.ml.principal.reference
+++ b/testsuite/tests/typing-gadts/test.ml.principal.reference
@@ -128,4 +128,36 @@ Error: This expression has type int but an expression was expected of type a
# val f : 'a t -> 'a -> 'a = <fun>
# val f : 'a t -> 'a -> 'a = <fun>
# val f : 'a t -> 'a -> int = <fun>
+# type 'a t = A of int | B of bool | C of float | D of 'a
+type 'a ty =
+ TE : 'b ty -> 'b array ty
+ | TA : int ty
+ | TB : bool ty
+ | TC : float ty
+ | TD : string -> bool ty
+val f : 'a ty -> 'a t -> int = <fun>
+# Characters 51-202:
+ ..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
+Warning 8: this pattern-matching is not exhaustive.
+Here is an example of a value that is not matched:
+(TE TC, D [| |])
+val f : 'a ty -> 'a t -> int = <fun>
+# Characters 147-154:
+ | 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
+# Characters 259-266:
+ | {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; }
+val f : 'a ty -> 'a t -> int = <fun>
#
diff --git a/testsuite/tests/typing-gadts/test.ml.reference b/testsuite/tests/typing-gadts/test.ml.reference
index 810280759..95cd0cc76 100644
--- a/testsuite/tests/typing-gadts/test.ml.reference
+++ b/testsuite/tests/typing-gadts/test.ml.reference
@@ -117,4 +117,47 @@ Error: This expression has type int but an expression was expected of type a
# val f : 'a t -> 'a -> 'a = <fun>
# val f : 'a t -> 'a -> 'a = <fun>
# val f : 'a t -> 'a -> 'a = <fun>
+# type 'a t = A of int | B of bool | C of float | D of 'a
+type 'a ty =
+ TE : 'b ty -> 'b array ty
+ | TA : int ty
+ | TB : bool ty
+ | TC : float ty
+ | TD : string -> bool ty
+val f : 'a ty -> 'a t -> int = <fun>
+# Characters 51-202:
+ ..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
+Warning 8: this pattern-matching is not exhaustive.
+Here is an example of a value that is not matched:
+(TE TC, D [| |])
+val f : 'a ty -> 'a t -> int = <fun>
+# Characters 147-154:
+ | 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
+# Characters 259-266:
+ | {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
+# Characters 92-334:
+ ..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
+Warning 8: this pattern-matching is not exhaustive.
+Here is an example of a value that is not matched:
+{left=TE (TE _); right=D [| _ |]}
+type ('a, 'b) pair = { left : 'a; right : 'b; }
+val f : 'a ty -> 'a t -> int = <fun>
#
diff --git a/typing/parmatch.ml b/typing/parmatch.ml
index e7f743c54..400246ba5 100644
--- a/typing/parmatch.ml
+++ b/typing/parmatch.ml
@@ -51,16 +51,19 @@ let is_absent_pat p = match p.pat_desc with
| Tpat_variant (tag, _, row) -> is_absent tag row
| _ -> false
+(*
let sort_fields args =
Sort.list
(fun (lbl1,_) (lbl2,_) -> lbl1.lbl_pos <= lbl2.lbl_pos)
args
+*)
let records_args l1 l2 =
- let l1 = sort_fields l1
- and l2 = sort_fields l2 in
+ (* let l1 = sort_fields l1
+ and l2 = sort_fields l2 in *)
+ (* Invariant: fields are already sorted by Typecore.type_label_a_list *)
let rec combine r1 r2 l1 l2 = match l1,l2 with
- | [],[] -> r1,r2
+ | [],[] -> List.rev r1, List.rev r2
| [],(_,p2)::rem2 -> combine (omega::r1) (p2::r2) [] rem2
| (_,p1)::rem1,[] -> combine (p1::r1) (omega::r2) rem1 []
| (lbl1,p1)::rem1, (lbl2,p2)::rem2 ->
@@ -311,12 +314,14 @@ let extract_fields omegas arg =
+(*
let sort_record p = match p.pat_desc with
| Tpat_record args ->
make_pat
(Tpat_record (sort_fields args))
p.pat_type p.pat_env
| _ -> p
+*)
let all_record_args lbls = match lbls with
| ({lbl_all=lbl_all},_)::_ ->
@@ -411,7 +416,7 @@ let discr_pat q pss =
match normalize_pat q with
| {pat_desc= (Tpat_any | Tpat_record _)} as q ->
- sort_record (acc_pat q pss)
+ (*sort_record*) (acc_pat q pss)
| q -> q
(*
@@ -1565,7 +1570,7 @@ with
| Empty -> lub p2 q
and record_lubs l1 l2 =
- let l1 = sort_fields l1 and l2 = sort_fields l2 in
+ (* let l1 = sort_fields l1 and l2 = sort_fields l2 in *)
let rec lub_rec l1 l2 = match l1,l2 with
| [],_ -> l2
| _,[] -> l1
@@ -1957,7 +1962,7 @@ let check_unused tdefs casel =
p.pat_loc Warnings.Unused_pat)
ps
| Used -> ()
- with e -> assert false
+ with Empty | Not_an_adt | Not_found | NoGuard -> assert false
end ;
if has_guard act then
diff --git a/typing/printtyp.ml b/typing/printtyp.ml
index 868bfddce..6b02e1b91 100644
--- a/typing/printtyp.ml
+++ b/typing/printtyp.ml
@@ -431,7 +431,7 @@ and tree_of_typobject sch fi nm =
| _ -> l)
fields [] in
let sorted_fields =
- Sort.list (fun (n, _) (n', _) -> n <= n') present_fields in
+ List.sort (fun (n, _) (n', _) -> compare n n') present_fields in
tree_of_typfields sch rest sorted_fields in
let (fields, rest) = pr_fields fi in
Otyp_object (fields, rest)
diff --git a/typing/typecore.ml b/typing/typecore.ml
index e6b85bc01..43af94b7b 100644
--- a/typing/typecore.ml
+++ b/typing/typecore.ml
@@ -405,21 +405,39 @@ let build_or_pat env loc lid =
pat pats in
(rp { r with pat_loc = loc },ty)
+(* Records *)
+
let rec find_record_qual = function
| [] -> None
| (Longident.Ldot (modname, _), _) :: _ -> Some modname
| _ :: rest -> find_record_qual rest
-let type_label_a_list type_lid_a lid_a_list =
- match find_record_qual lid_a_list with
- | None -> List.map type_lid_a lid_a_list
- | Some modname ->
- List.map
- (function
- | (Longident.Lident id), sarg ->
- type_lid_a (Longident.Ldot (modname, id), sarg)
- | lid_a -> type_lid_a lid_a)
- lid_a_list
+let type_label_a_list ?labels env loc type_lbl_a lid_a_list =
+ let record_qual = find_record_qual lid_a_list in
+ let lbl_a_list =
+ List.map
+ (fun (lid, a) ->
+ match lid, labels, record_qual with
+ Longident.Lident s, Some labels, _ when Hashtbl.mem labels s ->
+ Hashtbl.find labels s, a
+ | Longident.Lident s, _, Some modname ->
+ Typetexp.find_label env loc (Longident.Ldot (modname, s)), a
+ | _ ->
+ Typetexp.find_label env loc lid, a)
+ lid_a_list in
+ (* Invariant: records are sorted in the typed tree *)
+ let lbl_a_list =
+ List.sort
+ (fun (lbl1,_) (lbl2,_) -> compare lbl1.lbl_pos lbl2.lbl_pos)
+ lbl_a_list
+ in
+ List.map type_lbl_a lbl_a_list
+
+let lid_of_label label =
+ match repr label.lbl_res with
+ | {desc = Tconstr(Path.Pdot(mpath,_,_),_,_)} ->
+ Longident.Ldot(lid_of_path mpath, label.lbl_name)
+ | _ -> Longident.Lident label.lbl_name
(* Checks over the labels mentioned in a record pattern:
no duplicate definitions (error); properly closed (warning) *)
@@ -600,21 +618,15 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
pat_loc = loc;
pat_type = expected_ty;
pat_env = !env }
- | Ppat_record(lid_sp_list, closed) ->
- let type_label_pat (lid, sarg) =
- let label =
- match lid, labels with
- Longident.Lident s, Some labels when Hashtbl.mem labels s ->
- Hashtbl.find labels s
- | _ -> Typetexp.find_label !env loc lid
- in
+ | Ppat_record(lid_sp_list, closed) ->
+ let type_label_pat (label, sarg) =
begin_def ();
let (vars, ty_arg, ty_res) = instance_label false label in
if vars = [] then end_def ();
begin try
unify_pat_types loc !env ty_res expected_ty
with Unify trace ->
- raise(Error(loc, Label_mismatch(lid, trace)))
+ raise(Error(loc, Label_mismatch(lid_of_label label, trace)))
end;
let arg = type_pat sarg ty_arg in
if vars <> [] then begin
@@ -625,11 +637,12 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
let tv = expand_head !env tv in
tv.desc <> Tvar || tv.level <> generic_level in
if List.exists instantiated vars then
- raise (Error(loc, Polymorphic_label lid))
+ raise (Error(loc, Polymorphic_label (lid_of_label label)))
end;
(label, arg)
in
- let lbl_pat_list = type_label_a_list type_label_pat lid_sp_list in
+ let lbl_pat_list =
+ type_label_a_list ?labels !env loc type_label_pat lid_sp_list in
check_recordpat_labels loc lbl_pat_list closed;
rp {
pat_desc = Tpat_record lbl_pat_list;
@@ -1484,7 +1497,7 @@ and type_expect ?in_function env sexp ty_expected =
end
| Pexp_record(lid_sexp_list, opt_sexp) ->
let lbl_exp_list =
- type_label_a_list (type_label_exp true env loc ty_expected)
+ type_label_a_list env loc (type_label_exp true env loc ty_expected)
lid_sexp_list in
let rec check_duplicates seen_pos lid_sexp lbl_exp =
match (lid_sexp, lbl_exp) with
@@ -1553,8 +1566,9 @@ and type_expect ?in_function env sexp ty_expected =
exp_env = env }
| Pexp_setfield(srecord, lid, snewval) ->
let record = type_exp env srecord in
+ let label = Typetexp.find_label env loc lid in
let (label, newval) =
- type_label_exp false env loc record.exp_type (lid, snewval) in
+ type_label_exp false env loc record.exp_type (label, snewval) in
if label.lbl_mut = Immutable then
raise(Error(loc, Label_not_mutable lid));
rue {
@@ -2042,9 +2056,8 @@ and type_expect ?in_function env sexp ty_expected =
| Pexp_open (lid, e) ->
type_expect (!type_open env sexp.pexp_loc lid) e ty_expected
-and type_label_exp create env loc ty_expected (lid, sarg) =
+and type_label_exp create env loc ty_expected (label, sarg) =
(* Here also ty_expected may be at generic_level *)
- let label = Typetexp.find_label env sarg.pexp_loc lid in
begin_def ();
if !Clflags.principal then (begin_def (); begin_def ()) ;
let (vars, ty_arg, ty_res) = instance_label true label in
@@ -2057,7 +2070,7 @@ and type_label_exp create env loc ty_expected (lid, sarg) =
begin try
unify env (instance ty_res) (instance ty_expected)
with Unify trace ->
- raise(Error(loc , Label_mismatch(lid, trace)))
+ raise(Error(loc , Label_mismatch(lid_of_label label, trace)))
end;
(* Instantiate so that we can generalize internal nodes *)
let ty_arg = instance ty_arg in
@@ -2068,7 +2081,7 @@ and type_label_exp create env loc ty_expected (lid, sarg) =
end;
if label.lbl_private = Private then
raise(Error(loc, if create then Private_type ty_expected
- else Private_label (lid, ty_expected)));
+ else Private_label (lid_of_label label, ty_expected)));
let arg =
let snap = if vars = [] then None else Some (Btype.snapshot ()) in
let arg = type_argument env sarg ty_arg (instance ty_arg) in