@@ -48,13 +48,6 @@ type type_expected = {
48
48
explanation : type_forcing_context option ;
49
49
}
50
50
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
-
58
51
module Datatype_kind = struct
59
52
type t = Record | Variant
60
53
@@ -700,10 +693,18 @@ type pattern_variable =
700
693
pv_attributes : attributes ;
701
694
}
702
695
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
+
703
704
let pattern_variables = ref ([] : pattern_variable list )
704
705
let pattern_force = ref ([] : (unit -> unit ) list )
705
706
let allow_modules = ref Modules_rejected
706
- let module_variables = ref ([] : to_unpack list )
707
+ let module_variables = ref ([] : module_variable list )
707
708
let reset_pattern allow =
708
709
pattern_variables := [];
709
710
pattern_force := [];
@@ -737,6 +738,38 @@ let add_pattern_variables ?check ?check_as env pv =
737
738
)
738
739
pv env
739
740
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
+
740
773
let enter_variable ?(is_module =false ) ?(is_as_variable =false ) loc name mode ty
741
774
attrs =
742
775
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
755
788
escape ~loc ~env: Env. empty ~reason: Other mode;
756
789
let id = Ident. create_scoped name.txt ~scope in
757
790
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 () );
762
795
} :: ! module_variables;
763
796
id
764
797
end else
@@ -1722,7 +1755,7 @@ type 'case_pattern half_typed_case =
1722
1755
untyped_case : Parsetree .case ;
1723
1756
branch_env : Env .t ;
1724
1757
pat_vars : pattern_variable list ;
1725
- unpacks : to_unpack list ;
1758
+ module_vars : module_variable list ;
1726
1759
contains_gadt : bool ; }
1727
1760
1728
1761
let rec has_literal_pattern p =
@@ -2582,8 +2615,8 @@ let type_pattern category ~lev ~alloc_mode env spat expected_ty allow_modules =
2582
2615
let new_env = ref env in
2583
2616
let pat = type_pat category ~lev ~alloc_mode new_env spat expected_ty in
2584
2617
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 )
2587
2620
2588
2621
let type_pattern_list
2589
2622
category no_existentials env spatl expected_tys allow_modules
@@ -2599,9 +2632,8 @@ let type_pattern_list
2599
2632
in
2600
2633
let patl = List. map2 type_pat spatl expected_tys in
2601
2634
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)
2605
2637
2606
2638
let type_class_arg_pattern cl_num val_env met_env l spat =
2607
2639
if ! Clflags. principal then Ctype. begin_def () ;
@@ -3980,17 +4012,18 @@ and type_expect_
3980
4012
Modules_allowed { scope }
3981
4013
end else Modules_rejected
3982
4014
in
3983
- let (pat_exp_list, new_env, unpacks ) =
4015
+ let (pat_exp_list, new_env) =
3984
4016
type_let existential_context env rec_flag spat_sexp_list allow_modules
3985
4017
in
3986
4018
let in_function =
3987
4019
match sexp.pexp_attributes with
3988
4020
| [{Parsetree. attr_name = {txt= " #default" };_}] -> in_function
3989
4021
| _ -> None
3990
4022
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
3994
4027
let () =
3995
4028
if rec_flag = Recursive then
3996
4029
check_recursive_bindings env pat_exp_list
@@ -4008,9 +4041,9 @@ and type_expect_
4008
4041
*)
4009
4042
if may_contain_modules then begin
4010
4043
end_def () ;
4011
- unify_exp extended_env body (newvar () );
4044
+ unify_exp new_env body (newvar () );
4012
4045
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
4014
4047
end ;
4015
4048
re {
4016
4049
exp_desc = Texp_let (rec_flag, pat_exp_list, body);
@@ -6314,60 +6347,6 @@ and type_statement ?explanation env sexp =
6314
6347
exp
6315
6348
end
6316
6349
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
-
6371
6350
(* Typing of match cases *)
6372
6351
and type_cases
6373
6352
: type k . k pattern_category ->
@@ -6423,7 +6402,7 @@ and type_cases
6423
6402
let ty_arg = instance ?partial:take_partial_instance ty_arg in
6424
6403
end_def () ;
6425
6404
generalize_structure ty_arg;
6426
- let (pat, ext_env, force, pvs, unpacks ) =
6405
+ let (pat, ext_env, force, pvs, mvs ) =
6427
6406
type_pattern category ~lev ~alloc_mode: pmode env pc_lhs ty_arg
6428
6407
allow_modules
6429
6408
in
@@ -6442,7 +6421,7 @@ and type_cases
6442
6421
untyped_case = case;
6443
6422
branch_env = ext_env;
6444
6423
pat_vars = pvs;
6445
- unpacks ;
6424
+ module_vars = mvs ;
6446
6425
contains_gadt = contains_gadt (as_comp_pattern category pat); }
6447
6426
)
6448
6427
caselist in
@@ -6485,7 +6464,8 @@ and type_cases
6485
6464
let in_function = if List. length caselist = 1 then in_function else None in
6486
6465
let cases =
6487
6466
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 ;
6489
6469
untyped_case = {pc_lhs = _ ; pc_guard; pc_rhs} ;
6490
6470
contains_gadt; _ } ->
6491
6471
let ext_env =
@@ -6499,6 +6479,7 @@ and type_cases
6499
6479
~check: (fun s -> Warnings. Unused_var_strict s)
6500
6480
~check_as: (fun s -> Warnings. Unused_var s)
6501
6481
in
6482
+ let ext_env = add_module_variables ext_env mvs in
6502
6483
let ty_res' =
6503
6484
if ! Clflags. principal then begin
6504
6485
begin_def () ;
@@ -6515,12 +6496,12 @@ and type_cases
6515
6496
| None -> None
6516
6497
| Some scond ->
6517
6498
Some
6518
- (type_unpacks' ext_env mode_local unpacks scond
6499
+ (type_expect ext_env mode_local scond
6519
6500
(mk_expected ~explanation: When_guard Predef. type_bool))
6520
6501
in
6521
6502
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')
6524
6505
in
6525
6506
{
6526
6507
c_lhs = pat;
@@ -6663,9 +6644,21 @@ and type_let
6663
6644
let is_recursive = (rec_flag = Recursive ) in
6664
6645
let nvs = List. map (fun _ -> newvar () ) spatl in
6665
6646
if is_recursive then begin_def () ;
6666
- let (pat_list, new_env, force, pvs, unpacks ) =
6647
+ let (pat_list, new_env, force, pvs, mvs ) =
6667
6648
type_pattern_list Value existential_context env spatl nvs allow_modules
6668
6649
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
6669
6662
if is_recursive then begin
6670
6663
end_def () ;
6671
6664
iter_pattern_variables_type generalize pvs
@@ -6709,7 +6702,13 @@ and type_let
6709
6702
(* Only bind pattern variables after generalizing *)
6710
6703
List. iter (fun f -> f() ) force;
6711
6704
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
6713
6712
else if entirely_functions
6714
6713
then begin
6715
6714
(* Add ghost bindings to help detecting missing "rec" keywords.
@@ -6809,24 +6808,13 @@ and type_let
6809
6808
end ;
6810
6809
let exp =
6811
6810
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'))
6819
6812
in
6820
6813
exp, Some vars
6821
6814
| _ ->
6822
6815
let exp =
6823
6816
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))
6830
6818
in
6831
6819
exp, None )
6832
6820
spat_sexp_list mode_typ_slot_list in
@@ -6897,7 +6885,9 @@ and type_let
6897
6885
| _ -> false ) pat_extra) then
6898
6886
check_partial_application ~statement: false vb_expr
6899
6887
| _ -> () ) 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)
6901
6891
6902
6892
and type_andops env sarg sands expected_ty =
6903
6893
let rec loop env let_sarg rev_sands expected_ty =
@@ -7254,7 +7244,7 @@ and type_immutable_array
7254
7244
7255
7245
let type_binding env rec_flag ?force_global spat_sexp_list =
7256
7246
Typetexp.TyVarEnv. reset () ;
7257
- let (pat_exp_list, new_env, _unpacks ) =
7247
+ let (pat_exp_list, new_env) =
7258
7248
type_let
7259
7249
~check: (fun s -> Warnings. Unused_value_declaration s)
7260
7250
~check_strict: (fun s -> Warnings. Unused_value_declaration s)
@@ -7265,7 +7255,7 @@ let type_binding env rec_flag ?force_global spat_sexp_list =
7265
7255
(pat_exp_list, new_env)
7266
7256
7267
7257
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) =
7269
7259
type_let existential_ctx env rec_flag spat_sexp_list Modules_rejected
7270
7260
in
7271
7261
(pat_exp_list, new_env)
0 commit comments