diff options
author | Jacques Garrigue <garrigue at math.nagoya-u.ac.jp> | 2008-01-11 06:38:00 +0000 |
---|---|---|
committer | Jacques Garrigue <garrigue at math.nagoya-u.ac.jp> | 2008-01-11 06:38:00 +0000 |
commit | 9707174f6b4367dd6c432eb4a3f152c7628754cb (patch) | |
tree | 78f99ea94caf9fb808b0b7c8ef9f024cdd52d6fc | |
parent | 2a37a12f48c89dd124853646ae3771163ed53a6b (diff) | |
download | ocaml-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.ml | 39 |
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 (); |