Skip to content

Commit 2951b85

Browse files
committed
module aliases hold locks instead of walking them
1 parent 68556cc commit 2951b85

File tree

8 files changed

+130
-62
lines changed

8 files changed

+130
-62
lines changed

testsuite/tests/templates/basic/bad_instance_wrong_mode.ml

+2
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ let (f @ portable) () =
22
let module Monoid_utils_of_list_monoid =
33
Monoid_utils(Monoid)(List_monoid) [@jane.non_erasable.instances]
44
in
5+
(* module alias doesn't walk locks; using it does. *)
6+
let _ = Monoid_utils_of_list_monoid.concat in
57
()
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
File "bad_instance_wrong_mode.ml", line 3, characters 4-68:
2-
3 | Monoid_utils(Monoid)(List_monoid) [@jane.non_erasable.instances]
3-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4-
Error: Modules are nonportable, so cannot be used inside a function that is portable.
1+
File "bad_instance_wrong_mode.ml", line 6, characters 10-44:
2+
6 | let _ = Monoid_utils_of_list_monoid.concat in
3+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
Error: The value "Monoid_utils_of_list_monoid.concat" is nonportable, so cannot be used inside a function that is portable.

testsuite/tests/typing-modes/module.ml

+32-13
Original file line numberDiff line numberDiff line change
@@ -198,36 +198,55 @@ module type S = sig val foo : 'a -> 'a val baz : 'a -> 'a @@ portable end
198198
module M : S
199199
|}]
200200

201-
(* CR zqian: fix the following. *)
202201
let (bar @ portable) () =
203202
let module N = M in
204203
M.baz ();
205204
N.baz ()
206205
[%%expect{|
207-
Line 2, characters 19-20:
208-
2 | let module N = M in
209-
^
210-
Error: Modules are nonportable, so cannot be used inside a function that is portable.
206+
val bar : unit -> unit = <fun>
211207
|}]
212208

213209
let (bar @ portable) () =
214210
let module N = M in
215211
N.foo ()
216212
[%%expect{|
217-
Line 2, characters 19-20:
218-
2 | let module N = M in
219-
^
220-
Error: Modules are nonportable, so cannot be used inside a function that is portable.
213+
Line 3, characters 4-9:
214+
3 | N.foo ()
215+
^^^^^
216+
Error: The value "N.foo" is nonportable, so cannot be used inside a function that is portable.
221217
|}]
222218

223219
let (bar @ portable) () =
224220
let module N = M in
225221
M.foo ()
226222
[%%expect{|
227-
Line 2, characters 19-20:
228-
2 | let module N = M in
229-
^
230-
Error: Modules are nonportable, so cannot be used inside a function that is portable.
223+
Line 3, characters 4-9:
224+
3 | M.foo ()
225+
^^^^^
226+
Error: The value "M.foo" is nonportable, so cannot be used inside a function that is portable.
227+
|}]
228+
229+
(* chained aliases. Creating alias of alias is fine. *)
230+
let (bar @ portable) () =
231+
let module N = M in
232+
let module N' = N in
233+
M.baz ();
234+
N.baz ();
235+
N'.baz ()
236+
[%%expect{|
237+
val bar : unit -> unit = <fun>
238+
|}]
239+
240+
(* locks are accumulated and not lost *)
241+
let (bar @ portable) () =
242+
let module N = M in
243+
let module N' = N in
244+
N'.foo ()
245+
[%%expect{|
246+
Line 4, characters 4-10:
247+
4 | N'.foo ()
248+
^^^^^^
249+
Error: The value "N'.foo" is nonportable, so cannot be used inside a function that is portable.
231250
|}]
232251

233252
(* module aliases in structures still walk locks. *)

typing/env.ml

+28-20
Original file line numberDiff line numberDiff line change
@@ -719,8 +719,14 @@ and module_data =
719719
mda_address : address_lazy;
720720
mda_shape: Shape.t; }
721721

722+
and module_alias_locks = lock list
723+
(** If the module is an alias for another module, this is the list of locks
724+
from the original module to this module. This is accumulative: write
725+
[module B = A;; module C = B;;], then [C] will record all locks from [A]
726+
to [C]. Empty if not an alias. *)
727+
722728
and module_entry =
723-
| Mod_local of module_data
729+
| Mod_local of module_data * module_alias_locks
724730
| Mod_persistent
725731
| Mod_unbound of module_unbound_reason
726732

@@ -936,7 +942,7 @@ let diff env1 env2 =
936942
(* Functions for use in "wrap" parameters in IdTbl *)
937943
let wrap_identity x = x
938944
let wrap_value vda = Val_bound vda
939-
let wrap_module mda = Mod_local mda
945+
let wrap_module mda = Mod_local (mda, [])
940946

941947
(* Forward declarations *)
942948

@@ -1239,7 +1245,7 @@ let check_functor_appl
12391245

12401246
let find_ident_module id env =
12411247
match find_same_module id env.modules with
1242-
| Mod_local data -> data
1248+
| Mod_local (data, _) -> data
12431249
| Mod_unbound _ -> raise Not_found
12441250
| Mod_persistent ->
12451251
match Ident.to_global id with
@@ -1529,7 +1535,7 @@ let find_shape env (ns : Shape.Sig_component_kind.t) id =
15291535
end
15301536
| Module ->
15311537
begin match IdTbl.find_same_without_locks id env.modules with
1532-
| Mod_local { mda_shape; _ } -> mda_shape
1538+
| Mod_local ({ mda_shape; _ }, _) -> mda_shape
15331539
| Mod_persistent -> Shape.for_persistent_unit (Ident.name id)
15341540
| Mod_unbound _ ->
15351541
(* Only present temporarily while approximating the environment for
@@ -1765,7 +1771,7 @@ let iter_env wrap proj1 proj2 f env () =
17651771
(fun id (path, entry) ->
17661772
match entry with
17671773
| Mod_unbound _ -> ()
1768-
| Mod_local data ->
1774+
| Mod_local (data, _) ->
17691775
iter_components (Pident id) path data.mda_components
17701776
| Mod_persistent -> ())
17711777
env.modules;
@@ -1811,7 +1817,7 @@ let rec find_shadowed_comps path env =
18111817
List.filter_map
18121818
(fun (p, data) ->
18131819
match data with
1814-
| Mod_local x -> Some (p, x)
1820+
| Mod_local (x, _) -> Some (p, x)
18151821
| Mod_unbound _ | Mod_persistent -> None)
18161822
(IdTbl.find_all wrap_module (Ident.name id) env.modules)
18171823
| Pdot (p, s) ->
@@ -2077,7 +2083,7 @@ let rec components_of_module_maker
20772083
NameMap.add (Ident.name id) mda c.comp_modules;
20782084
env :=
20792085
store_module ~update_summary:false ~check:None
2080-
id addr pres md shape !env
2086+
id addr pres md shape [] !env
20812087
| Sig_modtype(id, decl, _) ->
20822088
let final_decl =
20832089
(* The prefixed items get the same scope as [cm_path], which is
@@ -2352,7 +2358,7 @@ and store_extension ~check ~rebind id addr ext shape env =
23522358
summary = Env_extension(env.summary, id, ext) }
23532359

23542360
and store_module ?(update_summary=true) ~check
2355-
id addr presence md shape env =
2361+
id addr presence md shape alias_locks env =
23562362
let open Subst.Lazy in
23572363
let loc = md.md_loc in
23582364
Option.iter
@@ -2373,7 +2379,7 @@ and store_module ?(update_summary=true) ~check
23732379
if not update_summary then env.summary
23742380
else Env_module (env.summary, id, presence, force_module_decl md) in
23752381
{ env with
2376-
modules = IdTbl.add id (Mod_local mda) env.modules;
2382+
modules = IdTbl.add id (Mod_local (mda, alias_locks)) env.modules;
23772383
summary }
23782384

23792385
and store_modtype ?(update_summary=true) id info shape env =
@@ -2466,7 +2472,7 @@ and add_extension ~check ?shape ~rebind id ext env =
24662472
store_extension ~check ~rebind id addr ext shape env
24672473

24682474
and add_module_declaration_lazy
2469-
~update_summary ?(arg=false) ?shape ~check id presence md env =
2475+
~update_summary ?(arg=false) ?shape ~check id presence md ?(locks = []) env =
24702476
let check =
24712477
if not check then
24722478
None
@@ -2478,13 +2484,13 @@ and add_module_declaration_lazy
24782484
let addr = module_declaration_address env id presence md in
24792485
let shape = shape_or_leaf md.Subst.Lazy.md_uid shape in
24802486
let env =
2481-
store_module ~update_summary ~check id addr presence md shape env
2487+
store_module ~update_summary ~check id addr presence md shape locks env
24822488
in
24832489
if arg then add_functor_arg id env else env
24842490

2485-
let add_module_declaration ?(arg=false) ?shape ~check id presence md env =
2491+
let add_module_declaration ?(arg=false) ?shape ~check id presence md ?locks env =
24862492
add_module_declaration_lazy ~update_summary:true ~arg ?shape ~check id
2487-
presence (Subst.Lazy.of_module_decl md) env
2493+
presence (Subst.Lazy.of_module_decl md) ?locks env
24882494

24892495
and add_modtype_lazy ~update_summary ?shape id info env =
24902496
let shape = shape_or_leaf info.Subst.Lazy.mtd_uid shape in
@@ -2543,9 +2549,9 @@ let enter_extension ~scope ~rebind name ext env =
25432549
let env = store_extension ~check:true ~rebind id addr ext shape env in
25442550
(id, env)
25452551

2546-
let enter_module_declaration ~scope ?arg ?shape s presence md env =
2552+
let enter_module_declaration ~scope ?arg ?shape s presence md ?locks env =
25472553
let id = Ident.create_scoped ~scope s in
2548-
(id, add_module_declaration ?arg ?shape ~check:true id presence md env)
2554+
(id, add_module_declaration ?arg ?shape ~check:true id presence md ?locks env)
25492555

25502556
let enter_modtype ~scope name mtd env =
25512557
let id = Ident.create_scoped ~scope name in
@@ -2608,7 +2614,8 @@ module Add_signature(T : Types.Wrapped)(M : sig
26082614
val add_value: ?shape:Shape.t -> mode:(Mode.allowed * 'r0) Mode.Value.t -> Ident.t ->
26092615
T.value_description -> t -> t
26102616
val add_module_declaration: ?arg:bool -> ?shape:Shape.t -> check:bool
2611-
-> Ident.t -> module_presence -> T.module_declaration -> t -> t
2617+
-> Ident.t -> module_presence -> T.module_declaration -> ?locks:lock list ->
2618+
t -> t
26122619
val add_modtype: ?shape:Shape.t -> Ident.t -> T.modtype_declaration -> t -> t
26132620
end) = struct
26142621
open T
@@ -2688,7 +2695,7 @@ let add_cltype = add_cltype ?shape:None
26882695
let add_modtype_lazy = add_modtype_lazy ?shape:None
26892696
let add_modtype = add_modtype ?shape:None
26902697
let add_module_declaration_lazy ?(arg=false) =
2691-
add_module_declaration_lazy ~arg ?shape:None ~check:false
2698+
add_module_declaration_lazy ~arg ?shape:None ~check:false ?locks:None
26922699
let add_signature sg env =
26932700
let _, env = add_signature Shape.Map.empty None sg env in
26942701
env
@@ -3001,8 +3008,9 @@ let lookup_ident_module (type a) (load : a load) ~errors ~use ~loc s env =
30013008
may_lookup_error errors loc env (Unbound_module (Lident s))
30023009
in
30033010
match data with
3004-
| Mod_local mda -> begin
3011+
| Mod_local (mda, alias_locks) -> begin
30053012
use_module ~use ~loc path mda;
3013+
let locks = alias_locks @ locks in
30063014
match load with
30073015
| Load -> path, locks, (mda : a)
30083016
| Don't_load -> path, locks, (() : a)
@@ -3572,7 +3580,7 @@ let lookup_module_path ~errors ~use ~loc ~load lid env =
35723580
match lid with
35733581
| Lident s ->
35743582
if !Clflags.transparent_modules && not load then
3575-
let path, locks, _ =
3583+
let path, locks, () =
35763584
lookup_ident_module Don't_load ~errors ~use ~loc s env
35773585
in
35783586
path, locks
@@ -3968,7 +3976,7 @@ let fold_modules f lid env acc =
39683976
(fun name (p, entry) acc ->
39693977
match entry with
39703978
| Mod_unbound _ -> acc
3971-
| Mod_local mda ->
3979+
| Mod_local (mda, _) ->
39723980
let md =
39733981
Subst.Lazy.force_module_decl mda.mda_declaration
39743982
in

typing/env.mli

+2-2
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ val add_module: ?arg:bool -> ?shape:Shape.t ->
403403
val add_module_lazy: update_summary:bool ->
404404
Ident.t -> module_presence -> Subst.Lazy.module_type -> t -> t
405405
val add_module_declaration: ?arg:bool -> ?shape:Shape.t -> check:bool ->
406-
Ident.t -> module_presence -> module_declaration -> t -> t
406+
Ident.t -> module_presence -> module_declaration -> ?locks:lock list -> t -> t
407407
val add_module_declaration_lazy: ?arg:bool -> update_summary:bool ->
408408
Ident.t -> module_presence -> Subst.Lazy.module_declaration -> t -> t
409409
val add_modtype: Ident.t -> modtype_declaration -> t -> t
@@ -467,7 +467,7 @@ val enter_module:
467467
module_type -> t -> Ident.t * t
468468
val enter_module_declaration:
469469
scope:int -> ?arg:bool -> ?shape:Shape.t -> string -> module_presence ->
470-
module_declaration -> t -> Ident.t * t
470+
module_declaration -> ?locks:lock list -> t -> Ident.t * t
471471
val enter_modtype:
472472
scope:int -> string -> modtype_declaration -> t -> Ident.t * t
473473
val enter_class: scope:int -> string -> class_declaration -> t -> Ident.t * t

typing/typecore.ml

+8-5
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,8 @@ let error_of_filter_arrow_failure ~explanation ~first ty_fun
300300

301301
let type_module =
302302
ref ((fun _env _md -> assert false) :
303-
Env.t -> Parsetree.module_expr -> Typedtree.module_expr * Shape.t)
303+
Env.t -> Parsetree.module_expr -> Typedtree.module_expr * Shape.t *
304+
Env.lock list)
304305

305306
(* Forward declaration, to be filled in by Typemod.type_open *)
306307

@@ -1273,7 +1274,7 @@ let add_module_variables env module_variables =
12731274
Here, on the other hand, we're calling [type_module] outside the
12741275
raised level, so there's no extra step to take.
12751276
*)
1276-
let modl, md_shape =
1277+
let modl, md_shape, locks =
12771278
!type_module env
12781279
Ast_helper.(
12791280
Mod.unpack ~loc:mv_loc
@@ -1291,7 +1292,9 @@ let add_module_variables env module_variables =
12911292
md_loc = mv_name.loc;
12921293
md_uid = mv_uid; }
12931294
in
1294-
Env.add_module_declaration ~shape:md_shape ~check:true mv_id pres md env
1295+
Env.add_module_declaration ~shape:md_shape ~check:true mv_id pres md
1296+
(* the [locks] is always empty, but typecore doesn't need to know *)
1297+
~locks env
12951298
end
12961299
) env module_variables_as_list
12971300

@@ -6401,7 +6404,7 @@ and type_expect_
64016404
with_local_level begin fun () ->
64026405
let modl, pres, id, new_env =
64036406
Typetexp.TyVarEnv.with_local_scope begin fun () ->
6404-
let modl, md_shape = !type_module env smodl in
6407+
let modl, md_shape, locks = !type_module env smodl in
64056408
Mtype.lower_nongen lv modl.mod_type;
64066409
let pres =
64076410
match modl.mod_type with
@@ -6422,7 +6425,7 @@ and type_expect_
64226425
| Some name ->
64236426
let id, env =
64246427
Env.enter_module_declaration
6425-
~scope ~shape:md_shape name pres md env
6428+
~scope ~shape:md_shape name pres md ~locks env
64266429
in
64276430
Some id, env
64286431
in

typing/typecore.mli

+2-1
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,8 @@ val report_error: loc:Location.t -> Env.t -> error -> Location.error
332332

333333
(* Forward declaration, to be filled in by Typemod.type_module *)
334334
val type_module:
335-
(Env.t -> Parsetree.module_expr -> Typedtree.module_expr * Shape.t) ref
335+
(Env.t -> Parsetree.module_expr -> Typedtree.module_expr * Shape.t *
336+
Env.lock list) ref
336337
(* Forward declaration, to be filled in by Typemod.type_open *)
337338
val type_open:
338339
(?used_slot:bool ref -> override_flag -> Env.t -> Location.t ->

0 commit comments

Comments
 (0)