diff options
author | Jacques Garrigue <garrigue@math.nagoya-u.ac.jp> | 2017-08-02 14:25:58 +0900 |
---|---|---|
committer | Jacques Garrigue <garrigue@math.nagoya-u.ac.jp> | 2017-08-02 14:25:58 +0900 |
commit | 9aea65451d3ce0ccba22f14de70fcf1c6e1e66c5 (patch) | |
tree | 0845dc78fa3db219a895f84a68180a98a4e58c96 | |
parent | 177713ec025cc49eabd7a95ab6d6aaa127d34c81 (diff) | |
download | ocaml-9aea65451d3ce0ccba22f14de70fcf1c6e1e66c5.tar.gz |
Fix PR#7519, but high cost in update_level
-rw-r--r-- | typing/ctype.ml | 71 | ||||
-rw-r--r-- | typing/typecore.ml | 6 |
2 files changed, 45 insertions, 32 deletions
diff --git a/typing/ctype.ml b/typing/ctype.ml index e5094ec0e8..a506b3bfed 100644 --- a/typing/ctype.ml +++ b/typing/ctype.ml @@ -658,6 +658,35 @@ let rec generalize_spine ty = List.iter generalize_spine tyl | _ -> () +(* + Check whether the abbreviation expands to a well-defined type. + During the typing of a class, abbreviations for correspondings + types expand to non-generic types. +*) +let generic_abbrev env path = + try + let (_, body, _) = Env.find_type_expansion path env in + (repr body).level = generic_level + with + Not_found -> + false + +let generic_private_abbrev env path = + try + match Env.find_type path env with + {type_kind = Type_abstract; + type_private = Private; + type_manifest = Some body} -> + (repr body).level = generic_level + | _ -> false + with Not_found -> false + +let is_contractive env p = + try + let decl = Env.find_type p env in + in_pervasives p && decl.type_manifest = None || is_datatype decl + with Not_found -> false + let forward_try_expand_once = (* Forward declaration *) ref (fun _env _ty -> raise Cannot_expand) @@ -719,6 +748,19 @@ let rec update_level env level ty = if level < get_level env p then raise (Unify [(ty, newvar2 level)]); iter_type_expr (update_level env level) ty end + | Tconstr(p, _tl, _abbrev) when generic_abbrev env p -> + let snap = snapshot () in + begin try + set_level ty level; + iter_type_expr (update_level env level) ty + with Unify _ -> try + backtrack snap; + link_type ty (!forward_try_expand_once env ty); + update_level env level ty + with Cannot_expand -> + set_level ty level; + iter_type_expr (update_level env level) ty + end | Tpackage (p, nl, tl) when level < Path.binding_time p -> let p' = normalize_package_path env p in if Path.same p p' then raise (Unify [(ty, newvar2 level)]); @@ -1545,35 +1587,6 @@ let full_expand env ty = | _ -> ty -(* - Check whether the abbreviation expands to a well-defined type. - During the typing of a class, abbreviations for correspondings - types expand to non-generic types. -*) -let generic_abbrev env path = - try - let (_, body, _) = Env.find_type_expansion path env in - (repr body).level = generic_level - with - Not_found -> - false - -let generic_private_abbrev env path = - try - match Env.find_type path env with - {type_kind = Type_abstract; - type_private = Private; - type_manifest = Some body} -> - (repr body).level = generic_level - | _ -> false - with Not_found -> false - -let is_contractive env p = - try - let decl = Env.find_type p env in - in_pervasives p && decl.type_manifest = None || is_datatype decl - with Not_found -> false - (*****************) (* Occur check *) diff --git a/typing/typecore.ml b/typing/typecore.ml index a1e47a10e6..a616ca84d2 100644 --- a/typing/typecore.ml +++ b/typing/typecore.ml @@ -2800,7 +2800,7 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected = let (id, new_env) = Env.enter_module name.txt modl.mod_type env in Ctype.init_def(Ident.current_time()); Typetexp.widen context; - let body = type_expect new_env sbody ty_expected in + let body = type_expect new_env sbody (correct_levels ty_expected) in (* go back to original level *) end_def (); (* Unification of body.exp_type with the fresh variable ty @@ -2809,11 +2809,11 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected = type body.exp_type. Thus, this unification enforces the scoping condition on "let module". *) begin try - Ctype.unify_var new_env ty body.exp_type + Ctype.unify_var new_env ty body.exp_type; with Unify _ -> raise(Error(loc, env, Scoping_let_module(name.txt, body.exp_type))) end; - re { + rue { exp_desc = Texp_letmodule(id, name, modl, body); exp_loc = loc; exp_extra = []; exp_type = ty; |