Skip to content

Commit cdb76c0

Browse files
cknittclaude
andcommitted
Connect renamed members of an applied functor to their declarations
Codex review on #9084: the members of an applied functor are registered under fresh stamps, so references to `IntSet.add` were no longer references to `MakeSet.add`; Find References missed them and renaming the declaration left them unchanged. Each renamed stamp now maps to the stamp it was renamed from: a use of the member is also recorded as a use of the original, and references starting from the member start from the original. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLMawVgtmiKy3TMBc3 Claude-Session: https://claude.ai/code/session_01Kr4cjoUi2f5VpMvE6wT9bo Signed-off-by: Christoph Knittel <ck@cca.io>
1 parent ccce81b commit cdb76c0

6 files changed

Lines changed: 206 additions & 15 deletions

File tree

‎analysis/src/process_cmt.ml‎

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,39 @@ and for_type_module ~name ~env module_type =
189189
in a typed tree, so that they never meet one of them. *)
190190
let renamed_stamp_floor = 1 lsl 40
191191

192+
(* [Subst] renames the items of a signature in place, so the original and
193+
the renamed signature list the same items in the same order. Records
194+
each renamed stamp's original, nested signatures included, for
195+
references to find the declarations in the functor body. *)
196+
let rec record_renamed_stamps table (original : Types.module_type)
197+
(renamed : Types.module_type) =
198+
match (original, renamed) with
199+
| Mty_signature items, Mty_signature renamed_items
200+
when List.length items = List.length renamed_items ->
201+
List.iter2
202+
(fun (item : Types.signature_item) (renamed_item : Types.signature_item)
203+
->
204+
let ids =
205+
match (item, renamed_item) with
206+
| Sig_value (id, _), Sig_value (id', _)
207+
| Sig_type (id, _, _), Sig_type (id', _, _)
208+
| Sig_typext (id, _, _), Sig_typext (id', _, _)
209+
| Sig_modtype (id, _), Sig_modtype (id', _) ->
210+
Some (id, id')
211+
| Sig_module (id, md, _), Sig_module (id', md', _) ->
212+
record_renamed_stamps table md.md_type md'.md_type;
213+
Some (id, id')
214+
| _ -> None
215+
in
216+
match ids with
217+
| Some (id, id') ->
218+
Hashtbl.replace table (Ident.binding_time id') (Ident.binding_time id)
219+
| None -> ())
220+
items renamed_items
221+
| Mty_functor (_, _, result), Mty_functor (_, _, renamed_result) ->
222+
record_renamed_stamps table result renamed_result
223+
| _ -> ()
224+
192225
let get_module_type_path mod_desc =
193226
match mod_desc with
194227
| Typedtree.Tmty_ident (path, _) | Tmty_alias (path, _) -> Some path
@@ -685,8 +718,9 @@ and for_module ~env (mod_expr : Typedtree.module_expr) module_name =
685718
in
686719
if Ident.current_time () < renamed_stamp_floor then
687720
Ident.set_current_time renamed_stamp_floor;
688-
for_type_module ~name:module_name ~env
689-
(Subst.modtype Subst.identity mod_expr.mod_type)
721+
let renamed = Subst.modtype Subst.identity mod_expr.mod_type in
722+
record_renamed_stamps env.renamed_stamps mod_expr.mod_type renamed;
723+
for_type_module ~name:module_name ~env renamed
690724
| Tmod_unpack (_expr, module_type) ->
691725
let env = env |> Env.add_module ~name:module_name in
692726
for_type_module ~name:module_name ~env module_type
@@ -742,7 +776,11 @@ and for_structure ~name ~env str_items =
742776
let file_for_cmt_infos ~module_name ~uri
743777
({cmt_modname; cmt_annots} : Cmt_format.cmt_infos) =
744778
let env =
745-
{Env.stamps = Stamps.init (); module_path = File (uri, module_name)}
779+
{
780+
Env.stamps = Stamps.init ();
781+
module_path = File (uri, module_name);
782+
renamed_stamps = Hashtbl.create 1;
783+
}
746784
in
747785
match cmt_annots with
748786
| Partial_implementation parts ->
@@ -756,7 +794,13 @@ let file_for_cmt_infos ~module_name ~uri
756794
|> List.concat
757795
in
758796
let structure = for_structure ~name:module_name ~env items in
759-
{File.uri; module_name = cmt_modname; stamps = env.stamps; structure}
797+
{
798+
File.uri;
799+
module_name = cmt_modname;
800+
stamps = env.stamps;
801+
structure;
802+
renamed_stamps = env.renamed_stamps;
803+
}
760804
| Partial_interface parts ->
761805
let items =
762806
parts |> Array.to_list
@@ -768,13 +812,31 @@ let file_for_cmt_infos ~module_name ~uri
768812
|> List.concat
769813
in
770814
let structure = for_signature ~name:module_name ~env items in
771-
{uri; module_name = cmt_modname; stamps = env.stamps; structure}
815+
{
816+
uri;
817+
module_name = cmt_modname;
818+
stamps = env.stamps;
819+
structure;
820+
renamed_stamps = env.renamed_stamps;
821+
}
772822
| Implementation structure ->
773823
let structure = for_structure ~name:module_name ~env structure.str_items in
774-
{uri; module_name = cmt_modname; stamps = env.stamps; structure}
824+
{
825+
uri;
826+
module_name = cmt_modname;
827+
stamps = env.stamps;
828+
structure;
829+
renamed_stamps = env.renamed_stamps;
830+
}
775831
| Interface signature ->
776832
let structure = for_signature ~name:module_name ~env signature.sig_items in
777-
{uri; module_name = cmt_modname; stamps = env.stamps; structure}
833+
{
834+
uri;
835+
module_name = cmt_modname;
836+
stamps = env.stamps;
837+
structure;
838+
renamed_stamps = env.renamed_stamps;
839+
}
778840

779841
let file_for_cmt ~state ~module_name ~cmt ~uri =
780842
match Hashtbl.find_opt state.cmt_cache cmt with

‎analysis/src/process_extra.ml‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,21 @@ let extra_for_cmt ~(iterator : Tast_iterator.iterator)
135135
extra_for_signature_items ~iterator items;
136136
extra_for_parts parts
137137

138+
(* A use of an applied functor's member is also a use of the declaration
139+
in the functor's body that it was renamed from. *)
140+
let add_reference_with_original ~(env : Query_env.t) ~extra stamp loc =
141+
add_reference ~extra stamp loc;
142+
match Hashtbl.find_opt env.file.renamed_stamps stamp with
143+
| Some original -> add_reference ~extra original loc
144+
| None -> ()
145+
138146
let add_for_path ~env ~extra path lident loc typ tip =
139147
let ident_name = Longident.last lident in
140148
let ident_loc = Utils.end_of_location loc (String.length ident_name) in
141149
let loc_type =
142150
match Resolve_path.from_compiler_path ~env path with
143151
| Stamp stamp ->
144-
add_reference ~extra stamp ident_loc;
152+
add_reference_with_original ~env ~extra stamp ident_loc;
145153
LocalReference (stamp, tip)
146154
| NotFound -> NotFound
147155
| Global (module_name, path) ->
@@ -154,7 +162,7 @@ let add_for_path ~env ~extra path lident loc typ tip =
154162
| _ -> Exported.find env.exported Exported.Value name
155163
with
156164
| Some stamp ->
157-
add_reference ~extra stamp ident_loc;
165+
add_reference_with_original ~env ~extra stamp ident_loc;
158166
LocalReference (stamp, tip)
159167
| None -> NotFound)
160168
| GlobalMod _ -> NotFound

‎analysis/src/references.ml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,11 @@ type references = {
440440

441441
let for_local_stamp ~state ~full:{file; extra; package} stamp (tip : Tip.t) =
442442
let env = Query_env.from_file file in
443+
let stamp =
444+
match Hashtbl.find_opt file.renamed_stamps stamp with
445+
| Some original -> original
446+
| None -> stamp
447+
in
443448
match
444449
match tip with
445450
| Constructor name ->

‎analysis/src/shared_types.ml‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,13 +274,15 @@ module File = struct
274274
stamps: Stamps.t;
275275
module_name: string;
276276
structure: Module.structure;
277+
renamed_stamps: (int, int) Hashtbl.t;
277278
}
278279

279280
let create module_name uri =
280281
{
281282
uri;
282283
stamps = Stamps.init ();
283284
module_name;
285+
renamed_stamps = Hashtbl.create 1;
284286
structure =
285287
{
286288
name = module_name;
@@ -404,7 +406,13 @@ and completion_type =
404406
}
405407

406408
module Env = struct
407-
type t = {stamps: Stamps.t; module_path: Module_path.t}
409+
type t = {
410+
stamps: Stamps.t;
411+
module_path: Module_path.t;
412+
renamed_stamps: (int, int) Hashtbl.t;
413+
(** the stamps of an applied functor's renamed members, mapped to
414+
those of the functor body's declarations they come from *)
415+
}
408416
let add_exported_module ~name ~is_type env =
409417
{
410418
env with

‎tests/analysis_tests/tests/src/AppliedFunctor.res‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module type Ord = {
66
module MakeSet = (O: Ord) => {
77
type t = array<O.t>
88
let add = (s: t, x: O.t) => s->Array.concat([x])
9+
// ^ref
910
}
1011

1112
module IntSet = MakeSet({
@@ -16,6 +17,12 @@ module IntSet = MakeSet({
1617
let s = IntSet.add([], 1)
1718
// ^hov
1819

20+
let s3 = IntSet.add([], 3)
21+
// ^ref
22+
23+
let s4 = IntSet.add([], 4)
24+
// ^ren insert
25+
1926
let t: IntSet.t = []
2027
// ^hov
2128

‎tests/analysis_tests/tests/src/expected/AppliedFunctor.res.txt‎

Lines changed: 106 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,123 @@
1-
Hover src/AppliedFunctor.res 15:15
1+
References src/AppliedFunctor.res 7:7
2+
[
3+
{
4+
"range": {
5+
"end": { "character": 9, "line": 7 },
6+
"start": { "character": 6, "line": 7 }
7+
},
8+
"uri": "file:///AppliedFunctor.res"
9+
},
10+
{
11+
"range": {
12+
"end": { "character": 18, "line": 16 },
13+
"start": { "character": 15, "line": 16 }
14+
},
15+
"uri": "file:///AppliedFunctor.res"
16+
},
17+
{
18+
"range": {
19+
"end": { "character": 19, "line": 19 },
20+
"start": { "character": 16, "line": 19 }
21+
},
22+
"uri": "file:///AppliedFunctor.res"
23+
},
24+
{
25+
"range": {
26+
"end": { "character": 19, "line": 22 },
27+
"start": { "character": 16, "line": 22 }
28+
},
29+
"uri": "file:///AppliedFunctor.res"
30+
}
31+
]
32+
33+
Hover src/AppliedFunctor.res 16:15
234
{
335
"contents": {
436
"kind": "markdown",
537
"value": "```rescript\n(IntSet.t, int) => array<int>\n```\n\n---\n\n```\n \n```\n```rescript\ntype IntSet.t = array<int>\n```\nGo to: [Type definition](AppliedFunctor.res#L7,3)\n"
638
}
739
}
840

9-
Hover src/AppliedFunctor.res 18:14
41+
References src/AppliedFunctor.res 19:16
42+
[
43+
{
44+
"range": {
45+
"end": { "character": 9, "line": 7 },
46+
"start": { "character": 6, "line": 7 }
47+
},
48+
"uri": "file:///AppliedFunctor.res"
49+
},
50+
{
51+
"range": {
52+
"end": { "character": 18, "line": 16 },
53+
"start": { "character": 15, "line": 16 }
54+
},
55+
"uri": "file:///AppliedFunctor.res"
56+
},
57+
{
58+
"range": {
59+
"end": { "character": 19, "line": 19 },
60+
"start": { "character": 16, "line": 19 }
61+
},
62+
"uri": "file:///AppliedFunctor.res"
63+
},
64+
{
65+
"range": {
66+
"end": { "character": 19, "line": 22 },
67+
"start": { "character": 16, "line": 22 }
68+
},
69+
"uri": "file:///AppliedFunctor.res"
70+
}
71+
]
72+
73+
Rename src/AppliedFunctor.res 22:16 insert
74+
[
75+
{
76+
"edits": [
77+
{
78+
"newText": "insert",
79+
"range": {
80+
"end": { "character": 9, "line": 7 },
81+
"start": { "character": 6, "line": 7 }
82+
}
83+
},
84+
{
85+
"newText": "insert",
86+
"range": {
87+
"end": { "character": 18, "line": 16 },
88+
"start": { "character": 15, "line": 16 }
89+
}
90+
},
91+
{
92+
"newText": "insert",
93+
"range": {
94+
"end": { "character": 19, "line": 19 },
95+
"start": { "character": 16, "line": 19 }
96+
}
97+
},
98+
{
99+
"newText": "insert",
100+
"range": {
101+
"end": { "character": 19, "line": 22 },
102+
"start": { "character": 16, "line": 22 }
103+
}
104+
}
105+
],
106+
"textDocument": { "uri": "file:///AppliedFunctor.res", "version": 0 }
107+
}
108+
]
109+
110+
Hover src/AppliedFunctor.res 25:14
10111
{
11112
"contents": {
12113
"kind": "markdown",
13114
"value": "```rescript\nIntSet.t\n```\n\n---\n\n```\n \n```\n```rescript\ntype IntSet.t = array<int>\n```\nGo to: [Type definition](AppliedFunctor.res#L7,3)\n"
14115
}
15116
}
16117

17-
Complete src/AppliedFunctor.res 21:19
18-
pos_cursor:[21:19] pos_no_white:[21:18] Found expr:[21:12->21:19]
19-
Pexp_ident IntSet.:[21:12->21:19]
118+
Complete src/AppliedFunctor.res 28:19
119+
pos_cursor:[28:19] pos_no_white:[28:18] Found expr:[28:12->28:19]
120+
Pexp_ident IntSet.:[28:12->28:19]
20121
Completable: Cpath Value[IntSet, ""]
21122
Package opens Stdlib.place holder Pervasives.JsxModules.place holder
22123
Resolved opens 1 Stdlib

0 commit comments

Comments
 (0)