summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Garrigue <garrigue at math.nagoya-u.ac.jp>2008-01-11 06:38:00 +0000
committerJacques Garrigue <garrigue at math.nagoya-u.ac.jp>2008-01-11 06:38:00 +0000
commit9707174f6b4367dd6c432eb4a3f152c7628754cb (patch)
tree78f99ea94caf9fb808b0b7c8ef9f024cdd52d6fc
parent2a37a12f48c89dd124853646ae3771163ed53a6b (diff)
downloadocaml-9707174f6b4367dd6c432eb4a3f152c7628754cb.tar.gz
add ground coercions
git-svn-id: http://caml.inria.fr/svn/ocaml/branches/ground_coercion@8760 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r--typing/typecore.ml39
1 files changed, 39 insertions, 0 deletions
diff --git a/typing/typecore.ml b/typing/typecore.ml
index 5865d31ced..4c60a490d6 100644
--- a/typing/typecore.ml
+++ b/typing/typecore.ml
@@ -889,6 +889,17 @@ let check_application_result env statement exp =
if statement then
Location.prerr_warning exp.exp_loc Warnings.Statement_type
+(* Check that a type is generalizable at some level *)
+let generalizable level ty =
+ let rec check ty =
+ let ty = repr ty in
+ if ty.level < lowest_level then () else
+ if ty.level <= level then raise Exit else
+ (mark_type_node ty; iter_type_expr check ty)
+ in
+ try check ty; unmark_type ty; true
+ with Exit -> unmark_type ty; false
+
(* Hack to allow coercion of self. Will clean-up later. *)
let self_coercion = ref ([] : (Path.t * Location.t list ref) list)
@@ -1225,12 +1236,40 @@ let rec type_exp env sexp =
let (ty', force) =
Typetexp.transl_simple_type_delayed env sty'
in
+ if !Clflags.principal then begin_def ();
let arg = type_exp env sarg in
+ let gen =
+ if !Clflags.principal then begin
+ end_def ();
+ let tv = newvar () in
+ let gen = generalizable tv.level arg.exp_type in
+ unify_var env tv arg.exp_type;
+ gen
+ end else true
+ in
begin match arg.exp_desc, !self_coercion, (repr ty').desc with
Texp_ident(_, {val_kind=Val_self _}), (path,r) :: _,
Tconstr(path',_,_) when Path.same path path' ->
r := sexp.pexp_loc :: !r;
force ()
+ | _ when free_variables arg.exp_type = []
+ && free_variables ty' = [] ->
+ if not gen && (* first try a single coercion *)
+ let snap = snapshot () in
+ let ty, b = enlarge_type env ty' in
+ force ();
+ (try Ctype.unify env arg.exp_type ty; true
+ with Unify _ -> backtrack snap; false)
+ then ()
+ else begin try
+ let force' = subtype env arg.exp_type ty' in
+ force (); force' ();
+ if not gen then
+ Location.prerr_warning sexp.pexp_loc
+ (Warnings.Not_principal "this ground coercion");
+ with Subtype (tr1, tr2) ->
+ raise(Error(sexp.pexp_loc, Not_subtype(tr1, tr2)))
+ end;
| _ ->
let ty, b = enlarge_type env ty' in
force ();