468 lines
18 KiB
Diff
468 lines
18 KiB
Diff
Index: typing/typecore.ml
|
|
===================================================================
|
|
--- typing/typecore.ml (revision 13003)
|
|
+++ typing/typecore.ml (working copy)
|
|
@@ -61,6 +61,7 @@
|
|
| Not_a_packed_module of type_expr
|
|
| Recursive_local_constraint of (type_expr * type_expr) list
|
|
| Unexpected_existential
|
|
+ | Pattern_newtype_non_closed of string * type_expr
|
|
|
|
exception Error of Location.t * error
|
|
|
|
@@ -121,7 +122,7 @@
|
|
| Pexp_function (_, eo, pel) ->
|
|
may expr eo; List.iter (fun (_, e) -> expr e) pel
|
|
| Pexp_apply (e, lel) -> expr e; List.iter (fun (_, e) -> expr e) lel
|
|
- | Pexp_let (_, pel, e)
|
|
+ | Pexp_let (_, pel, e) -> expr e; List.iter (fun (_, e) -> expr e) pel
|
|
| Pexp_match (e, pel)
|
|
| Pexp_try (e, pel) -> expr e; List.iter (fun (_, e) -> expr e) pel
|
|
| Pexp_array el
|
|
@@ -1454,7 +1455,7 @@
|
|
|
|
let duplicate_ident_types loc caselist env =
|
|
let caselist =
|
|
- List.filter (fun (pat, _) -> contains_gadt env pat) caselist in
|
|
+ List.filter (fun ((_,pat), _) -> contains_gadt env pat) caselist in
|
|
let idents = all_idents (List.map snd caselist) in
|
|
List.fold_left
|
|
(fun env s ->
|
|
@@ -1552,7 +1553,7 @@
|
|
exp_env = env }
|
|
| Pexp_let(Nonrecursive, [spat, sval], sbody) when contains_gadt env spat ->
|
|
type_expect ?in_function env
|
|
- {sexp with pexp_desc = Pexp_match (sval, [spat, sbody])}
|
|
+ {sexp with pexp_desc = Pexp_match (sval, [([],spat), sbody])}
|
|
ty_expected
|
|
| Pexp_let(rec_flag, spat_sexp_list, sbody) ->
|
|
let scp =
|
|
@@ -1572,20 +1573,21 @@
|
|
exp_env = env }
|
|
| Pexp_function (l, Some default, [spat, sbody]) ->
|
|
let default_loc = default.pexp_loc in
|
|
- let scases = [
|
|
+ let scases = [([],
|
|
{ppat_loc = default_loc;
|
|
ppat_desc =
|
|
Ppat_construct
|
|
(mknoloc (Longident.(Ldot (Lident "*predef*", "Some"))),
|
|
Some {ppat_loc = default_loc;
|
|
ppat_desc = Ppat_var (mknoloc "*sth*")},
|
|
- false)},
|
|
+ false)}),
|
|
{pexp_loc = default_loc;
|
|
pexp_desc = Pexp_ident(mknoloc (Longident.Lident "*sth*"))};
|
|
+ ([],
|
|
{ppat_loc = default_loc;
|
|
ppat_desc = Ppat_construct
|
|
(mknoloc (Longident.(Ldot (Lident "*predef*", "None"))),
|
|
- None, false)},
|
|
+ None, false)}),
|
|
default;
|
|
] in
|
|
let smatch = {
|
|
@@ -1603,10 +1605,10 @@
|
|
pexp_desc =
|
|
Pexp_function (
|
|
l, None,
|
|
- [ {ppat_loc = loc;
|
|
- ppat_desc = Ppat_var (mknoloc "*opt*")},
|
|
+ [ ([], {ppat_loc = loc;
|
|
+ ppat_desc = Ppat_var (mknoloc "*opt*")}),
|
|
{pexp_loc = loc;
|
|
- pexp_desc = Pexp_let(Default, [spat, smatch], sbody);
|
|
+ pexp_desc = Pexp_let(Default, [snd spat, smatch], sbody);
|
|
}
|
|
]
|
|
)
|
|
@@ -2733,10 +2735,10 @@
|
|
and type_cases ?in_function env ty_arg ty_res partial_flag loc caselist =
|
|
(* ty_arg is _fully_ generalized *)
|
|
let dont_propagate, has_gadts =
|
|
- let patterns = List.map fst caselist in
|
|
+ let patterns = List.map (fun ((_,p),_) -> p) caselist in
|
|
List.exists contains_polymorphic_variant patterns,
|
|
- List.exists (contains_gadt env) patterns in
|
|
-(* prerr_endline ( if has_gadts then "contains gadt" else "no gadt"); *)
|
|
+ List.exists (contains_gadt env) patterns ||
|
|
+ List.exists (fun ((l,_),_) -> l <> []) caselist in
|
|
let ty_arg, ty_res, env =
|
|
if has_gadts && not !Clflags.principal then
|
|
correct_levels ty_arg, correct_levels ty_res,
|
|
@@ -2761,9 +2763,21 @@
|
|
Printtyp.raw_type_expr ty_arg; *)
|
|
let pat_env_list =
|
|
List.map
|
|
- (fun (spat, sexp) ->
|
|
+ (fun ((stypes,spat), sexp) ->
|
|
let loc = sexp.pexp_loc in
|
|
if !Clflags.principal then begin_def (); (* propagation of pattern *)
|
|
+ (* For local types *)
|
|
+ if stypes <> [] then begin_def ();
|
|
+ let lev' = get_current_level () in
|
|
+ let types = List.map (fun name -> name, newvar ~name ()) stypes in
|
|
+ let env =
|
|
+ List.fold_left (fun env (name, manifest) ->
|
|
+ (* "Vanishing" definition *)
|
|
+ let decl = new_declaration ~manifest (lev',lev') in
|
|
+ snd (Env.enter_type name decl env))
|
|
+ env types
|
|
+ in
|
|
+ (* Type the pattern itself *)
|
|
let scope = Some (Annot.Idef loc) in
|
|
let (pat, ext_env, force, unpacks) =
|
|
let partial =
|
|
@@ -2773,14 +2787,42 @@
|
|
in type_pattern ~lev env spat scope ty_arg
|
|
in
|
|
pattern_force := force @ !pattern_force;
|
|
+ (* For local types *)
|
|
+ let ext_env =
|
|
+ List.fold_left (fun env (name, ty) ->
|
|
+ let ty = expand_head env ty in
|
|
+ match ty.desc with
|
|
+ Tconstr ((Path.Pident id as p), [], _) when
|
|
+ let decl = Env.find_type p env in
|
|
+ decl.type_newtype_level = Some (lev, lev) &&
|
|
+ decl.type_kind = Type_abstract ->
|
|
+ let (id', env) =
|
|
+ Env.enter_type name (new_declaration (lev, lev)) env in
|
|
+ let manifest = newconstr (Path.Pident id') [] in
|
|
+ (* Make previous existential "vanish" *)
|
|
+ Env.add_type id (new_declaration ~manifest (lev',lev')) env
|
|
+ | _ ->
|
|
+ if free_variables ty <> [] then
|
|
+ raise (Error (spat.ppat_loc,
|
|
+ Pattern_newtype_non_closed (name,ty)));
|
|
+ let manifest = correct_levels ty in
|
|
+ let decl = new_declaration ~manifest (lev, lev) in
|
|
+ snd (Env.enter_type name decl env))
|
|
+ ext_env types
|
|
+ in
|
|
+ if stypes <> [] then begin
|
|
+ end_def ();
|
|
+ iter_pattern (fun p -> unify_pat ext_env p (newvar())) pat;
|
|
+ end;
|
|
+ (* Principality *)
|
|
let pat =
|
|
if !Clflags.principal then begin
|
|
end_def ();
|
|
iter_pattern (fun {pat_type=t} -> generalize_structure t) pat;
|
|
- { pat with pat_type = instance env pat.pat_type }
|
|
+ { pat with pat_type = instance ext_env pat.pat_type }
|
|
end else pat
|
|
in
|
|
- unify_pat env pat ty_arg';
|
|
+ unify_pat ext_env pat ty_arg';
|
|
(pat, (ext_env, unpacks)))
|
|
caselist in
|
|
(* Check for polymorphic variants to close *)
|
|
@@ -2802,7 +2844,7 @@
|
|
let in_function = if List.length caselist = 1 then in_function else None in
|
|
let cases =
|
|
List.map2
|
|
- (fun (pat, (ext_env, unpacks)) (spat, sexp) ->
|
|
+ (fun (pat, (ext_env, unpacks)) ((stypes,spat), sexp) ->
|
|
let sexp = wrap_unpacks sexp unpacks in
|
|
let ty_res' =
|
|
if !Clflags.principal then begin
|
|
@@ -2811,8 +2853,8 @@
|
|
end_def ();
|
|
generalize_structure ty; ty
|
|
end
|
|
- else if contains_gadt env spat then correct_levels ty_res
|
|
- else ty_res in
|
|
+ else if contains_gadt env spat || stypes <> []
|
|
+ then correct_levels ty_res else ty_res in
|
|
(* Format.printf "@[%i %i, ty_res' =@ %a@]@." lev (get_current_level())
|
|
Printtyp.raw_type_expr ty_res'; *)
|
|
let exp = type_expect ?in_function ext_env sexp ty_res' in
|
|
@@ -3218,6 +3260,11 @@
|
|
| Unexpected_existential ->
|
|
fprintf ppf
|
|
"Unexpected existential"
|
|
+ | Pattern_newtype_non_closed (name, ty) ->
|
|
+ reset_and_mark_loops ty;
|
|
+ fprintf ppf
|
|
+ "@[In this pattern, local type %s has been inferred as@ %a@ %s@]"
|
|
+ name type_expr ty "It should not contain variables."
|
|
|
|
let () =
|
|
Env.add_delayed_check_forward := add_delayed_check
|
|
Index: typing/ctype.mli
|
|
===================================================================
|
|
--- typing/ctype.mli (revision 13003)
|
|
+++ typing/ctype.mli (working copy)
|
|
@@ -140,6 +140,9 @@
|
|
the parameters [pi] and returns the corresponding instance of
|
|
[t]. Exception [Cannot_apply] is raised in case of failure. *)
|
|
|
|
+val new_declaration:
|
|
+ ?manifest:type_expr -> ?loc:Location.t -> (int * int) -> type_declaration
|
|
+
|
|
val expand_head_once: Env.t -> type_expr -> type_expr
|
|
val expand_head: Env.t -> type_expr -> type_expr
|
|
val try_expand_once_opt: Env.t -> type_expr -> type_expr
|
|
Index: typing/typeclass.ml
|
|
===================================================================
|
|
--- typing/typeclass.ml (revision 13003)
|
|
+++ typing/typeclass.ml (working copy)
|
|
@@ -347,8 +347,8 @@
|
|
let mkid s = mkloc s self_loc in
|
|
{ pexp_desc =
|
|
Pexp_function ("", None,
|
|
- [mkpat (Ppat_alias (mkpat (Ppat_var (mkid "self-*")),
|
|
- mkid ("self-" ^ cl_num))),
|
|
+ [([],mkpat (Ppat_alias (mkpat (Ppat_var (mkid "self-*")),
|
|
+ mkid ("self-" ^ cl_num)))),
|
|
expr]);
|
|
pexp_loc = expr.pexp_loc }
|
|
|
|
@@ -836,15 +836,15 @@
|
|
| Pcl_fun (l, Some default, spat, sbody) ->
|
|
let loc = default.pexp_loc in
|
|
let scases =
|
|
- [{ppat_loc = loc; ppat_desc = Ppat_construct (
|
|
+ [([], {ppat_loc = loc; ppat_desc = Ppat_construct (
|
|
mknoloc (Longident.(Ldot (Lident"*predef*", "Some"))),
|
|
Some{ppat_loc = loc; ppat_desc = Ppat_var (mknoloc "*sth*")},
|
|
- false)},
|
|
+ false)}),
|
|
{pexp_loc = loc; pexp_desc =
|
|
Pexp_ident(mknoloc (Longident.Lident"*sth*"))};
|
|
- {ppat_loc = loc; ppat_desc =
|
|
+ ([], {ppat_loc = loc; ppat_desc =
|
|
Ppat_construct(mknoloc (Longident.(Ldot (Lident"*predef*", "None"))),
|
|
- None, false)},
|
|
+ None, false)}),
|
|
default] in
|
|
let smatch =
|
|
{pexp_loc = loc; pexp_desc =
|
|
Index: typing/ctype.ml
|
|
===================================================================
|
|
--- typing/ctype.ml (revision 13003)
|
|
+++ typing/ctype.ml (working copy)
|
|
@@ -696,6 +696,7 @@
|
|
Path.binding_time p
|
|
|
|
let rec update_level env level ty =
|
|
+ (* Format.eprintf "update_level %d %a@." level !Btype.print_raw ty; *)
|
|
let ty = repr ty in
|
|
if ty.level > level then begin
|
|
if Env.has_local_constraints env then begin
|
|
@@ -1043,7 +1044,7 @@
|
|
reified_var_counter := Vars.add s index !reified_var_counter;
|
|
Printf.sprintf "%s#%d" s index
|
|
|
|
-let new_declaration newtype manifest =
|
|
+let new_declaration ?manifest ?(loc=Location.none) newtype =
|
|
{
|
|
type_params = [];
|
|
type_arity = 0;
|
|
@@ -1051,7 +1052,7 @@
|
|
type_private = Public;
|
|
type_manifest = manifest;
|
|
type_variance = [];
|
|
- type_newtype_level = newtype;
|
|
+ type_newtype_level = Some newtype;
|
|
type_loc = Location.none;
|
|
}
|
|
|
|
@@ -1060,7 +1061,7 @@
|
|
| None -> ()
|
|
| Some (env, newtype_lev) ->
|
|
let process existential =
|
|
- let decl = new_declaration (Some (newtype_lev, newtype_lev)) None in
|
|
+ let decl = new_declaration (newtype_lev, newtype_lev) in
|
|
let name =
|
|
match repr existential with
|
|
{desc = Tvar (Some name)} -> name
|
|
@@ -1808,7 +1809,7 @@
|
|
let reify env t =
|
|
let newtype_level = get_newtype_level () in
|
|
let create_fresh_constr lev name =
|
|
- let decl = new_declaration (Some (newtype_level, newtype_level)) None in
|
|
+ let decl = new_declaration (newtype_level, newtype_level) in
|
|
let name = get_new_abstract_name name in
|
|
let (id, new_env) = Env.enter_type name decl !env in
|
|
let t = newty2 lev (Tconstr (Path.Pident id,[],ref Mnil)) in
|
|
@@ -2039,7 +2040,7 @@
|
|
let add_gadt_equation env source destination =
|
|
let destination = duplicate_type destination in
|
|
let source_lev = find_newtype_level !env (Path.Pident source) in
|
|
- let decl = new_declaration (Some source_lev) (Some destination) in
|
|
+ let decl = new_declaration ~manifest:destination source_lev in
|
|
let newtype_level = get_newtype_level () in
|
|
env := Env.add_local_constraint source decl newtype_level !env;
|
|
cleanup_abbrev ()
|
|
Index: typing/typecore.mli
|
|
===================================================================
|
|
--- typing/typecore.mli (revision 13003)
|
|
+++ typing/typecore.mli (working copy)
|
|
@@ -103,6 +103,7 @@
|
|
| Not_a_packed_module of type_expr
|
|
| Recursive_local_constraint of (type_expr * type_expr) list
|
|
| Unexpected_existential
|
|
+ | Pattern_newtype_non_closed of string * type_expr
|
|
|
|
exception Error of Location.t * error
|
|
|
|
Index: testsuite/tests/typing-gadts/test.ml.reference
|
|
===================================================================
|
|
--- testsuite/tests/typing-gadts/test.ml.reference (revision 13003)
|
|
+++ testsuite/tests/typing-gadts/test.ml.reference (working copy)
|
|
@@ -293,4 +293,18 @@
|
|
# type 'a ty = Int : int -> int ty
|
|
# val f : 'a ty -> 'a = <fun>
|
|
# val g : 'a ty -> 'a = <fun>
|
|
+# - : unit -> unit list = <fun>
|
|
+# - : unit list = []
|
|
+# Characters 17-19:
|
|
+ function type a. () -> ();; (* fail *)
|
|
+ ^^
|
|
+Error: In this pattern, local type a has been inferred as 'a
|
|
+ It should not contain variables.
|
|
+# type t = D : 'a * ('a -> int) -> t
|
|
+# val f : t -> int = <fun>
|
|
+# Characters 42-43:
|
|
+ let f = function type b. D ((x:b), f) -> (f:t->int) x;; (* fail *)
|
|
+ ^
|
|
+Error: This expression has type b -> int
|
|
+ but an expression was expected of type t -> int
|
|
#
|
|
Index: testsuite/tests/typing-gadts/test.ml
|
|
===================================================================
|
|
--- testsuite/tests/typing-gadts/test.ml (revision 13003)
|
|
+++ testsuite/tests/typing-gadts/test.ml (working copy)
|
|
@@ -512,3 +512,15 @@
|
|
let g : type a. a ty -> a =
|
|
let () = () in
|
|
fun x -> match x with Int y -> y;;
|
|
+
|
|
+(* Implicit type declarations in patterns *)
|
|
+
|
|
+(* alias *)
|
|
+function type a. (() : a) -> ([] : a list);;
|
|
+(function type a. (() : a) -> ([] : a list)) ();;
|
|
+function type a. () -> ();; (* fail *)
|
|
+
|
|
+(* existential *)
|
|
+type t = D : 'a * ('a -> int) -> t;;
|
|
+let f = function type b. D ((x:b), f) -> (f:b->int) x;;
|
|
+let f = function type b. D ((x:b), f) -> (f:t->int) x;; (* fail *)
|
|
Index: testsuite/tests/typing-gadts/test.ml.principal.reference
|
|
===================================================================
|
|
--- testsuite/tests/typing-gadts/test.ml.principal.reference (revision 13003)
|
|
+++ testsuite/tests/typing-gadts/test.ml.principal.reference (working copy)
|
|
@@ -306,4 +306,18 @@
|
|
# type 'a ty = Int : int -> int ty
|
|
# val f : 'a ty -> 'a = <fun>
|
|
# val g : 'a ty -> 'a = <fun>
|
|
+# - : unit -> unit list = <fun>
|
|
+# - : unit list = []
|
|
+# Characters 17-19:
|
|
+ function type a. () -> ();; (* fail *)
|
|
+ ^^
|
|
+Error: In this pattern, local type a has been inferred as 'a
|
|
+ It should not contain variables.
|
|
+# type t = D : 'a * ('a -> int) -> t
|
|
+# val f : t -> int = <fun>
|
|
+# Characters 42-43:
|
|
+ let f = function type b. D ((x:b), f) -> (f:t->int) x;; (* fail *)
|
|
+ ^
|
|
+Error: This expression has type b -> int
|
|
+ but an expression was expected of type t -> int
|
|
#
|
|
Index: parsing/parser.mly
|
|
===================================================================
|
|
--- parsing/parser.mly (revision 13003)
|
|
+++ parsing/parser.mly (working copy)
|
|
@@ -967,7 +967,7 @@
|
|
| FUNCTION opt_bar match_cases
|
|
{ mkexp(Pexp_function("", None, List.rev $3)) }
|
|
| FUN labeled_simple_pattern fun_def
|
|
- { let (l,o,p) = $2 in mkexp(Pexp_function(l, o, [p, $3])) }
|
|
+ { let (l,o,p) = $2 in mkexp(Pexp_function(l, o, [([],p), $3])) }
|
|
| FUN LPAREN TYPE LIDENT RPAREN fun_def
|
|
{ mkexp(Pexp_newtype($4, $6)) }
|
|
| MATCH seq_expr WITH opt_bar match_cases
|
|
@@ -1187,18 +1187,18 @@
|
|
EQUAL seq_expr
|
|
{ $2 }
|
|
| labeled_simple_pattern fun_binding
|
|
- { let (l, o, p) = $1 in ghexp(Pexp_function(l, o, [p, $2])) }
|
|
+ { let (l, o, p) = $1 in ghexp(Pexp_function(l, o, [([],p), $2])) }
|
|
| LPAREN TYPE LIDENT RPAREN fun_binding
|
|
{ mkexp(Pexp_newtype($3, $5)) }
|
|
;
|
|
match_cases:
|
|
- pattern match_action { [$1, $2] }
|
|
- | match_cases BAR pattern match_action { ($3, $4) :: $1 }
|
|
+ match_pattern match_action { [$1, $2] }
|
|
+ | match_cases BAR match_pattern match_action { ($3, $4) :: $1 }
|
|
;
|
|
fun_def:
|
|
match_action { $1 }
|
|
| labeled_simple_pattern fun_def
|
|
- { let (l,o,p) = $1 in ghexp(Pexp_function(l, o, [p, $2])) }
|
|
+ { let (l,o,p) = $1 in ghexp(Pexp_function(l, o, [([],p), $2])) }
|
|
| LPAREN TYPE LIDENT RPAREN fun_def
|
|
{ mkexp(Pexp_newtype($3, $5)) }
|
|
;
|
|
@@ -1245,6 +1245,10 @@
|
|
|
|
/* Patterns */
|
|
|
|
+match_pattern:
|
|
+ pattern { [], $1 }
|
|
+ | TYPE lident_list DOT pattern { $2, $4 }
|
|
+;
|
|
pattern:
|
|
simple_pattern
|
|
{ $1 }
|
|
Index: parsing/parsetree.mli
|
|
===================================================================
|
|
--- parsing/parsetree.mli (revision 13003)
|
|
+++ parsing/parsetree.mli (working copy)
|
|
@@ -90,10 +90,11 @@
|
|
Pexp_ident of Longident.t loc
|
|
| Pexp_constant of constant
|
|
| Pexp_let of rec_flag * (pattern * expression) list * expression
|
|
- | Pexp_function of label * expression option * (pattern * expression) list
|
|
+ | Pexp_function of
|
|
+ label * expression option * ((string list * pattern) * expression) list
|
|
| Pexp_apply of expression * (label * expression) list
|
|
- | Pexp_match of expression * (pattern * expression) list
|
|
- | Pexp_try of expression * (pattern * expression) list
|
|
+ | Pexp_match of expression * ((string list * pattern) * expression) list
|
|
+ | Pexp_try of expression * ((string list * pattern) * expression) list
|
|
| Pexp_tuple of expression list
|
|
| Pexp_construct of Longident.t loc * expression option * bool
|
|
| Pexp_variant of label * expression option
|
|
@@ -104,7 +105,8 @@
|
|
| Pexp_ifthenelse of expression * expression * expression option
|
|
| Pexp_sequence of expression * expression
|
|
| Pexp_while of expression * expression
|
|
- | Pexp_for of string loc * expression * expression * direction_flag * expression
|
|
+ | Pexp_for of
|
|
+ string loc * expression * expression * direction_flag * expression
|
|
| Pexp_constraint of expression * core_type option * core_type option
|
|
| Pexp_when of expression * expression
|
|
| Pexp_send of expression * string
|
|
Index: parsing/printast.ml
|
|
===================================================================
|
|
--- parsing/printast.ml (revision 13003)
|
|
+++ parsing/printast.ml (working copy)
|
|
@@ -686,8 +686,9 @@
|
|
line i ppf "%a\n" fmt_longident li;
|
|
pattern (i+1) ppf p;
|
|
|
|
-and pattern_x_expression_case i ppf (p, e) =
|
|
+and pattern_x_expression_case i ppf ((l,p), e) =
|
|
line i ppf "<case>\n";
|
|
+ list (i+1) string ppf l;
|
|
pattern (i+1) ppf p;
|
|
expression (i+1) ppf e;
|
|
|