Skip to content

Commit f5b5e49

Browse files
authored
Remove type_unpacks (#150)
1 parent 50d54db commit f5b5e49

File tree

1 file changed

+92
-102
lines changed

1 file changed

+92
-102
lines changed

typing/typecore.ml

Lines changed: 92 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,6 @@ type type_expected = {
4848
explanation: type_forcing_context option;
4949
}
5050

51-
type to_unpack = {
52-
tu_ident : Ident.t;
53-
tu_name: string Location.loc;
54-
tu_loc: Location.t;
55-
tu_uid: Uid.t
56-
}
57-
5851
module Datatype_kind = struct
5952
type t = Record | Variant
6053

@@ -700,10 +693,18 @@ type pattern_variable =
700693
pv_attributes: attributes;
701694
}
702695

696+
type module_variable =
697+
{
698+
mv_id : Ident.t;
699+
mv_name: string Location.loc;
700+
mv_loc: Location.t;
701+
mv_uid: Uid.t
702+
}
703+
703704
let pattern_variables = ref ([] : pattern_variable list)
704705
let pattern_force = ref ([] : (unit -> unit) list)
705706
let allow_modules = ref Modules_rejected
706-
let module_variables = ref ([] : to_unpack list)
707+
let module_variables = ref ([] : module_variable list)
707708
let reset_pattern allow =
708709
pattern_variables := [];
709710
pattern_force := [];
@@ -737,6 +738,38 @@ let add_pattern_variables ?check ?check_as env pv =
737738
)
738739
pv env
739740

741+
let add_module_variables env module_variables =
742+
List.fold_left (fun env { mv_id; mv_loc; mv_name; mv_uid } ->
743+
Typetexp.TyVarEnv.with_local_scope begin fun () ->
744+
(* This code is parallel to the typing of Pexp_letmodule. However we
745+
omit the call to [Mtype.lower_nongen] as it's not necessary here.
746+
For Pexp_letmodule, the call to [type_module] is done in a raised
747+
level and so needs to be modified to have the correct, outer level.
748+
Here, on the other hand, we're calling [type_module] outside the
749+
raised level, so there's no extra step to take.
750+
*)
751+
let modl, md_shape =
752+
!type_module env
753+
Ast_helper.(
754+
Mod.unpack ~loc:mv_loc
755+
(Exp.ident ~loc:mv_name.loc
756+
(mkloc (Longident.Lident mv_name.txt)
757+
mv_name.loc)))
758+
in
759+
let pres =
760+
match modl.mod_type with
761+
| Mty_alias _ -> Mp_absent
762+
| _ -> Mp_present
763+
in
764+
let md =
765+
{ md_type = modl.mod_type; md_attributes = [];
766+
md_loc = mv_name.loc;
767+
md_uid = mv_uid; }
768+
in
769+
Env.add_module_declaration ~shape:md_shape ~check:true mv_id pres md env
770+
end
771+
) env module_variables
772+
740773
let enter_variable ?(is_module=false) ?(is_as_variable=false) loc name mode ty
741774
attrs =
742775
if List.exists (fun {pv_id; _} -> Ident.name pv_id = name.txt)
@@ -755,10 +788,10 @@ let enter_variable ?(is_module=false) ?(is_as_variable=false) loc name mode ty
755788
escape ~loc ~env:Env.empty ~reason:Other mode;
756789
let id = Ident.create_scoped name.txt ~scope in
757790
module_variables :=
758-
{ tu_ident = id;
759-
tu_name = name;
760-
tu_loc = loc;
761-
tu_uid = Uid.mk ~current_unit:(Env.get_unit_name ());
791+
{ mv_id = id;
792+
mv_name = name;
793+
mv_loc = loc;
794+
mv_uid = Uid.mk ~current_unit:(Env.get_unit_name ());
762795
} :: !module_variables;
763796
id
764797
end else
@@ -1722,7 +1755,7 @@ type 'case_pattern half_typed_case =
17221755
untyped_case: Parsetree.case;
17231756
branch_env: Env.t;
17241757
pat_vars: pattern_variable list;
1725-
unpacks: to_unpack list;
1758+
module_vars: module_variable list;
17261759
contains_gadt: bool; }
17271760

17281761
let rec has_literal_pattern p =
@@ -2582,8 +2615,8 @@ let type_pattern category ~lev ~alloc_mode env spat expected_ty allow_modules =
25822615
let new_env = ref env in
25832616
let pat = type_pat category ~lev ~alloc_mode new_env spat expected_ty in
25842617
let pvs = get_ref pattern_variables in
2585-
let unpacks = get_ref module_variables in
2586-
(pat, !new_env, get_ref pattern_force, pvs, unpacks)
2618+
let mvs = get_ref module_variables in
2619+
(pat, !new_env, get_ref pattern_force, pvs, mvs)
25872620

25882621
let type_pattern_list
25892622
category no_existentials env spatl expected_tys allow_modules
@@ -2599,9 +2632,8 @@ let type_pattern_list
25992632
in
26002633
let patl = List.map2 type_pat spatl expected_tys in
26012634
let pvs = get_ref pattern_variables in
2602-
let unpacks = get_ref module_variables in
2603-
let new_env = add_pattern_variables !new_env pvs in
2604-
(patl, new_env, get_ref pattern_force, pvs, unpacks)
2635+
let mvs = get_ref module_variables in
2636+
(patl, !new_env, get_ref pattern_force, pvs, mvs)
26052637

26062638
let type_class_arg_pattern cl_num val_env met_env l spat =
26072639
if !Clflags.principal then Ctype.begin_def ();
@@ -3980,17 +4012,18 @@ and type_expect_
39804012
Modules_allowed { scope }
39814013
end else Modules_rejected
39824014
in
3983-
let (pat_exp_list, new_env, unpacks) =
4015+
let (pat_exp_list, new_env) =
39844016
type_let existential_context env rec_flag spat_sexp_list allow_modules
39854017
in
39864018
let in_function =
39874019
match sexp.pexp_attributes with
39884020
| [{Parsetree.attr_name = {txt="#default"};_}] -> in_function
39894021
| _ -> None
39904022
in
3991-
let extended_env, body =
3992-
type_unpacks ?in_function
3993-
new_env expected_mode unpacks sbody ty_expected_explained in
4023+
let body =
4024+
type_expect ?in_function
4025+
new_env expected_mode sbody ty_expected_explained
4026+
in
39944027
let () =
39954028
if rec_flag = Recursive then
39964029
check_recursive_bindings env pat_exp_list
@@ -4008,9 +4041,9 @@ and type_expect_
40084041
*)
40094042
if may_contain_modules then begin
40104043
end_def ();
4011-
unify_exp extended_env body (newvar ());
4044+
unify_exp new_env body (newvar ());
40124045
if rec_flag = Recursive then
4013-
check_scope_escape_let_bound_idents extended_env pat_exp_list
4046+
check_scope_escape_let_bound_idents new_env pat_exp_list
40144047
end;
40154048
re {
40164049
exp_desc = Texp_let(rec_flag, pat_exp_list, body);
@@ -6314,60 +6347,6 @@ and type_statement ?explanation env sexp =
63146347
exp
63156348
end
63166349

6317-
(* Type the body within an environment extended with the unpacked modules are
6318-
added, returning both the typechecked body and the extended environment. *)
6319-
and type_unpacks
6320-
?(in_function : (Location.t * type_expr * bool) option)
6321-
env (expected_mode : expected_mode) (unpacks : to_unpack list) sbody expected_ty =
6322-
if unpacks = [] then
6323-
let body = type_expect ?in_function env expected_mode sbody expected_ty in
6324-
env, body
6325-
else
6326-
let extended_env =
6327-
List.fold_left (fun env unpack ->
6328-
Typetexp.TyVarEnv.with_local_scope begin fun () ->
6329-
(* This code is parallel to the typing of Pexp_letmodule. However we
6330-
omit the call to [Mtype.lower_nongen] as it's not necessary here.
6331-
For Pexp_letmodule, the call to [type_module] is done in a raised
6332-
level and so needs to be modified to have the correct, outer level.
6333-
Here, on the other hand, we're calling [type_module] outside the
6334-
raised level, so there's no extra step to take.
6335-
*)
6336-
let modl, md_shape =
6337-
!type_module env
6338-
Ast_helper.(
6339-
Mod.unpack ~loc:unpack.tu_loc
6340-
(Exp.ident ~loc:unpack.tu_name.loc
6341-
(mkloc (Longident.Lident unpack.tu_name.txt)
6342-
unpack.tu_name.loc)))
6343-
in
6344-
let pres =
6345-
match modl.mod_type with
6346-
| Mty_alias _ -> Mp_absent
6347-
| _ -> Mp_present
6348-
in
6349-
let md =
6350-
{ md_type = modl.mod_type; md_attributes = [];
6351-
md_loc = unpack.tu_name.loc;
6352-
md_uid = unpack.tu_uid; }
6353-
in
6354-
Env.add_module_declaration ~shape:md_shape ~check:true
6355-
unpack.tu_ident pres md env
6356-
end
6357-
) env unpacks
6358-
in
6359-
(* ideally, we should catch Expr_type_clash errors
6360-
in type_expect triggered by escaping identifiers from the local module
6361-
and refine them into Scoping_let_module errors
6362-
*)
6363-
let body =
6364-
type_expect ?in_function extended_env expected_mode sbody expected_ty
6365-
in
6366-
extended_env, body
6367-
6368-
and type_unpacks' ?in_function env expected_mode unpacks sbody expected_ty =
6369-
snd (type_unpacks ?in_function env expected_mode unpacks sbody expected_ty)
6370-
63716350
(* Typing of match cases *)
63726351
and type_cases
63736352
: type k . k pattern_category ->
@@ -6423,7 +6402,7 @@ and type_cases
64236402
let ty_arg = instance ?partial:take_partial_instance ty_arg in
64246403
end_def ();
64256404
generalize_structure ty_arg;
6426-
let (pat, ext_env, force, pvs, unpacks) =
6405+
let (pat, ext_env, force, pvs, mvs) =
64276406
type_pattern category ~lev ~alloc_mode:pmode env pc_lhs ty_arg
64286407
allow_modules
64296408
in
@@ -6442,7 +6421,7 @@ and type_cases
64426421
untyped_case = case;
64436422
branch_env = ext_env;
64446423
pat_vars = pvs;
6445-
unpacks;
6424+
module_vars = mvs;
64466425
contains_gadt = contains_gadt (as_comp_pattern category pat); }
64476426
)
64486427
caselist in
@@ -6485,7 +6464,8 @@ and type_cases
64856464
let in_function = if List.length caselist = 1 then in_function else None in
64866465
let cases =
64876466
List.map
6488-
(fun { typed_pat = pat; branch_env = ext_env; pat_vars = pvs; unpacks;
6467+
(fun { typed_pat = pat; branch_env = ext_env;
6468+
pat_vars = pvs; module_vars = mvs;
64896469
untyped_case = {pc_lhs = _; pc_guard; pc_rhs};
64906470
contains_gadt; _ } ->
64916471
let ext_env =
@@ -6499,6 +6479,7 @@ and type_cases
64996479
~check:(fun s -> Warnings.Unused_var_strict s)
65006480
~check_as:(fun s -> Warnings.Unused_var s)
65016481
in
6482+
let ext_env = add_module_variables ext_env mvs in
65026483
let ty_res' =
65036484
if !Clflags.principal then begin
65046485
begin_def ();
@@ -6515,12 +6496,12 @@ and type_cases
65156496
| None -> None
65166497
| Some scond ->
65176498
Some
6518-
(type_unpacks' ext_env mode_local unpacks scond
6499+
(type_expect ext_env mode_local scond
65196500
(mk_expected ~explanation:When_guard Predef.type_bool))
65206501
in
65216502
let exp =
6522-
type_unpacks' ?in_function ext_env emode
6523-
unpacks pc_rhs (mk_expected ?explanation ty_res')
6503+
type_expect ?in_function ext_env emode
6504+
pc_rhs (mk_expected ?explanation ty_res')
65246505
in
65256506
{
65266507
c_lhs = pat;
@@ -6663,9 +6644,21 @@ and type_let
66636644
let is_recursive = (rec_flag = Recursive) in
66646645
let nvs = List.map (fun _ -> newvar ()) spatl in
66656646
if is_recursive then begin_def ();
6666-
let (pat_list, new_env, force, pvs, unpacks) =
6647+
let (pat_list, new_env, force, pvs, mvs) =
66676648
type_pattern_list Value existential_context env spatl nvs allow_modules
66686649
in
6650+
(* Note [add_module_variables after checking expressions]
6651+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6652+
6653+
Don't call [add_module_variables] here, because its use of [type_module]
6654+
will fail until after we have type-checked the expression of the let.
6655+
Example: [let m : (module S) = ... in let (module M) = m in ...]
6656+
We learn the signature [S] from the type of [m] in the RHS of the second
6657+
let, and we need that knowledge for [type_module] to succeed. If we
6658+
type-checked expressions before patterns, then we could call
6659+
[add_module_variables] here.
6660+
*)
6661+
let new_env = add_pattern_variables new_env pvs in
66696662
if is_recursive then begin
66706663
end_def ();
66716664
iter_pattern_variables_type generalize pvs
@@ -6709,7 +6702,13 @@ and type_let
67096702
(* Only bind pattern variables after generalizing *)
67106703
List.iter (fun f -> f()) force;
67116704
let exp_env =
6712-
if is_recursive then new_env
6705+
(* See Note [add_module_variables after checking expressions]
6706+
6707+
We can't defer type-checking module variables with recursive definitions,
6708+
so things like [let rec (module M) = m in ...] always fail, even if the
6709+
type of [m] is known.
6710+
*)
6711+
if is_recursive then add_module_variables new_env mvs
67136712
else if entirely_functions
67146713
then begin
67156714
(* Add ghost bindings to help detecting missing "rec" keywords.
@@ -6809,24 +6808,13 @@ and type_let
68096808
end;
68106809
let exp =
68116810
Builtin_attributes.warning_scope pvb_attributes (fun () ->
6812-
if rec_flag = Recursive then
6813-
type_unpacks' exp_env mode
6814-
unpacks sexp (mk_expected ty')
6815-
else
6816-
type_expect exp_env mode
6817-
sexp (mk_expected ty')
6818-
)
6811+
type_expect exp_env mode sexp (mk_expected ty'))
68196812
in
68206813
exp, Some vars
68216814
| _ ->
68226815
let exp =
68236816
Builtin_attributes.warning_scope pvb_attributes (fun () ->
6824-
if rec_flag = Recursive then
6825-
type_unpacks' exp_env mode
6826-
unpacks sexp (mk_expected expected_ty)
6827-
else
6828-
type_expect exp_env mode
6829-
sexp (mk_expected expected_ty))
6817+
type_expect exp_env mode sexp (mk_expected expected_ty))
68306818
in
68316819
exp, None)
68326820
spat_sexp_list mode_typ_slot_list in
@@ -6897,7 +6885,9 @@ and type_let
68976885
| _ -> false) pat_extra) then
68986886
check_partial_application ~statement:false vb_expr
68996887
| _ -> ()) l;
6900-
(l, new_env, unpacks)
6888+
(* See Note [add_module_variables after checking expressions] *)
6889+
let new_env = add_module_variables new_env mvs in
6890+
(l, new_env)
69016891
69026892
and type_andops env sarg sands expected_ty =
69036893
let rec loop env let_sarg rev_sands expected_ty =
@@ -7254,7 +7244,7 @@ and type_immutable_array
72547244
72557245
let type_binding env rec_flag ?force_global spat_sexp_list =
72567246
Typetexp.TyVarEnv.reset ();
7257-
let (pat_exp_list, new_env, _unpacks) =
7247+
let (pat_exp_list, new_env) =
72587248
type_let
72597249
~check:(fun s -> Warnings.Unused_value_declaration s)
72607250
~check_strict:(fun s -> Warnings.Unused_value_declaration s)
@@ -7265,7 +7255,7 @@ let type_binding env rec_flag ?force_global spat_sexp_list =
72657255
(pat_exp_list, new_env)
72667256
72677257
let type_let existential_ctx env rec_flag spat_sexp_list =
7268-
let (pat_exp_list, new_env, _unpacks) =
7258+
let (pat_exp_list, new_env) =
72697259
type_let existential_ctx env rec_flag spat_sexp_list Modules_rejected
72707260
in
72717261
(pat_exp_list, new_env)

0 commit comments

Comments
 (0)