···495495- #13289: Use C99 for loop to reduce the scope of the for loop iterator.
496496 (Antonin Décimo, review by Miod Vallat and Gabriel Scherer)
497497498498+- #13308: keep track of relations between declaration in the cmt files. This is
499499+ useful information for external tools for navigation and analysis purposis.
500500+ (Ulysse Gérard, Florian Angeletti, review by Florian Angeletti and Gabriel
501501+ Scherer)
502502+498503- #13336: compiler-libs, split the `Printtyp` in three to only keep
499504 "user-friendly" functions in the `Printtyp` module.
500505 (Florian Angeletti, review by Gabriel Scherer)
···11+(* TEST
22+33+flags = "-bin-annot -bin-annot-occurrences";
44+compile_only = "true";
55+setup-ocamlc.byte-build-env;
66+all_modules = "link_intf_impl.mli link_intf_impl.ml";
77+ocamlc.byte;
88+check-ocamlc.byte-output;
99+1010+program = "-quiet -uid-deps link_intf_impl.cmt";
1111+output = "out_objinfo";
1212+ocamlobjinfo;
1313+1414+check-program-output;
1515+*)
1616+1717+let x (* 0 *) = 42
1818+1919+type t (* 1 *) = int
2020+2121+module type S (* 3 *) = sig
2222+ val y (* 2 *) : t
2323+end
2424+2525+module M (* 5 *) : S = struct
2626+ let y (* 4 *) = 36
2727+end
2828+2929+module N (* 8 *) : sig
3030+ val y (* 7 *) : int
3131+end = struct
3232+ let y (* 6 *) = 2
3333+end
3434+3535+let _ = (module N : S)
3636+3737+module P (* 10 *)= struct
3838+ let y (* 9 *) = 12
3939+end
4040+4141+module F (* 12 *) (X (* 11 *) : S) = X
4242+4343+module G (* 13 *) = F(P)
4444+4545+module type Initial (* 16 *) = sig
4646+ module type Nested (* 15 *) = sig
4747+ type t (* 14 *)
4848+ end
4949+end
5050+5151+module MF (* 23 *) : sig
5252+ module F (* 22 *) (X (* 21 *) : sig val x (* 20 *) : int end) : sig end
5353+end = struct
5454+ module F (* 19 *) (X (* 18 *) : sig val x (* 17 *) : int end) = struct end
5555+end
5656+5757+module FMT (* 27 *) (X (* 26 *) : sig
5858+ module type MT (* 25 *) = sig val x (* 24 *) : int end
5959+end) : sig end = struct end
+19
testsuite/tests/uid-deps/link_intf_impl.mli
···11+type t (* 0 *)
22+33+val x (* 1 *) : t
44+55+module type S (* 3 *) = sig
66+ val y (* 2 *) : t
77+end
88+99+module M (* 4 *) : S
1010+1111+module type Initial (* 7 *) = sig
1212+ module type Nested (* 6 *) = sig
1313+ type t (* 5 *)
1414+ end
1515+end
1616+1717+module FMT (* 11 *) (X (* 10 *) : sig
1818+ module type MT (* 9 *) = sig val x (* 8 *) : int end
1919+end) : sig end
···3131let shape = ref false
3232let index = ref false
3333let decls = ref false
3434+let uid_deps = ref false
34353536module Magic_number = Misc.Magic_number
3637···128129 Shape_reduce.print_result item pp_loc loc)
129130 cmt.cmt_ident_occurrences;
130131 Format.print_flush ()
132132+ end;
133133+ if !uid_deps then begin
134134+ printf "\nUid dependencies:\n";
135135+ let arr = Array.of_list cmt.cmt_declaration_dependencies in
136136+ let () =
137137+ Array.sort (fun (_tr, u1, u2) (_tr', u1', u2') ->
138138+ match Shape.Uid.compare u1 u1' with
139139+ | 0 -> Shape.Uid.compare u2 u2'
140140+ | n -> n) arr
141141+ in
142142+ Format.printf "@[<v>";
143143+ Array.iter (fun (rk, u1, u2) ->
144144+ let rk = match rk with
145145+ | Definition_to_declaration -> "<-"
146146+ | Declaration_to_declaration -> "<->"
147147+ in
148148+ Format.printf "@[<h>%a %s %a@]@;"
149149+ Shape.Uid.print u1
150150+ rk
151151+ Shape.Uid.print u2) arr;
152152+ Format.printf "@]";
131153 end;
132154 if !decls then begin
133155 printf "\nUid of decls:\n";
···456478 " Print a list of all usages of values, types, etc. in the module";
457479 "-decls", Arg.Set decls,
458480 " Print a list of all declarations in the module";
481481+ "-uid-deps", Arg.Set uid_deps,
482482+ " Print the declarations' uids dependencies of the module";
459483 "-null-crc", Arg.Set no_crc, " Print a null CRC for imported interfaces";
460484 "-version", Arg.Unit print_version, " Print version and exit";
461485 "-vnum", Arg.Unit print_version_num, " Print version number and exit";
+1-1
toplevel/topcommon.ml
···216216 in
217217 if !Clflags.dump_typedtree then Printtyped.implementation ppf str;
218218 let sg' = Typemod.Signature_names.simplify newenv sn sg in
219219- ignore (Includemod.signatures ~mark:Mark_positive oldenv sg sg');
219219+ Includemod.check_implementation oldenv sg sg';
220220 Typecore.force_delayed_checks ();
221221 let shape = Shape_reduce.local_reduce Env.empty shape in
222222 if !Clflags.dump_shape then Shape.print ppf shape;
+210-110
typing/includemod.ml
···134134135135end
136136137137-type mark =
137137+module Directionality = struct
138138+139139+140140+ type mark =
138141 | Mark_both
139142 | Mark_positive
140140- | Mark_negative
141143 | Mark_neither
142144143143-let negate_mark = function
144144- | Mark_both -> Mark_both
145145- | Mark_positive -> Mark_negative
146146- | Mark_negative -> Mark_positive
147147- | Mark_neither -> Mark_neither
145145+ type pos =
146146+ | Strictly_positive
147147+ (** Strictly positive positions are notable for tools since they are the
148148+ the case where we match a implementation definition with an interface
149149+ declaration. Oherwise in the positive case we are matching
150150+ declatations inside functor arguments at even level of nesting.*)
151151+ | Positive
152152+ | Negative
148153149149-let mark_positive = function
150150- | Mark_both | Mark_positive -> true
151151- | Mark_negative | Mark_neither -> false
154154+155155+(**
156156+ When checking inclusion, the [Directionality.t] type tracks the
157157+ subtyping direction at the syntactic level.
158158+159159+ The [posivity] field is used in the [cmt_declaration_dependencies] to
160160+ distinguish between directed and undirected edges, and to avoid recording
161161+ matched declarations twice.
162162+163163+ The [mark_as_used] field describes if we should record only positive use,
164164+ any use (because there is no clear implementation side), or none (because we
165165+ are inside an auxiliary check function.)
166166+167167+ The [in_eq] field is [true] when we are checking both directions inside of
168168+ module types which allows optimizing module type equality checks. The module
169169+ subtyping relation [A <: B] checks that [A.T = B.T] when [A] and [B] define a
170170+ module type [T]. The relation [A.T = B.T] is equivalent to [(A.T <: B.T) and
171171+ (B.T <: A.T)], but checking both recursively would lead to an exponential
172172+ slowdown (see #10598 and #10616). To avoid this issue, when [in_eq] is
173173+ [true], we compute a coarser relation [A << B] which is the same as [A <: B]
174174+ except that module types [T] are checked only for [A.T << B.T] and not the
175175+ reverse. Thus, we can implement a cheap module type equality check [A.T =
176176+ B.T] by computing [(A.T << B.T) and (B.T << A.T)], avoiding the exponential
177177+ slowdown described above.
178178+*)
179179+ type t = {
180180+ in_eq:bool;
181181+ mark_as_used:mark;
182182+ pos:pos;
183183+ }
184184+185185+ let strictly_positive ~mark =
186186+ let mark_as_used = if mark then Mark_positive else Mark_neither in
187187+ { in_eq=false; pos=Strictly_positive; mark_as_used }
188188+189189+ let unknown ~mark =
190190+ let mark_as_used = if mark then Mark_both else Mark_neither in
191191+ { in_eq=false; pos=Positive; mark_as_used }
192192+193193+ let negate_pos = function
194194+ | Positive | Strictly_positive -> Negative
195195+ | Negative -> Positive
196196+197197+ let negate d = { d with pos = negate_pos d.pos }
198198+199199+ let at_most_positive = function
200200+ | Strictly_positive -> Positive
201201+ | Positive | Negative as non_strict -> non_strict
202202+203203+ let enter_eq d =
204204+ {
205205+ in_eq = true;
206206+ pos = at_most_positive d.pos;
207207+ mark_as_used = d.mark_as_used
208208+ }
209209+210210+ let mark_as_used d = match d.mark_as_used with
211211+ | Mark_neither -> false
212212+ | Mark_both -> true
213213+ | Mark_positive ->
214214+ match d.pos with
215215+ | Positive | Strictly_positive -> true
216216+ | Negative -> false
217217+218218+end
152219153220module Core_inclusion = struct
154221 (* All functions "blah env x1 x2" check that x1 is included in x2,
···157224158225 (* Inclusion between value descriptions *)
159226160160- let value_descriptions ~loc env ~mark subst id vd1 vd2 =
161161- Cmt_format.record_value_dependency vd1 vd2;
162162- if mark_positive mark then
227227+ let value_descriptions ~loc env ~direction subst id vd1 vd2 =
228228+ if Directionality.mark_as_used direction then
163229 Env.mark_value_used vd1.val_uid;
164230 let vd2 = Subst.value_description subst vd2 in
165231 try
···169235170236 (* Inclusion between type declarations *)
171237172172- let type_declarations ~loc env ~mark subst id decl1 decl2 =
173173- let mark = mark_positive mark in
238238+ let type_declarations ~loc env ~direction subst id decl1 decl2 =
239239+ let mark = Directionality.mark_as_used direction in
174240 if mark then
175241 Env.mark_type_used decl1.type_uid;
176242 let decl2 = Subst.type_declaration subst decl2 in
···184250185251 (* Inclusion between extension constructors *)
186252187187- let extension_constructors ~loc env ~mark subst id ext1 ext2 =
188188- let mark = mark_positive mark in
253253+ let extension_constructors ~loc env ~direction subst id ext1 ext2 =
254254+ let mark = Directionality.mark_as_used direction in
189255 let ext2 = Subst.extension_constructor subst ext2 in
190256 match Includecore.extension_constructors ~loc env ~mark id ext1 ext2 with
191257 | None -> Ok Tcoerce_none
···194260195261 (* Inclusion between class declarations *)
196262197197- let class_type_declarations ~loc env ~mark:_ subst _id decl1 decl2 =
263263+ let class_type_declarations ~loc env ~direction:_ subst _id decl1 decl2 =
198264 let decl2 = Subst.cltype_declaration subst decl2 in
199265 match Includeclass.class_type_declarations ~loc env decl1 decl2 with
200266 [] -> Ok Tcoerce_none
201267 | reason ->
202268 Error Error.(Core(Class_type_declarations(diff decl1 decl2 reason)))
203269204204- let class_declarations ~loc:_ env ~mark:_ subst _id decl1 decl2 =
270270+ let class_declarations ~loc:_ env ~direction:_ subst _id decl1 decl2 =
205271 let decl2 = Subst.class_declaration subst decl2 in
206272 match Includeclass.class_declarations env decl1 decl2 with
207273 [] -> Ok Tcoerce_none
···415481 - the coarse-grain consistency relation [C], which is defined by
416482 [d1 C d2] if there is an environment [E] such that [E |- d1 <: d2]. *)
417483type 'a core_incl =
418418- loc:Location.t -> Env.t -> mark:mark -> Subst.t -> Ident.t ->
484484+ loc:Location.t -> Env.t -> direction:Directionality.t -> Subst.t -> Ident.t ->
419485 'a -> 'a -> (module_coercion, Error.sigitem_symptom) result
420486421487type core_relation = {
···426492 class_type_declarations: Types.class_type_declaration core_incl;
427493}
428494429429-(**
430430- In the group of mutual functions below, the [~in_eq] argument is [true] when
431431- we are in fact checking equality of module types.
432495433433- The module subtyping relation [A <: B] checks that [A.T = B.T] when [A]
434434- and [B] define a module type [T]. The relation [A.T = B.T] is equivalent
435435- to [(A.T <: B.T) and (B.T <: A.T)], but checking both recursively would lead
436436- to an exponential slowdown (see #10598 and #10616).
437437- To avoid this issue, when [~in_eq] is [true], we compute a coarser relation
438438- [A << B] which is the same as [A <: B] except that module types [T] are
439439- checked only for [A.T << B.T] and not the reverse.
440440- Thus, we can implement a cheap module type equality check [A.T = B.T] by
441441- computing [(A.T << B.T) and (B.T << A.T)], avoiding the exponential slowdown
442442- described above.
443443-*)
444444-445445-let rec modtypes ~core ~in_eq ~loc env ~mark subst mty1 mty2 shape =
446446- match try_modtypes ~core ~in_eq ~loc env ~mark subst mty1 mty2 shape with
496496+let rec modtypes ~core ~direction ~loc env subst mty1 mty2 shape =
497497+ match try_modtypes ~core ~direction ~loc env subst mty1 mty2 shape with
447498 | Ok _ as ok -> ok
448499 | Error reason ->
449500 let mty2 = Subst.modtype Make_local subst mty2 in
450501 Error Error.(diff mty1 mty2 reason)
451502452452-and try_modtypes ~core ~in_eq ~loc env ~mark subst mty1 mty2 orig_shape =
503503+and try_modtypes ~core ~direction ~loc env subst mty1 mty2 orig_shape =
453504 match mty1, mty2 with
454505 | (Mty_alias p1, Mty_alias p2) ->
455506 if Env.is_functor_arg p2 env then
···467518 begin match expand_module_alias ~strengthen:false env p1 with
468519 | Error e -> Error (Error.Mt_core e)
469520 | Ok mty1 ->
470470- match strengthened_modtypes ~core ~in_eq ~loc ~aliasable:true env
471471- ~mark subst mty1 p1 mty2 orig_shape
521521+ match strengthened_modtypes ~core ~direction ~loc ~aliasable:true
522522+ env subst mty1 p1 mty2 orig_shape
472523 with
473524 | Ok _ as x -> x
474525 | Error reason -> Error (Error.After_alias_expansion reason)
···481532 else
482533 begin match expand_modtype_path env p1, expand_modtype_path env p2 with
483534 | Some mty1, Some mty2 ->
484484- try_modtypes ~core ~in_eq ~loc env ~mark subst mty1 mty2 orig_shape
535535+ try_modtypes ~core ~direction ~loc env subst mty1 mty2 orig_shape
485536 | None, _ | _, None -> Error (Error.Mt_core Abstract_module_type)
486537 end
487538 | (Mty_ident p1, _) ->
488539 let p1 = Env.normalize_modtype_path env p1 in
489540 begin match expand_modtype_path env p1 with
490541 | Some p1 ->
491491- try_modtypes ~core ~in_eq ~loc env ~mark subst p1 mty2 orig_shape
542542+ try_modtypes ~core ~direction ~loc env subst p1 mty2 orig_shape
492543 | None -> Error (Error.Mt_core Abstract_module_type)
493544 end
494545 | (_, Mty_ident p2) ->
495546 let p2 = Env.normalize_modtype_path env (Subst.modtype_path subst p2) in
496547 begin match expand_modtype_path env p2 with
497548 | Some p2 ->
498498- try_modtypes ~core ~in_eq ~loc env ~mark subst mty1 p2 orig_shape
549549+ try_modtypes ~core ~direction ~loc env subst mty1 p2 orig_shape
499550 | None ->
500551 begin match mty1 with
501552 | Mty_functor _ ->
···507558 end
508559 | (Mty_signature sig1, Mty_signature sig2) ->
509560 begin match
510510- signatures ~core ~in_eq ~loc env ~mark subst sig1 sig2 orig_shape
561561+ signatures ~core ~direction ~loc env subst sig1 sig2 orig_shape
511562 with
512563 | Ok _ as ok -> ok
513564 | Error e -> Error (Error.Signature e)
514565 end
515566 | Mty_functor (param1, res1), Mty_functor (param2, res2) ->
516567 let cc_arg, env, subst =
517517- functor_param ~core ~in_eq ~loc env ~mark:(negate_mark mark)
568568+ let direction = Directionality.negate direction in
569569+ functor_param ~core ~direction ~loc env
518570 subst param1 param2
519571 in
520572 let var, res_shape =
···532584 var, Shape.app orig_shape ~arg:shape_var
533585 in
534586 let cc_res =
535535- modtypes ~core ~in_eq ~loc env ~mark subst res1 res2 res_shape
587587+ modtypes ~core ~direction ~loc env subst res1 res2 res_shape
536588 in
537589 begin match cc_arg, cc_res with
538590 | Ok Tcoerce_none, Ok (Tcoerce_none, final_res_shape) ->
···575627576628(* Functor parameters *)
577629578578-and functor_param ~core ~in_eq ~loc env ~mark subst param1 param2 =
630630+and functor_param ~core ~direction ~loc env subst param1 param2 =
579631 match param1, param2 with
580632 | Unit, Unit ->
581633 Ok Tcoerce_none, env, subst
···583635 let arg2' = Subst.modtype Keep subst arg2 in
584636 let cc_arg =
585637 match
586586- modtypes ~core ~in_eq ~loc env ~mark Subst.identity arg2' arg1
638638+ modtypes ~core ~direction ~loc env Subst.identity arg2' arg1
587639 Shape.dummy_mod
588640 with
589641 | Ok (cc, _) -> Ok cc
···611663 | None, None ->
612664 env, subst
613665614614-and strengthened_modtypes ~core ~in_eq ~loc ~aliasable env ~mark
666666+and strengthened_modtypes ~core ~direction ~loc ~aliasable env
615667 subst mty1 path1 mty2 shape =
616668 match mty1, mty2 with
617669 | Mty_ident p1, Mty_ident p2 when equal_modtype_paths env p1 subst p2 ->
618670 Ok (Tcoerce_none, shape)
619671 | _, _ ->
620672 let mty1 = Mtype.strengthen ~aliasable env mty1 path1 in
621621- modtypes ~core ~in_eq ~loc env ~mark subst mty1 mty2 shape
673673+ modtypes ~core ~direction ~loc env subst mty1 mty2 shape
622674623623-and strengthened_module_decl ~core ~loc ~aliasable env ~mark
675675+and strengthened_module_decl ~core ~loc ~aliasable ~direction env
624676 subst md1 path1 md2 shape =
625677 match md1.md_type, md2.md_type with
626678 | Mty_ident p1, Mty_ident p2 when equal_modtype_paths env p1 subst p2 ->
627679 Ok (Tcoerce_none, shape)
628680 | _, _ ->
629681 let md1 = Mtype.strengthen_decl ~aliasable env md1 path1 in
630630- modtypes ~core ~in_eq:false ~loc env ~mark subst
631631- md1.md_type md2.md_type shape
682682+ modtypes ~core ~direction ~loc env subst md1.md_type md2.md_type shape
632683633684(* Inclusion between signatures *)
634685635635-and signatures ~core ~in_eq ~loc env ~mark subst sig1 sig2 mod_shape =
686686+and signatures ~core ~direction ~loc env subst sig1 sig2 mod_shape =
636687 (* Environment used to check inclusion of components *)
637688 let new_env =
638689 Env.add_signature sig1 (Env.in_signature true env) in
···681732 [] ->
682733 let open Sign_diff in
683734 let d =
684684- signature_components ~core ~in_eq ~loc env ~mark new_env subst
735735+ signature_components ~core ~direction ~loc env new_env subst
685736 mod_shape Shape.Map.empty
686737 (List.rev paired)
687738 in
···745796746797(* Inclusion between signature components *)
747798748748-and signature_components ~core ~in_eq ~loc old_env ~mark env subst
799799+and signature_components ~core ~direction ~loc old_env env subst
749800 orig_shape shape_map paired =
750801 match paired with
751802 | [] -> Sign_diff.{ empty with shape_map }
752803 | (sigi1, sigi2, pos) :: rem ->
753804 let shape_modified = ref false in
754754- let id, item, shape_map, present_at_runtime =
805805+ let id, item, paired_uids, shape_map, present_at_runtime =
755806 match sigi1, sigi2 with
756807 | Sig_value(id1, valdecl1, _) ,Sig_value(_id2, valdecl2, _) ->
757808 let item =
758758- core.value_descriptions ~loc env ~mark subst id1
809809+ core.value_descriptions ~loc ~direction env subst id1
759810 valdecl1 valdecl2
760811 in
761812 let item = mark_error_as_recoverable item in
···764815 | _ -> true
765816 in
766817 let shape_map = Shape.Map.add_value_proj shape_map id1 orig_shape in
767767- id1, item, shape_map, present_at_runtime
818818+ let paired_uids = (valdecl1.val_uid, valdecl2.val_uid) in
819819+ id1, item, paired_uids, shape_map, present_at_runtime
768820 | Sig_type(id1, tydec1, _, _), Sig_type(_id2, tydec2, _, _) ->
769821 let item =
770770- core.type_declarations ~loc env ~mark subst id1 tydec1 tydec2
822822+ core.type_declarations ~loc ~direction env subst id1 tydec1 tydec2
771823 in
772824 let item = mark_error_as_unrecoverable item in
773825 (* Right now we don't filter hidden constructors / labels from the
774826 shape. *)
775827 let shape_map = Shape.Map.add_type_proj shape_map id1 orig_shape in
776776- id1, item, shape_map, false
828828+ id1, item, (tydec1.type_uid, tydec2.type_uid), shape_map, false
777829 | Sig_typext(id1, ext1, _, _), Sig_typext(_id2, ext2, _, _) ->
778830 let item =
779779- core.extension_constructors ~loc env ~mark subst id1 ext1 ext2
831831+ core.extension_constructors ~loc ~direction env subst id1
832832+ ext1 ext2
780833 in
781834 let item = mark_error_as_unrecoverable item in
782835 let shape_map =
783836 Shape.Map.add_extcons_proj shape_map id1 orig_shape
784837 in
785785- id1, item, shape_map, true
838838+ id1, item, (ext1.ext_uid, ext2.ext_uid), shape_map, true
786839 | Sig_module(id1, pres1, mty1, _, _), Sig_module(_, pres2, mty2, _, _)
787840 -> begin
788841 let orig_shape =
789842 Shape.(proj orig_shape (Item.module_ id1))
790843 in
791844 let item =
792792- module_declarations ~core ~in_eq ~loc env ~mark subst id1
845845+ module_declarations ~core ~direction ~loc env subst id1
793846 mty1 mty2 orig_shape
794847 in
795848 let item, shape_map =
···814867 | Mp_absent, Mp_present, _ -> assert false
815868 in
816869 let item = mark_error_as_unrecoverable item in
817817- id1, item, shape_map, present_at_runtime
870870+ let paired_uids = (mty1.md_uid, mty2.md_uid) in
871871+ id1, item, paired_uids, shape_map, present_at_runtime
818872 end
819873 | Sig_modtype(id1, info1, _), Sig_modtype(_id2, info2, _) ->
820874 let item =
821821- modtype_infos ~core ~in_eq ~loc env ~mark subst id1 info1 info2
875875+ modtype_infos ~core ~direction ~loc env subst id1 info1 info2
822876 in
823877 let shape_map =
824878 Shape.Map.add_module_type_proj shape_map id1 orig_shape
825879 in
826880 let item = mark_error_as_unrecoverable item in
827827- id1, item, shape_map, false
881881+ id1, item, (info1.mtd_uid, info2.mtd_uid), shape_map, false
828882 | Sig_class(id1, decl1, _, _), Sig_class(_id2, decl2, _, _) ->
829883 let item =
830830- core.class_declarations ~loc env ~mark subst id1 decl1 decl2
884884+ core.class_declarations ~loc ~direction env subst id1 decl1 decl2
831885 in
832886 let shape_map =
833887 Shape.Map.add_class_proj shape_map id1 orig_shape
834888 in
835889 let item = mark_error_as_unrecoverable item in
836836- id1, item, shape_map, true
890890+ id1, item, (decl1.cty_uid, decl2.cty_uid), shape_map, true
837891 | Sig_class_type(id1, info1, _, _), Sig_class_type(_id2, info2, _, _) ->
838892 let item =
839839- core.class_type_declarations ~loc env ~mark subst id1 info1 info2
893893+ core.class_type_declarations ~loc ~direction env subst id1
894894+ info1 info2
840895 in
841896 let item = mark_error_as_unrecoverable item in
842897 let shape_map =
843898 Shape.Map.add_class_type_proj shape_map id1 orig_shape
844899 in
845845- id1, item, shape_map, false
900900+ id1, item, (info1.clty_uid, info2.clty_uid), shape_map, false
846901 | _ ->
847902 assert false
848903 in
···850905 let first =
851906 match item with
852907 | Ok x ->
908908+ begin match direction with
909909+ | { Directionality.in_eq = true; pos = Negative }
910910+ | { Directionality.mark_as_used = Mark_neither; _ } ->
911911+ (* We do not store paired uids when checking for reverse
912912+ module-type inclusion as it would introduce duplicates. *)
913913+ ()
914914+ | { Directionality.pos; _} ->
915915+ let paired_uids =
916916+ let elt1, elt2 = paired_uids in
917917+ match pos with
918918+ | Negative ->
919919+ (Cmt_format.Declaration_to_declaration, elt2, elt1)
920920+ | Positive ->
921921+ (Cmt_format.Declaration_to_declaration, elt1, elt2)
922922+ | Strictly_positive ->
923923+ (Cmt_format. Definition_to_declaration, elt1, elt2)
924924+ in
925925+ Cmt_format.record_declaration_dependency paired_uids
926926+ end;
853927 let runtime_coercions =
854928 if present_at_runtime then [pos,x] else []
855929 in
···863937 in
864938 let rest =
865939 if continue then
866866- signature_components ~core ~in_eq ~loc old_env ~mark env subst
940940+ signature_components ~core ~direction ~loc old_env env subst
867941 orig_shape shape_map rem
868942 else Sign_diff.{ empty with leftovers=rem }
869943 in
870944 Sign_diff.merge first rest
871945872872-and module_declarations ~in_eq ~loc env ~mark subst id1 md1 md2 orig_shape =
946946+and module_declarations ~direction ~loc env subst id1 md1 md2 orig_shape =
873947 Builtin_attributes.check_alerts_inclusion
874948 ~def:md1.md_loc
875949 ~use:md2.md_loc
···877951 md1.md_attributes md2.md_attributes
878952 (Ident.name id1);
879953 let p1 = Path.Pident id1 in
880880- if mark_positive mark then
954954+ if Directionality.mark_as_used direction then
881955 Env.mark_module_used md1.md_uid;
882882- strengthened_modtypes ~in_eq ~loc ~aliasable:true env ~mark subst
956956+ strengthened_modtypes ~direction ~loc ~aliasable:true env subst
883957 md1.md_type p1 md2.md_type orig_shape
884958885959(* Inclusion between module type specifications *)
886960887887-and modtype_infos ~core ~in_eq ~loc env ~mark subst id info1 info2 =
961961+and modtype_infos ~core ~direction ~loc env subst id info1 info2 =
888962 Builtin_attributes.check_alerts_inclusion
889963 ~def:info1.mtd_loc
890964 ~use:info2.mtd_loc
···897971 (None, None) -> Ok Tcoerce_none
898972 | (Some _, None) -> Ok Tcoerce_none
899973 | (Some mty1, Some mty2) ->
900900- check_modtype_equiv ~core ~in_eq ~loc env ~mark mty1 mty2
974974+ check_modtype_equiv ~core ~direction ~loc env mty1 mty2
901975 | (None, Some mty2) ->
902976 let mty1 = Mty_ident(Path.Pident id) in
903903- check_modtype_equiv ~core ~in_eq ~loc env ~mark mty1 mty2 in
977977+ check_modtype_equiv ~core ~direction ~loc env mty1 mty2 in
904978 match r with
905979 | Ok _ as ok -> ok
906980 | Error e -> Error Error.(Module_type_declaration (diff info1 info2 e))
907981908908-and check_modtype_equiv ~core ~in_eq ~loc env ~mark mty1 mty2 =
982982+and check_modtype_equiv ~core ~direction ~loc env mty1 mty2 =
983983+ let nested_eq = direction.Directionality.in_eq in
984984+ let direction = Directionality.enter_eq direction in
909985 let c1 =
910910- modtypes ~core ~in_eq:true ~loc env ~mark Subst.identity mty1 mty2
911911- Shape.dummy_mod
986986+ modtypes ~core ~direction ~loc env Subst.identity mty1 mty2 Shape.dummy_mod
912987 in
913988 let c2 =
914989 (* For nested module type paths, we check only one side of the equivalence:
915990 the outer module type is the one responsible for checking the other side
916991 of the equivalence.
917992 *)
918918- if in_eq then None
993993+ if nested_eq then None
919994 else
920920- let mark = negate_mark mark in
995995+ let direction = Directionality.negate direction in
921996 Some (
922922- modtypes ~core ~in_eq:true ~loc env ~mark Subst.identity
997997+ modtypes ~core ~direction ~loc env Subst.identity
923998 mty2 mty1 Shape.dummy_mod
924999 )
9251000 in
···9541029}
95510309561031let core_consistency =
957957- let type_declarations ~loc:_ env ~mark:_ _ _ d1 d2 =
10321032+ let type_declarations ~loc:_ env ~direction:_ _ _ d1 d2 =
9581033 match Includecore.type_declarations_consistency env d1 d2 with
9591034 | None -> Ok Tcoerce_none
9601035 | Some err -> Error Error.(Core(Type_declarations (diff d1 d2 err)))
9611036 in
962962- let value_descriptions ~loc:_ env ~mark:_ _ _ vd1 vd2 =
10371037+ let value_descriptions ~loc:_ env ~direction:_ _ _ vd1 vd2 =
9631038 match Includecore.value_descriptions_consistency env vd1 vd2 with
9641039 | x -> Ok x
9651040 | exception Includecore.Dont_match err ->
9661041 Error Error.(Core (Value_descriptions (diff vd1 vd2 err)))
9671042 in
968968- let accept ~loc:_ _env ~mark:_ _subst _id _d1 _d2 = Ok Tcoerce_none in
10431043+ let accept ~loc:_ _env ~direction:_ _subst _id _d1 _d2 = Ok Tcoerce_none in
9691044 {
9701045 type_declarations;
9711046 value_descriptions;
···99110669921067let check_modtype_inclusion_raw ~loc env mty1 path1 mty2 =
9931068 let aliasable = can_alias env path1 in
994994- strengthened_modtypes ~core:core_inclusion ~in_eq:false ~loc ~aliasable env
995995- ~mark:Mark_both Subst.identity mty1 path1 mty2 Shape.dummy_mod
10691069+ let direction = Directionality.unknown ~mark:true in
10701070+ strengthened_modtypes ~core:core_inclusion ~direction ~loc ~aliasable env
10711071+ Subst.identity mty1 path1 mty2 Shape.dummy_mod
9961072 |> Result.map fst
99710739981074let check_modtype_inclusion ~loc env mty1 path1 mty2 =
···1028110410291105let compunit env ~mark impl_name impl_sig intf_name intf_sig unit_shape =
10301106 let loc = Location.in_file impl_name in
11071107+ let direction = Directionality.strictly_positive ~mark in
10311108 match
10321032- signatures ~core:core_inclusion ~in_eq:false ~loc env
10331033- ~mark Subst.identity impl_sig intf_sig unit_shape
11091109+ signatures ~core:core_inclusion ~direction ~loc env Subst.identity
11101110+ impl_sig intf_sig unit_shape
10341111 with Result.Error reasons ->
10351112 let cdiff =
10361113 Error.In_Compilation_unit(Error.diff impl_name intf_name reasons) in
···11331210 let test st mty1 mty2 =
11341211 let loc = Location.none in
11351212 let res, _, _ =
11361136- functor_param ~core:core_inclusion ~in_eq:false ~loc st.env
11371137- ~mark:Mark_neither st.subst mty1 mty2
12131213+ let direction=Directionality.unknown ~mark:false in
12141214+ functor_param ~core:core_inclusion ~direction ~loc st.env
12151215+ st.subst mty1 mty2
11381216 in
11391217 res
11401218 let update = update
···12271305 | Unit, Named _ | (Anonymous | Named _), Unit ->
12281306 Result.Error (Error.Incompatible_params(arg,param))
12291307 | ( Anonymous | Named _ | Empty_struct ), Named (_, param) ->
13081308+ let direction=Directionality.unknown ~mark:false in
12301309 match
12311231- modtypes ~core:core_inclusion ~in_eq:false ~loc state.env
12321232- ~mark:Mark_neither state.subst arg_mty param
12331233- Shape.dummy_mod
13101310+ modtypes
13111311+ ~core:core_inclusion ~direction ~loc
13121312+ state.env state.subst arg_mty param
13131313+ Shape.dummy_mod
12341314 with
12351315 | Error mty -> Result.Error (Error.Mismatch mty)
12361316 | Ok (cc, _) -> Ok cc
···12511331(* Hide the context and substitution parameters to the outside world *)
1252133212531333let modtypes_with_shape ~shape ~loc env ~mark mty1 mty2 =
12541254- match modtypes ~core:core_inclusion ~in_eq:false ~loc env ~mark
12551255- Subst.identity mty1 mty2 shape
13341334+ (* modtypes with shape is used when typing module expressions in [Typemod] *)
13351335+ let direction = Directionality.strictly_positive ~mark in
13361336+ match
13371337+ modtypes ~core:core_inclusion ~direction ~loc env Subst.identity
13381338+ mty1 mty2 shape
12561339 with
12571340 | Ok (cc, shape) -> cc, shape
12581341 | Error reason -> raise (Error (env, Error.(In_Module_type reason)))
1259134212601343let modtypes_consistency ~loc env mty1 mty2 =
12611261- match modtypes ~core:core_consistency ~in_eq:false ~loc env ~mark:Mark_neither
12621262- Subst.identity mty1 mty2 Shape.dummy_mod
13441344+ let direction = Directionality.unknown ~mark:false in
13451345+ match
13461346+ modtypes ~core:core_consistency ~direction ~loc env Subst.identity
13471347+ mty1 mty2 Shape.dummy_mod
12631348 with
12641349 | Ok _ -> ()
12651350 | Error reason -> raise (Error (env, Error.(In_Module_type reason)))
1266135112671352let modtypes ~loc env ~mark mty1 mty2 =
12681268- match modtypes ~core:core_inclusion ~in_eq:false ~loc env ~mark
12691269- Subst.identity mty1 mty2 Shape.dummy_mod
13531353+ let direction = Directionality.unknown ~mark in
13541354+ match
13551355+ modtypes ~core:core_inclusion ~direction ~loc env Subst.identity
13561356+ mty1 mty2 Shape.dummy_mod
12701357 with
12711358 | Ok (cc, _) -> cc
12721359 | Error reason -> raise (Error (env, Error.(In_Module_type reason)))
1273136012741274-let signatures env ~mark sig1 sig2 =
12751275- match signatures ~core:core_inclusion ~in_eq:false ~loc:Location.none env
12761276- ~mark Subst.identity sig1 sig2 Shape.dummy_mod
13611361+let gen_signatures env ~direction sig1 sig2 =
13621362+ match
13631363+ signatures
13641364+ ~core:core_inclusion ~direction ~loc:Location.none env
13651365+ Subst.identity sig1 sig2 Shape.dummy_mod
12771366 with
12781367 | Ok (cc, _) -> cc
12791368 | Error reason -> raise (Error(env,Error.(In_Signature reason)))
1280136913701370+let signatures env ~mark sig1 sig2 =
13711371+ let direction = Directionality.unknown ~mark in
13721372+ gen_signatures env ~direction sig1 sig2
13731373+13741374+let check_implementation env impl intf =
13751375+ let direction = Directionality.strictly_positive ~mark:true in
13761376+ ignore (gen_signatures env ~direction impl intf)
13771377+12811378let type_declarations ~loc env ~mark id decl1 decl2 =
12821282- match Core_inclusion.type_declarations ~loc env ~mark
13791379+ let direction = Directionality.unknown ~mark in
13801380+ match Core_inclusion.type_declarations ~loc env ~direction
12831381 Subst.identity id decl1 decl2
12841382 with
12851383 | Ok _ -> ()
···12881386 | Error _ -> assert false
1289138712901388let strengthened_module_decl ~loc ~aliasable env ~mark md1 path1 md2 =
12911291- match strengthened_module_decl ~core:core_inclusion ~loc ~aliasable env ~mark
12921292- Subst.identity md1 path1 md2 Shape.dummy_mod with
13891389+ let direction = Directionality.unknown ~mark in
13901390+ match strengthened_module_decl ~core:core_inclusion ~loc ~aliasable ~direction
13911391+ env Subst.identity md1 path1 md2 Shape.dummy_mod with
12931392 | Ok (x, _shape) -> x
12941393 | Error mdiff ->
12951394 raise (Error(env,Error.(In_Module_type mdiff)))
···13011400 raise (Error(env,In_Expansion(Error.Unbound_module_path path)))
1302140113031402let check_modtype_equiv ~loc env id mty1 mty2 =
13041304- match check_modtype_equiv ~core:core_inclusion ~in_eq:false ~loc env
13051305- ~mark:Mark_both mty1 mty2
14031403+ let direction = Directionality.unknown ~mark:true in
14041404+ match
14051405+ check_modtype_equiv ~core:core_inclusion ~loc ~direction env mty1 mty2
13061406 with
13071407 | Ok _ -> ()
13081408 | Error e ->
+9-20
typing/includemod.mli
···1818open Typedtree
1919open Types
20202121-(** Type describing which arguments of an inclusion to consider as used
2222- for the usage warnings. [Mark_both] is the default. *)
2323-type mark =
2424- | Mark_both
2525- (** Mark definitions used from both arguments *)
2626- | Mark_positive
2727- (** Mark definitions used from the positive (first) argument *)
2828- | Mark_negative
2929- (** Mark definitions used from the negative (second) argument *)
3030- | Mark_neither
3131- (** Do not mark definitions used from either argument *)
3232-3321module Error: sig
34223523 type ('elt,'explanation) diff = {
···152140(* Typechecking *)
153141154142val modtypes:
155155- loc:Location.t -> Env.t -> mark:mark ->
143143+ loc:Location.t -> Env.t -> mark:bool ->
156144 module_type -> module_type -> module_coercion
157157-158145159146val modtypes_consistency:
160147 loc:Location.t -> Env.t -> module_type -> module_type -> unit
161148162149val modtypes_with_shape:
163163- shape:Shape.t -> loc:Location.t -> Env.t -> mark:mark ->
150150+ shape:Shape.t -> loc:Location.t -> Env.t -> mark:bool ->
164151 module_type -> module_type -> module_coercion * Shape.t
165152166153val strengthened_module_decl:
167167- loc:Location.t -> aliasable:bool -> Env.t -> mark:mark ->
154154+ loc:Location.t -> aliasable:bool -> Env.t -> mark:bool ->
168155 module_declaration -> Path.t -> module_declaration -> module_coercion
169156170157val check_modtype_inclusion :
···177164val check_modtype_equiv:
178165 loc:Location.t -> Env.t -> Ident.t -> module_type -> module_type -> unit
179166180180-val signatures: Env.t -> mark:mark ->
181181- signature -> signature -> module_coercion
167167+val signatures: Env.t -> mark:bool -> signature -> signature -> module_coercion
168168+169169+(** Check an implementation against an interface *)
170170+val check_implementation: Env.t -> signature -> signature -> unit
182171183172val compunit:
184184- Env.t -> mark:mark -> string -> signature ->
173173+ Env.t -> mark:bool -> string -> signature ->
185174 string -> signature -> Shape.t -> module_coercion * Shape.t
186175187176val type_declarations:
188188- loc:Location.t -> Env.t -> mark:mark ->
177177+ loc:Location.t -> Env.t -> mark:bool ->
189178 Ident.t -> type_declaration -> type_declaration -> unit
190179191180val print_coercion: Format.formatter -> module_coercion -> unit
+12-14
typing/typemod.ml
···232232 | Some fresh_row_id -> Env.add_type ~check:false fresh_row_id newdecl env
233233 in
234234 let env = Env.add_signature sg env in
235235- Includemod.type_declarations ~mark:Mark_both ~loc env fresh_id newdecl decl;
235235+ Includemod.type_declarations ~mark:true ~loc env fresh_id newdecl decl;
236236 Typedecl.check_coherence env loc path newdecl
237237238238let make_variance p n i =
···627627 let mty = Mtype.scrape_for_type_of ~remove_aliases sig_env mty in
628628 let md'' = { md' with md_type = mty } in
629629 let newmd = Mtype.strengthen_decl ~aliasable:false sig_env md'' path in
630630- ignore(Includemod.modtypes ~mark:Mark_both ~loc sig_env
630630+ ignore(Includemod.modtypes ~mark:true ~loc sig_env
631631 newmd.md_type md.md_type);
632632 return
633633 ~replace_by:(Some(Sig_module(id, pres, newmd, rs, priv)))
···637637 let sig_env = Env.add_signature sg_for_env outer_sig_env in
638638 let aliasable = not (Env.is_functor_arg path sig_env) in
639639 ignore
640640- (Includemod.strengthened_module_decl ~loc ~mark:Mark_both
640640+ (Includemod.strengthened_module_decl ~loc ~mark:true
641641 ~aliasable sig_env md' path md);
642642 real_ids := [Pident id];
643643 return ~replace_by:None
···20242024 let coercion, shape =
20252025 try
20262026 Includemod.modtypes_with_shape ~shape
20272027- ~loc:modl.mod_loc ~mark:Mark_both
20272027+ ~loc:modl.mod_loc ~mark:true
20282028 env mty_actual' mty_decl'
20292029 with Includemod.Error msg ->
20302030 raise(Error(modl.mod_loc, env, Not_included msg)) in
···21112111 Result.Error (Errortrace.Package_cannot_scrape r)
21122112 | mty1, mty2 ->
21132113 let loc = Location.none in
21142114- match Includemod.modtypes ~loc ~mark:Mark_both env mty1 mty2 with
21142114+ match Includemod.modtypes ~loc ~mark:true env mty1 mty2 with
21152115 | Tcoerce_none -> Ok ()
21162116 | c ->
21172117 let msg =
···21252125let () = Ctype.package_subtype := package_subtype
2126212621272127let wrap_constraint_package env mark arg mty explicit =
21282128- let mark = if mark then Includemod.Mark_both else Includemod.Mark_neither in
21292128 let mty1 = Subst.modtype Keep Subst.identity arg.mod_type in
21302129 let mty2 = Subst.modtype Keep Subst.identity mty in
21312130 let coercion =
···2141214021422141let wrap_constraint_with_shape env mark arg mty
21432142 shape explicit =
21442144- let mark = if mark then Includemod.Mark_both else Includemod.Mark_neither in
21452143 let coercion, shape =
21462144 try
21472145 Includemod.modtypes_with_shape ~shape ~loc:arg.mod_loc env ~mark
···24092407 | { loc = app_loc; attributes = app_attributes;
24102408 arg = Some { shape = arg_shape; path = arg_path; arg } } ->
24112409 let coercion =
24122412- try Includemod.modtypes
24132413- ~loc:arg.mod_loc ~mark:Mark_both env arg.mod_type mty_param
24102410+ try Includemod.modtypes ~loc:arg.mod_loc ~mark:true env
24112411+ arg.mod_type mty_param
24142412 with Includemod.Error _ -> apply_error ()
24152413 in
24162414 let mty_appl =
···24392437 raise (Error(app_loc, env, error))
24402438 in
24412439 begin match
24422442- Includemod.modtypes
24432443- ~loc:app_loc ~mark:Mark_neither env mty_res nondep_mty
24402440+ Includemod.modtypes ~loc:app_loc ~mark:false env
24412441+ mty_res nondep_mty
24442442 with
24452443 | Tcoerce_none -> ()
24462444 | _ ->
···31223120 in
31233121 let dclsig = Env.read_signature compiled_intf_file in
31243122 let coercion, shape =
31253125- Includemod.compunit initial_env ~mark:Mark_positive
31233123+ Includemod.compunit initial_env ~mark:true
31263124 sourcefile sg source_intf
31273125 dclsig shape
31283126 in
···31433141 (Location.in_file (Unit_info.source_file target))
31443142 Warnings.Missing_mli;
31453143 let coercion, shape =
31463146- Includemod.compunit initial_env ~mark:Mark_positive
31443144+ Includemod.compunit initial_env ~mark:true
31473145 sourcefile sg "(inferred signature)" simple_sg shape
31483146 in
31493147 check_nongen_signature finalenv simple_sg;
···32543252 end;
32553253 let dclsig = Env.read_signature target_cmi in
32563254 let cc, _shape =
32573257- Includemod.compunit initial_env ~mark:Mark_both
32553255+ Includemod.compunit initial_env ~mark:true
32583256 "(obtained by packing)" sg mli dclsig shape
32593257 in
32603258 Cmt_format.save_cmt (Unit_info.companion_cmt target_cmi)