@@ -55,6 +55,35 @@ module PosHash = struct
5555 replace h k (PosSet. add v set)
5656end
5757
58+ (* * State tracking positions annotated as @dead, @live, or @genType *)
59+ module AnnotationState = struct
60+ type annotated_as = GenType | Dead | Live
61+ type t = annotated_as PosHash .t
62+
63+ let create () : t = PosHash. create 1
64+
65+ let is_annotated_dead (state : t ) pos = PosHash. find_opt state pos = Some Dead
66+
67+ let is_annotated_gentype_or_live (state : t ) pos =
68+ match PosHash. find_opt state pos with
69+ | Some (Live | GenType ) -> true
70+ | Some Dead | None -> false
71+
72+ let is_annotated_gentype_or_dead (state : t ) pos =
73+ match PosHash. find_opt state pos with
74+ | Some (Dead | GenType ) -> true
75+ | Some Live | None -> false
76+
77+ let annotate_gentype (state : t ) (pos : Lexing.position ) =
78+ PosHash. replace state pos GenType
79+
80+ let annotate_dead (state : t ) (pos : Lexing.position ) =
81+ PosHash. replace state pos Dead
82+
83+ let annotate_live (state : t ) (pos : Lexing.position ) =
84+ PosHash. replace state pos Live
85+ end
86+
5887type decls = decl PosHash .t
5988(* * all exported declarations *)
6089
@@ -114,7 +143,7 @@ let addValueReference ~config ~(binding : Location.t) ~addFileReference
114143 && effectiveFrom.loc_start.pos_fname <> locTo.loc_start.pos_fname
115144 then FileReferences. add effectiveFrom locTo)
116145
117- let iterFilesFromRootsToLeaves ~ config iterFun =
146+ let iterFilesFromRootsToLeaves iterFun =
118147 (* For each file, the number of incoming references *)
119148 let inverseReferences = (Hashtbl. create 1 : (string, int ) Hashtbl. t) in
120149 (* For each number of incoming references, the files *)
@@ -189,43 +218,19 @@ let iterFilesFromRootsToLeaves ~config iterFun =
189218 });
190219 iterFun fileName))
191220
192- (* * Keep track of the location of values annotated @genType or @dead *)
221+ (* * Process AST to collect locations annotated @genType, @dead, or @live *)
193222module ProcessDeadAnnotations = struct
194- type annotatedAs = GenType | Dead | Live
195-
196- let positionsAnnotated = PosHash. create 1
197- let isAnnotatedDead pos = PosHash. find_opt positionsAnnotated pos = Some Dead
198-
199- let isAnnotatedGenTypeOrLive pos =
200- match PosHash. find_opt positionsAnnotated pos with
201- | Some (Live | GenType ) -> true
202- | Some Dead | None -> false
203-
204- let isAnnotatedGenTypeOrDead pos =
205- match PosHash. find_opt positionsAnnotated pos with
206- | Some (Dead | GenType ) -> true
207- | Some Live | None -> false
208-
209- let annotateGenType (pos : Lexing.position ) =
210- PosHash. replace positionsAnnotated pos GenType
211-
212- let annotateDead (pos : Lexing.position ) =
213- PosHash. replace positionsAnnotated pos Dead
214-
215- let annotateLive (pos : Lexing.position ) =
216- PosHash. replace positionsAnnotated pos Live
217-
218- let processAttributes ~config ~doGenType ~name ~pos attributes =
223+ let processAttributes ~state ~config ~doGenType ~name ~pos attributes =
219224 let getPayloadFun f = attributes |> Annotation. getAttributePayload f in
220225 let getPayload (x : string ) =
221226 attributes |> Annotation. getAttributePayload (( = ) x)
222227 in
223228 if
224229 doGenType
225230 && getPayloadFun Annotation. tagIsOneOfTheGenTypeAnnotations <> None
226- then pos |> annotateGenType ;
231+ then AnnotationState. annotate_gentype state pos ;
227232 if getPayload WriteDeadAnnotations. deadAnnotation <> None then
228- pos |> annotateDead ;
233+ AnnotationState. annotate_dead state pos ;
229234 let nameIsInLiveNamesOrPaths () =
230235 config.DceConfig. cli.live_names |> List. mem name
231236 ||
@@ -243,21 +248,23 @@ module ProcessDeadAnnotations = struct
243248 with Invalid_argument _ -> false )
244249 in
245250 if getPayload liveAnnotation <> None || nameIsInLiveNamesOrPaths () then
246- pos |> annotateLive ;
251+ AnnotationState. annotate_live state pos ;
247252 if attributes |> Annotation. isOcamlSuppressDeadWarning then
248- pos |> annotateLive
253+ AnnotationState. annotate_live state pos
249254
250- let collectExportLocations ~config ~doGenType =
255+ let collectExportLocations ~state ~ config ~doGenType =
251256 let super = Tast_mapper. default in
252257 let currentlyDisableWarnings = ref false in
253258 let value_binding self
254259 ({vb_attributes; vb_pat} as value_binding : Typedtree.value_binding ) =
255260 (match vb_pat.pat_desc with
256261 | Tpat_var (id, {loc = {loc_start = pos}})
257262 | Tpat_alias ({pat_desc = Tpat_any } , id , {loc = {loc_start = pos } } ) ->
258- if ! currentlyDisableWarnings then pos |> annotateLive;
263+ if ! currentlyDisableWarnings then
264+ AnnotationState. annotate_live state pos;
259265 vb_attributes
260- |> processAttributes ~config ~do GenType ~name: (id |> Ident. name) ~pos
266+ |> processAttributes ~state ~config ~do GenType ~name: (id |> Ident. name)
267+ ~pos
261268 | _ -> () );
262269 super.value_binding self value_binding
263270 in
@@ -268,7 +275,7 @@ module ProcessDeadAnnotations = struct
268275 |> List. iter
269276 (fun ({ld_attributes; ld_loc} : Typedtree.label_declaration ) ->
270277 toplevelAttrs @ ld_attributes
271- |> processAttributes ~config ~do GenType:false ~name: " "
278+ |> processAttributes ~state ~ config ~do GenType:false ~name: " "
272279 ~pos: ld_loc.loc_start)
273280 | Ttype_variant constructorDeclarations ->
274281 constructorDeclarations
@@ -284,13 +291,13 @@ module ProcessDeadAnnotations = struct
284291 (fun ({ld_attributes; ld_loc} :
285292 Typedtree.label_declaration ) ->
286293 toplevelAttrs @ cd_attributes @ ld_attributes
287- |> processAttributes ~config ~do GenType:false ~name: " "
288- ~pos: ld_loc.loc_start)
294+ |> processAttributes ~state ~ config ~do GenType:false
295+ ~name: " " ~ pos: ld_loc.loc_start)
289296 flds
290297 | Cstr_tuple _ -> ()
291298 in
292299 toplevelAttrs @ cd_attributes
293- |> processAttributes ~config ~do GenType:false ~name: " "
300+ |> processAttributes ~state ~ config ~do GenType:false ~name: " "
294301 ~pos: cd_loc.loc_start)
295302 | _ -> () );
296303 super.type_kind self typeKind
@@ -304,9 +311,10 @@ module ProcessDeadAnnotations = struct
304311 ({val_attributes; val_id; val_val = {val_loc = {loc_start = pos } } } as
305312 value_description :
306313 Typedtree. value_description ) =
307- if ! currentlyDisableWarnings then pos |> annotateLive ;
314+ if ! currentlyDisableWarnings then AnnotationState. annotate_live state pos ;
308315 val_attributes
309- |> processAttributes ~config ~do GenType ~name: (val_id |> Ident. name) ~pos ;
316+ |> processAttributes ~state ~config ~do GenType
317+ ~name: (val_id |> Ident. name) ~pos ;
310318 super.value_description self value_description
311319 in
312320 let structure_item self (item : Typedtree.structure_item ) =
@@ -348,15 +356,17 @@ module ProcessDeadAnnotations = struct
348356 value_description;
349357 }
350358
351- let structure ~config ~doGenType structure =
352- let collectExportLocations = collectExportLocations ~config ~do GenType in
359+ let structure ~state ~config ~doGenType structure =
360+ let collectExportLocations =
361+ collectExportLocations ~state ~config ~do GenType
362+ in
353363 structure
354364 |> collectExportLocations.structure collectExportLocations
355365 |> ignore
356366
357- let signature ~config signature =
367+ let signature ~state ~ config signature =
358368 let collectExportLocations =
359- collectExportLocations ~config ~do GenType:true
369+ collectExportLocations ~state ~ config ~do GenType:true
360370 in
361371 signature
362372 |> collectExportLocations.signature collectExportLocations
@@ -579,17 +589,18 @@ module Decl = struct
579589 emitWarning ~config ~decl ~message name)
580590end
581591
582- let declIsDead ~refs decl =
592+ let declIsDead ~state ~ refs decl =
583593 let liveRefs =
584594 refs
585- |> PosSet. filter (fun p -> not (ProcessDeadAnnotations. isAnnotatedDead p))
595+ |> PosSet. filter (fun p -> not (AnnotationState. is_annotated_dead state p))
586596 in
587597 liveRefs |> PosSet. cardinal = 0
588- && not (ProcessDeadAnnotations. isAnnotatedGenTypeOrLive decl.pos)
598+ && not (AnnotationState. is_annotated_gentype_or_live state decl.pos)
589599
590- let doReportDead pos = not (ProcessDeadAnnotations. isAnnotatedGenTypeOrDead pos)
600+ let doReportDead ~state pos =
601+ not (AnnotationState. is_annotated_gentype_or_dead state pos)
591602
592- let rec resolveRecursiveRefs ~config
603+ let rec resolveRecursiveRefs ~state ~ config
593604 ~checkOptionalArg :(checkOptionalArgFn : config:DceConfig.t -> decl -> unit )
594605 ~deadDeclarations ~level ~orderedFiles ~refs ~refsBeingResolved decl : bool
595606 =
@@ -599,7 +610,7 @@ let rec resolveRecursiveRefs ~config
599610 Log_. item " recursiveDebug %s [%d] already resolved@."
600611 (decl.path |> Path. toString)
601612 level;
602- decl.pos |> ProcessDeadAnnotations. isAnnotatedDead
613+ AnnotationState. is_annotated_dead state decl.pos
603614 | _ when PosSet. mem decl.pos ! refsBeingResolved ->
604615 if Config. recursiveDebug then
605616 Log_. item " recursiveDebug %s [%d] is being resolved: assume dead@."
@@ -636,15 +647,15 @@ let rec resolveRecursiveRefs ~config
636647 in
637648 let xDeclIsDead =
638649 xDecl
639- |> resolveRecursiveRefs ~config
650+ |> resolveRecursiveRefs ~state ~ config
640651 ~check OptionalArg:checkOptionalArgFn ~dead Declarations
641652 ~level: (level + 1 ) ~ordered Files ~refs: xRefs
642653 ~refs BeingResolved
643654 in
644655 if xDecl.resolvedDead = None then allDepsResolved := false ;
645656 not xDeclIsDead)
646657 in
647- let isDead = decl |> declIsDead ~refs: newRefs in
658+ let isDead = decl |> declIsDead ~state ~ refs: newRefs in
648659 let isResolved = (not isDead) || ! allDepsResolved || level = 0 in
649660 if isResolved then (
650661 decl.resolvedDead < - Some isDead;
@@ -653,17 +664,17 @@ let rec resolveRecursiveRefs ~config
653664 |> DeadModules. markDead ~config
654665 ~is Type:(decl.declKind |> DeclKind. isType)
655666 ~loc: decl.moduleLoc;
656- if not (decl.pos |> doReportDead ) then decl.report < - false ;
667+ if not (doReportDead ~state decl.pos) then decl.report < - false ;
657668 deadDeclarations := decl :: ! deadDeclarations;
658669 if not (Decl. isToplevelValueWithSideEffects decl) then
659- decl.pos |> ProcessDeadAnnotations. annotateDead )
670+ AnnotationState. annotate_dead state decl.pos )
660671 else (
661672 checkOptionalArgFn ~config decl;
662673 decl.path
663674 |> DeadModules. markLive ~config
664675 ~is Type:(decl.declKind |> DeclKind. isType)
665676 ~loc: decl.moduleLoc;
666- if decl.pos |> ProcessDeadAnnotations. isAnnotatedDead then
677+ if AnnotationState. is_annotated_dead state decl.pos then
667678 emitWarning ~config ~decl ~message: " is annotated @dead but is live"
668679 IncorrectDeadAnnotation );
669680 if config.DceConfig. cli.debug then
@@ -681,16 +692,18 @@ let rec resolveRecursiveRefs ~config
681692 refsString level);
682693 isDead
683694
684- let reportDead ~config
685- ~checkOptionalArg :(checkOptionalArgFn : config:DceConfig.t -> decl -> unit )
686- =
695+ let reportDead ~state ~config
696+ ~checkOptionalArg :
697+ (checkOptionalArgFn :
698+ state:AnnotationState.t -> config:DceConfig.t -> decl -> unit ) =
687699 let iterDeclInOrder ~deadDeclarations ~orderedFiles decl =
688700 let refs =
689701 match decl |> Decl. isValue with
690702 | true -> ValueReferences. find decl.pos
691703 | false -> TypeReferences. find decl.pos
692704 in
693- resolveRecursiveRefs ~config ~check OptionalArg:checkOptionalArgFn
705+ resolveRecursiveRefs ~state ~config
706+ ~check OptionalArg:(checkOptionalArgFn ~state )
694707 ~dead Declarations ~level: 0 ~ordered Files
695708 ~refs BeingResolved:(ref PosSet. empty) ~refs decl
696709 |> ignore
@@ -711,7 +724,7 @@ let reportDead ~config
711724 PosHash. fold (fun _pos decl declarations -> decl :: declarations) decls []
712725 in
713726 let orderedFiles = Hashtbl. create 256 in
714- iterFilesFromRootsToLeaves ~config
727+ iterFilesFromRootsToLeaves
715728 (let current = ref 0 in
716729 fun fileName ->
717730 incr current;
0 commit comments