···665665- #12764: Move all installable headers in `caml/` sub-directories.
666666 (Antonin Décimo, review by Gabriel Scherer and David Allsopp)
667667668668+- #12508 : Add compiler-side support for project-wide occurrences in Merlin, by
669669+ generating index tables of all identifier occurrences. This extra data in .cmt
670670+ files is only added when the new flag -bin-annot-occurrences is passed.
671671+ (Ulysse Gérard, Nathanaëlle Courant, suggestions by Gabriel Scherer and Thomas
672672+ Refis, review by Florian Angeletti, Gabriel Scherer and Thomas Refis)
673673+668674### Build system:
669675670676- #12198, #12321, #12586, #12616, #12706: continue the merge of the
···4040let mk_binannot f =
4141 "-bin-annot", Arg.Unit f, " Save typedtree in <filename>.cmt"
42424343+let mk_binannot_occurrences f =
4444+ "-bin-annot-occurrences", Arg.Unit f,
4545+ " Store every occurrence of a bound name in the .cmt file.\n\
4646+ This information can be used by external tools to provide\n\
4747+ features such as project-wide occurrences. This flag has\n\
4848+ no effect in the absence of '-bin-annot'."
4949+4350let mk_c f =
4451 "-c", Arg.Unit f, " Compile only (do not link)"
4552···820827 val _a : unit -> unit
821828 val _annot : unit -> unit
822829 val _binannot : unit -> unit
830830+ val _binannot_occurrences : unit -> unit
823831 val _c : unit -> unit
824832 val _cc : string -> unit
825833 val _cclib : string -> unit
···10151023 mk_no_absname F._no_absname;
10161024 mk_annot F._annot;
10171025 mk_binannot F._binannot;
10261026+ mk_binannot_occurrences F._binannot_occurrences;
10181027 mk_c F._c;
10191028 mk_cc F._cc;
10201029 mk_cclib F._cclib;
···12081217 mk_afl_inst_ratio F._afl_inst_ratio;
12091218 mk_annot F._annot;
12101219 mk_binannot F._binannot;
12201220+ mk_binannot_occurrences F._binannot_occurrences;
12111221 mk_inline_branch_factor F._inline_branch_factor;
12121222 mk_c F._c;
12131223 mk_cc F._cc;
···17361746 let _args = Arg.read_arg
17371747 let _args0 = Arg.read_arg0
17381748 let _binannot = set binary_annotations
17491749+ let _binannot_occurrences = set store_occurrences
17391750 let _c = set compile_only
17401751 let _cc s = c_compiler := (Some s)
17411752 let _cclib s = Compenv.defer (ProcessObjects (Misc.rev_split_words s))
+1
driver/main_args.mli
···7777 val _a : unit -> unit
7878 val _annot : unit -> unit
7979 val _binannot : unit -> unit
8080+ val _binannot_occurrences : unit -> unit
8081 val _c : unit -> unit
8182 val _cc : string -> unit
8283 val _cclib : string -> unit
+297-13
file_formats/cmt_format.ml
···3636 | Partial_interface of binary_part array
37373838and binary_part =
3939-| Partial_structure of structure
4040-| Partial_structure_item of structure_item
4141-| Partial_expression of expression
4242-| Partial_pattern : 'k pattern_category * 'k general_pattern -> binary_part
4343-| Partial_class_expr of class_expr
4444-| Partial_signature of signature
4545-| Partial_signature_item of signature_item
4646-| Partial_module_type of module_type
3939+ | Partial_structure of structure
4040+ | Partial_structure_item of structure_item
4141+ | Partial_expression of expression
4242+ | Partial_pattern : 'k pattern_category * 'k general_pattern -> binary_part
4343+ | Partial_class_expr of class_expr
4444+ | Partial_signature of signature
4545+ | Partial_signature_item of signature_item
4646+ | Partial_module_type of module_type
47474848type cmt_infos = {
4949 cmt_modname : string;
···6060 cmt_imports : (string * Digest.t option) list;
6161 cmt_interface_digest : Digest.t option;
6262 cmt_use_summaries : bool;
6363- cmt_uid_to_loc : Location.t Shape.Uid.Tbl.t;
6363+ cmt_uid_to_decl : item_declaration Shape.Uid.Tbl.t;
6464 cmt_impl_shape : Shape.t option; (* None for mli *)
6565+ cmt_ident_occurrences :
6666+ (Longident.t Location.loc * Shape_reduce.result) list
6567}
66686769type error =
6870 Not_a_typedtree of string
69717272+let iter_on_parts (it : Tast_iterator.iterator) = function
7373+ | Partial_structure s -> it.structure it s
7474+ | Partial_structure_item s -> it.structure_item it s
7575+ | Partial_expression e -> it.expr it e
7676+ | Partial_pattern (_category, p) -> it.pat it p
7777+ | Partial_class_expr ce -> it.class_expr it ce
7878+ | Partial_signature s -> it.signature it s
7979+ | Partial_signature_item s -> it.signature_item it s
8080+ | Partial_module_type s -> it.module_type it s
8181+8282+let iter_on_annots (it : Tast_iterator.iterator) = function
8383+ | Implementation s -> it.structure it s
8484+ | Interface s -> it.signature it s
8585+ | Packed _ -> ()
8686+ | Partial_implementation array -> Array.iter (iter_on_parts it) array
8787+ | Partial_interface array -> Array.iter (iter_on_parts it) array
8888+8989+let iter_on_declaration f decl =
9090+ match decl with
9191+ | Value vd -> f vd.val_val.val_uid decl;
9292+ | Value_binding vb ->
9393+ let bound_idents = let_bound_idents_full [vb] in
9494+ List.iter (fun (_, _, _, uid) -> f uid decl) bound_idents
9595+ | Type td ->
9696+ if not (Btype.is_row_name (Ident.name td.typ_id)) then
9797+ f td.typ_type.type_uid (Type td)
9898+ | Constructor cd -> f cd.cd_uid decl
9999+ | Extension_constructor ec -> f ec.ext_type.ext_uid decl;
100100+ | Label ld -> f ld.ld_uid decl
101101+ | Module md -> f md.md_uid decl
102102+ | Module_type mtd -> f mtd.mtd_uid decl
103103+ | Module_substitution ms -> f ms.ms_uid decl
104104+ | Module_binding mb -> f mb.mb_uid decl
105105+ | Class cd -> f cd.ci_decl.cty_uid decl
106106+ | Class_type ct -> f ct.ci_decl.cty_uid decl
107107+108108+let iter_on_declarations ~(f: Shape.Uid.t -> item_declaration -> unit) = {
109109+ Tast_iterator.default_iterator with
110110+ item_declaration = (fun _sub decl -> iter_on_declaration f decl);
111111+}
112112+70113let need_to_clear_env =
71114 try ignore (Sys.getenv "OCAML_BINANNOT_WITHENV"); false
72115 with Not_found -> true
7311674117let keep_only_summary = Env.keep_only_summary
7575-7676-open Tast_mapper
7711878119let cenv =
79120 {Tast_mapper.default with env = fun _sub env -> keep_only_summary env}
···103144104145 else binary_annots
105146147147+(* Every typedtree node with a located longident corresponding to user-facing
148148+ syntax should be indexed. *)
149149+let iter_on_occurrences
150150+ ~(f : namespace:Shape.Sig_component_kind.t ->
151151+ Env.t -> Path.t -> Longident.t Location.loc ->
152152+ unit) =
153153+ let path_in_type typ name =
154154+ match Types.get_desc typ with
155155+ | Tconstr (type_path, _, _) ->
156156+ Some (Path.Pdot (type_path, name))
157157+ | _ -> None
158158+ in
159159+ let add_constructor_description env lid =
160160+ function
161161+ | { Types.cstr_tag = Cstr_extension (path, _); _ } ->
162162+ f ~namespace:Extension_constructor env path lid
163163+ | { Types.cstr_uid = Predef name; _} ->
164164+ let id = List.assoc name Predef.builtin_idents in
165165+ f ~namespace:Constructor env (Pident id) lid
166166+ | { Types.cstr_res; cstr_name; _ } ->
167167+ let path = path_in_type cstr_res cstr_name in
168168+ Option.iter (fun path -> f ~namespace:Constructor env path lid) path
169169+ in
170170+ let add_label env lid { Types.lbl_name; lbl_res; _ } =
171171+ let path = path_in_type lbl_res lbl_name in
172172+ Option.iter (fun path -> f ~namespace:Label env path lid) path
173173+ in
174174+ let with_constraint ~env (_path, _lid, with_constraint) =
175175+ match with_constraint with
176176+ | Twith_module (path', lid') | Twith_modsubst (path', lid') ->
177177+ f ~namespace:Module env path' lid'
178178+ | _ -> ()
179179+ in
180180+ Tast_iterator.{ default_iterator with
181181+182182+ expr = (fun sub ({ exp_desc; exp_env; _ } as e) ->
183183+ (match exp_desc with
184184+ | Texp_ident (path, lid, _) ->
185185+ f ~namespace:Value exp_env path lid
186186+ | Texp_construct (lid, constr_desc, _) ->
187187+ add_constructor_description exp_env lid constr_desc
188188+ | Texp_field (_, lid, label_desc)
189189+ | Texp_setfield (_, lid, label_desc, _) ->
190190+ add_label exp_env lid label_desc
191191+ | Texp_new (path, lid, _) ->
192192+ f ~namespace:Class exp_env path lid
193193+ | Texp_record { fields; _ } ->
194194+ Array.iter (fun (label_descr, record_label_definition) ->
195195+ match record_label_definition with
196196+ | Overridden (
197197+ { Location.txt; loc},
198198+ {exp_loc; _})
199199+ when not exp_loc.loc_ghost
200200+ && loc.loc_start = exp_loc.loc_start
201201+ && loc.loc_end = exp_loc.loc_end ->
202202+ (* In the presence of punning we want to index the label
203203+ even if it is ghosted *)
204204+ let lid = { Location.txt; loc = {loc with loc_ghost = false} } in
205205+ add_label exp_env lid label_descr
206206+ | Overridden (lid, _) -> add_label exp_env lid label_descr
207207+ | Kept _ -> ()) fields
208208+ | Texp_instvar (_self_path, path, name) ->
209209+ let lid = { name with txt = Longident.Lident name.txt } in
210210+ f ~namespace:Value exp_env path lid
211211+ | Texp_setinstvar (_self_path, path, name, _) ->
212212+ let lid = { name with txt = Longident.Lident name.txt } in
213213+ f ~namespace:Value exp_env path lid
214214+ | Texp_override (_self_path, modifs) ->
215215+ List.iter (fun (id, (name : string Location.loc), _exp) ->
216216+ let lid = { name with txt = Longident.Lident name.txt } in
217217+ f ~namespace:Value exp_env (Path.Pident id) lid)
218218+ modifs
219219+ | Texp_extension_constructor (lid, path) ->
220220+ f ~namespace:Extension_constructor exp_env path lid
221221+ | Texp_constant _ | Texp_let _ | Texp_function _ | Texp_apply _
222222+ | Texp_match _ | Texp_try _ | Texp_tuple _ | Texp_variant _ | Texp_array _
223223+ | Texp_ifthenelse _ | Texp_sequence _ | Texp_while _ | Texp_for _
224224+ | Texp_send _
225225+ | Texp_letmodule _ | Texp_letexception _ | Texp_assert _ | Texp_lazy _
226226+ | Texp_object _ | Texp_pack _ | Texp_letop _ | Texp_unreachable
227227+ | Texp_open _ -> ());
228228+ default_iterator.expr sub e);
229229+230230+ (* Remark: some types get iterated over twice due to how constraints are
231231+ encoded in the typedtree. For example, in [let x : t = 42], [t] is
232232+ present in both a [Tpat_constraint] and a [Texp_constraint] node) *)
233233+ typ =
234234+ (fun sub ({ ctyp_desc; ctyp_env; _ } as ct) ->
235235+ (match ctyp_desc with
236236+ | Ttyp_constr (path, lid, _ctyps) ->
237237+ f ~namespace:Type ctyp_env path lid
238238+ | Ttyp_package {pack_path; pack_txt} ->
239239+ f ~namespace:Module_type ctyp_env pack_path pack_txt
240240+ | Ttyp_class (path, lid, _typs) ->
241241+ (* Deprecated syntax to extend a polymorphic variant *)
242242+ f ~namespace:Type ctyp_env path lid
243243+ | Ttyp_open (path, lid, _ct) ->
244244+ f ~namespace:Module ctyp_env path lid
245245+ | Ttyp_any | Ttyp_var _ | Ttyp_arrow _ | Ttyp_tuple _ | Ttyp_object _
246246+ | Ttyp_alias _ | Ttyp_variant _ | Ttyp_poly _ -> ());
247247+ default_iterator.typ sub ct);
248248+249249+ pat =
250250+ (fun (type a) sub
251251+ ({ pat_desc; pat_extra; pat_env; _ } as pat : a general_pattern) ->
252252+ (match pat_desc with
253253+ | Tpat_construct (lid, constr_desc, _, _) ->
254254+ add_constructor_description pat_env lid constr_desc
255255+ | Tpat_record (fields, _) ->
256256+ List.iter (fun (lid, label_descr, pat) ->
257257+ let lid =
258258+ let open Location in
259259+ (* In the presence of punning we want to index the label
260260+ even if it is ghosted *)
261261+ if (not pat.pat_loc.loc_ghost
262262+ && lid.loc.loc_start = pat.pat_loc.loc_start
263263+ && lid.loc.loc_end = pat.pat_loc.loc_end)
264264+ then {lid with loc = {lid.loc with loc_ghost = false}}
265265+ else lid
266266+ in
267267+ add_label pat_env lid label_descr)
268268+ fields
269269+ | Tpat_any | Tpat_var _ | Tpat_alias _ | Tpat_constant _ | Tpat_tuple _
270270+ | Tpat_variant _ | Tpat_array _ | Tpat_lazy _ | Tpat_value _
271271+ | Tpat_exception _ | Tpat_or _ -> ());
272272+ List.iter (fun (pat_extra, _, _) ->
273273+ match pat_extra with
274274+ | Tpat_open (path, lid, _) ->
275275+ f ~namespace:Module pat_env path lid
276276+ | Tpat_type (path, lid) ->
277277+ f ~namespace:Type pat_env path lid
278278+ | Tpat_constraint _ | Tpat_unpack -> ())
279279+ pat_extra;
280280+ default_iterator.pat sub pat);
281281+282282+ binding_op = (fun sub ({bop_op_path; bop_op_name; bop_exp; _} as bop) ->
283283+ let lid = { bop_op_name with txt = Longident.Lident bop_op_name.txt } in
284284+ f ~namespace:Value bop_exp.exp_env bop_op_path lid;
285285+ default_iterator.binding_op sub bop);
286286+287287+ module_expr =
288288+ (fun sub ({ mod_desc; mod_env; _ } as me) ->
289289+ (match mod_desc with
290290+ | Tmod_ident (path, lid) -> f ~namespace:Module mod_env path lid
291291+ | Tmod_structure _ | Tmod_functor _ | Tmod_apply _ | Tmod_apply_unit _
292292+ | Tmod_constraint _ | Tmod_unpack _ -> ());
293293+ default_iterator.module_expr sub me);
294294+295295+ open_description =
296296+ (fun sub ({ open_expr = (path, lid); open_env; _ } as od) ->
297297+ f ~namespace:Module open_env path lid;
298298+ default_iterator.open_description sub od);
299299+300300+ module_type =
301301+ (fun sub ({ mty_desc; mty_env; _ } as mty) ->
302302+ (match mty_desc with
303303+ | Tmty_ident (path, lid) ->
304304+ f ~namespace:Module_type mty_env path lid
305305+ | Tmty_with (_mty, l) ->
306306+ List.iter (with_constraint ~env:mty_env) l
307307+ | Tmty_alias (path, lid) ->
308308+ f ~namespace:Module mty_env path lid
309309+ | Tmty_signature _ | Tmty_functor _ | Tmty_typeof _ -> ());
310310+ default_iterator.module_type sub mty);
311311+312312+ class_expr =
313313+ (fun sub ({ cl_desc; cl_env; _} as ce) ->
314314+ (match cl_desc with
315315+ | Tcl_ident (path, lid, _) -> f ~namespace:Class cl_env path lid
316316+ | Tcl_structure _ | Tcl_fun _ | Tcl_apply _ | Tcl_let _
317317+ | Tcl_constraint _ | Tcl_open _ -> ());
318318+ default_iterator.class_expr sub ce);
319319+320320+ class_type =
321321+ (fun sub ({ cltyp_desc; cltyp_env; _} as ct) ->
322322+ (match cltyp_desc with
323323+ | Tcty_constr (path, lid, _) -> f ~namespace:Class_type cltyp_env path lid
324324+ | Tcty_signature _ | Tcty_arrow _ | Tcty_open _ -> ());
325325+ default_iterator.class_type sub ct);
326326+327327+ signature_item =
328328+ (fun sub ({ sig_desc; sig_env; _ } as sig_item) ->
329329+ (match sig_desc with
330330+ | Tsig_exception {
331331+ tyexn_constructor = { ext_kind = Text_rebind (path, lid)}} ->
332332+ f ~namespace:Extension_constructor sig_env path lid
333333+ | Tsig_modsubst { ms_manifest; ms_txt } ->
334334+ f ~namespace:Module sig_env ms_manifest ms_txt
335335+ | Tsig_typext { tyext_path; tyext_txt } ->
336336+ f ~namespace:Type sig_env tyext_path tyext_txt
337337+ | Tsig_value _ | Tsig_type _ | Tsig_typesubst _ | Tsig_exception _
338338+ | Tsig_module _ | Tsig_recmodule _ | Tsig_modtype _ | Tsig_modtypesubst _
339339+ | Tsig_open _ | Tsig_include _ | Tsig_class _ | Tsig_class_type _
340340+ | Tsig_attribute _ -> ());
341341+ default_iterator.signature_item sub sig_item);
342342+343343+ structure_item =
344344+ (fun sub ({ str_desc; str_env; _ } as str_item) ->
345345+ (match str_desc with
346346+ | Tstr_exception {
347347+ tyexn_constructor = { ext_kind = Text_rebind (path, lid)}} ->
348348+ f ~namespace:Extension_constructor str_env path lid
349349+ | Tstr_typext { tyext_path; tyext_txt } ->
350350+ f ~namespace:Type str_env tyext_path tyext_txt
351351+ | Tstr_eval _ | Tstr_value _ | Tstr_primitive _ | Tstr_type _
352352+ | Tstr_exception _ | Tstr_module _ | Tstr_recmodule _
353353+ | Tstr_modtype _ | Tstr_open _ | Tstr_class _ | Tstr_class_type _
354354+ | Tstr_include _ | Tstr_attribute _ -> ());
355355+ default_iterator.structure_item sub str_item)
356356+}
357357+358358+let index_declarations binary_annots =
359359+ let index : item_declaration Types.Uid.Tbl.t = Types.Uid.Tbl.create 16 in
360360+ let f uid fragment = Types.Uid.Tbl.add index uid fragment in
361361+ iter_on_annots (iter_on_declarations ~f) binary_annots;
362362+ index
363363+364364+let index_occurrences binary_annots =
365365+ let index : (Longident.t Location.loc * Shape_reduce.result) list ref =
366366+ ref []
367367+ in
368368+ let f ~namespace env path lid =
369369+ let not_ghost { Location.loc = { loc_ghost; _ }; _ } = not loc_ghost in
370370+ if not_ghost lid then
371371+ match Env.shape_of_path ~namespace env path with
372372+ | exception Not_found -> ()
373373+ | { uid = Some (Predef _); _ } -> ()
374374+ | path_shape ->
375375+ let result = Shape_reduce.local_reduce_for_uid env path_shape in
376376+ index := (lid, result) :: !index
377377+ in
378378+ iter_on_annots (iter_on_occurrences ~f) binary_annots;
379379+ !index
380380+106381exception Error of error
107382108383let input_cmt ic = (input_value ic : cmt_infos)
···175450 | Some cmi -> Some (output_cmi temp_file_name oc cmi)
176451 in
177452 let sourcefile = Unit_info.Artifact.source_file target in
453453+ let cmt_ident_occurrences =
454454+ if !Clflags.store_occurrences then
455455+ index_occurrences binary_annots
456456+ else
457457+ []
458458+ in
459459+ let cmt_annots = clear_env binary_annots in
460460+ let cmt_uid_to_decl = index_declarations cmt_annots in
178461 let source_digest = Option.map Digest.file sourcefile in
179462 let cmt = {
180463 cmt_modname = Unit_info.Artifact.modname target;
181181- cmt_annots = clear_env binary_annots;
464464+ cmt_annots;
182465 cmt_value_dependencies = !value_deps;
183466 cmt_comments = Lexer.comments ();
184467 cmt_args = Sys.argv;
···191474 cmt_imports = List.sort compare (Env.imports ());
192475 cmt_interface_digest = this_crc;
193476 cmt_use_summaries = need_to_clear_env;
194194- cmt_uid_to_loc = Env.get_uid_to_loc_tbl ();
477477+ cmt_uid_to_decl;
195478 cmt_impl_shape = shape;
479479+ cmt_ident_occurrences;
196480 } in
197481 output_cmt oc cmt)
198482 end;
···212212 | Tpat_any
213213 | Tpat_var _ ->
214214 p
215215- | Tpat_alias (q, id, s) ->
216216- { p with pat_desc = Tpat_alias (simpl_under_orpat q, id, s) }
215215+ | Tpat_alias (q, id, s, uid) ->
216216+ { p with pat_desc = Tpat_alias (simpl_under_orpat q, id, s, uid) }
217217 | Tpat_or (p1, p2, o) ->
218218 let p1, p2 = (simpl_under_orpat p1, simpl_under_orpat p2) in
219219 if le_pat p1 p2 then
···236236 in
237237 match p.pat_desc with
238238 | `Any -> stop p `Any
239239- | `Var (id, s) -> continue p (`Alias (Patterns.omega, id, s))
240240- | `Alias (p, id, _) ->
239239+ | `Var (id, s, uid) -> continue p (`Alias (Patterns.omega, id, s, uid))
240240+ | `Alias (p, id, _, _) ->
241241 aux
242242 ( (General.view p, patl),
243243 bind_alias p id ~arg ~action )
···331331 match p.pat_desc with
332332 | `Or (p1, p2, _) ->
333333 split_explode p1 aliases (split_explode p2 aliases rem)
334334- | `Alias (p, id, _) -> split_explode p (id :: aliases) rem
335335- | `Var (id, str) ->
334334+ | `Alias (p, id, _, _) -> split_explode p (id :: aliases) rem
335335+ | `Var (id, str, uid) ->
336336 explode
337337- { p with pat_desc = `Alias (Patterns.omega, id, str) }
337337+ { p with pat_desc = `Alias (Patterns.omega, id, str, uid) }
338338 aliases rem
339339 | #view as view ->
340340 (* We are doing two things here:
···585585 match p.pat_desc with
586586 | `Or (p1, p2, _) ->
587587 filter_rec ((left, p1, right) :: (left, p2, right) :: rem)
588588- | `Alias (p, _, _) -> filter_rec ((left, p, right) :: rem)
588588+ | `Alias (p, _, _, _) -> filter_rec ((left, p, right) :: rem)
589589 | `Var _ -> filter_rec ((left, Patterns.omega, right) :: rem)
590590 | #Simple.view as view -> (
591591 let p = { p with pat_desc = view } in
···635635 | Tpat_tuple args -> args :: k
636636 | Tpat_or (p1, p2, _) ->
637637 flatten_pat_line size p1 (flatten_pat_line size p2 k)
638638- | Tpat_alias (p, _, _) ->
638638+ | Tpat_alias (p, _, _, _) ->
639639 (* Note: we are only called from flatten_matrix,
640640 which is itself only ever used in places
641641 where variables do not matter (default environments,
···713713 | (p, ps) :: rem -> (
714714 let p = General.view p in
715715 match p.pat_desc with
716716- | `Alias (p, _, _) -> filter_rec ((p, ps) :: rem)
716716+ | `Alias (p, _, _, _) -> filter_rec ((p, ps) :: rem)
717717 | `Var _ -> filter_rec ((Patterns.omega, ps) :: rem)
718718 | `Or (p1, p2, _) -> filter_rec_or p1 p2 ps rem
719719 | #Simple.view as view -> (
···12511251 | Tpat_any
12521252 | Tpat_var _ ->
12531253 true
12541254- | Tpat_alias (p, _, _) -> omega_like p
12541254+ | Tpat_alias (p, _, _, _) -> omega_like p
12551255 | Tpat_or (p1, p2, _) -> omega_like p1 || omega_like p2
12561256 | _ -> false
12571257···16451645 (* variables bound in the or-pattern
16461646 that are used in the orpm actions *)
16471647 Typedtree.pat_bound_idents_full orp
16481648- |> List.filter (fun (id, _, _) -> Ident.Set.mem id pm_fv)
16491649- |> List.map (fun (id, _, ty) ->
16481648+ |> List.filter (fun (id, _, _, _) -> Ident.Set.mem id pm_fv)
16491649+ |> List.map (fun (id, _, ty, _) ->
16501650 (id, Typeopt.value_kind orp.pat_env ty))
16511651 in
16521652 let or_num = next_raise_count () in
···33513351let rec name_pattern default = function
33523352 | ((pat, _), _) :: rem -> (
33533353 match pat.pat_desc with
33543354- | Tpat_var (id, _) -> id
33553355- | Tpat_alias (_, id, _) -> id
33543354+ | Tpat_var (id, _, _) -> id
33553355+ | Tpat_alias (_, id, _, _) -> id
33563356 | _ -> name_pattern default rem
33573357 )
33583358 | _ -> Ident.create_local default
···38583858 (* This eliminates a useless variable (and stack slot in bytecode)
38593859 for "let _ = ...". See #6865. *)
38603860 Lsequence (param, body)
38613861- | Tpat_var (id, _) | Tpat_alias ({ pat_desc = Tpat_any }, id, _) ->
38613861+ | Tpat_var (id, _, _) | Tpat_alias ({ pat_desc = Tpat_any }, id, _, _) ->
38623862 (* Fast path, and keep track of simple bindings to unboxable numbers.
3863386338643864 Note: the (Tpat_alias (Tpat_any, id)) case needs to be
···38743874 let catch_ids = pat_bound_idents_full pat in
38753875 let ids_with_kinds =
38763876 List.map
38773877- (fun (id, _, typ) -> (id, Typeopt.value_kind pat.pat_env typ))
38773877+ (fun (id, _, typ, _) -> (id, Typeopt.value_kind pat.pat_env typ))
38783878 catch_ids
38793879 in
38803880- let ids = List.map (fun (id, _, _) -> id) catch_ids in
38803880+ let ids = List.map (fun (id, _, _, _) -> id) catch_ids in
38813881 let bind =
38823882 map_return (assign_pat ~scopes opt nraise ids loc pat) param in
38833883 if !opt then
+2-2
lambda/translclass.ml
···124124125125let name_pattern default p =
126126 match p.pat_desc with
127127- | Tpat_var (id, _) -> id
128128- | Tpat_alias(_, id, _) -> id
127127+ | Tpat_var (id, _, _) -> id
128128+ | Tpat_alias(_, id, _, _) -> id
129129 | _ -> Ident.create_local default
130130131131let rec build_object_init ~scopes cl_table obj params inh_init obj_init cl =
+6-6
lambda/translcore.ml
···157157158158let rec iter_exn_names f pat =
159159 match pat.pat_desc with
160160- | Tpat_var (id, _) -> f id
161161- | Tpat_alias (p, id, _) ->
160160+ | Tpat_var (id, _, _) -> f id
161161+ | Tpat_alias (p, id, _, _) ->
162162 f id;
163163 iter_exn_names f p
164164 | _ -> ()
···927927 let idlist =
928928 List.map
929929 (fun {vb_pat=pat} -> match pat.pat_desc with
930930- Tpat_var (id,_) -> id
931931- | Tpat_alias ({pat_desc=Tpat_any}, id,_) -> id
930930+ Tpat_var (id,_,_) -> id
931931+ | Tpat_alias ({pat_desc=Tpat_any}, id,_,_) -> id
932932 | _ -> assert false)
933933 pat_expr_list in
934934 let transl_case {vb_expr=expr; vb_attributes; vb_rec_kind = rkind;
···10691069 (* Simplif doesn't like it if binders are not uniq, so we make sure to
10701070 use different names in the value and the exception branches. *)
10711071 let ids_full = Typedtree.pat_bound_idents_full pv in
10721072- let ids = List.map (fun (id, _, _) -> id) ids_full in
10721072+ let ids = List.map (fun (id, _, _, _) -> id) ids_full in
10731073 let ids_kinds =
10741074- List.map (fun (id, _, ty) -> id, Typeopt.value_kind pv.pat_env ty)
10741074+ List.map (fun (id, _, ty, _) -> id, Typeopt.value_kind pv.pat_env ty)
10751075 ids_full
10761076 in
10771077 let vids = List.map Ident.rename ids in
+7-7
ocamldoc/odoc_ast.ml
···50505151 let iter_val_pattern = function
5252 | Typedtree.Tpat_any -> None
5353- | Typedtree.Tpat_var (name, _)
5454- | Typedtree.Tpat_alias (_, name, _) -> Some (Name.from_ident name)
5353+ | Typedtree.Tpat_var (name, _, _)
5454+ | Typedtree.Tpat_alias (_, name, _, _) -> Some (Name.from_ident name)
5555 | Typedtree.Tpat_tuple _ -> None (* FIXME when we will handle tuples *)
5656 | _ -> None
5757···251251 let tt_param_info_from_pattern env f_desc pat =
252252 let rec iter_pattern pat =
253253 match pat.pat_desc with
254254- Typedtree.Tpat_var (ident, _) ->
254254+ Typedtree.Tpat_var (ident, _, _) ->
255255 let name = Name.from_ident ident in
256256 Simple_name { sn_name = name ;
257257 sn_text = f_desc name ;
258258 sn_type = Odoc_env.subst_type env pat.pat_type
259259 }
260260261261- | Typedtree.Tpat_alias (pat, _, _) ->
261261+ | Typedtree.Tpat_alias (pat, _, _, _) ->
262262 iter_pattern pat
263263264264 | Typedtree.Tpat_tuple patlist ->
···334334 let (pat, exp) = pat_exp in
335335 let comment_opt = Odoc_sig.analyze_alerts comment_opt attrs in
336336 match pat.pat_desc with
337337- | Tpat_var (ident, _) | Tpat_alias (_, ident, _) ->
337337+ | Tpat_var (ident, _, _) | Tpat_alias (_, ident, _, _) ->
338338 begin match exp.exp_desc with
339339 | Texp_function (params, body) ->
340340···673673 a default value. In this case, we look for the good parameter pattern *)
674674 let (parameter, next_tt_class_exp) =
675675 match pat.Typedtree.pat_desc with
676676- Typedtree.Tpat_var (ident, _) when Name.from_ident ident = "*opt*" ->
676676+ Typedtree.Tpat_var (ident, _, _) when Name.from_ident ident = "*opt*" ->
677677 (
678678 (* there must be a Tcl_let just after *)
679679 match tt_class_expr2.Typedtree.cl_desc with
680680- Typedtree.Tcl_let (_, {vb_pat={pat_desc = Typedtree.Tpat_var (id,_) };
680680+ Typedtree.Tcl_let (_, {vb_pat={pat_desc = Typedtree.Tpat_var (id,_,_) };
681681 vb_expr=exp} :: _, _, tt_class_expr3) ->
682682 let name = Name.from_ident id in
683683 let new_param = Simple_name
···11+(* TEST
22+33+flags = "-bin-annot -bin-annot-occurrences";
44+compile_only = "true";
55+readonly_files = "auxiliaire.ml";
66+setup-ocamlc.byte-build-env;
77+all_modules = "auxiliaire.ml index.ml";
88+ocamlc.byte;
99+check-ocamlc.byte-output;
1010+1111+program = "-quiet -index -decls index.cmt";
1212+output = "out_objinfo";
1313+ocamlobjinfo;
1414+1515+check-program-output;
1616+*)
1717+1818+module type AS = sig
1919+ type t
2020+ val x : t
2121+end
2222+2323+module A = struct
2424+ type t = int
2525+ let (x : t) = 42
2626+end
2727+2828+module B = A
2929+3030+module C : sig
3131+ open A
3232+ val c : t
3333+end = struct
3434+ include A
3535+ let c = 42
3636+end
3737+3838+open A
3939+4040+let y = A.x + Auxiliaire.z
4141+4242+let () = print_int y
4343+4444+let a = (module A : AS)
4545+module _ = (val a)
4646+4747+module F (P : AS) = struct include P end
4848+module G = F (A)
4949+type u = F (A).t;; (* FIXME F and A are missing*)
5050+5151+module type MS = sig
5252+ module type MT
5353+ module M : AS
5454+ module X = A
5555+ type u
5656+end
5757+module type MSA = MS with
5858+ module M = A (* M, MT and u are missing *)
5959+ and module type MT = AS
6060+ and type u = B.t
6161+6262+let () = match 4 with
6363+ | A.(0) | _ -> ()
6464+6565+module type MSB = sig
6666+ type u
6767+ include AS with type t := u
6868+ module G := A
6969+end
+63
testsuite/tests/shape-index/index.reference
···11+Indexed shapes:
22+Resolved: Index.5 : A (File "index.ml", line 68, characters 14-15)
33+Resolved: Index.25 : u (File "index.ml", line 67, characters 28-29)
44+Resolved: Index.2 : AS (File "index.ml", line 67, characters 10-12)
55+Resolved: Index.5 : A (File "index.ml", line 63, characters 4-5)
66+Resolved: Index.3 : B.t (File "index.ml", line 60, characters 15-18)
77+Resolved: Index.2 : AS (File "index.ml", line 59, characters 23-25)
88+Resolved: Index.21 : MS (File "index.ml", line 57, characters 18-20)
99+Resolved: Index.5 : A (File "index.ml", line 58, characters 13-14)
1010+Resolved: Index.5 : A (File "index.ml", line 54, characters 13-14)
1111+Resolved: Index.2 : AS (File "index.ml", line 53, characters 13-15)
1212+Resolved: Index.3 : F(A).t (File "index.ml", line 49, characters 9-16)
1313+Resolved: Index.5 : A (File "index.ml", line 48, characters 14-15)
1414+Resolved: Index.14 : F (File "index.ml", line 48, characters 11-12)
1515+Resolved: Index.13 : P (File "index.ml", line 47, characters 35-36)
1616+Resolved: Index.2 : AS (File "index.ml", line 47, characters 14-16)
1717+Resolved: Index.11 : a (File "index.ml", line 45, characters 16-17)
1818+Resolved: Index.5 : A (File "index.ml", line 44, characters 16-17)
1919+Resolved: Index.2 : AS (File "index.ml", line 44, characters 20-22)
2020+Resolved: Index.10 : y (File "index.ml", line 42, characters 19-20)
2121+Unresolved: CU Stdlib . "print_int"[value] :
2222+ print_int (File "index.ml", line 42, characters 9-18)
2323+Unresolved: CU Auxiliaire . "z"[value] :
2424+ Auxiliaire.z (File "index.ml", line 40, characters 14-26)
2525+Resolved: Index.4 : A.x (File "index.ml", line 40, characters 8-11)
2626+Unresolved: CU Stdlib . "+"[value] :
2727+ (+) (File "index.ml", line 40, characters 12-13)
2828+Resolved: Index.5 : A (File "index.ml", line 38, characters 5-6)
2929+Resolved: Index.3 : t (File "index.ml", line 32, characters 10-11)
3030+Resolved: Index.5 : A (File "index.ml", line 31, characters 7-8)
3131+Resolved: Index.5 : A (File "index.ml", line 34, characters 10-11)
3232+Resolved: Index.5 : A (File "index.ml", line 28, characters 11-12)
3333+Resolved: Index.3 : t (File "index.ml", line 25, characters 11-12)
3434+Resolved: Index.0 : t (File "index.ml", line 20, characters 10-11)
3535+3636+Uid of decls:
3737+Index.10: y (File "index.ml", line 40, characters 4-5)
3838+Index.21: MS (File "index.ml", line 51, characters 12-14)
3939+Index.5: A (File "index.ml", line 23, characters 7-8)
4040+Index.15: G (File "index.ml", line 48, characters 7-8)
4141+Index.0: t (File "index.ml", line 19, characters 7-8)
4242+Index.28: MSB (File "index.ml", line 65, characters 12-15)
4343+Index.3: t (File "index.ml", line 24, characters 7-8)
4444+Index.17: MT (File "index.ml", line 52, characters 14-16)
4545+Index.11: a (File "index.ml", line 44, characters 4-5)
4646+Index.25: u (File "index.ml", line 66, characters 7-8)
4747+Index.24: MSA (File "index.ml", line 57, characters 12-15)
4848+Index.1: x (File "index.ml", line 20, characters 6-7)
4949+Index.16: u (File "index.ml", line 49, characters 5-6)
5050+Index.8: c (File "index.ml", line 32, characters 6-7)
5151+Index.9: C (File "index.ml", line 30, characters 7-8)
5252+Index.23: u (File "index.ml", line 60, characters 11-12)
5353+Index.14: F (File "index.ml", line 47, characters 7-8)
5454+Index.12: _ (File "index.ml", line 45, characters 7-8)
5555+Index.27: G (File "index.ml", line 68, characters 9-10)
5656+Index.20: u (File "index.ml", line 55, characters 7-8)
5757+Index.26: t (File "index.ml", line 67, characters 23-24)
5858+Index.19: X (File "index.ml", line 54, characters 9-10)
5959+Index.6: B (File "index.ml", line 28, characters 7-8)
6060+Index.4: x (File "index.ml", line 25, characters 7-8)
6161+Index.18: M (File "index.ml", line 53, characters 9-10)
6262+Index.7: c (File "index.ml", line 35, characters 6-7)
6363+Index.2: AS (File "index.ml", line 18, characters 12-14)
+29
testsuite/tests/shape-index/index_aliases.ml
···11+(* TEST
22+33+flags = "-bin-annot -bin-annot-occurrences";
44+compile_only = "true";
55+setup-ocamlc.byte-build-env;
66+all_modules = "index_aliases.ml";
77+ocamlc.byte;
88+check-ocamlc.byte-output;
99+1010+program = "-quiet -index -decls index_aliases.cmt";
1111+output = "out_objinfo";
1212+ocamlobjinfo;
1313+1414+check-program-output;
1515+*)
1616+1717+1818+module A = struct type t end
1919+module B = A
2020+2121+module F (X : sig type t end) = X
2222+module F' = F
2323+module C = F'(A)
2424+2525+module C' = F(B)
2626+module D = C
2727+2828+module G = B
2929+include G
···11+Indexed shapes:
22+Resolved_alias: Index_aliases.10 -> Index_aliases.2 -> Index_aliases.1 :
33+ G (File "index_aliases.ml", line 29, characters 8-9)
44+Resolved_alias: Index_aliases.2 -> Index_aliases.1 :
55+ B (File "index_aliases.ml", line 28, characters 11-12)
66+Resolved: Index_aliases.7 :
77+ C (File "index_aliases.ml", line 26, characters 11-12)
88+Resolved_alias: Index_aliases.2 -> Index_aliases.1 :
99+ B (File "index_aliases.ml", line 25, characters 14-15)
1010+Resolved: Index_aliases.5 :
1111+ F (File "index_aliases.ml", line 25, characters 12-13)
1212+Resolved: Index_aliases.1 :
1313+ A (File "index_aliases.ml", line 23, characters 14-15)
1414+Resolved_alias: Index_aliases.6 -> Index_aliases.5 :
1515+ F' (File "index_aliases.ml", line 23, characters 11-13)
1616+Resolved: Index_aliases.5 :
1717+ F (File "index_aliases.ml", line 22, characters 12-13)
1818+Resolved: Index_aliases.4 :
1919+ X (File "index_aliases.ml", line 21, characters 32-33)
2020+Resolved: Index_aliases.1 :
2121+ A (File "index_aliases.ml", line 19, characters 11-12)
2222+2323+Uid of decls:
2424+Index_aliases.1: A (File "index_aliases.ml", line 18, characters 7-8)
2525+Index_aliases.2: B (File "index_aliases.ml", line 19, characters 7-8)
2626+Index_aliases.5: F (File "index_aliases.ml", line 21, characters 7-8)
2727+Index_aliases.7: C (File "index_aliases.ml", line 23, characters 7-8)
2828+Index_aliases.9: D (File "index_aliases.ml", line 26, characters 7-8)
2929+Index_aliases.8: C' (File "index_aliases.ml", line 25, characters 7-9)
3030+Index_aliases.10: G (File "index_aliases.ml", line 28, characters 7-8)
3131+Index_aliases.6: F' (File "index_aliases.ml", line 22, characters 7-9)
3232+Index_aliases.3: t (File "index_aliases.ml", line 21, characters 23-24)
3333+Index_aliases.0: t (File "index_aliases.ml", line 18, characters 23-24)
+30
testsuite/tests/shape-index/index_bindingops.ml
···11+(* TEST
22+33+flags = "-bin-annot -bin-annot-occurrences";
44+compile_only = "true";
55+setup-ocamlc.byte-build-env;
66+all_modules = "index_bindingops.ml";
77+ocamlc.byte;
88+check-ocamlc.byte-output;
99+1010+program = "-quiet -index -decls index_bindingops.cmt";
1111+output = "out_objinfo";
1212+ocamlobjinfo;
1313+1414+check-program-output;
1515+*)
1616+1717+let (let+) x f = Option.map f x
1818+1919+let (and+) x y =
2020+ Option.bind x @@ fun x ->
2121+ Option.map (fun y -> (x, y)) y
2222+2323+let minus_three =
2424+ let+ foo = None
2525+ and+ bar = None
2626+ and+ man = None in
2727+ foo + bar - man
2828+2929+let _ = (let+)
3030+let _ = (and+)
···11+Indexed shapes:
22+Resolved: Index_labels.2 :
33+ b (File "index_labels.ml", line 26, characters 14-15)
44+Resolved: Index_labels.1 :
55+ a (File "index_labels.ml", line 26, characters 6-7)
66+Resolved: Index_labels.3 :
77+ x (File "index_labels.ml", line 23, characters 2-3)
88+Resolved: Index_labels.1 :
99+ a (File "index_labels.ml", line 23, characters 4-5)
1010+Resolved: Index_labels.3 :
1111+ x (File "index_labels.ml", line 22, characters 2-3)
1212+Resolved: Index_labels.1 :
1313+ a (File "index_labels.ml", line 22, characters 4-5)
1414+Resolved: Index_labels.2 :
1515+ b (File "index_labels.ml", line 20, characters 18-19)
1616+Resolved: Index_labels.1 :
1717+ a (File "index_labels.ml", line 20, characters 10-11)
1818+1919+Uid of decls:
2020+Index_labels.5: f (File "index_labels.ml", line 25, characters 4-5)
2121+Index_labels.2: b (File "index_labels.ml", line 18, characters 27-28)
2222+Index_labels.3: x (File "index_labels.ml", line 20, characters 4-5)
2323+Index_labels.1: a (File "index_labels.ml", line 18, characters 19-20)
2424+Index_labels.4: _y (File "index_labels.ml", line 21, characters 4-6)
2525+Index_labels.0: t (File "index_labels.ml", line 18, characters 5-6)
+22
testsuite/tests/shape-index/index_modules.ml
···11+(* TEST
22+33+flags = "-bin-annot -bin-annot-occurrences";
44+compile_only = "true";
55+setup-ocamlc.byte-build-env;
66+all_modules = "index_modules.ml";
77+ocamlc.byte;
88+check-ocamlc.byte-output;
99+1010+program = "-quiet -index -decls index_modules.cmt";
1111+output = "out_objinfo";
1212+ocamlobjinfo;
1313+1414+check-program-output;
1515+*)
1616+1717+(* Local modules: *)
1818+1919+let () =
2020+ let module A = struct let x = 42 end in
2121+ let open A in
2222+ print_int (x + A.x)
···11+Indexed shapes:
22+Resolved: Index_objects.21 :
33+ ins (File "index_objects.ml", line 48, characters 21-24)
44+Resolved: Index_objects.28 :
55+ self (File "index_objects.ml", line 47, characters 20-24)
66+Resolved: Index_objects.26 :
77+ i (File "index_objects.ml", line 46, characters 28-29)
88+Resolved: Index_objects.21 :
99+ ins (File "index_objects.ml", line 46, characters 21-24)
1010+Resolved: Index_objects.21 :
1111+ ins (File "index_objects.ml", line 45, characters 22-25)
1212+Resolved: Index_objects.13 :
1313+ ct (File "index_objects.ml", line 40, characters 28-30)
1414+Resolved: Index_objects.5 :
1515+ c (File "index_objects.ml", line 32, characters 10-11)
1616+Resolved: Index_objects.5 :
1717+ c (File "index_objects.ml", line 29, characters 8-9)
1818+Resolved: Index_objects.5 :
1919+ c (File "index_objects.ml", line 29, characters 16-17)
2020+Resolved: Index_objects.5 :
2121+ c (File "index_objects.ml", line 29, characters 8-9)
2222+Resolved: Index_objects.0 :
2323+ o (File "index_objects.ml", line 23, characters 9-10)
2424+2525+Uid of decls:
2626+Index_objects.10: d (File "index_objects.ml", line 31, characters 6-7)
2727+Index_objects.15: M (File "index_objects.ml", line 35, characters 12-13)
2828+Index_objects.14: dt (File "index_objects.ml", line 40, characters 8-10)
2929+Index_objects.5: c (File "index_objects.ml", line 25, characters 6-7)
3030+Index_objects.0: o (File "index_objects.ml", line 18, characters 4-5)
3131+Index_objects.16: ins_var (File "index_objects.ml", line 43, characters 6-13)
3232+Index_objects.13: ct (File "index_objects.ml", line 36, characters 8-10)
+41
testsuite/tests/shape-index/index_types.ml
···11+(* TEST
22+33+flags = "-bin-annot -bin-annot-occurrences";
44+compile_only = "true";
55+readonly_files = "index_types.ml";
66+setup-ocamlc.byte-build-env;
77+all_modules = "index_types.ml";
88+ocamlc.byte;
99+check-ocamlc.byte-output;
1010+1111+program = "-quiet -index -decls index_types.cmt";
1212+output = "out_objinfo";
1313+ocamlobjinfo;
1414+1515+check-program-output;
1616+*)
1717+1818+type t = int
1919+2020+let x : t = 42
2121+2222+module M = struct end
2323+2424+let () = match 4 with
2525+ | (_ : t) -> ()
2626+2727+type poly = [`A|`B]
2828+2929+let () = match `A with #poly -> ()
3030+3131+module type S = sig
3232+ type t2 = ..
3333+ type t2 += B
3434+end
3535+3636+type t1 = ..
3737+type t1 += B
3838+3939+(* 5.2 local open for types *)
4040+module N = struct type t end
4141+type u = N.(t)
+26
testsuite/tests/shape-index/index_types.reference
···11+Indexed shapes:
22+Resolved: Index_types.9 :
33+ t (File "index_types.ml", line 41, characters 12-13)
44+Resolved: Index_types.10 :
55+ N (File "index_types.ml", line 41, characters 9-10)
66+Resolved: Index_types.7 : t1 (File "index_types.ml", line 37, characters 5-7)
77+Resolved: Index_types.4 : t2 (File "index_types.ml", line 33, characters 7-9)
88+Resolved: Index_types.3 :
99+ poly (File "index_types.ml", line 29, characters 24-28)
1010+Resolved: Index_types.0 : t (File "index_types.ml", line 25, characters 9-10)
1111+Resolved: Index_types.0 : t (File "index_types.ml", line 20, characters 8-9)
1212+Resolved: Index_types.0 : t (File "index_types.ml", line 20, characters 8-9)
1313+1414+Uid of decls:
1515+Index_types.11: u (File "index_types.ml", line 41, characters 5-6)
1616+Index_types.3: poly (File "index_types.ml", line 27, characters 5-9)
1717+Index_types.2: M (File "index_types.ml", line 22, characters 7-8)
1818+Index_types.6: S (File "index_types.ml", line 31, characters 12-13)
1919+Index_types.10: N (File "index_types.ml", line 40, characters 7-8)
2020+Index_types.5: B (File "index_types.ml", line 33, characters 13-14)
2121+Index_types.9: t (File "index_types.ml", line 40, characters 23-24)
2222+Index_types.4: t2 (File "index_types.ml", line 32, characters 7-9)
2323+Index_types.1: x (File "index_types.ml", line 20, characters 4-5)
2424+Index_types.8: B (File "index_types.ml", line 37, characters 11-12)
2525+Index_types.0: t (File "index_types.ml", line 18, characters 5-6)
2626+Index_types.7: t1 (File "index_types.ml", line 36, characters 5-7)
+22
testsuite/tests/shape-index/index_vb.ml
···11+(* TEST
22+33+flags = "-bin-annot -bin-annot-occurrences";
44+compile_only = "true";
55+readonly_files = "index_vb.ml";
66+setup-ocamlc.byte-build-env;
77+all_modules = "index_vb.ml";
88+ocamlc.byte;
99+check-ocamlc.byte-output;
1010+1111+program = "-quiet -index -decls index_vb.cmt";
1212+output = "out_objinfo";
1313+ocamlobjinfo;
1414+1515+check-program-output;
1616+*)
1717+1818+type t = { a : int; b : string * int }
1919+2020+let { a; b = (c, d) } = { a = 42; b = ("", 4) }
2121+2222+let () = print_int (a + d * (int_of_string c))
+24
testsuite/tests/shape-index/index_vb.reference
···11+Indexed shapes:
22+Resolved: Index_vb.4 : c (File "index_vb.ml", line 22, characters 43-44)
33+Unresolved: CU Stdlib . "int_of_string"[value] :
44+ int_of_string (File "index_vb.ml", line 22, characters 29-42)
55+Resolved: Index_vb.5 : d (File "index_vb.ml", line 22, characters 24-25)
66+Unresolved: CU Stdlib . "*"[value] : ( *
77+ ) (File "index_vb.ml", line 22, characters 26-27)
88+Resolved: Index_vb.3 : a (File "index_vb.ml", line 22, characters 20-21)
99+Unresolved: CU Stdlib . "+"[value] :
1010+ (+) (File "index_vb.ml", line 22, characters 22-23)
1111+Unresolved: CU Stdlib . "print_int"[value] :
1212+ print_int (File "index_vb.ml", line 22, characters 9-18)
1313+Resolved: Index_vb.2 : b (File "index_vb.ml", line 20, characters 34-35)
1414+Resolved: Index_vb.1 : a (File "index_vb.ml", line 20, characters 26-27)
1515+Resolved: Index_vb.2 : b (File "index_vb.ml", line 20, characters 9-10)
1616+Resolved: Index_vb.1 : a (File "index_vb.ml", line 20, characters 6-7)
1717+1818+Uid of decls:
1919+Index_vb.3: a (File "index_vb.ml", line 20, characters 6-7)
2020+Index_vb.1: a (File "index_vb.ml", line 18, characters 11-12)
2121+Index_vb.0: t (File "index_vb.ml", line 18, characters 5-6)
2222+Index_vb.2: b (File "index_vb.ml", line 18, characters 20-21)
2323+Index_vb.5: a (File "index_vb.ml", line 20, characters 6-7)
2424+Index_vb.4: a (File "index_vb.ml", line 20, characters 6-7)
+127
testsuite/tests/shapes/aliases.ml
···11+(* TEST
22+ flags = "-dshape";
33+ expect;
44+*)
55+66+module A = struct type t end
77+module B = A
88+[%%expect{|
99+{
1010+ "A"[module] -> {<.1>
1111+ "t"[type] -> <.0>;
1212+ };
1313+ }
1414+module A : sig type t end
1515+{
1616+ "B"[module] -> Alias(<.2>
1717+ {<.1>
1818+ "t"[type] -> <.0>;
1919+ });
2020+ }
2121+module B = A
2222+|}]
2323+2424+type u = B.t
2525+2626+[%%expect{|
2727+{
2828+ "u"[type] -> <.3>;
2929+ }
3030+type u = B.t
3131+|}]
3232+3333+module F (X : sig type t end) = X
3434+module F' = F
3535+[%%expect{|
3636+{
3737+ "F"[module] -> Abs<.6>(X, X<.5>);
3838+ }
3939+module F : functor (X : sig type t end) -> sig type t = X.t end
4040+{
4141+ "F'"[module] -> Alias(<.7>
4242+ Abs<.6>(X, X<.5>));
4343+ }
4444+module F' = F
4545+|}]
4646+4747+module C = F'(A)
4848+[%%expect{|
4949+{
5050+ "C"[module] -> {<.8>
5151+ "t"[type] -> <.0>;
5252+ };
5353+ }
5454+module C : sig type t = A.t end
5555+|}]
5656+5757+5858+module C = F(B)
5959+6060+[%%expect{|
6161+{
6262+ "C"[module] -> Alias(<.9>
6363+ {<.1>
6464+ "t"[type] -> <.0>;
6565+ });
6666+ }
6767+module C : sig type t = B.t end
6868+|}]
6969+7070+module D = C
7171+7272+[%%expect{|
7373+{
7474+ "D"[module] -> Alias(<.10>
7575+ Alias(<.9>
7676+ {<.1>
7777+ "t"[type] -> <.0>;
7878+ }));
7979+ }
8080+module D = C
8181+|}]
8282+8383+module G (X : sig type t end) = struct include X end
8484+[%%expect{|
8585+{
8686+ "G"[module] -> Abs<.13>(X, {
8787+ "t"[type] -> X<.12> . "t"[type];
8888+ });
8989+ }
9090+module G : functor (X : sig type t end) -> sig type t = X.t end
9191+|}]
9292+9393+module E = G(B)
9494+[%%expect{|
9595+{
9696+ "E"[module] -> {<.14>
9797+ "t"[type] -> <.0>;
9898+ };
9999+ }
100100+module E : sig type t = B.t end
101101+|}]
102102+103103+module M = struct type t let x = 1 end
104104+module N : sig type t end = M
105105+module O = N
106106+[%%expect{|
107107+{
108108+ "M"[module] -> {<.17>
109109+ "t"[type] -> <.15>;
110110+ "x"[value] -> <.16>;
111111+ };
112112+ }
113113+module M : sig type t val x : int end
114114+{
115115+ "N"[module] -> {<.19>
116116+ "t"[type] -> <.15>;
117117+ };
118118+ }
119119+module N : sig type t end
120120+{
121121+ "O"[module] -> Alias(<.20>
122122+ {<.19>
123123+ "t"[type] -> <.15>;
124124+ });
125125+ }
126126+module O = N
127127+|}]
+9-5
testsuite/tests/shapes/comp_units.ml
···99module Mdirect = Stdlib__Unit
1010[%%expect{|
1111{
1212- "Mdirect"[module] -> CU Stdlib__Unit;
1212+ "Mdirect"[module] -> Alias(<.0>
1313+ CU Stdlib__Unit);
1314 }
1415module Mdirect = Unit
1516|}]
···1718module Mproj = Stdlib.Unit
1819[%%expect{|
1920{
2020- "Mproj"[module] -> (CU Stdlib . "Unit"[module])<.1>;
2121+ "Mproj"[module] -> Alias(<.1>
2222+ CU Stdlib . "Unit"[module]);
2123 }
2224module Mproj = Unit
2325|}]
···2527module F (X : sig type t end) = X
2628[%%expect{|
2729{
2828- "F"[module] -> Abs<.4>(X/280, X/280<.3>);
3030+ "F"[module] -> Abs<.4>(X, X<.3>);
2931 }
3032module F : functor (X : sig type t end) -> sig type t = X.t end
3133|}]
···4951module App_direct_indir = F (Mdirect)
5052[%%expect{|
5153{
5252- "App_direct_indir"[module] -> CU Stdlib__Unit;
5454+ "App_direct_indir"[module] -> Alias(<.7>
5555+ CU Stdlib__Unit);
5356 }
5457module App_direct_indir : sig type t = Mdirect.t end
5558|}]
···5760module App_proj_indir = F (Mproj)
5861[%%expect{|
5962{
6060- "App_proj_indir"[module] -> (CU Stdlib . "Unit"[module])<.1>;
6363+ "App_proj_indir"[module] -> Alias(<.8>
6464+ CU Stdlib . "Unit"[module]);
6165 }
6266module App_proj_indir : sig type t = Mproj.t end
6367|}]
···1414[%%expect{|
1515{
1616 "Foo"[module] -> {<.2>
1717- "Bar"[module] -> {<.0>
1818- };
1717+ "Bar"[module] -> {<.0>};
1918 };
2019 }
2120module Foo : sig module Bar : sig end end
···4241[%%expect{|
4342{
4443 "E"[module] -> {<.6>
4545- "Bar"[module] -> {<.5>
4646- };
4444+ "Bar"[module] -> {<.5>};
4745 };
4846 }
4947module E : Extended
+121
testsuite/tests/shapes/more_func.ml
···11+(* TEST
22+ flags = "-dshape";
33+ expect;
44+*)
55+66+module M = struct end (* uid 0 *)
77+module F(X : sig end) = M
88+module App = F(List)
99+[%%expect{|
1010+{
1111+ "M"[module] -> {<.0>};
1212+ }
1313+module M : sig end
1414+{
1515+ "F"[module] -> Abs<.2>(X, {<.0>});
1616+ }
1717+module F : functor (X : sig end) -> sig end
1818+{
1919+ "App"[module] -> {<.3>};
2020+ }
2121+module App : sig end
2222+|}]
2323+2424+2525+module M = struct end (* uid 4 *)
2626+module F(X : sig end) = struct include M type t end
2727+module App = F(List)
2828+[%%expect{|
2929+{
3030+ "M"[module] -> {<.4>};
3131+ }
3232+module M : sig end
3333+{
3434+ "F"[module] -> Abs<.7>(X, {
3535+ "t"[type] -> <.6>;
3636+ });
3737+ }
3838+module F : functor (X : sig end) -> sig type t end
3939+{
4040+ "App"[module] -> {<.8>
4141+ "t"[type] -> <.6>;
4242+ };
4343+ }
4444+module App : sig type t = F(List).t end
4545+|}]
4646+4747+module M = struct end (* uid 9 *)
4848+module F(X : sig end) = X
4949+module App = F(M)
5050+[%%expect{|
5151+{
5252+ "M"[module] -> {<.9>};
5353+ }
5454+module M : sig end
5555+{
5656+ "F"[module] -> Abs<.11>(X, X<.10>);
5757+ }
5858+module F : functor (X : sig end) -> sig end
5959+{
6060+ "App"[module] -> {<.12>};
6161+ }
6262+module App : sig end
6363+|}]
6464+6565+module Id(X : sig end) = X
6666+module Struct = struct
6767+ module L = List
6868+end
6969+[%%expect{|
7070+{
7171+ "Id"[module] -> Abs<.14>(X, X<.13>);
7272+ }
7373+module Id : functor (X : sig end) -> sig end
7474+{
7575+ "Struct"[module] ->
7676+ {<.16>
7777+ "L"[module] -> Alias(<.15>
7878+ CU Stdlib . "List"[module]);
7979+ };
8080+ }
8181+module Struct : sig module L = List end
8282+|}]
8383+8484+module App = Id(List) (* this should have the App uid *)
8585+module Proj = Struct.L
8686+ (* this should have the Proj uid and be an alias to Struct.L *)
8787+[%%expect{|
8888+{
8989+ "App"[module] -> (CU Stdlib . "List"[module])<.17>;
9090+ }
9191+module App : sig end
9292+{
9393+ "Proj"[module] -> Alias(<.18>
9494+ Alias(<.15>
9595+ CU Stdlib . "List"[module]));
9696+ }
9797+module Proj = Struct.L
9898+|}]
9999+100100+module F (X :sig end ) = struct module M = X end
101101+module N = F(struct end)
102102+module O = N.M
103103+[%%expect{|
104104+{
105105+ "F"[module] -> Abs<.21>(X, {
106106+ "M"[module] -> X<.19>;
107107+ });
108108+ }
109109+module F : functor (X : sig end) -> sig module M : sig end end
110110+{
111111+ "N"[module] -> {<.22>
112112+ "M"[module] -> {<.19>};
113113+ };
114114+ }
115115+module N : sig module M : sig end end
116116+{
117117+ "O"[module] -> Alias(<.23>
118118+ {<.19>});
119119+ }
120120+module O = N.M
121121+|}]
+50
testsuite/tests/shapes/nested_types.ml
···11+(* TEST
22+ flags = "-dshape";
33+ expect;
44+*)
55+66+module M : sig
77+88+ exception Exn of { lbl_exn : int }
99+ type l = { lbl : int }
1010+ type ext = ..
1111+ type ext += Ext of { lbl_ext : int }
1212+ type t = C of { lbl_cstr : int }
1313+end = struct
1414+ exception Exn of { lbl_exn : int }
1515+ type l = { lbl : int }
1616+ type ext = ..
1717+ type ext += Ext of { lbl_ext : int }
1818+ type t = C of { lbl_cstr : int }
1919+end
2020+[%%expect{|
2121+{
2222+ "M"[module] ->
2323+ {<.37>
2424+ "Exn"[extension constructor] -> {<.1>
2525+ "lbl_exn"[label] -> <.0>;
2626+ };
2727+ "Ext"[extension constructor] -> {<.7>
2828+ "lbl_ext"[label] -> <.6>;
2929+ };
3030+ "ext"[type] -> <.5>;
3131+ "l"[type] -> {<.3>
3232+ "lbl"[label] -> <.4>;
3333+ };
3434+ "t"[type] ->
3535+ {<.9>
3636+ "C"[constructor] -> {<.11>
3737+ "lbl_cstr"[label] -> <.10>;
3838+ };
3939+ };
4040+ };
4141+ }
4242+module M :
4343+ sig
4444+ exception Exn of { lbl_exn : int; }
4545+ type l = { lbl : int; }
4646+ type ext = ..
4747+ type ext += Ext of { lbl_ext : int; }
4848+ type t = C of { lbl_cstr : int; }
4949+ end
5050+|}]
+1-2
testsuite/tests/shapes/open_arg.ml
···22222323[%%expect{|
2424{
2525- "Make"[module] -> Abs<.3>(I/282, {
2626- });
2525+ "Make"[module] -> Abs<.3>(I, {});
2726 }
2827module Make : functor (I : sig end) -> sig end
2928|}]
+38-18
testsuite/tests/shapes/open_struct.ml
···1111 end
1212end
1313[%%expect{|
1414-{
1515- }
1414+{}
1615module M : sig type t = A end
1716|}]
18171918include M
2019[%%expect{|
2120{
2222- "t"[type] -> <.0>;
2121+ "t"[type] -> {<.0>
2222+ "A"[constructor] -> {<.1>};
2323+ };
2324 }
2425type t = M.t = A
2526|}]
···2728module N = M
2829[%%expect{|
2930{
3030- "N"[module] -> {<.2>
3131- "t"[type] -> <.0>;
3232- };
3131+ "N"[module] ->
3232+ Alias(<.3>
3333+ {<.2>
3434+ "t"[type] -> {<.0>
3535+ "A"[constructor] -> {<.1>};
3636+ };
3737+ });
3338 }
3439module N = M
3540|}]
···4651[%%expect{|
4752{
4853 "M'"[module] -> {<.6>
4949- "t"[type] -> <.4>;
5454+ "t"[type] -> {<.4>
5555+ "A"[constructor] -> {<.5>};
5656+ };
5057 };
5158 }
5259module M' : sig type t = A end
···5562module N' = M'
5663[%%expect{|
5764{
5858- "N'"[module] -> {<.6>
5959- "t"[type] -> <.4>;
6060- };
6565+ "N'"[module] ->
6666+ Alias(<.7>
6767+ {<.6>
6868+ "t"[type] -> {<.4>
6969+ "A"[constructor] -> {<.5>};
7070+ };
7171+ });
6172 }
6273module N' = M'
6374|}]
···6980end
7081[%%expect{|
7182{
7272- "Test"[module] -> {<.11>
7373- "M"[module] -> {<.10>
7474- "t"[type] -> <.8>;
7575- };
8383+ "Test"[module] ->
8484+ {<.11>
8585+ "M"[module] -> {<.10>
8686+ "t"[type] -> {<.8>
8787+ "A"[constructor] -> {<.9>};
8888+ };
7689 };
9090+ };
7791 }
7892module Test : sig module M : sig type t = A end end
7993|}]
···8296[%%expect{|
8397{
8498 "M"[module] -> {<.10>
8585- "t"[type] -> <.8>;
9999+ "t"[type] -> {<.8>
100100+ "A"[constructor] -> {<.9>};
101101+ };
86102 };
87103 }
88104module M = Test.M
···91107module N = M
92108[%%expect{|
93109{
9494- "N"[module] -> {<.10>
9595- "t"[type] -> <.8>;
9696- };
110110+ "N"[module] ->
111111+ Alias(<.12>
112112+ {<.10>
113113+ "t"[type] -> {<.8>
114114+ "A"[constructor] -> {<.9>};
115115+ };
116116+ });
97117 }
98118module N = M
99119|}]
+17-11
testsuite/tests/shapes/recmodules.ml
···1818[%%expect{|
1919{
2020 "A"[module] -> {
2121- "t"[type] -> <.8>;
2121+ "t"[type] -> {<.8>
2222+ "Leaf"[constructor] -> {<.9>};
2323+ };
2224 };
2325 "B"[module] -> {
2426 "t"[type] -> <.10>;
···4345end = B
4446[%%expect{|
4547{
4646- "A"[module] -> A/305<.11>;
4747- "B"[module] -> B/306<.12>;
4848+ "A"[module] -> A<.11>;
4949+ "B"[module] -> B<.12>;
4850 }
4951module rec A : sig type t = Leaf of B.t end
5052and B : sig type t = int end
···7577end = Set.Make(A)
7678[%%expect{|
7779{
7878- "A"[module] -> {
7979- "compare"[value] -> <.38>;
8080- "t"[type] -> <.35>;
8181- };
8080+ "A"[module] ->
8181+ {
8282+ "compare"[value] -> <.38>;
8383+ "t"[type] ->
8484+ {<.35>
8585+ "Leaf"[constructor] -> {<.36>};
8686+ "Node"[constructor] -> {<.37>};
8787+ };
8888+ };
8289 "ASet"[module] ->
8390 {
8491 "compare"[value] ->
8585- CU Stdlib . "Set"[module] . "Make"[module](A/327<.19>) .
8686- "compare"[value];
9292+ CU Stdlib . "Set"[module] . "Make"[module](A<.19>) . "compare"[value];
8793 "elt"[type] ->
8888- CU Stdlib . "Set"[module] . "Make"[module](A/327<.19>) . "elt"[type];
9494+ CU Stdlib . "Set"[module] . "Make"[module](A<.19>) . "elt"[type];
8995 "t"[type] ->
9090- CU Stdlib . "Set"[module] . "Make"[module](A/327<.19>) . "t"[type];
9696+ CU Stdlib . "Set"[module] . "Make"[module](A<.19>) . "t"[type];
9197 };
9298 }
9399module rec A :
···2323and foo = Bar
2424[%%expect{|
2525{
2626- "foo"[type] -> <.3>;
2727- "t"[type] -> <.2>;
2626+ "foo"[type] -> {<.3>
2727+ "Bar"[constructor] -> {<.5>};
2828+ };
2929+ "t"[type] -> {<.2>
3030+ "A"[constructor] -> {<.4>};
3131+ };
2832 }
2933type t = A of foo
3034and foo = Bar
···4347exception E
4448[%%expect{|
4549{
4646- "E"[extension constructor] -> <.8>;
5050+ "E"[extension constructor] -> {<.8>};
4751 }
4852exception E
4953|}]
···5963type ext += A | B
6064[%%expect{|
6165{
6262- "A"[extension constructor] -> <.10>;
6363- "B"[extension constructor] -> <.11>;
6666+ "A"[extension constructor] -> {<.10>};
6767+ "B"[extension constructor] -> {<.11>};
6468 }
6569type ext += A | B
6670|}]
···7175[%%expect{|
7276{
7377 "M"[module] -> {<.13>
7474- "C"[extension constructor] -> <.12>;
7878+ "C"[extension constructor] -> {<.12>};
7579 };
7680 }
7781module M : sig type ext += C end
···8185 type t = Should_not_appear_in_shape
8286end
8387[%%expect{|
8484-{
8585- }
8888+{}
8689|}]
87908891module rec M1 : sig
···101104[%%expect{|
102105{
103106 "M1"[module] -> {
104104- "t"[type] -> <.27>;
107107+ "t"[type] -> {<.27>
108108+ "C"[constructor] -> {<.28>};
109109+ };
105110 };
106106- "M2"[module] -> {
107107- "t"[type] -> <.29>;
108108- "x"[value] -> <.31>;
111111+ "M2"[module] ->
112112+ {
113113+ "t"[type] -> {<.29>
114114+ "T"[constructor] -> {<.30>};
109115 };
116116+ "x"[value] -> <.31>;
117117+ };
110118 }
111119module rec M1 : sig type t = C of M2.t end
112120and M2 : sig type t val x : t end
···125133class type c = object end
126134[%%expect{|
127135{
128128- "c"[type] -> <.34>;
129129- "c"[class type] -> <.34>;
136136+ "c"[type] -> <.35>;
137137+ "c"[class type] -> <.35>;
130138 }
131139class type c = object end
132140|}]
141141+142142+type u = t
143143+[%%expect{|
144144+{
145145+ "u"[type] -> <.36>;
146146+ }
147147+type u = t
148148+|}]
+80-20
tools/objinfo.ml
···2424(* Command line options to prevent printing approximation,
2525 function code and CRC
2626 *)
2727+let quiet = ref false
2728let no_approx = ref false
2829let no_code = ref false
2930let no_crc = ref false
3031let shape = ref false
3232+let index = ref false
3333+let decls = ref false
31343235module Magic_number = Misc.Magic_number
3336···8285 List.iter print_cmo_infos lib.lib_units
83868487let print_cmi_infos name crcs =
8585- printf "Unit name: %s\n" name;
8686- printf "Interfaces imported:\n";
8787- List.iter print_name_crc crcs
8888+ if not !quiet then begin
8989+ printf "Unit name: %s\n" name;
9090+ printf "Interfaces imported:\n";
9191+ List.iter print_name_crc crcs
9292+ end
88938994let print_cmt_infos cmt =
9095 let open Cmt_format in
9191- printf "Cmt unit name: %s\n" cmt.cmt_modname;
9292- print_string "Cmt interfaces imported:\n";
9393- List.iter print_name_crc cmt.cmt_imports;
9494- printf "Source file: %s\n"
9595- (match cmt.cmt_sourcefile with None -> "(none)" | Some f -> f);
9696- printf "Compilation flags:";
9797- Array.iter print_spaced_string cmt.cmt_args;
9898- printf "\nLoad path:\n Visible:";
9999- List.iter print_spaced_string cmt.cmt_loadpath.visible;
100100- printf "\n Hidden:";
101101- List.iter print_spaced_string cmt.cmt_loadpath.hidden;
102102- printf "\n";
103103- printf "cmt interface digest: %s\n"
104104- (match cmt.cmt_interface_digest with
105105- | None -> ""
106106- | Some crc -> string_of_crc crc);
9696+ if not !quiet then begin
9797+ printf "Cmt unit name: %s\n" cmt.cmt_modname;
9898+ print_string "Cmt interfaces imported:\n";
9999+ List.iter print_name_crc cmt.cmt_imports;
100100+ printf "Source file: %s\n"
101101+ (match cmt.cmt_sourcefile with None -> "(none)" | Some f -> f);
102102+ printf "Compilation flags:";
103103+ Array.iter print_spaced_string cmt.cmt_args;
104104+ printf "\nLoad path:\n Visible:";
105105+ List.iter print_spaced_string cmt.cmt_loadpath.visible;
106106+ printf "\n Hidden:";
107107+ List.iter print_spaced_string cmt.cmt_loadpath.hidden;
108108+ printf "\n";
109109+ printf "cmt interface digest: %s\n"
110110+ (match cmt.cmt_interface_digest with
111111+ | None -> ""
112112+ | Some crc -> string_of_crc crc);
113113+ end;
107114 if !shape then begin
108115 printf "Implementation shape: ";
109116 (match cmt.cmt_impl_shape with
110117 | None -> printf "(none)\n"
111118 | Some shape -> Format.printf "\n%a" Shape.print shape)
119119+ end;
120120+ if !index then begin
121121+ printf "Indexed shapes:\n";
122122+ List.iter (fun (loc, item) ->
123123+ let pp_loc fmt { Location.txt; loc } =
124124+ Format.fprintf fmt "%a (%a)"
125125+ Pprintast.longident txt Location.print_loc loc
126126+ in
127127+ Format.printf "@[<hov 2>%a:@ %a@]@;"
128128+ Shape_reduce.print_result item pp_loc loc)
129129+ cmt.cmt_ident_occurrences;
130130+ Format.print_flush ()
131131+ end;
132132+ if !decls then begin
133133+ printf "\nUid of decls:\n";
134134+ Shape.Uid.Tbl.iter (fun uid item ->
135135+ let loc = match (item : Typedtree.item_declaration) with
136136+ | Value vd -> vd.val_name
137137+ | Value_binding vb ->
138138+ let (_, name, _, _) =
139139+ List.hd (Typedtree.let_bound_idents_full [vb])
140140+ in
141141+ name
142142+ | Type td -> td.typ_name
143143+ | Constructor cd -> cd.cd_name
144144+ | Extension_constructor ec -> ec.ext_name
145145+ | Label ld -> ld.ld_name
146146+ | Module md ->
147147+ { md.md_name with
148148+ txt = Option.value md.md_name.txt ~default:"_" }
149149+ | Module_substitution ms -> ms.ms_name
150150+ | Module_binding mb ->
151151+ { mb.mb_name with
152152+ txt = Option.value mb.mb_name.txt ~default:"_" }
153153+ | Module_type mtd -> mtd.mtd_name
154154+ | Class cd -> cd.ci_id_name
155155+ | Class_type ctd -> ctd.ci_id_name
156156+ in
157157+ let pp_loc fmt { Location.txt; loc } =
158158+ Format.fprintf fmt "%s (%a)"
159159+ txt Location.print_loc loc
160160+ in
161161+ Format.printf "@[<hov 2>%a:@ %a@]@;"
162162+ Shape.Uid.print uid
163163+ pp_loc loc)
164164+ cmt.cmt_uid_to_decl;
165165+ Format.print_flush ()
112166 end
113167114168let print_general_infos name crc defines cmi cmx =
···367421 dump_obj_by_kind filename ic Cmxs;
368422 ()
369423 in
370370- printf "File %s\n" filename;
424424+ if not !quiet then printf "File %s\n" filename;
371425 let ic = open_in_bin filename in
372426 match dump_standard ic with
373427 | Ok () -> ()
···380434 else exit_magic_error ~expected_kind:None (Parse_error head_error)
381435382436let arg_list = [
437437+ "-quiet", Arg.Set quiet,
438438+ " Only print explicitely required information";
383439 "-no-approx", Arg.Set no_approx,
384440 " Do not print module approximation information";
385441 "-no-code", Arg.Set no_code,
386442 " Do not print code from exported flambda functions";
387443 "-shape", Arg.Set shape,
388444 " Print the shape of the module";
445445+ "-index", Arg.Set index,
446446+ " Print a list of all usages of values, types, etc. in the module";
447447+ "-decls", Arg.Set decls,
448448+ " Print a list of all declarations in the module";
389449 "-null-crc", Arg.Set no_crc, " Print a null CRC for imported interfaces";
390450 "-args", Arg.Expand Arg.read_arg,
391451 "<file> Read additional newline separated command line arguments \n\
+1-1
toplevel/byte/topeval.ml
···131131 let sg' = Typemod.Signature_names.simplify newenv sn sg in
132132 ignore (Includemod.signatures ~mark:Mark_positive oldenv sg sg');
133133 Typecore.force_delayed_checks ();
134134- let shape = Shape.local_reduce shape in
134134+ let shape = Shape_reduce.local_reduce Env.empty shape in
135135 if !Clflags.dump_shape then Shape.print ppf shape;
136136 let lam = Translmod.transl_toplevel_definition str in
137137 Warnings.check_fatal ();
+2-2
toplevel/native/topeval.ml
···129129 in
130130 let sg = [Sig_value(id, vd, Exported)] in
131131 let pat =
132132- { pat_desc = Tpat_var(id, mknoloc name);
132132+ { pat_desc = Tpat_var(id, mknoloc name, vd.val_uid);
133133 pat_loc = loc;
134134 pat_extra = [];
135135 pat_type = exp.exp_type;
···171171 let sg' = Typemod.Signature_names.simplify newenv names sg in
172172 ignore (Includemod.signatures oldenv ~mark:Mark_positive sg sg');
173173 Typecore.force_delayed_checks ();
174174- let shape = Shape.local_reduce shape in
174174+ let shape = Shape_reduce.local_reduce Env.empty shape in
175175 if !Clflags.dump_shape then Shape.print ppf shape;
176176 (* `let _ = <expression>` or even just `<expression>` require special
177177 handling in toplevels, or nothing is displayed. In bytecode, the
+1-1
typing/cmt2annot.ml
···2323 let super = default_iterator in
2424 let pat sub (type k) (p : k general_pattern) =
2525 begin match p.pat_desc with
2626- | Tpat_var (id, _) | Tpat_alias (_, id, _) ->
2626+ | Tpat_var (id, _, _) | Tpat_alias (_, id, _, _) ->
2727 Stypes.record (Stypes.An_ident (p.pat_loc,
2828 Ident.name id,
2929 Annot.Idef scope))
···6565module General : sig
6666 type view = [
6767 | Half_simple.view
6868- | `Var of Ident.t * string loc
6969- | `Alias of pattern * Ident.t * string loc
6868+ | `Var of Ident.t * string loc * Uid.t
6969+ | `Alias of pattern * Ident.t * string loc * Uid.t
7070 ]
7171 type pattern = view pattern_data
7272
+2-2
typing/printpat.ml
···5252 | [] ->
5353 match v.pat_desc with
5454 | Tpat_any -> fprintf ppf "_"
5555- | Tpat_var (x,_) -> fprintf ppf "%s" (Ident.name x)
5555+ | Tpat_var (x,_,_) -> fprintf ppf "%s" (Ident.name x)
5656 | Tpat_constant c -> fprintf ppf "%s" (pretty_const c)
5757 | Tpat_tuple vs ->
5858 fprintf ppf "@[(%a)@]" (pretty_vals ",") vs
···9898 fprintf ppf "@[[| %a |]@]" (pretty_vals " ;") vs
9999 | Tpat_lazy v ->
100100 fprintf ppf "@[<2>lazy@ %a@]" pretty_arg v
101101- | Tpat_alias (v, x,_) ->
101101+ | Tpat_alias (v, x,_,_) ->
102102 fprintf ppf "@[(%a@ as %a)@]" pretty_val v Ident.print x
103103 | Tpat_value v ->
104104 fprintf ppf "%a" pretty_val (v :> pattern)
+8-4
typing/printtyp.ml
···5555 type namespace = Sig_component_kind.t =
5656 | Value
5757 | Type
5858+ | Constructor
5959+ | Label
5860 | Module
5961 | Module_type
6062 | Extension_constructor
···7072 | Module_type -> 2
7173 | Class -> 3
7274 | Class_type -> 4
7373- | Extension_constructor | Value -> 5
7575+ | Extension_constructor | Value | Constructor | Label -> 5
7476 (* we do not handle those component *)
75777678 let size = 1 + id Value
···9092 | Some Module_type -> to_lookup Env.find_modtype_by_name
9193 | Some Class -> to_lookup Env.find_class_by_name
9294 | Some Class_type -> to_lookup Env.find_cltype_by_name
9393- | None | Some(Value|Extension_constructor) -> fun _ -> raise Not_found
9595+ | None | Some(Value|Extension_constructor|Constructor|Label) ->
9696+ fun _ -> raise Not_found
94979598 let location namespace id =
9699 let path = Path.Pident id in
···101104 | Some Module_type -> (in_printing_env @@ Env.find_modtype path).mtd_loc
102105 | Some Class -> (in_printing_env @@ Env.find_class path).cty_loc
103106 | Some Class_type -> (in_printing_env @@ Env.find_cltype path).clty_loc
104104- | Some (Extension_constructor|Value) | None -> Location.none
107107+ | Some (Extension_constructor|Value|Constructor|Label) | None ->
108108+ Location.none
105109 ) with Not_found -> None
106110107111 let best_class_namespace = function
···284288 | Module_type -> Env.find_modtype_index id env
285289 | Class -> Env.find_class_index id env
286290 | Class_type-> Env.find_cltype_index id env
287287- | Value | Extension_constructor -> None
291291+ | Value | Extension_constructor | Constructor | Label -> None
288292 in
289293 let index =
290294 match M.find_opt (Ident.name id) !bound_in_recursion with
+2-2
typing/printtyped.ml
···235235 end;
236236 match x.pat_desc with
237237 | Tpat_any -> line i ppf "Tpat_any\n";
238238- | Tpat_var (s,_) -> line i ppf "Tpat_var \"%a\"\n" fmt_ident s;
239239- | Tpat_alias (p, s,_) ->
238238+ | Tpat_var (s,_,_) -> line i ppf "Tpat_var \"%a\"\n" fmt_ident s;
239239+ | Tpat_alias (p, s,_,_) ->
240240 line i ppf "Tpat_alias \"%a\"\n" fmt_ident s;
241241 pattern i ppf p;
242242 | Tpat_constant (c) -> line i ppf "Tpat_constant %a\n" fmt_constant c;
+83-264
typing/shape.ml
···6767 type t =
6868 | Value
6969 | Type
7070+ | Constructor
7171+ | Label
7072 | Module
7173 | Module_type
7274 | Extension_constructor
···7678 let to_string = function
7779 | Value -> "value"
7880 | Type -> "type"
8181+ | Constructor -> "constructor"
8282+ | Label -> "label"
7983 | Module -> "module"
8084 | Module_type -> "module type"
8185 | Extension_constructor -> "extension constructor"
···8791 | Extension_constructor ->
8892 false
8993 | Type
9494+ | Constructor
9595+ | Label
9096 | Module
9197 | Module_type
9298 | Class
···99105 type t = string * Sig_component_kind.t
100106 let compare = compare
101107108108+ let name (name, _) = name
109109+ let kind (_, kind) = kind
110110+102111 let make str ns = str, ns
103112104113 let value id = Ident.name id, Sig_component_kind.Value
105114 let type_ id = Ident.name id, Sig_component_kind.Type
115115+ let constr id = Ident.name id, Sig_component_kind.Constructor
116116+ let label id = Ident.name id, Sig_component_kind.Label
106117 let module_ id = Ident.name id, Sig_component_kind.Module
107118 let module_type id = Ident.name id, Sig_component_kind.Module_type
108119 let extension_constructor id =
···124135end
125136126137type var = Ident.t
127127-type t = { uid: Uid.t option; desc: desc }
138138+type t = { uid: Uid.t option; desc: desc; approximated: bool }
128139and desc =
129140 | Var of var
130141 | Abs of var * t
131142 | App of t * t
132143 | Struct of t Item.Map.t
144144+ | Alias of t
133145 | Leaf
134146 | Proj of t * Item.t
135147 | Comp_unit of string
148148+ | Error of string
136149137137-let print fmt =
150150+let print fmt t =
138151 let print_uid_opt =
139152 Format.pp_print_option (fun fmt -> Format.fprintf fmt "<%a>" Uid.print)
140153 in
141154 let rec aux fmt { uid; desc } =
142155 match desc with
143156 | Var id ->
144144- Format.fprintf fmt "%a%a" Ident.print id print_uid_opt uid
157157+ Format.fprintf fmt "%s%a" (Ident.name id) print_uid_opt uid
145158 | Abs (id, t) ->
146159 let rec collect_idents = function
147160 | { uid = None; desc = Abs(id, t) } ->
···152165 in
153166 let (other_idents, body) = collect_idents t in
154167 let pp_idents fmt idents =
168168+ let idents_names = List.map Ident.name idents in
155169 let pp_sep fmt () = Format.fprintf fmt ",@ " in
156156- Format.pp_print_list ~pp_sep Ident.print fmt idents
170170+ Format.pp_print_list ~pp_sep Format.pp_print_string fmt idents_names
157171 in
158172 Format.fprintf fmt "Abs@[%a@,(@[%a,@ @[%a@]@])@]"
159173 print_uid_opt uid pp_idents (id :: other_idents) aux body
···183197 aux t
184198 )
185199 in
186186- Format.fprintf fmt "{@[<v>%a@,%a@]}" print_uid_opt uid print_map map
200200+ if Item.Map.is_empty map then
201201+ Format.fprintf fmt "@[<hv>{%a}@]" print_uid_opt uid
202202+ else
203203+ Format.fprintf fmt "{@[<v>%a@,%a@]}" print_uid_opt uid print_map map
204204+ | Alias t ->
205205+ Format.fprintf fmt "Alias@[(@[<v>%a@,%a@])@]" print_uid_opt uid aux t
206206+ | Error s ->
207207+ Format.fprintf fmt "Error %s" s
187208 in
188188- Format.fprintf fmt"@[%a@]@;" aux
209209+ if t.approximated then
210210+ Format.fprintf fmt "@[(approx)@ %a@]@;" aux t
211211+ else
212212+ Format.fprintf fmt "@[%a@]@;" aux t
213213+214214+let rec strip_head_aliases = function
215215+ | { desc = Alias t; _ } -> strip_head_aliases t
216216+ | t -> t
189217190218let fresh_var ?(name="shape-var") uid =
191219 let var = Ident.create_local name in
192192- var, { uid = Some uid; desc = Var var }
220220+ var, { uid = Some uid; desc = Var var; approximated = false }
193221194222let for_unnamed_functor_param = Ident.create_local "()"
195223196224let var uid id =
197197- { uid = Some uid; desc = Var id }
225225+ { uid = Some uid; desc = Var id; approximated = false }
198226199227let abs ?uid var body =
200200- { uid; desc = Abs (var, body) }
228228+ { uid; desc = Abs (var, body); approximated = false }
201229202230let str ?uid map =
203203- { uid; desc = Struct map }
231231+ { uid; desc = Struct map; approximated = false }
232232+233233+let alias ?uid t =
234234+ { uid; desc = Alias t; approximated = false}
204235205236let leaf uid =
206206- { uid = Some uid; desc = Leaf }
237237+ { uid = Some uid; desc = Leaf; approximated = false }
238238+239239+let approx t = { t with approximated = true}
207240208241let proj ?uid t item =
209242 match t.desc with
210243 | Leaf ->
211244 (* When stuck projecting in a leaf we propagate the leaf
212245 as a best effort *)
213213- t
246246+ approx t
214247 | Struct map ->
215248 begin try Item.Map.find item map
216216- with Not_found -> t (* ill-typed program *)
249249+ with Not_found -> approx t (* ill-typed program *)
217250 end
218251 | _ ->
219219- { uid; desc = Proj (t, item) }
252252+ { uid; desc = Proj (t, item); approximated = false }
220253221254let app ?uid f ~arg =
222222- { uid; desc = App (f, arg) }
255255+ { uid; desc = App (f, arg); approximated = false }
223256224257let decompose_abs t =
225258 match t.desc with
226259 | Abs (x, t) -> Some (x, t)
227260 | _ -> None
228261229229-module Make_reduce(Params : sig
230230- type env
231231- val fuel : int
232232- val read_unit_shape : unit_name:string -> t option
233233- val find_shape : env -> Ident.t -> t
234234-end) = struct
235235- (* We implement a strong call-by-need reduction, following an
236236- evaluator from Nathanaelle Courant. *)
237237-238238- type nf = { uid: Uid.t option; desc: nf_desc }
239239- and nf_desc =
240240- | NVar of var
241241- | NApp of nf * nf
242242- | NAbs of local_env * var * t * delayed_nf
243243- | NStruct of delayed_nf Item.Map.t
244244- | NProj of nf * Item.t
245245- | NLeaf
246246- | NComp_unit of string
247247- | NoFuelLeft of desc
248248- (* A type of normal forms for strong call-by-need evaluation.
249249- The normal form of an abstraction
250250- Abs(x, t)
251251- is a closure
252252- NAbs(env, x, t, dnf)
253253- when [env] is the local environment, and [dnf] is a delayed
254254- normal form of [t].
255255-256256- A "delayed normal form" is morally equivalent to (nf Lazy.t), but
257257- we use a different representation that is compatible with
258258- memoization (lazy values are not hashable/comparable by default
259259- comparison functions): we represent a delayed normal form as
260260- just a not-yet-computed pair [local_env * t] of a term in a
261261- local environment -- we could also see this as a term under
262262- an explicit substitution. This delayed thunked is "forced"
263263- by calling the normalization function as usual, but duplicate
264264- computations are precisely avoided by memoization.
265265- *)
266266- and delayed_nf = Thunk of local_env * t
267267-268268- and local_env = delayed_nf option Ident.Map.t
269269- (* When reducing in the body of an abstraction [Abs(x, body)], we
270270- bind [x] to [None] in the environment. [Some v] is used for
271271- actual substitutions, for example in [App(Abs(x, body), t)], when
272272- [v] is a thunk that will evaluate to the normal form of [t]. *)
273273-274274- let improve_uid uid (nf : nf) =
275275- match nf.uid with
276276- | Some _ -> nf
277277- | None -> { nf with uid }
278278-279279- let in_memo_table memo_table memo_key f arg =
280280- match Hashtbl.find memo_table memo_key with
281281- | res -> res
282282- | exception Not_found ->
283283- let res = f arg in
284284- Hashtbl.replace memo_table memo_key res;
285285- res
262262+let dummy_mod =
263263+ { uid = None; desc = Struct Item.Map.empty; approximated = false }
286264287287- type env = {
288288- fuel: int ref;
289289- global_env: Params.env;
290290- local_env: local_env;
291291- reduce_memo_table: (local_env * t, nf) Hashtbl.t;
292292- read_back_memo_table: (nf, t) Hashtbl.t;
293293- }
294294-295295- let bind env var shape =
296296- { env with local_env = Ident.Map.add var shape env.local_env }
297297-298298- let rec reduce_ env t =
299299- let memo_key = (env.local_env, t) in
300300- in_memo_table env.reduce_memo_table memo_key (reduce__ env) t
301301- (* Memoization is absolutely essential for performance on this
302302- problem, because the normal forms we build can in some real-world
303303- cases contain an exponential amount of redundancy. Memoization
304304- can avoid the repeated evaluation of identical subterms,
305305- providing a large speedup, but even more importantly it
306306- implicitly shares the memory of the repeated results, providing
307307- much smaller normal forms (that blow up again if printed back
308308- as trees). A functor-heavy file from Irmin has its shape normal
309309- form decrease from 100Mio to 2.5Mio when memoization is enabled.
310310-311311- Note: the local environment is part of the memoization key, while
312312- it is defined using a type Ident.Map.t of non-canonical balanced
313313- trees: two maps could have exactly the same items, but be
314314- balanced differently and therefore hash differently, reducing
315315- the effectivenss of memoization.
316316- This could in theory happen, say, with the two programs
317317- (fun x -> fun y -> ...)
318318- and
319319- (fun y -> fun x -> ...)
320320- having "the same" local environments, with additions done in
321321- a different order, giving non-structurally-equal trees. Should we
322322- define our own hash functions to provide robust hashing on
323323- environments?
324324-325325- We believe that the answer is "no": this problem does not occur
326326- in practice. We can assume that identifiers are unique on valid
327327- typedtree fragments (identifier "stamps" distinguish
328328- binding positions); in particular the two program fragments above
329329- in fact bind *distinct* identifiers x (with different stamps) and
330330- different identifiers y, so the environments are distinct. If two
331331- environments are structurally the same, they must correspond to
332332- the evaluation evnrionments of two sub-terms that are under
333333- exactly the same scope of binders. So the two environments were
334334- obtained by the same term traversal, adding binders in the same
335335- order, giving the same balanced trees: the environments have the
336336- same hash.
337337-*)
338338-339339- and reduce__ ({fuel; global_env; local_env; _} as env) (t : t) =
340340- let reduce env t = reduce_ env t in
341341- let delay_reduce env t = Thunk (env.local_env, t) in
342342- let force (Thunk (local_env, t)) =
343343- reduce { env with local_env } t in
344344- let return desc : nf = { uid = t.uid; desc } in
345345- if !fuel < 0 then return (NoFuelLeft t.desc)
346346- else
347347- match t.desc with
348348- | Comp_unit unit_name ->
349349- begin match Params.read_unit_shape ~unit_name with
350350- | Some t -> reduce env t
351351- | None -> return (NComp_unit unit_name)
352352- end
353353- | App(f, arg) ->
354354- let f = reduce env f in
355355- begin match f.desc with
356356- | NAbs(clos_env, var, body, _body_nf) ->
357357- let arg = delay_reduce env arg in
358358- let env = bind { env with local_env = clos_env } var (Some arg) in
359359- reduce env body
360360- |> improve_uid t.uid
361361- | _ ->
362362- let arg = reduce env arg in
363363- return (NApp(f, arg))
364364- end
365365- | Proj(str, item) ->
366366- let str = reduce env str in
367367- let nored () = return (NProj(str, item)) in
368368- begin match str.desc with
369369- | NStruct (items) ->
370370- begin match Item.Map.find item items with
371371- | exception Not_found -> nored ()
372372- | nf ->
373373- force nf
374374- |> improve_uid t.uid
375375- end
376376- | _ ->
377377- nored ()
378378- end
379379- | Abs(var, body) ->
380380- let body_nf = delay_reduce (bind env var None) body in
381381- return (NAbs(local_env, var, body, body_nf))
382382- | Var id ->
383383- begin match Ident.Map.find id local_env with
384384- (* Note: instead of binding abstraction-bound variables to
385385- [None], we could unify it with the [Some v] case by
386386- binding the bound variable [x] to [NVar x].
387387-388388- One reason to distinguish the situations is that we can
389389- provide a different [Uid.t] location; for bound
390390- variables, we use the [Uid.t] of the bound occurrence
391391- (not the binding site), whereas for bound values we use
392392- their binding-time [Uid.t]. *)
393393- | None -> return (NVar id)
394394- | Some def -> force def
395395- | exception Not_found ->
396396- match Params.find_shape global_env id with
397397- | exception Not_found -> return (NVar id)
398398- | res when res = t -> return (NVar id)
399399- | res ->
400400- decr fuel;
401401- reduce env res
402402- end
403403- | Leaf -> return NLeaf
404404- | Struct m ->
405405- let mnf = Item.Map.map (delay_reduce env) m in
406406- return (NStruct mnf)
407407-408408- let rec read_back env (nf : nf) : t =
409409- in_memo_table env.read_back_memo_table nf (read_back_ env) nf
410410- (* The [nf] normal form we receive may contain a lot of internal
411411- sharing due to the use of memoization in the evaluator. We have
412412- to memoize here again, otherwise the sharing is lost by mapping
413413- over the term as a tree. *)
414414-415415- and read_back_ env (nf : nf) : t =
416416- { uid = nf.uid; desc = read_back_desc env nf.desc }
417417-418418- and read_back_desc env desc =
419419- let read_back nf = read_back env nf in
420420- let read_back_force (Thunk (local_env, t)) =
421421- read_back (reduce_ { env with local_env } t) in
422422- match desc with
423423- | NVar v ->
424424- Var v
425425- | NApp (nft, nfu) ->
426426- App(read_back nft, read_back nfu)
427427- | NAbs (_env, x, _t, nf) ->
428428- Abs(x, read_back_force nf)
429429- | NStruct nstr ->
430430- Struct (Item.Map.map read_back_force nstr)
431431- | NProj (nf, item) ->
432432- Proj (read_back nf, item)
433433- | NLeaf -> Leaf
434434- | NComp_unit s -> Comp_unit s
435435- | NoFuelLeft t -> t
436436-437437- let reduce global_env t =
438438- let fuel = ref Params.fuel in
439439- let reduce_memo_table = Hashtbl.create 42 in
440440- let read_back_memo_table = Hashtbl.create 42 in
441441- let local_env = Ident.Map.empty in
442442- let env = {
443443- fuel;
444444- global_env;
445445- reduce_memo_table;
446446- read_back_memo_table;
447447- local_env;
448448- } in
449449- reduce_ env t |> read_back env
450450-end
451451-452452-module Local_reduce =
453453- (* Note: this definition with [type env = unit] is only suitable for
454454- reduction of toplevel shapes -- shapes of compilation units,
455455- where free variables are only Comp_unit names. If we wanted to
456456- reduce shapes inside module signatures, we would need to take
457457- a typing environment as parameter. *)
458458- Make_reduce(struct
459459- type env = unit
460460- let fuel = 10
461461- let read_unit_shape ~unit_name:_ = None
462462- let find_shape _env _id = raise Not_found
463463- end)
464464-465465-let local_reduce shape =
466466- Local_reduce.reduce () shape
467467-468468-let dummy_mod = { uid = None; desc = Struct Item.Map.empty }
469469-470470-let of_path ~find_shape ~namespace =
265265+let of_path ~find_shape ~namespace path =
266266+ (* We need to handle the following cases:
267267+ Path of constructor:
268268+ M.t.C
269269+ Path of label:
270270+ M.t.lbl
271271+ Path of label of inline record:
272272+ M.t.C.lbl *)
471273 let rec aux : Sig_component_kind.t -> Path.t -> t = fun ns -> function
472274 | Pident id -> find_shape ns id
473473- | Pdot (path, name) -> proj (aux Module path) (name, ns)
275275+ | Pdot (path, name) ->
276276+ let namespace : Sig_component_kind.t =
277277+ match (ns : Sig_component_kind.t) with
278278+ | Constructor -> Type
279279+ | Label -> Type
280280+ | _ -> Module
281281+ in
282282+ proj (aux namespace path) (name, ns)
474283 | Papply (p1, p2) -> app (aux Module p1) ~arg:(aux Module p2)
475284 | Pextra_ty (path, extra) -> begin
476285 match extra with
477477- Pcstr_ty _ -> aux Type path
286286+ Pcstr_ty name -> proj (aux Type path) (name, Constructor)
478287 | Pext_ty -> aux Extension_constructor path
479288 end
480289 in
481481- aux namespace
290290+ aux namespace path
482291483292let for_persistent_unit s =
484293 { uid = Some (Uid.of_compilation_unit_id (Ident.create_persistent s));
485485- desc = Comp_unit s }
294294+ desc = Comp_unit s; approximated = false }
486295487487-let leaf_for_unpack = { uid = None; desc = Leaf }
296296+let leaf_for_unpack = { uid = None; desc = Leaf; approximated = false }
488297489298let set_uid_if_none t uid =
490299 match t.uid with
···504313 let item = Item.value id in
505314 Item.Map.add item (proj shape item) t
506315507507- let add_type t id uid = Item.Map.add (Item.type_ id) (leaf uid) t
316316+ let add_type t id shape = Item.Map.add (Item.type_ id) shape t
508317 let add_type_proj t id shape =
509318 let item = Item.type_ id in
510319 Item.Map.add item (proj shape item) t
511320321321+ let add_constr t id shape = Item.Map.add (Item.constr id) shape t
322322+ let add_constr_proj t id shape =
323323+ let item = Item.constr id in
324324+ Item.Map.add item (proj shape item) t
325325+326326+ let add_label t id uid = Item.Map.add (Item.label id) (leaf uid) t
327327+ let add_label_proj t id shape =
328328+ let item = Item.label id in
329329+ Item.Map.add item (proj shape item) t
330330+512331 let add_module t id shape = Item.Map.add (Item.module_ id) shape t
513332 let add_module_proj t id shape =
514333 let item = Item.module_ id in
···520339 let item = Item.module_type id in
521340 Item.Map.add item (proj shape item) t
522341523523- let add_extcons t id uid =
524524- Item.Map.add (Item.extension_constructor id) (leaf uid) t
342342+ let add_extcons t id shape =
343343+ Item.Map.add (Item.extension_constructor id) shape t
525344 let add_extcons_proj t id shape =
526345 let item = Item.extension_constructor id in
527346 Item.Map.add item (proj shape item) t
+72-28
typing/shape.mli
···1313(* *)
1414(**************************************************************************)
15151616+(** Shapes are an abstract representation of modules' implementations which
1717+ allow the tracking of definitions through functor applications and other
1818+ module-level operations.
1919+2020+ The Shape of a compilation unit is elaborated during typing, partially
2121+ reduced (without loading external shapes) and written to the [cmt] file.
2222+2323+ External tools can retrieve the definition of any value (or type, or module,
2424+ etc) by following this procedure:
2525+2626+ - Build the Shape corresponding to the value's path:
2727+ [let shape = Env.shape_of_path ~namespace env path]
2828+2929+ - Instantiate the [Shape_reduce.Make] functor with a way to load shapes from
3030+ external units and to looks for shapes in the environment (usually using
3131+ [Env.shape_of_path]).
3232+3333+ - Completely reduce the shape:
3434+ [let shape = My_reduce.(weak_)reduce env shape]
3535+3636+ - The [Uid.t] stored in the reduced shape should be the one of the
3737+ definition. However, if the [approximate] field of the reduced shape is
3838+ [true] then the [Uid.t] will not correspond to the definition, but to the
3939+ closest parent module's uid. This happens when Shape reduction gets stuck,
4040+ for example when hitting first-class modules.
4141+4242+ - The location of the definition can be easily found with the
4343+ [cmt_format.cmt_uid_to_decl] table of the corresponding compilation unit.
4444+4545+ See:
4646+ - {{: https://icfp22.sigplan.org/details/mlfamilyworkshop-2022-papers/10/Module-Shapes-for-Modern-Tooling }
4747+ the design document}
4848+ - {{: https://www.lix.polytechnique.fr/Labo/Gabriel.Scherer/research/shapes/2022-ml-workshop-shapes-talk.pdf }
4949+ a talk about the reduction strategy
5050+*)
5151+5252+(** A [Uid.t] is associated to every declaration in signatures and
5353+ implementations. They uniquely identify bindings in the program. When
5454+ associated with these bindings' locations they are useful to external tools
5555+ when trying to jump to an identifier's declaration or definition. They are
5656+ stored to that effect in the [uid_to_decl] table of cmt files. *)
1657module Uid : sig
1758 type t = private
1859 | Compilation_unit of string
···3677 type t =
3778 | Value
3879 | Type
8080+ | Constructor
8181+ | Label
3982 | Module
4083 | Module_type
4184 | Extension_constructor
···4891 val can_appear_in_types : t -> bool
4992end
50939494+(** Shape's items are elements of a structure or, in the case of constructors
9595+ and labels, elements of a record or variants definition seen as a structure.
9696+ These structures model module components and nested types' constructors and
9797+ labels. *)
5198module Item : sig
5252- type t
9999+ type t = string * Sig_component_kind.t
100100+ val name : t -> string
101101+ val kind : t -> Sig_component_kind.t
5310254103 val make : string -> Sig_component_kind.t -> t
5510456105 val value : Ident.t -> t
57106 val type_ : Ident.t -> t
107107+ val constr : Ident.t -> t
108108+ val label : Ident.t -> t
58109 val module_ : Ident.t -> t
59110 val module_type : Ident.t -> t
60111 val extension_constructor : Ident.t -> t
61112 val class_ : Ident.t -> t
62113 val class_type : Ident.t -> t
63114115115+ val print : Format.formatter -> t -> unit
116116+64117 module Map : Map.S with type key = t
65118end
6611967120type var = Ident.t
6868-type t = { uid: Uid.t option; desc: desc }
121121+type t = { uid: Uid.t option; desc: desc; approximated: bool }
69122and desc =
70123 | Var of var
71124 | Abs of var * t
72125 | App of t * t
73126 | Struct of t Item.Map.t
127127+ | Alias of t
74128 | Leaf
75129 | Proj of t * Item.t
76130 | Comp_unit of string
131131+ | Error of string
7713278133val print : Format.formatter -> t -> unit
79134135135+val strip_head_aliases : t -> t
136136+80137(* Smart constructors *)
8113882139val for_unnamed_functor_param : var
···86143val abs : ?uid:Uid.t -> var -> t -> t
87144val app : ?uid:Uid.t -> t -> arg:t -> t
88145val str : ?uid:Uid.t -> t Item.Map.t -> t
146146+val alias : ?uid:Uid.t -> t -> t
89147val proj : ?uid:Uid.t -> t -> Item.t -> t
90148val leaf : Uid.t -> t
91149···105163 val add_value : t -> Ident.t -> Uid.t -> t
106164 val add_value_proj : t -> Ident.t -> shape -> t
107165108108- val add_type : t -> Ident.t -> Uid.t -> t
166166+ val add_type : t -> Ident.t -> shape -> t
109167 val add_type_proj : t -> Ident.t -> shape -> t
110168169169+ val add_constr : t -> Ident.t -> shape -> t
170170+ val add_constr_proj : t -> Ident.t -> shape -> t
171171+172172+ val add_label : t -> Ident.t -> Uid.t -> t
173173+ val add_label_proj : t -> Ident.t -> shape -> t
174174+111175 val add_module : t -> Ident.t -> shape -> t
112176 val add_module_proj : t -> Ident.t -> shape -> t
113177114178 val add_module_type : t -> Ident.t -> Uid.t -> t
115179 val add_module_type_proj : t -> Ident.t -> shape -> t
116180117117- val add_extcons : t -> Ident.t -> Uid.t -> t
181181+ val add_extcons : t -> Ident.t -> shape -> t
118182 val add_extcons_proj : t -> Ident.t -> shape -> t
119183120184 val add_class : t -> Ident.t -> Uid.t -> t
···126190127191val dummy_mod : t
128192193193+(** This function returns the shape corresponding to a given path. It requires a
194194+ callback to find shapes in the environment. It is generally more useful to
195195+ rely directly on the [Env.shape_of_path] function to get the shape
196196+ associated with a given path. *)
129197val of_path :
130198 find_shape:(Sig_component_kind.t -> Ident.t -> t) ->
131199 namespace:Sig_component_kind.t -> Path.t -> t
132200133201val set_uid_if_none : t -> Uid.t -> t
134134-135135-(** The [Make_reduce] functor is used to generate a reduction function for
136136- shapes.
137137-138138- It is parametrized by:
139139- - an environment and a function to find shapes by path in that environment
140140- - a function to load the shape of an external compilation unit
141141- - some fuel, which is used to bound recursion when dealing with recursive
142142- shapes introduced by recursive modules. (FTR: merlin currently uses a
143143- fuel of 10, which seems to be enough for most practical examples)
144144-*)
145145-module Make_reduce(Context : sig
146146- type env
147147-148148- val fuel : int
149149-150150- val read_unit_shape : unit_name:string -> t option
151151-152152- val find_shape : env -> Ident.t -> t
153153- end) : sig
154154- val reduce : Context.env -> t -> t
155155-end
156156-157157-val local_reduce : t -> t
+347
typing/shape_reduce.ml
···11+(**************************************************************************)
22+(* *)
33+(* OCaml *)
44+(* *)
55+(* Ulysse Gérard, Thomas Refis, Tarides *)
66+(* Nathanaëlle Courant, OCamlPro *)
77+(* Gabriel Scherer, projet Picube, INRIA Paris *)
88+(* *)
99+(* Copyright 2021 Institut National de Recherche en Informatique et *)
1010+(* en Automatique. *)
1111+(* *)
1212+(* All rights reserved. This file is distributed under the terms of *)
1313+(* the GNU Lesser General Public License version 2.1, with the *)
1414+(* special exception on linking described in the file LICENSE. *)
1515+(* *)
1616+(**************************************************************************)
1717+1818+open Shape
1919+2020+type result =
2121+ | Resolved of Uid.t
2222+ | Resolved_alias of Uid.t list
2323+ | Unresolved of t
2424+ | Approximated of Uid.t option
2525+ | Internal_error_missing_uid
2626+2727+let print_result fmt result =
2828+ match result with
2929+ | Resolved uid ->
3030+ Format.fprintf fmt "@[Resolved: %a@]@;" Uid.print uid
3131+ | Resolved_alias uids ->
3232+ Format.fprintf fmt "@[Resolved_alias: %a@]@;"
3333+ Format.(pp_print_list ~pp_sep:(fun fmt () -> fprintf fmt "@ -> ")
3434+ Uid.print) uids
3535+ | Unresolved shape ->
3636+ Format.fprintf fmt "@[Unresolved: %a@]@;" print shape
3737+ | Approximated (Some uid) ->
3838+ Format.fprintf fmt "@[Approximated: %a@]@;" Uid.print uid
3939+ | Approximated None ->
4040+ Format.fprintf fmt "@[Approximated: No uid@]@;"
4141+ | Internal_error_missing_uid ->
4242+ Format.fprintf fmt "@[Missing uid@]@;"
4343+4444+4545+let find_shape env id =
4646+ let namespace = Shape.Sig_component_kind.Module in
4747+ Env.shape_of_path ~namespace env (Pident id)
4848+4949+module Make(Params : sig
5050+ val fuel : int
5151+ val read_unit_shape : unit_name:string -> t option
5252+end) = struct
5353+ (* We implement a strong call-by-need reduction, following an
5454+ evaluator from Nathanaelle Courant. *)
5555+5656+ type nf = { uid: Uid.t option; desc: nf_desc; approximated: bool }
5757+ and nf_desc =
5858+ | NVar of var
5959+ | NApp of nf * nf
6060+ | NAbs of local_env * var * t * delayed_nf
6161+ | NStruct of delayed_nf Item.Map.t
6262+ | NAlias of delayed_nf
6363+ | NProj of nf * Item.t
6464+ | NLeaf
6565+ | NComp_unit of string
6666+ | NError of string
6767+6868+ (* A type of normal forms for strong call-by-need evaluation.
6969+ The normal form of an abstraction
7070+ Abs(x, t)
7171+ is a closure
7272+ NAbs(env, x, t, dnf)
7373+ when [env] is the local environment, and [dnf] is a delayed
7474+ normal form of [t].
7575+7676+ A "delayed normal form" is morally equivalent to (nf Lazy.t), but
7777+ we use a different representation that is compatible with
7878+ memoization (lazy values are not hashable/comparable by default
7979+ comparison functions): we represent a delayed normal form as
8080+ just a not-yet-computed pair [local_env * t] of a term in a
8181+ local environment -- we could also see this as a term under
8282+ an explicit substitution. This delayed thunked is "forced"
8383+ by calling the normalization function as usual, but duplicate
8484+ computations are precisely avoided by memoization.
8585+ *)
8686+ and delayed_nf = Thunk of local_env * t
8787+8888+ and local_env = delayed_nf option Ident.Map.t
8989+ (* When reducing in the body of an abstraction [Abs(x, body)], we
9090+ bind [x] to [None] in the environment. [Some v] is used for
9191+ actual substitutions, for example in [App(Abs(x, body), t)], when
9292+ [v] is a thunk that will evaluate to the normal form of [t]. *)
9393+9494+ let approx_nf nf = { nf with approximated = true }
9595+9696+ let in_memo_table memo_table memo_key f arg =
9797+ match Hashtbl.find memo_table memo_key with
9898+ | res -> res
9999+ | exception Not_found ->
100100+ let res = f arg in
101101+ Hashtbl.replace memo_table memo_key res;
102102+ res
103103+104104+ type env = {
105105+ fuel: int ref;
106106+ global_env: Env.t;
107107+ local_env: local_env;
108108+ reduce_memo_table: (local_env * t, nf) Hashtbl.t;
109109+ read_back_memo_table: (nf, t) Hashtbl.t;
110110+ }
111111+112112+ let bind env var shape =
113113+ { env with local_env = Ident.Map.add var shape env.local_env }
114114+115115+ let rec reduce_ env t =
116116+ let local_env = env.local_env in
117117+ let memo_key = (local_env, t) in
118118+ in_memo_table env.reduce_memo_table memo_key (reduce__ env) t
119119+ (* Memoization is absolutely essential for performance on this
120120+ problem, because the normal forms we build can in some real-world
121121+ cases contain an exponential amount of redundancy. Memoization
122122+ can avoid the repeated evaluation of identical subterms,
123123+ providing a large speedup, but even more importantly it
124124+ implicitly shares the memory of the repeated results, providing
125125+ much smaller normal forms (that blow up again if printed back
126126+ as trees). A functor-heavy file from Irmin has its shape normal
127127+ form decrease from 100Mio to 2.5Mio when memoization is enabled.
128128+129129+ Note: the local environment is part of the memoization key, while
130130+ it is defined using a type Ident.Map.t of non-canonical balanced
131131+ trees: two maps could have exactly the same items, but be
132132+ balanced differently and therefore hash differently, reducing
133133+ the effectivenss of memoization.
134134+ This could in theory happen, say, with the two programs
135135+ (fun x -> fun y -> ...)
136136+ and
137137+ (fun y -> fun x -> ...)
138138+ having "the same" local environments, with additions done in
139139+ a different order, giving non-structurally-equal trees. Should we
140140+ define our own hash functions to provide robust hashing on
141141+ environments?
142142+143143+ We believe that the answer is "no": this problem does not occur
144144+ in practice. We can assume that identifiers are unique on valid
145145+ typedtree fragments (identifier "stamps" distinguish
146146+ binding positions); in particular the two program fragments above
147147+ in fact bind *distinct* identifiers x (with different stamps) and
148148+ different identifiers y, so the environments are distinct. If two
149149+ environments are structurally the same, they must correspond to
150150+ the evaluation evnrionments of two sub-terms that are under
151151+ exactly the same scope of binders. So the two environments were
152152+ obtained by the same term traversal, adding binders in the same
153153+ order, giving the same balanced trees: the environments have the
154154+ same hash.
155155+*)
156156+157157+ and reduce__
158158+ ({fuel; global_env; local_env; _} as env) (t : t) =
159159+ let reduce env t = reduce_ env t in
160160+ let delay_reduce env t = Thunk (env.local_env, t) in
161161+ let force (Thunk (local_env, t)) = reduce { env with local_env } t in
162162+ let return desc = { uid = t.uid; desc; approximated = t.approximated } in
163163+ let rec force_aliases nf = match nf.desc with
164164+ | NAlias delayed_nf ->
165165+ let nf = force delayed_nf in
166166+ force_aliases nf
167167+ | _ -> nf
168168+ in
169169+ let reset_uid_if_new_binding t' =
170170+ match t.uid with
171171+ | None -> t'
172172+ | Some _ as uid -> { t' with uid }
173173+ in
174174+ if !fuel < 0 then approx_nf (return (NError "NoFuelLeft"))
175175+ else
176176+ match t.desc with
177177+ | Comp_unit unit_name ->
178178+ begin match Params.read_unit_shape ~unit_name with
179179+ | Some t -> reduce env t
180180+ | None -> return (NComp_unit unit_name)
181181+ end
182182+ | App(f, arg) ->
183183+ let f = reduce env f |> force_aliases in
184184+ begin match f.desc with
185185+ | NAbs(clos_env, var, body, _body_nf) ->
186186+ let arg = delay_reduce env arg in
187187+ let env = bind { env with local_env = clos_env } var (Some arg) in
188188+ reduce env body |> reset_uid_if_new_binding
189189+ | _ ->
190190+ let arg = reduce env arg in
191191+ return (NApp(f, arg))
192192+ end
193193+ | Proj(str, item) ->
194194+ let str = reduce env str |> force_aliases in
195195+ let nored () = return (NProj(str, item)) in
196196+ begin match str.desc with
197197+ | NStruct (items) ->
198198+ begin match Item.Map.find item items with
199199+ | exception Not_found -> nored ()
200200+ | nf -> force nf |> reset_uid_if_new_binding
201201+ end
202202+ | _ ->
203203+ nored ()
204204+ end
205205+ | Abs(var, body) ->
206206+ let body_nf = delay_reduce (bind env var None) body in
207207+ return (NAbs(local_env, var, body, body_nf))
208208+ | Var id ->
209209+ begin match Ident.Map.find id local_env with
210210+ (* Note: instead of binding abstraction-bound variables to
211211+ [None], we could unify it with the [Some v] case by
212212+ binding the bound variable [x] to [NVar x].
213213+214214+ One reason to distinguish the situations is that we can
215215+ provide a different [Uid.t] location; for bound
216216+ variables, we use the [Uid.t] of the bound occurrence
217217+ (not the binding site), whereas for bound values we use
218218+ their binding-time [Uid.t]. *)
219219+ | None -> return (NVar id)
220220+ | Some def ->
221221+ begin match force def with
222222+ | { uid = Some _; _ } as nf -> nf
223223+ (* This var already has a binding uid *)
224224+ | { uid = None; _ } as nf -> { nf with uid = t.uid }
225225+ (* Set the var's binding uid *)
226226+ end
227227+ | exception Not_found ->
228228+ match find_shape global_env id with
229229+ | exception Not_found -> return (NVar id)
230230+ | res when res = t -> return (NVar id)
231231+ | res ->
232232+ decr fuel;
233233+ reduce env res
234234+ end
235235+ | Leaf -> return NLeaf
236236+ | Struct m ->
237237+ let mnf = Item.Map.map (delay_reduce env) m in
238238+ return (NStruct mnf)
239239+ | Alias t -> return (NAlias (delay_reduce env t))
240240+ | Error s -> approx_nf (return (NError s))
241241+242242+ and read_back env (nf : nf) : t =
243243+ in_memo_table env.read_back_memo_table nf (read_back_ env) nf
244244+ (* The [nf] normal form we receive may contain a lot of internal
245245+ sharing due to the use of memoization in the evaluator. We have
246246+ to memoize here again, otherwise the sharing is lost by mapping
247247+ over the term as a tree. *)
248248+249249+ and read_back_ env (nf : nf) : t =
250250+ { uid = nf.uid ;
251251+ desc = read_back_desc env nf.desc;
252252+ approximated = nf.approximated }
253253+254254+ and read_back_desc env desc =
255255+ let read_back nf = read_back env nf in
256256+ let read_back_force (Thunk (local_env, t)) =
257257+ read_back (reduce_ { env with local_env } t) in
258258+ match desc with
259259+ | NVar v ->
260260+ Var v
261261+ | NApp (nft, nfu) ->
262262+ App(read_back nft, read_back nfu)
263263+ | NAbs (_env, x, _t, nf) ->
264264+ Abs(x, read_back_force nf)
265265+ | NStruct nstr ->
266266+ Struct (Item.Map.map read_back_force nstr)
267267+ | NAlias nf -> Alias (read_back_force nf)
268268+ | NProj (nf, item) ->
269269+ Proj (read_back nf, item)
270270+ | NLeaf -> Leaf
271271+ | NComp_unit s -> Comp_unit s
272272+ | NError s -> Error s
273273+274274+ (* Sharing the memo tables is safe at the level of a compilation unit since
275275+ idents should be unique *)
276276+ let reduce_memo_table = Local_store.s_table Hashtbl.create 42
277277+ let read_back_memo_table = Local_store.s_table Hashtbl.create 42
278278+279279+ let reduce global_env t =
280280+ let fuel = ref Params.fuel in
281281+ let local_env = Ident.Map.empty in
282282+ let env = {
283283+ fuel;
284284+ global_env;
285285+ reduce_memo_table = !reduce_memo_table;
286286+ read_back_memo_table = !read_back_memo_table;
287287+ local_env;
288288+ } in
289289+ reduce_ env t |> read_back env
290290+291291+ let rec is_stuck_on_comp_unit (nf : nf) =
292292+ match nf.desc with
293293+ | NVar _ ->
294294+ (* This should not happen if we only reduce closed terms *)
295295+ false
296296+ | NApp (nf, _) | NProj (nf, _) -> is_stuck_on_comp_unit nf
297297+ | NStruct _ | NAbs _ -> false
298298+ | NAlias _ -> false
299299+ | NComp_unit _ -> true
300300+ | NError _ -> false
301301+ | NLeaf -> false
302302+303303+ let get_aliases_uids (t : t) =
304304+ let rec aux acc (t : t) = match t with
305305+ | { uid = Some uid; desc = Alias t; _ } -> aux (uid::acc) t
306306+ | { uid = Some uid; _ } -> Resolved_alias (List.rev (uid::acc))
307307+ | _ -> Internal_error_missing_uid
308308+ in
309309+ aux [] t
310310+311311+ let reduce_for_uid global_env t =
312312+ let fuel = ref Params.fuel in
313313+ let local_env = Ident.Map.empty in
314314+ let env = {
315315+ fuel;
316316+ global_env;
317317+ reduce_memo_table = !reduce_memo_table;
318318+ read_back_memo_table = !read_back_memo_table;
319319+ local_env;
320320+ } in
321321+ let nf = reduce_ env t in
322322+ if is_stuck_on_comp_unit nf then
323323+ Unresolved (read_back env nf)
324324+ else match nf with
325325+ | { desc = NAlias _; approximated = false; _ } ->
326326+ get_aliases_uids (read_back env nf)
327327+ | { uid = Some uid; approximated = false; _ } ->
328328+ Resolved uid
329329+ | { uid; approximated = true; _ } ->
330330+ Approximated uid
331331+ | { uid = None; approximated = false; _ } ->
332332+ (* A missing Uid after a complete reduction means the Uid was first
333333+ missing in the shape which is a code error. Having the
334334+ [Missing_uid] reported will allow Merlin (or another tool working
335335+ with the index) to ask users to report the issue if it does happen.
336336+ *)
337337+ Internal_error_missing_uid
338338+end
339339+340340+module Local_reduce =
341341+ Make(struct
342342+ let fuel = 10
343343+ let read_unit_shape ~unit_name:_ = None
344344+ end)
345345+346346+let local_reduce = Local_reduce.reduce
347347+let local_reduce_for_uid = Local_reduce.reduce_for_uid
+62
typing/shape_reduce.mli
···11+(**************************************************************************)
22+(* *)
33+(* OCaml *)
44+(* *)
55+(* Ulysse Gérard, Thomas Refis, Tarides *)
66+(* Nathanaëlle Courant, OCamlPro *)
77+(* Gabriel Scherer, projet Picube, INRIA Paris *)
88+(* *)
99+(* Copyright 2021 Institut National de Recherche en Informatique et *)
1010+(* en Automatique. *)
1111+(* *)
1212+(* All rights reserved. This file is distributed under the terms of *)
1313+(* the GNU Lesser General Public License version 2.1, with the *)
1414+(* special exception on linking described in the file LICENSE. *)
1515+(* *)
1616+(**************************************************************************)
1717+1818+(** The result of reducing a shape and looking for its uid *)
1919+type result =
2020+ | Resolved of Shape.Uid.t (** Shape reduction succeeded and a uid was found *)
2121+ | Resolved_alias of Shape.Uid.t list (** Reduction led to an alias chain *)
2222+ | Unresolved of Shape.t (** Result still contains [Comp_unit] terms *)
2323+ | Approximated of Shape.Uid.t option
2424+ (** Reduction failed: it can arrive with first-clsss modules for example *)
2525+ | Internal_error_missing_uid
2626+ (** Reduction succeeded but no uid was found, this should never happen *)
2727+2828+val print_result : Format.formatter -> result -> unit
2929+3030+(** The [Make] functor is used to generate a reduction function for
3131+ shapes.
3232+3333+ It is parametrized by:
3434+ - a function to load the shape of an external compilation unit
3535+ - some fuel, which is used to bound recursion when dealing with recursive
3636+ shapes introduced by recursive modules. (FTR: merlin currently uses a
3737+ fuel of 10, which seems to be enough for most practical examples)
3838+3939+ Usage warning: To ensure good performances, every reduction made with the
4040+ same instance of that functor share the same ident-based memoization tables.
4141+ Such an instance should only be used to perform reduction inside a unique
4242+ compilation unit to prevent conflicting entries in these memoization tables.
4343+*)
4444+module Make(_ : sig
4545+ val fuel : int
4646+4747+ val read_unit_shape : unit_name:string -> Shape.t option
4848+ end) : sig
4949+ val reduce : Env.t -> Shape.t -> Shape.t
5050+5151+ (** Perform weak reduction and return the head's uid if any. If reduction was
5252+ incomplete the partially reduced shape is returned. *)
5353+ val reduce_for_uid : Env.t -> Shape.t -> result
5454+end
5555+5656+(** [local_reduce] will not reduce shapes that require loading external
5757+ compilation units. *)
5858+val local_reduce : Env.t -> Shape.t -> Shape.t
5959+6060+(** [local_reduce_for_uid] will not reduce shapes that require loading external
6161+ compilation units. *)
6262+val local_reduce_for_uid : Env.t -> Shape.t -> result
+28-8
typing/tast_iterator.ml
···6262 value_bindings: iterator -> (rec_flag * value_binding list) -> unit;
6363 value_description: iterator -> value_description -> unit;
6464 with_constraint: iterator -> with_constraint -> unit;
6565+ item_declaration: iterator -> item_declaration -> unit;
6566 }
66676768let iter_snd f (_, y) = f y
···9293 f x.ci_expr
93949495let module_type_declaration sub x =
9696+ sub.item_declaration sub (Module_type x);
9597 sub.location sub x.mtd_loc;
9698 sub.attributes sub x.mtd_attributes;
9799 iter_loc sub x.mtd_name;
98100 Option.iter (sub.module_type sub) x.mtd_type
99101100100-let module_declaration sub {md_loc; md_name; md_type; md_attributes; _} =
102102+let module_declaration sub md =
103103+ let {md_loc; md_name; md_type; md_attributes; _} = md in
104104+ sub.item_declaration sub (Module md);
101105 sub.location sub md_loc;
102106 sub.attributes sub md_attributes;
103107 iter_loc sub md_name;
104108 sub.module_type sub md_type
105109106106-let module_substitution sub {ms_loc; ms_name; ms_txt; ms_attributes; _} =
110110+let module_substitution sub ms =
111111+ let {ms_loc; ms_name; ms_txt; ms_attributes; _} = ms in
112112+ sub.item_declaration sub (Module_substitution ms);
107113 sub.location sub ms_loc;
108114 sub.attributes sub ms_attributes;
109115 iter_loc sub ms_name;
···115121 f incl_mod
116122117123let class_type_declaration sub x =
124124+ sub.item_declaration sub (Class_type x);
118125 class_infos sub (sub.class_type sub) x
119126120127let class_declaration sub x =
128128+ sub.item_declaration sub (Class x);
121129 class_infos sub (sub.class_expr sub) x
122130123131let structure_item sub {str_loc; str_desc; str_env; _} =
···143151 | Tstr_attribute attr -> sub.attribute sub attr
144152145153let value_description sub x =
154154+ sub.item_declaration sub (Value x);
146155 sub.location sub x.val_loc;
147156 sub.attributes sub x.val_attributes;
148157 iter_loc sub x.val_name;
149158 sub.typ sub x.val_desc
150159151151-let label_decl sub {ld_loc; ld_name; ld_type; ld_attributes; _} =
160160+let label_decl sub ({ld_loc; ld_name; ld_type; ld_attributes; _} as ld) =
161161+ sub.item_declaration sub (Label ld);
152162 sub.location sub ld_loc;
153163 sub.attributes sub ld_attributes;
154164 iter_loc sub ld_name;
···159169 | Cstr_record l -> List.iter (label_decl sub) l
160170161171let constructor_decl sub x =
172172+ sub.item_declaration sub (Constructor x);
162173 sub.location sub x.cd_loc;
163174 sub.attributes sub x.cd_attributes;
164175 iter_loc sub x.cd_name;
···173184 | Ttype_open -> ()
174185175186let type_declaration sub x =
187187+ sub.item_declaration sub (Type x);
176188 sub.location sub x.typ_loc;
177189 sub.attributes sub x.typ_attributes;
178190 iter_loc sub x.typ_name;
···200212 sub.attributes sub tyexn_attributes;
201213 sub.extension_constructor sub tyexn_constructor
202214203203-let extension_constructor sub {ext_loc; ext_name; ext_kind; ext_attributes; _} =
215215+let extension_constructor sub ec =
216216+ let {ext_loc; ext_name; ext_kind; ext_attributes; _} = ec in
217217+ sub.item_declaration sub (Extension_constructor ec);
204218 sub.location sub ext_loc;
205219 sub.attributes sub ext_attributes;
206220 iter_loc sub ext_name;
···229243 List.iter (pat_extra sub) extra;
230244 match pat_desc with
231245 | Tpat_any -> ()
232232- | Tpat_var (_, s) -> iter_loc sub s
246246+ | Tpat_var (_, s, _) -> iter_loc sub s
233247 | Tpat_constant _ -> ()
234248 | Tpat_tuple l -> List.iter (sub.pat sub) l
235249 | Tpat_construct (lid, _, l, vto) ->
···241255 | Tpat_record (l, _) ->
242256 List.iter (fun (lid, _, i) -> iter_loc sub lid; sub.pat sub i) l
243257 | Tpat_array l -> List.iter (sub.pat sub) l
244244- | Tpat_alias (p, _, s) -> sub.pat sub p; iter_loc sub s
258258+ | Tpat_alias (p, _, s, _) -> sub.pat sub p; iter_loc sub s
245259 | Tpat_lazy p -> sub.pat sub p
246260 | Tpat_value p -> sub.pat sub (p :> pattern)
247261 | Tpat_exception p -> sub.pat sub p
···399413 | Tsig_attribute _ -> ()
400414401415let class_description sub x =
416416+ sub.item_declaration sub (Class_type x);
402417 class_infos sub (sub.class_type sub) x
403418404419let functor_parameter sub = function
···483498 sub.module_coercion sub c
484499 | Tmod_unpack (exp, _) -> sub.expr sub exp
485500486486-let module_binding sub {mb_loc; mb_name; mb_expr; mb_attributes; _} =
501501+let module_binding sub ({mb_loc; mb_name; mb_expr; mb_attributes; _} as mb) =
502502+ sub.item_declaration sub (Module_binding mb);
487503 sub.location sub mb_loc;
488504 sub.attributes sub mb_attributes;
489505 iter_loc sub mb_name;
···616632 Option.iter (sub.expr sub) c_guard;
617633 sub.expr sub c_rhs
618634619619-let value_binding sub {vb_loc; vb_pat; vb_expr; vb_attributes; _} =
635635+let value_binding sub ({vb_loc; vb_pat; vb_expr; vb_attributes; _} as vb) =
636636+ sub.item_declaration sub (Value_binding vb);
620637 sub.location sub vb_loc;
621638 sub.attributes sub vb_attributes;
622639 sub.pat sub vb_pat;
623640 sub.expr sub vb_expr
624641625642let env _sub _ = ()
643643+644644+let item_declaration _sub _ = ()
626645627646let default_iterator =
628647 {
···670689 value_bindings;
671690 value_description;
672691 with_constraint;
692692+ item_declaration;
673693 }
···279279 match x.pat_desc with
280280 | Tpat_any
281281 | Tpat_constant _ -> x.pat_desc
282282- | Tpat_var (id, s) -> Tpat_var (id, map_loc sub s)
282282+ | Tpat_var (id, s, uid) -> Tpat_var (id, map_loc sub s, uid)
283283 | Tpat_tuple l -> Tpat_tuple (List.map (sub.pat sub) l)
284284 | Tpat_construct (loc, cd, l, vto) ->
285285 let vto = Option.map (fun (vl,cty) ->
···290290 | Tpat_record (l, closed) ->
291291 Tpat_record (List.map (tuple3 (map_loc sub) id (sub.pat sub)) l, closed)
292292 | Tpat_array l -> Tpat_array (List.map (sub.pat sub) l)
293293- | Tpat_alias (p, id, s) -> Tpat_alias (sub.pat sub p, id, map_loc sub s)
293293+ | Tpat_alias (p, id, s, uid) ->
294294+ Tpat_alias (sub.pat sub p, id, map_loc sub s, uid)
294295 | Tpat_lazy p -> Tpat_lazy (sub.pat sub p)
295296 | Tpat_value p ->
296297 (as_computation_pattern (sub.pat sub (p :> pattern))).pat_desc
+1-1
typing/typeclass.ml
···13091309 Typecore.type_let In_class_def val_env rec_flag sdefs in
13101310 let (vals, met_env) =
13111311 List.fold_right
13121312- (fun (id, _id_loc, _typ) (vals, met_env) ->
13121312+ (fun (id, _id_loc, _typ, _uid) (vals, met_env) ->
13131313 let path = Pident id in
13141314 (* do not mark the value as used *)
13151315 let vd = Env.find_value path val_env in
+30-22
typing/typecore.ml
···476476 pv_loc: Location.t;
477477 pv_as_var: bool;
478478 pv_attributes: attributes;
479479+ pv_uid : Uid.t;
479480 }
480481481482type module_variable =
···595596 end else
596597 Ident.create_local name.txt
597598 in
599599+ let pv_uid = Uid.mk ~current_unit:(Env.get_unit_name ()) in
598600 tps.tps_pattern_variables <-
599601 {pv_id = id;
600602 pv_type = ty;
601603 pv_loc = loc;
602604 pv_as_var = is_as_variable;
603603- pv_attributes = attrs} :: tps.tps_pattern_variables;
604604- id
605605+ pv_attributes = attrs;
606606+ pv_uid} :: tps.tps_pattern_variables;
607607+ id, pv_uid
605608606609let sort_pattern_variables vs =
607610 List.sort
···671674672675and build_as_type_aux (env : Env.t) p =
673676 match p.pat_desc with
674674- Tpat_alias(p1,_, _) -> build_as_type env p1
677677+ Tpat_alias(p1,_, _, _) -> build_as_type env p1
675678 | Tpat_tuple pl ->
676679 let tyl = List.map (build_as_type env) pl in
677680 newty (Ttuple tyl)
···16411644 pat_env = !!penv }
16421645 | Ppat_var name ->
16431646 let ty = instance expected_ty in
16441644- let id = enter_variable tps loc name ty sp.ppat_attributes in
16471647+ let id, uid = enter_variable tps loc name ty sp.ppat_attributes in
16451648 rvp {
16461646- pat_desc = Tpat_var (id, name);
16491649+ pat_desc = Tpat_var (id, name, uid);
16471650 pat_loc = loc; pat_extra=[];
16481651 pat_type = ty;
16491652 pat_attributes = sp.ppat_attributes;
···16641667 (* We're able to pass ~is_module:true here without an error because
16651668 [Ppat_unpack] is a case identified by [may_contain_modules]. See
16661669 the comment on [may_contain_modules]. *)
16671667- let id =
16701670+ let id, uid =
16681671 enter_variable tps loc v t ~is_module:true sp.ppat_attributes
16691672 in
16701673 rvp {
16711671- pat_desc = Tpat_var (id, v);
16741674+ pat_desc = Tpat_var (id, v, uid);
16721675 pat_loc = sp.ppat_loc;
16731676 pat_extra=[Tpat_unpack, loc, sp.ppat_attributes];
16741677 pat_type = t;
···16811684 (* explicitly polymorphic type *)
16821685 let cty, ty, ty' =
16831686 solve_Ppat_poly_constraint tps !!penv lloc sty expected_ty in
16841684- let id = enter_variable tps lloc name ty' attrs in
16851685- rvp { pat_desc = Tpat_var (id, name);
16871687+ let id, uid = enter_variable tps lloc name ty' attrs in
16881688+ rvp { pat_desc = Tpat_var (id, name, uid);
16861689 pat_loc = lloc;
16871690 pat_extra = [Tpat_constraint cty, loc, sp.ppat_attributes];
16881691 pat_type = ty;
···16911694 | Ppat_alias(sq, name) ->
16921695 let q = type_pat tps Value sq expected_ty in
16931696 let ty_var = solve_Ppat_alias !!penv q in
16941694- let id =
16971697+ let id, uid =
16951698 enter_variable
16961699 ~is_as_variable:true tps name.loc name ty_var sp.ppat_attributes
16971700 in
16981698- rvp { pat_desc = Tpat_alias(q, id, name);
17011701+ rvp { pat_desc = Tpat_alias(q, id, name, uid);
16991702 pat_loc = loc; pat_extra=[];
17001703 pat_type = q.pat_type;
17011704 pat_attributes = sp.ppat_attributes;
···19561959 let p = type_pat tps category sp expected_ty' in
19571960 let extra = (Tpat_constraint cty, loc, sp.ppat_attributes) in
19581961 begin match category, (p : k general_pattern) with
19591959- | Value, {pat_desc = Tpat_var (id,s); _} ->
19621962+ | Value, {pat_desc = Tpat_var (id,s,uid); _} ->
19601963 { p with
19611964 pat_type = ty;
19621965 pat_desc =
19631966 Tpat_alias
19641964- ({p with pat_desc = Tpat_any; pat_attributes = []}, id,s);
19671967+ ({p with pat_desc = Tpat_any; pat_attributes = []}, id,s, uid);
19651968 pat_extra = [extra];
19661969 }
19671970 | _, p ->
···2002200520032006let add_pattern_variables ?check ?check_as env pv =
20042007 List.fold_right
20052005- (fun {pv_id; pv_type; pv_loc; pv_as_var; pv_attributes} env ->
20082008+ (fun {pv_id; pv_type; pv_loc; pv_as_var; pv_attributes; pv_uid} env ->
20062009 let check = if pv_as_var then check_as else check in
20072010 Env.add_value ?check pv_id
20082011 {val_type = pv_type; val_kind = Val_reg; Types.val_loc = pv_loc;
20092012 val_attributes = pv_attributes;
20102010- val_uid = Uid.mk ~current_unit:(Env.get_unit_name ());
20132013+ val_uid = pv_uid;
20112014 } env
20122015 )
20132016 pv env
···23392342 in
23402343 check_rec ~info:(decrease 5) tp expected_ty k
23412344 end
23422342- | Tpat_alias (p, _, _) -> check_rec ~info p expected_ty k
23452345+ | Tpat_alias (p, _, _, _) -> check_rec ~info p expected_ty k
23432346 | Tpat_constant cst ->
23442347 let cst = constant_or_raise !!penv loc (Untypeast.constant cst) in
23452348 k @@ solve_expected (mp (Tpat_constant cst) ~pat_type:(type_constant cst))
···30933096 [] -> Ident.create_local default
30943097 | p :: rem ->
30953098 match p.pat_desc with
30963096- Tpat_var (id, _) -> id
30973097- | Tpat_alias(_, id, _) -> id
30993099+ Tpat_var (id, _, _) -> id
31003100+ | Tpat_alias(_, id, _, _) -> id
30983101 | _ -> name_pattern default rem
3099310231003103let name_cases default lst =
···40054008 | _ -> Mp_present
40064009 in
40074010 let scope = create_scope () in
40114011+ let md_uid = Uid.mk ~current_unit:(Env.get_unit_name ()) in
40124012+ let md_shape = Shape.set_uid_if_none md_shape md_uid in
40084013 let md =
40094014 { md_type = modl.mod_type; md_attributes = [];
40104015 md_loc = name.loc;
40114011- md_uid = Uid.mk ~current_unit:(Env.get_unit_name ()); }
40164016+ md_uid; }
40124017 in
40134018 let (id, new_env) =
40144019 match name.txt with
···40444049 exp_attributes = sexp.pexp_attributes;
40454050 exp_env = env }
40464051 | Pexp_letexception(cd, sbody) ->
40474047- let (cd, newenv) = Typedecl.transl_exception env cd in
40524052+ let (cd, newenv, _shape) = Typedecl.transl_exception env cd in
40484053 let body = type_expect newenv sbody ty_expected_explained in
40494054 re {
40504055 exp_desc = Texp_letexception(cd, body);
···51815186 }
51825187 in
51835188 let exp_env = Env.add_value id desc env in
51845184- {pat_desc = Tpat_var (id, mknoloc name); pat_type = ty;pat_extra=[];
51895189+ {pat_desc =
51905190+ Tpat_var (id, mknoloc name, desc.val_uid);
51915191+ pat_type = ty;
51925192+ pat_extra=[];
51855193 pat_attributes = [];
51865194 pat_loc = Location.none; pat_env = env},
51875195 {exp_type = ty; exp_loc = Location.none; exp_env = exp_env;
···60406048 List.iter
60416049 (fun {vb_pat=pat} -> match pat.pat_desc with
60426050 Tpat_var _ -> ()
60436043- | Tpat_alias ({pat_desc=Tpat_any}, _, _) -> ()
60516051+ | Tpat_alias ({pat_desc=Tpat_any}, _, _, _) -> ()
60446052 | _ -> raise(Error(pat.pat_loc, env, Illegal_letrec_pat)))
60456053 l;
60466054 List.iter (fun vb ->