@@ -452,21 +452,35 @@ and try_modtypes ~in_eq ~loc env ~mark subst mty1 mty2 orig_shape =
452
452
functor_param ~in_eq ~loc env ~mark: (negate_mark mark)
453
453
subst param1 param2
454
454
in
455
- (* Using a fresh variable with a placeholder uid here is fine: users will
456
- never try to jump to the definition of that variable.
457
- If they try to jump to the parameter from inside the functor, they will
458
- use the variable shape that is stored in the local environment. *)
459
- let var, shape_var = Shape. fresh_var Uid. internal_not_actually_unique in
460
- let cc_res =
461
- let res_shape = Shape. app orig_shape ~arg: shape_var in
462
- modtypes ~in_eq ~loc env ~mark subst res1 res2 res_shape
455
+ let var, res_shape =
456
+ match Shape. decompose_abs orig_shape with
457
+ | Some (var , res_shape ) -> var, res_shape
458
+ | None ->
459
+ (* Using a fresh variable with a placeholder uid here is fine: users
460
+ will never try to jump to the definition of that variable.
461
+ If they try to jump to the parameter from inside the functor,
462
+ they will use the variable shape that is stored in the local
463
+ environment. *)
464
+ let var, shape_var =
465
+ Shape. fresh_var Uid. internal_not_actually_unique
466
+ in
467
+ var, Shape. app orig_shape ~arg: shape_var
463
468
in
469
+ let cc_res = modtypes ~in_eq ~loc env ~mark subst res1 res2 res_shape in
464
470
begin match cc_arg, cc_res with
465
- | Ok Tcoerce_none , Ok (Tcoerce_none, res_shape ) ->
466
- let final_shape = Shape. abs var res_shape in
471
+ | Ok Tcoerce_none , Ok (Tcoerce_none, final_res_shape ) ->
472
+ let final_shape =
473
+ if final_res_shape == res_shape
474
+ then orig_shape
475
+ else Shape. abs var final_res_shape
476
+ in
467
477
Ok (Tcoerce_none , final_shape)
468
- | Ok cc_arg , Ok (cc_res , res_shape ) ->
469
- let final_shape = Shape. abs var res_shape in
478
+ | Ok cc_arg , Ok (cc_res , final_res_shape ) ->
479
+ let final_shape =
480
+ if final_res_shape == res_shape
481
+ then orig_shape
482
+ else Shape. abs var final_res_shape
483
+ in
470
484
Ok (Tcoerce_functor (cc_arg, cc_res), final_shape)
471
485
| _ , Error {Error. symptom = Error. Functor Error. Params res ; _} ->
472
486
let got_params, got_res = res.got in
@@ -562,33 +576,31 @@ and signatures ~in_eq ~loc env ~mark subst sig1 sig2 mod_shape =
562
576
([] , 0 ) sig1 in
563
577
(* Build a table of the components of sig1, along with their positions.
564
578
The table is indexed by kind and name of component *)
565
- let rec build_component_table pos tbl = function
566
- [] -> pos, tbl
567
- | (Sig_value (_, _, Hidden )
568
- | Sig_type (_, _, _, Hidden )
569
- | Sig_typext (_, _, _, Hidden )
570
- | Sig_module (_, _, _, _, Hidden )
571
- | Sig_modtype (_, _, Hidden )
572
- | Sig_class (_, _, _, Hidden )
573
- | Sig_class_type (_, _, _, Hidden )
574
- ) as item :: rem ->
575
- let pos = if is_runtime_component item then pos + 1 else pos in
576
- build_component_table pos tbl rem (* do not pair private items. *)
579
+ let rec build_component_table nb_exported pos tbl = function
580
+ [] -> nb_exported, pos, tbl
577
581
| item :: rem ->
578
- let (id, _loc, name) = item_ident_name item in
579
582
let pos, nextpos =
580
583
if is_runtime_component item then pos, pos + 1
581
584
else - 1 , pos
582
585
in
583
- build_component_table nextpos
584
- (FieldMap. add name (id, item, pos) tbl) rem in
585
- let len1, comps1 =
586
- build_component_table 0 FieldMap. empty sig1 in
587
- let len2 =
588
- List. fold_left
589
- (fun n i -> if is_runtime_component i then n + 1 else n)
590
- 0
591
- sig2
586
+ match item_visibility item with
587
+ | Hidden ->
588
+ (* do not pair private items. *)
589
+ build_component_table nb_exported nextpos tbl rem
590
+ | Exported ->
591
+ let (id, _loc, name) = item_ident_name item in
592
+ build_component_table (nb_exported + 1 ) nextpos
593
+ (FieldMap. add name (id, item, pos) tbl) rem
594
+ in
595
+ let exported_len1, runtime_len1, comps1 =
596
+ build_component_table 0 0 FieldMap. empty sig1
597
+ in
598
+ let exported_len2, runtime_len2 =
599
+ List. fold_left (fun (el , rl ) i ->
600
+ let el = match item_visibility i with Hidden -> el | Exported -> el + 1 in
601
+ let rl = if is_runtime_component i then rl + 1 else rl in
602
+ el, rl
603
+ ) (0 , 0 ) sig2
592
604
in
593
605
(* Pair each component of sig2 with a component of sig1,
594
606
identifying the names along the way.
@@ -597,15 +609,19 @@ and signatures ~in_eq ~loc env ~mark subst sig1 sig2 mod_shape =
597
609
and the coercion to be applied to it. *)
598
610
let rec pair_components subst paired unpaired = function
599
611
[] ->
600
- let oks, shape_map, errors =
612
+ let oks, ( shape_map, deep_modifications) , errors =
601
613
signature_components ~in_eq ~loc env ~mark new_env subst mod_shape
602
614
Shape.Map. empty
603
615
(List. rev paired)
604
616
in
605
617
begin match unpaired, errors, oks with
606
618
| [] , [] , cc ->
607
- let shape = Shape. str ?uid:mod_shape.Shape. uid shape_map in
608
- if len1 = len2 then (* see PR#5098 *)
619
+ let shape =
620
+ if not deep_modifications && exported_len1 = exported_len2
621
+ then mod_shape
622
+ else Shape. str ?uid:mod_shape.Shape. uid shape_map
623
+ in
624
+ if runtime_len1 = runtime_len2 then (* see PR#5098 *)
609
625
Ok (simplify_structure_coercion cc id_pos_list, shape)
610
626
else
611
627
Ok (Tcoerce_structure (cc, id_pos_list), shape)
@@ -655,8 +671,9 @@ and signatures ~in_eq ~loc env ~mark subst sig1 sig2 mod_shape =
655
671
and signature_components ~in_eq ~loc old_env ~mark env subst
656
672
orig_shape shape_map paired =
657
673
match paired with
658
- | [] -> [] , shape_map, []
674
+ | [] -> [] , ( shape_map, false ) , []
659
675
| (sigi1 , sigi2 , pos ) :: rem ->
676
+ let shape_modified = ref false in
660
677
let id, item, shape_map, present_at_runtime =
661
678
match sigi1, sigi2 with
662
679
| Sig_value (id1 , valdecl1 , _ ) ,Sig_value (_id2 , valdecl2 , _ ) ->
@@ -695,6 +712,7 @@ and signature_components ~in_eq ~loc old_env ~mark env subst
695
712
let item, shape_map =
696
713
match item with
697
714
| Ok (cc , shape ) ->
715
+ if shape != orig_shape then shape_modified := true ;
698
716
let mod_shape = Shape. set_uid_if_none shape mty1.md_uid in
699
717
Ok cc, Shape.Map. add_module shape_map id1 mod_shape
700
718
| Error diff ->
@@ -741,10 +759,11 @@ and signature_components ~in_eq ~loc old_env ~mark env subst
741
759
| _ ->
742
760
assert false
743
761
in
744
- let oks, final_map, errors =
762
+ let oks, ( final_map, deep_modifications) , errors =
745
763
signature_components ~in_eq ~loc old_env ~mark env subst
746
764
orig_shape shape_map rem
747
765
in
766
+ let final_map = final_map, deep_modifications || ! shape_modified in
748
767
match item with
749
768
| Ok x when present_at_runtime -> (pos,x) :: oks, final_map, errors
750
769
| Ok _ -> oks, final_map, errors
0 commit comments