diff --git a/CHANGELOG.md b/CHANGELOG.md index 65d4fd5725..e7c39f52f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ #### :bug: Bug fix - Preserve multibyte characters when wrapping long source lines in compiler code frames. https://github.com/rescript-lang/rescript/pull/8520 +- Fix reanalyze optional-argument diagnostics for functions passed or returned as first-class values. https://github.com/rescript-lang/rescript/pull/8321 #### :memo: Documentation diff --git a/analysis/reanalyze/src/cross_file_items.ml b/analysis/reanalyze/src/cross_file_items.ml index 81ccc95111..6d0554a12d 100644 --- a/analysis/reanalyze/src/cross_file_items.ml +++ b/analysis/reanalyze/src/cross_file_items.ml @@ -16,24 +16,36 @@ type optional_arg_call = { type function_ref = {pos_from: Lexing.position; pos_to: Lexing.position} +type optional_arg_value_escape = { + pos_from: Lexing.position; + pos_to: Lexing.position; +} + (** {2 Types} *) type t = { exception_refs: exception_ref list; optional_arg_calls: optional_arg_call list; function_refs: function_ref list; + optional_arg_value_escapes: optional_arg_value_escape list; } type builder = { mutable exception_refs: exception_ref list; mutable optional_arg_calls: optional_arg_call list; mutable function_refs: function_ref list; + mutable optional_arg_value_escapes: optional_arg_value_escape list; } (** {2 Builder API} *) let create_builder () : builder = - {exception_refs = []; optional_arg_calls = []; function_refs = []} + { + exception_refs = []; + optional_arg_calls = []; + function_refs = []; + optional_arg_value_escapes = []; + } let add_exception_ref (b : builder) ~exception_path ~loc_from = b.exception_refs <- {exception_path; loc_from} :: b.exception_refs @@ -46,6 +58,10 @@ let add_optional_arg_call (b : builder) ~pos_from ~pos_to ~arg_names let add_function_reference (b : builder) ~pos_from ~pos_to = b.function_refs <- {pos_from; pos_to} :: b.function_refs +let add_optional_arg_value_escape (b : builder) ~pos_from ~pos_to = + b.optional_arg_value_escapes <- + {pos_from; pos_to} :: b.optional_arg_value_escapes + (** {2 Merge API} *) let merge_all (builders : builder list) : t = @@ -56,7 +72,15 @@ let merge_all (builders : builder list) : t = builders |> List.concat_map (fun b -> b.optional_arg_calls) in let function_refs = builders |> List.concat_map (fun b -> b.function_refs) in - {exception_refs; optional_arg_calls; function_refs} + let optional_arg_value_escapes = + builders |> List.concat_map (fun b -> b.optional_arg_value_escapes) + in + { + exception_refs; + optional_arg_calls; + function_refs; + optional_arg_value_escapes; + } (** {2 Builder extraction for reactive merge} *) @@ -65,6 +89,7 @@ let builder_to_t (builder : builder) : t = exception_refs = builder.exception_refs; optional_arg_calls = builder.optional_arg_calls; function_refs = builder.function_refs; + optional_arg_value_escapes = builder.optional_arg_value_escapes; } (** {2 Processing API} *) diff --git a/analysis/reanalyze/src/cross_file_items.mli b/analysis/reanalyze/src/cross_file_items.mli index 1fb9b92cbf..4863b92e73 100644 --- a/analysis/reanalyze/src/cross_file_items.mli +++ b/analysis/reanalyze/src/cross_file_items.mli @@ -18,12 +18,18 @@ type optional_arg_call = { type function_ref = {pos_from: Lexing.position; pos_to: Lexing.position} +type optional_arg_value_escape = { + pos_from: Lexing.position; + pos_to: Lexing.position; +} + (** {2 Types} *) type t = { exception_refs: exception_ref list; optional_arg_calls: optional_arg_call list; function_refs: function_ref list; + optional_arg_value_escapes: optional_arg_value_escape list; } (** Immutable cross-file items - for processing after merge *) @@ -49,7 +55,10 @@ val add_optional_arg_call : val add_function_reference : builder -> pos_from:Lexing.position -> pos_to:Lexing.position -> unit -(** Add a cross-file function reference (for optional args combining). *) + +val add_optional_arg_value_escape : + builder -> pos_from:Lexing.position -> pos_to:Lexing.position -> unit +(** Record an optional-arg function used as a first-class value. *) (** {2 Merge API} *) diff --git a/analysis/reanalyze/src/cross_file_items_store.ml b/analysis/reanalyze/src/cross_file_items_store.ml index 3a07beb11d..e80d82a510 100644 --- a/analysis/reanalyze/src/cross_file_items_store.ml +++ b/analysis/reanalyze/src/cross_file_items_store.ml @@ -28,6 +28,15 @@ let iter_function_refs t f = (fun _path items -> List.iter f items.Cross_file_items.function_refs) r +let iter_optional_arg_value_escapes t f = + match t with + | Frozen cfi -> List.iter f cfi.Cross_file_items.optional_arg_value_escapes + | Reactive r -> + Reactive.iter + (fun _path items -> + List.iter f items.Cross_file_items.optional_arg_value_escapes) + r + (** Compute optional args state from calls and function references. Returns a map from position to final OptionalArgs.t state. Pure function - does not mutate declarations. *) @@ -65,3 +74,30 @@ let compute_optional_args_state (store : t) ~find_decl ~is_live : set_state pos_from updated_from; set_state pos_to updated_to)); state + +let compute_live_optional_arg_value_escapes (store : t) ~is_live : Pos_set.t = + (* Compute this as a batch after solver propagation: the result depends on + final liveness and on the fully merged cross-file items. If it becomes a + cached/reactive value, both dependencies must participate in invalidation. *) + let escapes = ref Pos_set.empty in + iter_optional_arg_value_escapes store + (fun {Cross_file_items.pos_from; pos_to} -> + if is_live pos_from then escapes := Pos_set.add pos_to !escapes); + let function_refs = ref [] in + iter_function_refs store (fun {Cross_file_items.pos_from; pos_to} -> + if is_live pos_from then + function_refs := (pos_from, pos_to) :: !function_refs); + (* A function reference aliases both declaration positions. Close escapes over + the undirected links so aliases and interface/implementation pairs agree. *) + let rec propagate escapes = + let propagated = + List.fold_left + (fun escapes (pos_from, pos_to) -> + if Pos_set.mem pos_from escapes then Pos_set.add pos_to escapes + else if Pos_set.mem pos_to escapes then Pos_set.add pos_from escapes + else escapes) + escapes !function_refs + in + if Pos_set.equal propagated escapes then escapes else propagate propagated + in + propagate !escapes diff --git a/analysis/reanalyze/src/cross_file_items_store.mli b/analysis/reanalyze/src/cross_file_items_store.mli index f8da5db43c..d3729d6339 100644 --- a/analysis/reanalyze/src/cross_file_items_store.mli +++ b/analysis/reanalyze/src/cross_file_items_store.mli @@ -22,9 +22,17 @@ val iter_optional_arg_calls : val iter_function_refs : t -> (Cross_file_items.function_ref -> unit) -> unit (** Iterate over all function refs *) +val iter_optional_arg_value_escapes : + t -> (Cross_file_items.optional_arg_value_escape -> unit) -> unit +(** Iterate over optional-arg functions used as first-class values *) + val compute_optional_args_state : t -> find_decl:(Lexing.position -> Decl.t option) -> is_live:(Lexing.position -> bool) -> Optional_args_state.t (** Compute optional args state from calls and function references *) + +val compute_live_optional_arg_value_escapes : + t -> is_live:(Lexing.position -> bool) -> Pos_set.t +(** Compute optional-arg declarations with live first-class value escapes *) diff --git a/analysis/reanalyze/src/dead_common.ml b/analysis/reanalyze/src/dead_common.ml index a843d68606..a3f39096f8 100644 --- a/analysis/reanalyze/src/dead_common.ml +++ b/analysis/reanalyze/src/dead_common.ml @@ -124,11 +124,13 @@ let addDeclaration_ ~config ~decls ~(file : File_context.t) ?pos_end ?pos_start Declarations.add decls pos decl) let add_value_declaration ~config ~decls ~file ?(is_toplevel = true) - ~(loc : Location.t) ~module_loc ?(optional_args = Optional_args.empty) ~path - ~side_effects name = + ?(reports_optional_args = false) ~(loc : Location.t) ~module_loc + ?(optional_args = Optional_args.empty) ~path ~side_effects name = name |> addDeclaration_ ~config ~decls ~file - ~decl_kind:(Value {is_toplevel; optional_args; side_effects}) + ~decl_kind: + (Value + {is_toplevel; reports_optional_args; optional_args; side_effects}) ~loc ~module_loc ~path (** Create a dead code issue. Pure - no side effects. *) diff --git a/analysis/reanalyze/src/dead_optional_args.ml b/analysis/reanalyze/src/dead_optional_args.ml index 2131181539..6e5f7bb9db 100644 --- a/analysis/reanalyze/src/dead_optional_args.ml +++ b/analysis/reanalyze/src/dead_optional_args.ml @@ -2,25 +2,6 @@ open Dead_common let active () = true -let add_function_reference ~config ~decls ~cross_file ~(loc_from : Location.t) - ~(loc_to : Location.t) = - if active () then - let pos_to = loc_to.loc_start in - let pos_from = loc_from.loc_start in - (* Check if target has optional args - for filtering and debug logging *) - let should_add = - match Declarations.find_opt_builder decls pos_to with - | Some {decl_kind = Value {optional_args}} -> - not (Optional_args.is_empty optional_args) - | _ -> false - in - if should_add then ( - if config.Dce_config.cli.debug then - Log_.item "OptionalArgs.addFunctionReference %s %s@." - (pos_from |> Pos.to_string) - (pos_to |> Pos.to_string); - Cross_file_items.add_function_reference cross_file ~pos_from ~pos_to) - let rec has_optional_args (texpr : Types.type_expr) = match texpr.desc with | _ when not (active ()) -> false @@ -30,6 +11,20 @@ let rec has_optional_args (texpr : Types.type_expr) = | Tsubst t -> has_optional_args t | _ -> false +let add_function_reference ~config ~cross_file ~(loc_from : Location.t) + ~(loc_to : Location.t) ~type_from ~type_to = + (* Keep this filter type-based rather than consulting the declaration table. + References can be collected before their target declaration is visited, + notably in [let rec ... and ...] groups. *) + if has_optional_args type_from && has_optional_args type_to then ( + let pos_to = loc_to.loc_start in + let pos_from = loc_from.loc_start in + if config.Dce_config.cli.debug then + Log_.item "OptionalArgs.addFunctionReference %s %s@." + (pos_from |> Pos.to_string) + (pos_to |> Pos.to_string); + Cross_file_items.add_function_reference cross_file ~pos_from ~pos_to) + let rec from_type_expr (texpr : Types.type_expr) = match texpr.desc with | _ when not (active ()) -> [] @@ -39,6 +34,25 @@ let rec from_type_expr (texpr : Types.type_expr) = | Tsubst t -> from_type_expr t | _ -> [] +let rec from_type_expr_with_arity (texpr : Types.type_expr) arity = + if arity <= 0 then [] + else + match texpr.desc with + | _ when not (active ()) -> [] + | Tarrow ({lbl = Optional {txt = s}}, t_to, _, _) -> + s :: from_type_expr_with_arity t_to (arity - 1) + | Tarrow (_, t_to, _, _) -> from_type_expr_with_arity t_to (arity - 1) + | Tlink t -> from_type_expr_with_arity t arity + | Tsubst t -> from_type_expr_with_arity t arity + | _ -> [] + +let rec from_type_expr_with_declared_arity (texpr : Types.type_expr) = + match texpr.desc with + | Tarrow (_, _, _, Some arity) -> from_type_expr_with_arity texpr arity + | Tlink t -> from_type_expr_with_declared_arity t + | Tsubst t -> from_type_expr_with_declared_arity t + | _ -> from_type_expr texpr + let add_references ~config ~cross_file ~(loc_from : Location.t) ~(loc_to : Location.t) ~(binding : Location.t) ~path (arg_names, arg_names_maybe) = @@ -59,10 +73,15 @@ let add_references ~config ~cross_file ~(loc_from : Location.t) (** Check for optional args issues. Returns issues instead of logging. Uses optional_args_state map for final computed state. *) -let check ~optional_args_state ~ann_store ~config:_ decl : Issue.t list = +let check ~optional_args_state ~optional_arg_value_escapes ~ann_store ~config:_ + decl : Issue.t list = match decl with - | {Decl.decl_kind = Value {optional_args}} + | {Decl.decl_kind = Value {reports_optional_args = true; optional_args}} when active () + (* A live escape makes both diagnostic classes unknown: unseen callers + may either omit or supply an optional argument, so neither "never + used" nor "always supplied" remains trustworthy. *) + && (not (Pos_set.mem decl.pos optional_arg_value_escapes)) && not (Annotation_store.is_annotated_gentype_or_live ann_store decl.pos) -> diff --git a/analysis/reanalyze/src/dead_value.ml b/analysis/reanalyze/src/dead_value.ml index 3fd1c343b7..981142eb08 100644 --- a/analysis/reanalyze/src/dead_value.ml +++ b/analysis/reanalyze/src/dead_value.ml @@ -2,6 +2,21 @@ open Dead_common +(** Physical identity avoids conflating generated expressions that share source + locations. Hashing by [exp_loc] is safe because [==] disambiguates collisions + during the bucket scan. + + This table relies on [Tast_mapper] visiting an enclosing [Texp_apply] before + its callee child and passing the same physical expression object to the child + callback. If either invariant changes, direct calls are conservatively + classified as escapes and optional-argument diagnostics silently disappear. *) +module Expression_table = Hashtbl.Make (struct + type t = Typedtree.expression + + let equal = ( == ) + let hash (e : t) = Hashtbl.hash e.exp_loc +end) + let check_any_value_binding_with_no_side_effects ~config ~decls ~file ~(module_path : Module_path.t) ({vb_pat = {pat_desc}; vb_expr = expr; vb_loc = loc} : @@ -27,13 +42,27 @@ let collect_value_binding ~config ~decls ~file ~(current_binding : Location.t) ({pat_desc = Tpat_any}, id, {loc = {loc_start; loc_ghost} as loc}) when (not loc_ghost) && not vb.vb_loc.loc_ghost -> let name = Ident.name id |> Name.create ~is_interface:false in - let optional_args = - vb.vb_expr.exp_type |> Dead_optional_args.from_type_expr - |> Optional_args.from_list + let optional_args, reports_optional_args = + match vb.vb_expr.exp_desc with + | Texp_function {arity = Some arity; _} -> + ( vb.vb_expr.exp_type + |> (fun texpr -> + Dead_optional_args.from_type_expr_with_arity texpr arity) + |> Optional_args.from_list, + true ) + | Texp_function _ -> + ( vb.vb_expr.exp_type |> Dead_optional_args.from_type_expr + |> Optional_args.from_list, + true ) + | _ -> + ( vb.vb_expr.exp_type |> Dead_optional_args.from_type_expr + |> Optional_args.from_list, + false ) in let exists = match Declarations.find_opt_builder decls loc_start with | Some {decl_kind = Value r} -> + r.reports_optional_args <- reports_optional_args; r.optional_args <- optional_args; true | _ -> false @@ -50,7 +79,8 @@ let collect_value_binding ~config ~decls ~file ~(current_binding : Location.t) let side_effects = Side_effects.check_expr vb.vb_expr in name |> add_value_declaration ~config ~decls ~file ~is_toplevel ~loc - ~module_loc:module_path.loc ~optional_args ~path ~side_effects); + ~module_loc:module_path.loc ~reports_optional_args ~optional_args + ~path ~side_effects); (match Declarations.find_opt_builder decls loc_start with | None -> () | Some decl -> @@ -109,12 +139,19 @@ let process_optional_args ~config ~cross_file ~exp_type ~(loc_from : Location.t) |> Dead_optional_args.add_references ~config ~cross_file ~loc_from ~loc_to ~binding ~path) -let rec collect_expr ~config ~refs ~file_deps ~cross_file +let rec collect_expr ~config ~refs ~file_deps ~cross_file ~direct_callees ~(last_binding : Location.t) super self (e : Typedtree.expression) = let loc_from = e.exp_loc in let binding = last_binding in + let add_optional_arg_value_escape ~val_type pos_from pos_to = + if Dead_optional_args.has_optional_args val_type then + Cross_file_items.add_optional_arg_value_escape cross_file ~pos_from + ~pos_to + in (match e.exp_desc with - | Texp_ident (_path, _, {Types.val_loc = {loc_ghost = false; _} as loc_to}) -> + | Texp_ident + (_path, _, {Types.val_loc = {loc_ghost = false; _} as loc_to; val_type}) + -> (* if Path.name _path = "rc" then assert false; *) if loc_from = loc_to && _path |> Path.name = "emptyArray" then ( (* Work around lowercase jsx with no children producing an artifact `emptyArray` @@ -125,9 +162,19 @@ let rec collect_expr ~config ~refs ~file_deps ~cross_file (loc_to.loc_start |> Pos.to_string); References.add_value_ref refs ~pos_to:loc_to.loc_start ~pos_from:Location.none.loc_start) - else + else ( add_value_reference ~config ~refs ~file_deps ~binding - ~add_file_reference:true ~loc_from ~loc_to + ~add_file_reference:true ~loc_from ~loc_to; + if not (Expression_table.mem direct_callees e) then + let pos_from = + (* [Location.none] identifies a top-level [Tstr_eval], which executes + unconditionally, so use the expression's own position. Both + liveness implementations deliberately treat non-declaration + positions as live; that behavior is load-bearing here. *) + if binding = Location.none then loc_from.loc_start + else binding.loc_start + in + add_optional_arg_value_escape ~val_type pos_from loc_to.loc_start) | Texp_apply { funct = @@ -136,9 +183,10 @@ let rec collect_expr ~config ~refs ~file_deps ~cross_file Texp_ident (path, _, {Types.val_loc = {loc_ghost = false; _} as loc_to}); exp_type; - }; + } as direct_callee; args; } -> + Expression_table.replace direct_callees direct_callee (); args |> process_optional_args ~config ~cross_file ~exp_type ~loc_from:(loc_from : Location.t) @@ -155,7 +203,7 @@ let rec collect_expr ~config ~refs ~file_deps ~cross_file Texp_ident (path, _, {Types.val_loc = {loc_ghost = false; _} as loc_to}); exp_type; - }; + } as direct_callee; }; ], { @@ -180,6 +228,7 @@ let rec collect_expr ~config ~refs ~file_deps ~cross_file when Ident.name id_arg = "arg" && Ident.name eta_arg = "eta" && Path.name id_arg2 = "arg" -> + Expression_table.replace direct_callees direct_callee (); args |> process_optional_args ~config ~cross_file ~exp_type ~loc_from:(loc_from : Location.t) @@ -213,8 +262,8 @@ let rec collect_expr ~config ~refs ~file_deps ~cross_file -> (* Punned field in OCaml projects has ghost location in expression *) let e = {e with exp_loc = {exp_loc with loc_ghost = false}} in - collect_expr ~config ~refs ~file_deps ~cross_file ~last_binding - super self e + collect_expr ~config ~refs ~file_deps ~cross_file ~direct_callees + ~last_binding super self e |> ignore | _ -> ()) | _ -> ()); @@ -348,16 +397,19 @@ let rec process_signature_item ~config ~decls ~file ~do_types ~do_values in if (not is_primitive) || !Config.analyze_externals then let optional_args = - val_type |> Dead_optional_args.from_type_expr + val_type |> Dead_optional_args.from_type_expr_with_declared_arity |> Optional_args.from_list in + let reports_optional_args = + not (Optional_args.is_empty optional_args) + in (* if Ident.name id = "someValue" then Printf.printf "XXX %s\n" (Ident.name id); *) Ident.name id |> Name.create ~is_interface:false |> add_value_declaration ~config ~decls ~file ~loc ~module_loc - ~optional_args ~path ~side_effects:false + ~reports_optional_args ~optional_args ~path ~side_effects:false | Sig_module (id, {Types.md_type = module_type; md_loc = module_loc}, _) | Sig_modtype (id, {Types.mtd_type = Some module_type; mtd_loc = module_loc}) -> @@ -382,6 +434,7 @@ let rec process_signature_item ~config ~decls ~file ~do_types ~do_values (* Traverse the AST *) let traverse_structure ~config ~decls ~refs ~file_deps ~cross_file ~file ~do_types ~do_externals (structure : Typedtree.structure) : unit = + let direct_callees = Expression_table.create 16 in let rec create_mapper (last_binding : Location.t) (module_path : Module_path.t) = let super = Tast_mapper.default in @@ -391,8 +444,8 @@ let traverse_structure ~config ~decls ~refs ~file_deps ~cross_file ~file expr = (fun _self e -> e - |> collect_expr ~config ~refs ~file_deps ~cross_file ~last_binding - super mapper); + |> collect_expr ~config ~refs ~file_deps ~cross_file ~direct_callees + ~last_binding super mapper); pat = (fun _self p -> p @@ -530,25 +583,27 @@ let traverse_structure ~config ~decls ~refs ~file_deps ~cross_file ~file mapper.structure mapper structure |> ignore (* Merge a location's references to another one's *) -let process_value_dependency ~config ~decls ~refs ~file_deps ~cross_file +let process_value_dependency ~config ~refs ~file_deps ~cross_file ( ({ val_loc = {loc_start = {pos_fname = fn_to} as pos_to; loc_ghost = ghost1} as loc_to; + val_type = type_to; } : Types.value_description), ({ val_loc = {loc_start = {pos_fname = fn_from} as pos_from; loc_ghost = ghost2} as loc_from; + val_type = type_from; } : Types.value_description) ) = if (not ghost1) && (not ghost2) && pos_to <> pos_from then ( let add_file_reference = file_is_implementation_of fn_to fn_from in add_value_reference ~config ~refs ~file_deps ~binding:Location.none ~add_file_reference ~loc_from ~loc_to; - Dead_optional_args.add_function_reference ~config ~decls ~cross_file - ~loc_from ~loc_to) + Dead_optional_args.add_function_reference ~config ~cross_file ~loc_from + ~loc_to ~type_from ~type_to) let process_structure ~config ~decls ~refs ~file_deps ~cross_file ~file ~cmt_value_dependencies ~do_types ~do_externals @@ -557,5 +612,4 @@ let process_structure ~config ~decls ~refs ~file_deps ~cross_file ~file ~do_externals structure; let value_dependencies = cmt_value_dependencies |> List.rev in value_dependencies - |> List.iter - (process_value_dependency ~config ~decls ~refs ~file_deps ~cross_file) + |> List.iter (process_value_dependency ~config ~refs ~file_deps ~cross_file) diff --git a/analysis/reanalyze/src/decl.ml b/analysis/reanalyze/src/decl.ml index aa457b3f5b..9ddaad60ac 100644 --- a/analysis/reanalyze/src/decl.ml +++ b/analysis/reanalyze/src/decl.ml @@ -7,6 +7,7 @@ module Kind = struct | VariantCase | Value of { is_toplevel: bool; + mutable reports_optional_args: bool; mutable optional_args: Optional_args.t; side_effects: bool; } diff --git a/analysis/reanalyze/src/reactive_merge.ml b/analysis/reanalyze/src/reactive_merge.ml index 6c376e0efa..14dc222d71 100644 --- a/analysis/reanalyze/src/reactive_merge.ml +++ b/analysis/reanalyze/src/reactive_merge.ml @@ -88,6 +88,8 @@ let create (source : (string, Dce_file_processing.file_data option) Reactive.t) exception_refs = a.exception_refs @ b.exception_refs; optional_arg_calls = a.optional_arg_calls @ b.optional_arg_calls; function_refs = a.function_refs @ b.function_refs; + optional_arg_value_escapes = + a.optional_arg_value_escapes @ b.optional_arg_value_escapes; }) () in @@ -225,17 +227,22 @@ let collect_cross_file_items (t : t) : Cross_file_items.t = let exception_refs = ref [] in let optional_arg_calls = ref [] in let function_refs = ref [] in + let optional_arg_value_escapes = ref [] in Reactive.iter (fun _path items -> exception_refs := items.Cross_file_items.exception_refs @ !exception_refs; optional_arg_calls := items.Cross_file_items.optional_arg_calls @ !optional_arg_calls; - function_refs := items.Cross_file_items.function_refs @ !function_refs) + function_refs := items.Cross_file_items.function_refs @ !function_refs; + optional_arg_value_escapes := + items.Cross_file_items.optional_arg_value_escapes + @ !optional_arg_value_escapes) t.cross_file_items; { Cross_file_items.exception_refs = !exception_refs; optional_arg_calls = !optional_arg_calls; function_refs = !function_refs; + optional_arg_value_escapes = !optional_arg_value_escapes; } (** Convert reactive file deps to FileDeps.t for solver. diff --git a/analysis/reanalyze/src/reanalyze.ml b/analysis/reanalyze/src/reanalyze.ml index 062df5c6ee..b96ad7a793 100644 --- a/analysis/reanalyze/src/reanalyze.ml +++ b/analysis/reanalyze/src/reanalyze.ml @@ -347,11 +347,16 @@ let run_analysis ~dce_config ~cmt_root ~reactive_collection ~reactive_merge Cross_file_items_store.compute_optional_args_state cross_file_store ~find_decl ~is_live in + let optional_arg_value_escapes = + Cross_file_items_store.compute_live_optional_arg_value_escapes + cross_file_store ~is_live + in (* Iterate live declarations and check for optional args issues *) let issues = ref [] in Reactive_solver.iter_live_decls ~t:solver (fun decl -> let decl_issues = - Dead_optional_args.check ~optional_args_state ~ann_store + Dead_optional_args.check ~optional_args_state + ~optional_arg_value_escapes ~ann_store ~config:dce_config decl in issues := List.rev_append decl_issues !issues); @@ -399,13 +404,18 @@ let run_analysis ~dce_config ~cmt_root ~reactive_collection ~reactive_merge ~find_decl:(Declaration_store.find_opt decl_store) ~is_live in + let optional_arg_value_escapes = + Cross_file_items_store.compute_live_optional_arg_value_escapes + cross_file_store ~is_live + in (* Collect optional args issues only for live declarations *) let optional_args_issues = Declaration_store.fold (fun _pos decl acc -> if Decl.is_live decl then let issues = - Dead_optional_args.check ~optional_args_state ~ann_store + Dead_optional_args.check ~optional_args_state + ~optional_arg_value_escapes ~ann_store ~config:dce_config decl in List.rev_append issues acc diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/expected/deadcode.txt b/tests/analysis_tests/tests-reanalyze/deadcode/expected/deadcode.txt index dafbaffeb6..79e44acd7a 100644 --- a/tests/analysis_tests/tests-reanalyze/deadcode/expected/deadcode.txt +++ b/tests/analysis_tests/tests-reanalyze/deadcode/expected/deadcode.txt @@ -32,6 +32,52 @@ addTypeReference _none_:1:-1 --> ComponentAsProp.res:6:20 addTypeReference _none_:1:-1 --> ComponentAsProp.res:6:34 addValueReference ComponentAsProp.res:6:4 --> React.res:16:0 + Scanning ContextOptionalArgs.cmt Source:ContextOptionalArgs.res + addValueDeclaration +dispatchNotificationContext ContextOptionalArgs.res:2:6 path:+ContextOptionalArgs.NotificationProvider + addValueDeclaration +make ContextOptionalArgs.res:8:8 path:+ContextOptionalArgs.NotificationProvider.Provider + addValueDeclaration +make ContextOptionalArgs.res:12:6 path:+ContextOptionalArgs.NotificationProvider + addValueDeclaration +useNotification ContextOptionalArgs.res:22:6 path:+ContextOptionalArgs.NotificationProvider + addValueDeclaration +make ContextOptionalArgs.res:27:6 path:+ContextOptionalArgs.ComponentUsingAction + addValueDeclaration +make ContextOptionalArgs.res:41:6 path:+ContextOptionalArgs.ComponentNotUsingAction + addValueDeclaration +make ContextOptionalArgs.res:55:4 path:+ContextOptionalArgs + addRecordLabelDeclaration children ContextOptionalArgs.res:12:14 path:+ContextOptionalArgs.NotificationProvider.props + addValueReference ContextOptionalArgs.res:2:6 --> React.res:81:0 + addValueReference ContextOptionalArgs.res:8:8 --> ContextOptionalArgs.res:2:6 + addValueReference ContextOptionalArgs.res:8:8 --> React.res:77:2 + addRecordLabelDeclaration children ContextOptionalArgs.res:12:14 path:+ContextOptionalArgs.NotificationProvider.props + addValueDeclaration +dispatchNotification ContextOptionalArgs.res:13:8 path:+ContextOptionalArgs.NotificationProvider + addValueReference ContextOptionalArgs.res:13:8 --> ContextOptionalArgs.res:13:43 + addValueReference ContextOptionalArgs.res:13:8 --> ContextOptionalArgs.res:15:13 + addValueReference ContextOptionalArgs.res:13:8 --> ContextOptionalArgs.res:13:43 + addValueReference ContextOptionalArgs.res:13:8 --> ContextOptionalArgs.res:13:32 + addValueReference ContextOptionalArgs.res:19:5 --> ContextOptionalArgs.res:8:8 + addValueReference ContextOptionalArgs.res:19:20 --> ContextOptionalArgs.res:13:8 + addValueReference ContextOptionalArgs.res:19:43 --> ContextOptionalArgs.res:12:14 + addTypeReference _none_:1:-1 --> ContextOptionalArgs.res:12:14 + addValueReference ContextOptionalArgs.res:12:6 --> React.res:16:0 + DeadOptionalArgs.addReferences React.useContext called with optional argNames: argNamesMaybe: ContextOptionalArgs.res:22:30 + addValueReference ContextOptionalArgs.res:22:6 --> ContextOptionalArgs.res:2:6 + addValueReference ContextOptionalArgs.res:22:6 --> React.res:250:0 + addValueDeclaration +dispatchNotification ContextOptionalArgs.res:28:8 path:+ContextOptionalArgs.ComponentUsingAction + DeadOptionalArgs.addReferences NotificationProvider.useNotification called with optional argNames: argNamesMaybe: ContextOptionalArgs.res:28:31 + addValueReference ContextOptionalArgs.res:28:8 --> ContextOptionalArgs.res:22:6 + addValueReference ContextOptionalArgs.res:35:4 --> React.res:3:0 + DeadOptionalArgs.addReferences dispatchNotification called with optional argNames:action argNamesMaybe: ContextOptionalArgs.res:31:6 + addValueReference ContextOptionalArgs.res:31:6 --> ContextOptionalArgs.res:28:8 + addValueReference ContextOptionalArgs.res:30:4 --> React.res:150:0 + addValueReference ContextOptionalArgs.res:27:6 --> React.res:16:0 + addValueDeclaration +dispatchNotification ContextOptionalArgs.res:42:8 path:+ContextOptionalArgs.ComponentNotUsingAction + DeadOptionalArgs.addReferences NotificationProvider.useNotification called with optional argNames: argNamesMaybe: ContextOptionalArgs.res:42:31 + addValueReference ContextOptionalArgs.res:42:8 --> ContextOptionalArgs.res:22:6 + addValueReference ContextOptionalArgs.res:49:4 --> React.res:3:0 + DeadOptionalArgs.addReferences dispatchNotification called with optional argNames: argNamesMaybe: ContextOptionalArgs.res:45:6 + addValueReference ContextOptionalArgs.res:45:6 --> ContextOptionalArgs.res:42:8 + addValueReference ContextOptionalArgs.res:44:4 --> React.res:150:0 + addValueReference ContextOptionalArgs.res:41:6 --> React.res:16:0 + addValueReference ContextOptionalArgs.res:56:3 --> ContextOptionalArgs.res:12:6 + addValueReference ContextOptionalArgs.res:57:5 --> ContextOptionalArgs.res:27:6 + addValueReference ContextOptionalArgs.res:58:5 --> ContextOptionalArgs.res:41:6 + addValueReference ContextOptionalArgs.res:55:4 --> React.res:16:0 Scanning CreateErrorHandler1.cmt Source:CreateErrorHandler1.res addValueDeclaration +notification CreateErrorHandler1.res:3:6 path:+CreateErrorHandler1.Error1 addValueReference CreateErrorHandler1.res:3:6 --> CreateErrorHandler1.res:3:21 @@ -42,6 +88,14 @@ addValueDeclaration +notification CreateErrorHandler2.res:3:6 path:+CreateErrorHandler2.Error2 addValueReference CreateErrorHandler2.res:3:6 --> CreateErrorHandler2.res:3:21 addValueReference ErrorHandler.resi:3:2 --> CreateErrorHandler2.res:3:6 + Scanning CrossFileOptionalArgProvider.cmt Source:CrossFileOptionalArgProvider.res + addValueDeclaration +formatDate CrossFileOptionalArgProvider.res:1:4 path:+CrossFileOptionalArgProvider + addValueReference CrossFileOptionalArgProvider.res:1:4 --> CrossFileOptionalArgProvider.res:1:26 + Scanning CrossFileOptionalArgValueUse.cmt Source:CrossFileOptionalArgValueUse.res + addValueDeclaration +liveReturnCaller CrossFileOptionalArgValueUse.res:1:4 path:+CrossFileOptionalArgValueUse + addValueReference CrossFileOptionalArgValueUse.res:1:4 --> CrossFileOptionalArgProvider.res:1:4 + DeadOptionalArgs.addReferences liveReturnCaller called with optional argNames: argNamesMaybe: CrossFileOptionalArgValueUse.res:5:8 + addValueReference CrossFileOptionalArgValueUse.res:5:8 --> CrossFileOptionalArgValueUse.res:1:4 Scanning DeadCodeImplementation.cmt Source:DeadCodeImplementation.res addValueDeclaration +x DeadCodeImplementation.res:2:6 path:+DeadCodeImplementation.M addValueReference DeadCodeInterface.res:2:2 --> DeadCodeImplementation.res:2:6 @@ -962,6 +1016,21 @@ addVariantCaseDeclaration Foo InnerModuleTypes.res:2:11 path:+InnerModuleTypes.I.t Scanning InnerModuleTypes.cmti Source:InnerModuleTypes.resi addVariantCaseDeclaration Foo InnerModuleTypes.resi:2:11 path:InnerModuleTypes.I.t + Scanning InterfaceOptionalArgEscape.cmt Source:InterfaceOptionalArgEscape.res + addValueDeclaration +escaped InterfaceOptionalArgEscape.res:1:4 path:+InterfaceOptionalArgEscape + addValueDeclaration +takesFn InterfaceOptionalArgEscape.res:3:4 path:+InterfaceOptionalArgEscape + addValueReference InterfaceOptionalArgEscape.res:1:4 --> InterfaceOptionalArgEscape.res:1:23 + addValueReference InterfaceOptionalArgEscape.res:5:8 --> InterfaceOptionalArgEscape.res:1:4 + addValueReference InterfaceOptionalArgEscape.res:5:0 --> InterfaceOptionalArgEscape.res:3:4 + addValueReference InterfaceOptionalArgEscape.resi:1:0 --> InterfaceOptionalArgEscape.res:1:4 + OptionalArgs.addFunctionReference InterfaceOptionalArgEscape.resi:1:0 InterfaceOptionalArgEscape.res:1:4 + Scanning InterfaceOptionalArgEscape.cmti Source:InterfaceOptionalArgEscape.resi + addValueDeclaration +escaped InterfaceOptionalArgEscape.resi:1:0 path:InterfaceOptionalArgEscape + Scanning InterfaceOptionalArgEscapeUse.cmt Source:InterfaceOptionalArgEscapeUse.res + addValueDeclaration +use InterfaceOptionalArgEscapeUse.res:1:4 path:+InterfaceOptionalArgEscapeUse + DeadOptionalArgs.addReferences InterfaceOptionalArgEscape.escaped called with optional argNames: argNamesMaybe: InterfaceOptionalArgEscapeUse.res:1:16 + addValueReference InterfaceOptionalArgEscapeUse.res:1:4 --> InterfaceOptionalArgEscape.resi:1:0 + addValueReference InterfaceOptionalArgEscapeUse.res:3:8 --> InterfaceOptionalArgEscapeUse.res:1:4 Scanning JSResource.cmt Source:JSResource.res Scanning JsxV4.cmt Source:JsxV4.res addValueDeclaration +make JsxV4.res:4:23 path:+JsxV4.C @@ -1344,6 +1413,27 @@ addTypeReference RepeatedLabel.res:12:16 --> RepeatedLabel.res:8:2 addValueReference RepeatedLabel.res:14:12 --> RepeatedLabel.res:12:4 Scanning RequireCond.cmt Source:RequireCond.res + Scanning ReturnedOptionalSignature.cmt Source:ReturnedOptionalSignature.res + addValueDeclaration +returnedOptional ReturnedOptionalSignature.res:1:4 path:+ReturnedOptionalSignature + addValueReference ReturnedOptionalSignature.res:1:4 --> ReturnedOptionalSignature.res:1:34 + addValueReference ReturnedOptionalSignature.resi:1:0 --> ReturnedOptionalSignature.res:1:4 + OptionalArgs.addFunctionReference ReturnedOptionalSignature.resi:1:0 ReturnedOptionalSignature.res:1:4 + Scanning ReturnedOptionalSignature.cmti Source:ReturnedOptionalSignature.resi + addValueDeclaration +returnedOptional ReturnedOptionalSignature.resi:1:0 path:ReturnedOptionalSignature + Scanning ReturnedOptionalSignatureUse.cmt Source:ReturnedOptionalSignatureUse.res + addValueDeclaration +useInterfaceDeclaration ReturnedOptionalSignatureUse.res:1:4 path:+ReturnedOptionalSignatureUse + addValueDeclaration +returnedOptional ReturnedOptionalSignatureUse.res:5:2 path:+ReturnedOptionalSignatureUse.InlineSignature + addValueDeclaration +useInlineSignature ReturnedOptionalSignatureUse.res:10:4 path:+ReturnedOptionalSignatureUse + DeadOptionalArgs.addReferences ReturnedOptionalSignature.returnedOptional called with optional argNames: argNamesMaybe: ReturnedOptionalSignatureUse.res:2:2 + addValueReference ReturnedOptionalSignatureUse.res:1:4 --> ReturnedOptionalSignature.resi:1:0 + addValueDeclaration +returnedOptional ReturnedOptionalSignatureUse.res:7:6 path:+ReturnedOptionalSignatureUse.InlineSignature + addValueReference ReturnedOptionalSignatureUse.res:7:6 --> ReturnedOptionalSignatureUse.res:7:36 + DeadOptionalArgs.addReferences InlineSignature.returnedOptional called with optional argNames: argNamesMaybe: ReturnedOptionalSignatureUse.res:11:2 + addValueReference ReturnedOptionalSignatureUse.res:10:4 --> ReturnedOptionalSignatureUse.res:5:2 + addValueReference ReturnedOptionalSignatureUse.res:13:8 --> ReturnedOptionalSignatureUse.res:1:4 + addValueReference ReturnedOptionalSignatureUse.res:14:8 --> ReturnedOptionalSignatureUse.res:10:4 + addValueReference ReturnedOptionalSignatureUse.res:5:2 --> ReturnedOptionalSignatureUse.res:7:6 + OptionalArgs.addFunctionReference ReturnedOptionalSignatureUse.res:5:2 ReturnedOptionalSignatureUse.res:7:6 Scanning ScopedAnnotationsLiveVsDead.cmt Source:ScopedAnnotationsLiveVsDead.res addValueDeclaration +leafLive ScopedAnnotationsLiveVsDead.res:1:4 path:+ScopedAnnotationsLiveVsDead addValueDeclaration +middleLive ScopedAnnotationsLiveVsDead.res:2:4 path:+ScopedAnnotationsLiveVsDead @@ -1456,6 +1546,71 @@ addTypeReference TestPromise.res:14:48 --> TestPromise.res:7:2 Scanning ToSuppress.cmt Source:ToSuppress.res addValueDeclaration +toSuppress ToSuppress.res:1:4 path:+ToSuppress + Scanning TopLevelOptionalArgValueUse.cmt Source:TopLevelOptionalArgValueUse.res + addValueDeclaration +formatDate TopLevelOptionalArgValueUse.res:4:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +formatDateEscapes TopLevelOptionalArgValueUse.res:5:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +formatDateReturn TopLevelOptionalArgValueUse.res:6:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +formatDateTuple TopLevelOptionalArgValueUse.res:7:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +formatDateForwarded TopLevelOptionalArgValueUse.res:8:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +formatDateTopLevelEscape TopLevelOptionalArgValueUse.res:9:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +formatDateAlias TopLevelOptionalArgValueUse.res:10:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +takesFn TopLevelOptionalArgValueUse.res:12:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +deadEscape TopLevelOptionalArgValueUse.res:16:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +liveCaller TopLevelOptionalArgValueUse.res:18:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +liveEscapeCaller TopLevelOptionalArgValueUse.res:20:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +liveReturnCaller TopLevelOptionalArgValueUse.res:25:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +liveTupleCaller TopLevelOptionalArgValueUse.res:29:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +liveForwardingCaller TopLevelOptionalArgValueUse.res:33:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +formatDateAlias2 TopLevelOptionalArgValueUse.res:37:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +liveAliasCaller TopLevelOptionalArgValueUse.res:38:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +mutuallyRecursiveCaller TopLevelOptionalArgValueUse.res:40:8 path:+TopLevelOptionalArgValueUse + addValueDeclaration +mutuallyRecursiveTarget TopLevelOptionalArgValueUse.res:41:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +returnsFunction TopLevelOptionalArgValueUse.res:43:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +returnedFunction TopLevelOptionalArgValueUse.res:44:4 path:+TopLevelOptionalArgValueUse + addValueDeclaration +liveReturnedFunctionCaller TopLevelOptionalArgValueUse.res:45:4 path:+TopLevelOptionalArgValueUse + addValueReference TopLevelOptionalArgValueUse.res:4:4 --> TopLevelOptionalArgValueUse.res:4:26 + addValueReference TopLevelOptionalArgValueUse.res:5:4 --> TopLevelOptionalArgValueUse.res:5:33 + addValueReference TopLevelOptionalArgValueUse.res:6:4 --> TopLevelOptionalArgValueUse.res:6:32 + addValueReference TopLevelOptionalArgValueUse.res:7:4 --> TopLevelOptionalArgValueUse.res:7:31 + addValueReference TopLevelOptionalArgValueUse.res:8:4 --> TopLevelOptionalArgValueUse.res:8:35 + addValueReference TopLevelOptionalArgValueUse.res:9:4 --> TopLevelOptionalArgValueUse.res:9:40 + addValueReference TopLevelOptionalArgValueUse.res:10:4 --> TopLevelOptionalArgValueUse.res:10:31 + addValueReference TopLevelOptionalArgValueUse.res:14:8 --> TopLevelOptionalArgValueUse.res:9:4 + addValueReference TopLevelOptionalArgValueUse.res:14:0 --> TopLevelOptionalArgValueUse.res:12:4 + addValueReference TopLevelOptionalArgValueUse.res:16:4 --> TopLevelOptionalArgValueUse.res:4:4 + addValueReference TopLevelOptionalArgValueUse.res:16:4 --> TopLevelOptionalArgValueUse.res:12:4 + DeadOptionalArgs.addReferences formatDate called with optional argNames: argNamesMaybe: TopLevelOptionalArgValueUse.res:18:23 + addValueReference TopLevelOptionalArgValueUse.res:18:4 --> TopLevelOptionalArgValueUse.res:4:4 + DeadOptionalArgs.addReferences formatDateEscapes called with optional argNames: argNamesMaybe: TopLevelOptionalArgValueUse.res:22:2 + addValueReference TopLevelOptionalArgValueUse.res:20:4 --> TopLevelOptionalArgValueUse.res:5:4 + addValueReference TopLevelOptionalArgValueUse.res:20:4 --> TopLevelOptionalArgValueUse.res:5:4 + addValueReference TopLevelOptionalArgValueUse.res:20:4 --> TopLevelOptionalArgValueUse.res:12:4 + addValueReference TopLevelOptionalArgValueUse.res:25:4 --> TopLevelOptionalArgValueUse.res:6:4 + addValueReference TopLevelOptionalArgValueUse.res:29:4 --> TopLevelOptionalArgValueUse.res:7:4 + DeadOptionalArgs.addReferences formatDateForwarded called with optional argNames:fmt argNamesMaybe:fmt TopLevelOptionalArgValueUse.res:34:2 + addValueReference TopLevelOptionalArgValueUse.res:33:4 --> TopLevelOptionalArgValueUse.res:33:28 + addValueReference TopLevelOptionalArgValueUse.res:33:4 --> TopLevelOptionalArgValueUse.res:8:4 + addValueReference TopLevelOptionalArgValueUse.res:37:4 --> TopLevelOptionalArgValueUse.res:10:4 + DeadOptionalArgs.addReferences formatDateAlias2 called with optional argNames: argNamesMaybe: TopLevelOptionalArgValueUse.res:38:28 + addValueReference TopLevelOptionalArgValueUse.res:38:4 --> TopLevelOptionalArgValueUse.res:37:4 + DeadOptionalArgs.addReferences mutuallyRecursiveTarget called with optional argNames:fmt argNamesMaybe: TopLevelOptionalArgValueUse.res:40:40 + addValueReference TopLevelOptionalArgValueUse.res:40:8 --> TopLevelOptionalArgValueUse.res:41:4 + addValueReference TopLevelOptionalArgValueUse.res:41:4 --> TopLevelOptionalArgValueUse.res:41:39 + addValueReference TopLevelOptionalArgValueUse.res:43:4 --> TopLevelOptionalArgValueUse.res:43:22 + DeadOptionalArgs.addReferences returnsFunction called with optional argNames: argNamesMaybe: TopLevelOptionalArgValueUse.res:44:23 + addValueReference TopLevelOptionalArgValueUse.res:44:4 --> TopLevelOptionalArgValueUse.res:43:4 + DeadOptionalArgs.addReferences returnedFunction called with optional argNames: argNamesMaybe: TopLevelOptionalArgValueUse.res:45:39 + addValueReference TopLevelOptionalArgValueUse.res:45:4 --> TopLevelOptionalArgValueUse.res:44:4 + addValueReference TopLevelOptionalArgValueUse.res:47:8 --> TopLevelOptionalArgValueUse.res:18:4 + addValueReference TopLevelOptionalArgValueUse.res:48:8 --> TopLevelOptionalArgValueUse.res:20:4 + DeadOptionalArgs.addReferences liveReturnCaller called with optional argNames: argNamesMaybe: TopLevelOptionalArgValueUse.res:49:8 + addValueReference TopLevelOptionalArgValueUse.res:49:8 --> TopLevelOptionalArgValueUse.res:25:4 + addValueReference TopLevelOptionalArgValueUse.res:50:8 --> TopLevelOptionalArgValueUse.res:29:4 + DeadOptionalArgs.addReferences liveForwardingCaller called with optional argNames: argNamesMaybe: TopLevelOptionalArgValueUse.res:51:8 + addValueReference TopLevelOptionalArgValueUse.res:51:8 --> TopLevelOptionalArgValueUse.res:33:4 + addValueReference TopLevelOptionalArgValueUse.res:52:8 --> TopLevelOptionalArgValueUse.res:38:4 + addValueReference TopLevelOptionalArgValueUse.res:53:8 --> TopLevelOptionalArgValueUse.res:40:8 + addValueReference TopLevelOptionalArgValueUse.res:54:8 --> TopLevelOptionalArgValueUse.res:45:4 Scanning TransitiveType1.cmt Source:TransitiveType1.res addValueDeclaration +convert TransitiveType1.res:2:4 path:+TransitiveType1 addValueDeclaration +convertAlias TransitiveType1.res:5:4 path:+TransitiveType1 @@ -1957,9 +2112,9 @@ Forward Liveness Analysis - decls: 700 - roots(external targets): 137 - decl-deps: decls_with_out=411 edges_to_decls=289 + decls: 744 + roots(external targets): 162 + decl-deps: decls_with_out=452 edges_to_decls=323 Root (external ref): Value +FirstClassModules.M.InnerModule2.+k Root (external ref): VariantCase DeadRT.moduleAccessPath.Root @@ -1978,6 +2133,7 @@ Forward Liveness Analysis Root (annotated): Value +NestedModules.Universe.Nested2.+nested2Function Root (external ref): Value +OptArg.+wrapfourArgs Root (annotated): Value +Docstrings.+unitArgWithoutConversionU + Root (external ref): Value +InterfaceOptionalArgEscape.+escaped Root (external ref): VariantCase +DeadTypeTest.deadType.OnlyInImplementation Root (annotated): Value +TestImport.+valueStartingWithUpperCaseLetter Root (external ref): Value +TypeReexport.VariantUseReexported.+value @@ -1988,6 +2144,7 @@ Forward Liveness Analysis Root (annotated): Value +Types.+optFunction Root (annotated): Value +Variants.+sunday Root (annotated): Value +NestedModules.Universe.Nested2.Nested3.+nested3Value + Root (external ref): Value +TopLevelOptionalArgValueUse.+liveReturnCaller Root (external ref): RecordLabel +Unison.t.doc Root (annotated): Value +Tuples.+computeAreaWithIdent Root (annotated): Value +LetPrivate.+y @@ -1997,7 +2154,9 @@ Forward Liveness Analysis Root (annotated): Value +Uncurried.+uncurried3 Root (external ref): Value +Newton.+f Root (external ref): RecordLabel +Records.record.v + Root (external ref): Value +ContextOptionalArgs.ComponentUsingAction.+make Root (external ref): RecordLabel +Records.person.address + Root (external ref): RecordLabel +ContextOptionalArgs.NotificationProvider.props.children Root (annotated): Value +Variants.+testConvert2 Root (annotated): Value +Tuples.+coord2d Root (external ref): Value +CreateErrorHandler1.Error1.+notification @@ -2031,16 +2190,19 @@ Forward Liveness Analysis Root (annotated): Value +TestOptArg.+liveSuppressesOptArgs Root (annotated): Value +Uncurried.+sumU2 Root (external ref): Value OptArg.+bar + Root (external ref): Value +TopLevelOptionalArgValueUse.+liveAliasCaller Root (annotated): Value +Records.+payloadValue Root (annotated): Value +Hooks.+default Root (annotated): Value +Types.+currentTime Root (annotated): Value +VariantsWithPayload.+testVariant1Object Root (external ref): VariantCase +Unison.break_.Never + Root (external ref): Value +ContextOptionalArgs.NotificationProvider.+make Root (annotated): Value +Records.+computeArea3 Root (annotated): Value +TestEmitInnerModules.Inner.+y Root (external ref): VariantCase InnerModuleTypes.I.t.Foo Root (annotated): Value +Types.+selfRecursiveConverter Root (annotated): Value +Opaque.+testConvertNestedRecordFromOtherFile + Root (external ref): Value +ReturnedOptionalSignatureUse.+useInterfaceDeclaration Root (external ref): RecordLabel +DeadTest.inlineRecord.IR.b Root (external ref): Value +OptArg.+bar Root (annotated): Value +TestFirstClassModules.+convertRecord @@ -2050,6 +2212,7 @@ Forward Liveness Analysis Root (annotated): Value +Variants.+restResult3 Root (external ref): Value +FirstClassModules.M.InnerModule3.+k3 Root (annotated): Value +DeadTest.+fortyTwoButExported + Root (external ref): Value +ContextOptionalArgs.ComponentNotUsingAction.+dispatchNotification Root (external ref): VariantCase +DeadTest.VariantUsedOnlyInImplementation.t.A Root (external ref): RecordLabel +Records.coord.x Root (annotated): RecordLabel +DeadTypeTest.record.y @@ -2064,6 +2227,7 @@ Forward Liveness Analysis Root (annotated): Value +TestImport.+innerStuffContents Root (external ref): Value +ModuleExceptionBug.+ddjdj Root (annotated): Value +TransitiveType1.+convert + Root (external ref): Value +CrossFileOptionalArgValueUse.+liveReturnCaller Root (annotated): Value +ImportHooks.+make Root (external ref): VariantCase +Unison.break_.IfNeed Root (external ref): VariantCase +DeadTest.WithInclude.t.A @@ -2084,10 +2248,12 @@ Forward Liveness Analysis Root (annotated): Value +Types.+testMarshalFields Root (annotated): Value +Hooks.Inner.Inner2.+make Root (annotated): Value +ImportJsValue.+area + Root (external ref): Value +TopLevelOptionalArgValueUse.+mutuallyRecursiveCaller Root (external ref): Value +DeadTest.MM.+x Root (external ref): RecordLabel +Uncurried.auth.login Root (annotated): Value +ImportJsValue.+roundedNumber Root (external ref): RecordLabel +RepeatedLabel.tabState.a + Root (external ref): Value +ReturnedOptionalSignatureUse.+useInlineSignature Root (external ref): Value ErrorHandler.Make.+notify Root (annotated): Value +References.+make Root (annotated): Value +Shadow.+test @@ -2104,7 +2270,9 @@ Forward Liveness Analysis Root (annotated): Value +DeadTest.+thisIsMarkedLive Root (annotated): Value +Docstrings.+one Root (annotated): Value +OcamlWarningSuppressToplevel.+suppressed1 + Root (external ref): Value +TopLevelOptionalArgValueUse.+liveCaller Root (annotated): Value +Tuples.+testTuple + Root (external ref): Value +ContextOptionalArgs.NotificationProvider.+dispatchNotification Root (external ref): Value +OptArg.+wrapOneArg Root (annotated): Value +Uncurried.+callback2 Root (annotated): Value +ImportMyBanner.+make @@ -2116,16 +2284,19 @@ Forward Liveness Analysis Root (annotated): Value +TestEmitInnerModules.Inner.+x Root (annotated): Value +Tuples.+changeSecondAge Root (external ref): RecordLabel +ComponentAsProp.props.title + Root (external ref): Value +ContextOptionalArgs.ComponentUsingAction.+dispatchNotification Root (annotated): Value +Records.+findAddress Root (annotated): Value +Uncurried.+callback Root (external ref): Value +DeadTest.+thisIsUsedTwice Root (annotated): Value +VariantsWithPayload.+printVariantWithPayload Root (annotated): Value +TestImmutableArray.+testImmutableArrayGet Root (annotated): Value +VariantsWithPayload.+printManyPayloads + Root (external ref): Value +TopLevelOptionalArgValueUse.+formatDateTopLevelEscape Root (external ref): Value +TypeReexport.UseOriginal.+value Root (annotated): Value +Docstrings.+unnamed2 Root (annotated): Value +LetPrivate.local_1.+x Root (annotated): Value +TestImport.+make + Root (external ref): Value +ContextOptionalArgs.NotificationProvider.Provider.+make Root (annotated): Value +Docstrings.+grouped Root (annotated): Value +OcamlWarningSuppressToplevel.M.+suppressed4 Root (external ref): VariantCase +DeadTest.inlineRecord.IR @@ -2161,12 +2332,17 @@ Forward Liveness Analysis Root (annotated): Value +Types.+map Root (annotated): RecordLabel +DeadTypeTest.record.x Root (external ref): Value +TestOptArg.+bar + Root (external ref): Value +ContextOptionalArgs.ComponentNotUsingAction.+make Root (external ref): RecordLabel +Records.myRec.type_ Root (external ref): Value +DeadTest.+make Root (annotated): Value NestedModulesInSignature.Universe.+theAnswer Root (annotated): Value +Docstrings.+unitArgWithoutConversion + Root (annotated): Value +ContextOptionalArgs.+make Root (annotated): Value +References.+create + Root (external ref): Value +InterfaceOptionalArgEscapeUse.+use + Root (external ref): Value +TopLevelOptionalArgValueUse.+liveEscapeCaller Root (annotated): Value +FirstClassModules.+testConvert + Root (external ref): Value +TopLevelOptionalArgValueUse.+liveTupleCaller Root (external ref): RecordLabel +Records.coord.z Root (annotated): Value +Types.+someIntList Root (annotated): Value +Types.+i64Const @@ -2211,6 +2387,7 @@ Forward Liveness Analysis Root (annotated): Value +Variants.+restResult2 Root (annotated): Value +Docstrings.+useParam Root (annotated): Value +Records.+getPayload + Root (external ref): Value +TopLevelOptionalArgValueUse.+liveReturnedFunctionCaller Root (annotated): Value +VariantsWithPayload.+printVariantWithPayloads Root (annotated): Value +ScopedAnnotationsOverride.M.NestedInLive.+nestedLive Root (external ref): Value +FirstClassModules.M.+y @@ -2231,6 +2408,7 @@ Forward Liveness Analysis Root (external ref): VariantCase +Unison.stack.Cons Root (external ref): Exception +DeadExn.Inside.Einside Root (annotated): Value +TestImport.+defaultValue2 + Root (external ref): Value +TopLevelOptionalArgValueUse.+liveForwardingCaller Root (external ref): Exception +DeadExn.Etoplevel Root (annotated): Value +Variants.+monday Root (annotated): Value +Unboxed.+r2Test @@ -2250,6 +2428,7 @@ Forward Liveness Analysis Root (external ref): Value +OptArg.+twoArgs Root (external ref): Value +FirstClassModules.M.+x Root (external ref): Value +TypeReexportCrossFileB.+recordValue + Root (external ref): Value +InterfaceOptionalArgEscape.+takesFn Root (annotated): Value +TestModuleAliases.+testInner1Expanded Root (external ref): Value +TypeReexport.OnlyReexportedDead.+value Root (annotated): Value +DeadTest.GloobLive.+globallyLive3 @@ -2269,6 +2448,7 @@ Forward Liveness Analysis Root (annotated): Value +VariantsWithPayload.+testManyPayloads Root (external ref): RecordLabel +TypeReexport.OnlyReexportedDead.reexportedType.usedField Root (annotated): Value +Docstrings.+unitArgWithConversion + Root (external ref): Value +TopLevelOptionalArgValueUse.+takesFn Root (external ref): RecordLabel +Records.business.owner Root (external ref): VariantCase +DeadTypeTest.deadType.InBoth Root (external ref): RecordLabel +Records.business.address @@ -2285,25 +2465,32 @@ Forward Liveness Analysis Root (annotated): Value +UseImportJsValue.+useGetProp Root (annotated): Value +Hooks.+functionWithRenamedArgs - 323 roots found + 348 roots found Propagate: DeadRT.moduleAccessPath.Root -> +DeadRT.moduleAccessPath.Root Propagate: +TypeReexportCrossFileB.reexportedRecord.usedField -> +TypeReexportCrossFileA.originalRecord.usedField Propagate: +OptArg.+wrapfourArgs -> +OptArg.+fourArgs Propagate: +DeadTypeTest.deadType.OnlyInImplementation -> DeadTypeTest.deadType.OnlyInImplementation Propagate: +OptionalArgsLiveDead.+liveCaller -> +OptionalArgsLiveDead.+formatDate + Propagate: +TopLevelOptionalArgValueUse.+liveReturnCaller -> +TopLevelOptionalArgValueUse.+formatDateReturn Propagate: +Newton.+f -> +Newton.+- Propagate: +Newton.+f -> +Newton.++ Propagate: +Newton.+f -> +Newton.+* + Propagate: +ContextOptionalArgs.ComponentUsingAction.+make -> +ContextOptionalArgs.NotificationProvider.+useNotification Propagate: +TypeReexport.UseOriginal.reexportedType.directlyUsed -> +TypeReexport.UseOriginal.originalType.directlyUsed + Propagate: +TopLevelOptionalArgValueUse.+liveAliasCaller -> +TopLevelOptionalArgValueUse.+formatDateAlias2 Propagate: +Hooks.+default -> +Hooks.+make Propagate: InnerModuleTypes.I.t.Foo -> +InnerModuleTypes.I.t.Foo + Propagate: +ReturnedOptionalSignatureUse.+useInterfaceDeclaration -> ReturnedOptionalSignature.+returnedOptional Propagate: DeadTypeTest.deadType.OnlyInInterface -> +DeadTypeTest.deadType.OnlyInInterface Propagate: +DeadTest.VariantUsedOnlyInImplementation.t.A -> +DeadTest.VariantUsedOnlyInImplementation.t.A Propagate: +TypeReexport.UseReexported.reexportedType.usedField -> +TypeReexport.UseReexported.originalType.usedField + Propagate: +CrossFileOptionalArgValueUse.+liveReturnCaller -> +CrossFileOptionalArgProvider.+formatDate Propagate: +DeadTest.WithInclude.t.A -> +DeadTest.WithInclude.t.A Propagate: +References.+get -> +References.R.+get + Propagate: +TopLevelOptionalArgValueUse.+mutuallyRecursiveCaller -> +TopLevelOptionalArgValueUse.+mutuallyRecursiveTarget Propagate: +DeadTest.MM.+x -> +DeadTest.MM.+x + Propagate: +ReturnedOptionalSignatureUse.+useInlineSignature -> +ReturnedOptionalSignatureUse.InlineSignature.+returnedOptional Propagate: ErrorHandler.Make.+notify -> +ErrorHandler.Make.+notify Propagate: +References.+make -> +References.R.+make Propagate: +ScopedAnnotationsLiveVsDead.LiveScope.+root -> +ScopedAnnotationsLiveVsDead.+middleLive @@ -2311,23 +2498,33 @@ Forward Liveness Analysis Propagate: +Newton.+result -> +Newton.+fPrimed Propagate: +Records.+findAllAddresses -> +Records.+getOpt Propagate: +DeadTest.+thisIsMarkedLive -> +DeadTest.+thisIsKeptAlive + Propagate: +TopLevelOptionalArgValueUse.+liveCaller -> +TopLevelOptionalArgValueUse.+formatDate Propagate: +OptArg.+wrapOneArg -> +OptArg.+oneArg Propagate: +TestImmutableArray.+testImmutableArrayGet -> ImmutableArray.Array.+get + Propagate: +ContextOptionalArgs.NotificationProvider.Provider.+make -> +ContextOptionalArgs.NotificationProvider.+dispatchNotificationContext Propagate: +TypeReexport.VariantUseReexported.reexportedType.A -> +TypeReexport.VariantUseReexported.originalType.A Propagate: +Unison.+toString -> +Unison.+fits Propagate: +References.+set -> +References.R.+set Propagate: +TestOptArg.+bar -> +TestOptArg.+foo Propagate: NestedModulesInSignature.Universe.+theAnswer -> +NestedModulesInSignature.Universe.+theAnswer + Propagate: +InterfaceOptionalArgEscapeUse.+use -> InterfaceOptionalArgEscape.+escaped + Propagate: +TopLevelOptionalArgValueUse.+liveEscapeCaller -> +TopLevelOptionalArgValueUse.+formatDateEscapes + Propagate: +TopLevelOptionalArgValueUse.+liveTupleCaller -> +TopLevelOptionalArgValueUse.+formatDateTuple Propagate: +DeadTypeTest.t.A -> DeadTypeTest.t.A Propagate: ImmutableArray.+fromArray -> +ImmutableArray.+fromArray Propagate: +DeadRT.moduleAccessPath.Kaboom -> DeadRT.moduleAccessPath.Kaboom + Propagate: +TopLevelOptionalArgValueUse.+liveReturnedFunctionCaller -> +TopLevelOptionalArgValueUse.+returnedFunction Propagate: DeadValueTest.+valueAlive -> +DeadValueTest.+valueAlive + Propagate: +TopLevelOptionalArgValueUse.+liveForwardingCaller -> +TopLevelOptionalArgValueUse.+formatDateForwarded Propagate: +DeadTest.VariantUsedOnlyInImplementation.+a -> +DeadTest.VariantUsedOnlyInImplementation.+a Propagate: +ImportJsValue.+useGetAbs -> +ImportJsValue.AbsoluteValue.+getAbs Propagate: +TypeReexport.VariantUseOriginal.reexportedType.A -> +TypeReexport.VariantUseOriginal.originalType.A Propagate: +TypeReexport.OnlyReexportedDead.reexportedType.usedField -> +TypeReexport.OnlyReexportedDead.originalType.usedField + Propagate: +TopLevelOptionalArgValueUse.+formatDateAlias2 -> +TopLevelOptionalArgValueUse.+formatDateAlias + Propagate: ReturnedOptionalSignature.+returnedOptional -> +ReturnedOptionalSignature.+returnedOptional Propagate: +References.R.+get -> +References.R.+get Propagate: +DeadTest.MM.+x -> +DeadTest.MM.+y + Propagate: +ReturnedOptionalSignatureUse.InlineSignature.+returnedOptional -> +ReturnedOptionalSignatureUse.InlineSignature.+returnedOptional Propagate: +References.R.+make -> +References.R.+make Propagate: +ScopedAnnotationsLiveVsDead.+middleLive -> +ScopedAnnotationsLiveVsDead.+leafLive Propagate: +Newton.+newton -> +Newton.+/ @@ -2339,9 +2536,10 @@ Forward Liveness Analysis Propagate: +Newton.+newton -> +Newton.+next Propagate: ImmutableArray.Array.+get -> +ImmutableArray.+get Propagate: +References.R.+set -> +References.R.+set + Propagate: +TopLevelOptionalArgValueUse.+returnedFunction -> +TopLevelOptionalArgValueUse.+returnsFunction Propagate: +ImportJsValue.AbsoluteValue.+getAbs -> +ImportJsValue.AbsoluteValue.+getAbs - 53 declarations marked live via propagation + 71 declarations marked live via propagation Dead VariantCase +AutoAnnotate.variant.R Dead RecordLabel +AutoAnnotate.record.variant @@ -2370,8 +2568,64 @@ Forward Liveness Analysis Live (external ref) RecordLabel +ComponentAsProp.props.button deps: in=1 (live=1 dead=0) out=0 <- +ComponentAsProp.+make (live) + Live (propagated) Value +ContextOptionalArgs.NotificationProvider.+dispatchNotificationContext + deps: in=2 (live=2 dead=0) out=0 + <- +ContextOptionalArgs.NotificationProvider.Provider.+make (live) + <- +ContextOptionalArgs.NotificationProvider.+useNotification (live) + Live (external ref) Value +ContextOptionalArgs.NotificationProvider.Provider.+make + deps: in=1 (live=1 dead=0) out=1 + <- +ContextOptionalArgs.NotificationProvider.+make (live) + -> +ContextOptionalArgs.NotificationProvider.+dispatchNotificationContext + Live (external ref) Value +ContextOptionalArgs.NotificationProvider.+make + deps: in=1 (live=1 dead=0) out=3 + <- +ContextOptionalArgs.+make (live) + -> +ContextOptionalArgs.NotificationProvider.Provider.+make + -> +ContextOptionalArgs.NotificationProvider.props.children + -> +ContextOptionalArgs.NotificationProvider.+dispatchNotification + Live (external ref) RecordLabel +ContextOptionalArgs.NotificationProvider.props.children + deps: in=1 (live=1 dead=0) out=0 + <- +ContextOptionalArgs.NotificationProvider.+make (live) + Live (external ref) Value +ContextOptionalArgs.NotificationProvider.+dispatchNotification + deps: in=1 (live=1 dead=0) out=0 + <- +ContextOptionalArgs.NotificationProvider.+make (live) + Live (propagated) Value +ContextOptionalArgs.NotificationProvider.+useNotification + deps: in=4 (live=4 dead=0) out=1 + <- +ContextOptionalArgs.ComponentUsingAction.+make (live) + <- +ContextOptionalArgs.ComponentUsingAction.+dispatchNotification (live) + <- +ContextOptionalArgs.ComponentNotUsingAction.+make (live) + <- ... (1 more) + -> +ContextOptionalArgs.NotificationProvider.+dispatchNotificationContext + Live (external ref) Value +ContextOptionalArgs.ComponentUsingAction.+make + deps: in=1 (live=1 dead=0) out=2 + <- +ContextOptionalArgs.+make (live) + -> +ContextOptionalArgs.NotificationProvider.+useNotification + -> +ContextOptionalArgs.ComponentUsingAction.+dispatchNotification + Live (external ref) Value +ContextOptionalArgs.ComponentUsingAction.+dispatchNotification + deps: in=1 (live=1 dead=0) out=1 + <- +ContextOptionalArgs.ComponentUsingAction.+make (live) + -> +ContextOptionalArgs.NotificationProvider.+useNotification + Live (external ref) Value +ContextOptionalArgs.ComponentNotUsingAction.+make + deps: in=1 (live=1 dead=0) out=2 + <- +ContextOptionalArgs.+make (live) + -> +ContextOptionalArgs.NotificationProvider.+useNotification + -> +ContextOptionalArgs.ComponentNotUsingAction.+dispatchNotification + Live (external ref) Value +ContextOptionalArgs.ComponentNotUsingAction.+dispatchNotification + deps: in=1 (live=1 dead=0) out=1 + <- +ContextOptionalArgs.ComponentNotUsingAction.+make (live) + -> +ContextOptionalArgs.NotificationProvider.+useNotification + Live (annotated) Value +ContextOptionalArgs.+make + deps: in=0 (live=0 dead=0) out=3 + -> +ContextOptionalArgs.NotificationProvider.+make + -> +ContextOptionalArgs.ComponentUsingAction.+make + -> +ContextOptionalArgs.ComponentNotUsingAction.+make Live (external ref) Value +CreateErrorHandler1.Error1.+notification Live (external ref) Value +CreateErrorHandler2.Error2.+notification + Live (propagated) Value +CrossFileOptionalArgProvider.+formatDate + deps: in=1 (live=1 dead=0) out=0 + <- +CrossFileOptionalArgValueUse.+liveReturnCaller (live) + Live (external ref) Value +CrossFileOptionalArgValueUse.+liveReturnCaller + deps: in=0 (live=0 dead=0) out=1 + -> +CrossFileOptionalArgProvider.+formatDate Live (external ref) Value +DeadCodeImplementation.M.+x Live (external ref) Exception +DeadExn.Etoplevel deps: in=1 (live=0 dead=1) out=0 @@ -3248,6 +3502,17 @@ Forward Liveness Analysis <- +InnerModuleTypes.I.t.Foo (live) <- +TestInnedModuleTypes.+_ (dead) -> +InnerModuleTypes.I.t.Foo + Live (external ref) Value +InterfaceOptionalArgEscape.+escaped + deps: in=1 (live=1 dead=0) out=0 + <- InterfaceOptionalArgEscape.+escaped (live) + Live (external ref) Value +InterfaceOptionalArgEscape.+takesFn + Live (propagated) Value InterfaceOptionalArgEscape.+escaped + deps: in=1 (live=1 dead=0) out=1 + <- +InterfaceOptionalArgEscapeUse.+use (live) + -> +InterfaceOptionalArgEscape.+escaped + Live (external ref) Value +InterfaceOptionalArgEscapeUse.+use + deps: in=0 (live=0 dead=0) out=1 + -> InterfaceOptionalArgEscape.+escaped Live (external ref) Value +JsxV4.C.+make Live (annotated) Value +LetPrivate.local_1.+x deps: in=1 (live=1 dead=0) out=0 @@ -3581,6 +3846,26 @@ Forward Liveness Analysis deps: in=0 (live=0 dead=0) out=2 -> +RepeatedLabel.tabState.a -> +RepeatedLabel.tabState.b + Live (propagated) Value +ReturnedOptionalSignature.+returnedOptional + deps: in=1 (live=1 dead=0) out=0 + <- ReturnedOptionalSignature.+returnedOptional (live) + Live (propagated) Value ReturnedOptionalSignature.+returnedOptional + deps: in=1 (live=1 dead=0) out=1 + <- +ReturnedOptionalSignatureUse.+useInterfaceDeclaration (live) + -> +ReturnedOptionalSignature.+returnedOptional + Live (external ref) Value +ReturnedOptionalSignatureUse.+useInterfaceDeclaration + deps: in=0 (live=0 dead=0) out=1 + -> ReturnedOptionalSignature.+returnedOptional + Live (propagated) Value +ReturnedOptionalSignatureUse.InlineSignature.+returnedOptional + deps: in=1 (live=1 dead=0) out=1 + <- +ReturnedOptionalSignatureUse.+useInlineSignature (live) + -> +ReturnedOptionalSignatureUse.InlineSignature.+returnedOptional + Live (propagated) Value +ReturnedOptionalSignatureUse.InlineSignature.+returnedOptional + deps: in=1 (live=1 dead=0) out=0 + <- +ReturnedOptionalSignatureUse.InlineSignature.+returnedOptional (live) + Live (external ref) Value +ReturnedOptionalSignatureUse.+useInlineSignature + deps: in=0 (live=0 dead=0) out=1 + -> +ReturnedOptionalSignatureUse.InlineSignature.+returnedOptional Live (propagated) Value +ScopedAnnotationsLiveVsDead.+leafLive deps: in=1 (live=1 dead=0) out=0 <- +ScopedAnnotationsLiveVsDead.+middleLive (live) @@ -3666,6 +3951,73 @@ Forward Liveness Analysis deps: in=0 (live=0 dead=0) out=1 -> +TestPromise.fromPayload.s Dead Value +ToSuppress.+toSuppress + Live (propagated) Value +TopLevelOptionalArgValueUse.+formatDate + deps: in=2 (live=1 dead=1) out=0 + <- +TopLevelOptionalArgValueUse.+deadEscape (dead) + <- +TopLevelOptionalArgValueUse.+liveCaller (live) + Live (propagated) Value +TopLevelOptionalArgValueUse.+formatDateEscapes + deps: in=1 (live=1 dead=0) out=0 + <- +TopLevelOptionalArgValueUse.+liveEscapeCaller (live) + Live (propagated) Value +TopLevelOptionalArgValueUse.+formatDateReturn + deps: in=1 (live=1 dead=0) out=0 + <- +TopLevelOptionalArgValueUse.+liveReturnCaller (live) + Live (propagated) Value +TopLevelOptionalArgValueUse.+formatDateTuple + deps: in=1 (live=1 dead=0) out=0 + <- +TopLevelOptionalArgValueUse.+liveTupleCaller (live) + Live (propagated) Value +TopLevelOptionalArgValueUse.+formatDateForwarded + deps: in=1 (live=1 dead=0) out=0 + <- +TopLevelOptionalArgValueUse.+liveForwardingCaller (live) + Live (external ref) Value +TopLevelOptionalArgValueUse.+formatDateTopLevelEscape + Live (propagated) Value +TopLevelOptionalArgValueUse.+formatDateAlias + deps: in=1 (live=1 dead=0) out=0 + <- +TopLevelOptionalArgValueUse.+formatDateAlias2 (live) + Live (external ref) Value +TopLevelOptionalArgValueUse.+takesFn + deps: in=2 (live=1 dead=1) out=0 + <- +TopLevelOptionalArgValueUse.+deadEscape (dead) + <- +TopLevelOptionalArgValueUse.+liveEscapeCaller (live) + Dead Value +TopLevelOptionalArgValueUse.+deadEscape + deps: in=0 (live=0 dead=0) out=2 + -> +TopLevelOptionalArgValueUse.+formatDate + -> +TopLevelOptionalArgValueUse.+takesFn + Live (external ref) Value +TopLevelOptionalArgValueUse.+liveCaller + deps: in=0 (live=0 dead=0) out=1 + -> +TopLevelOptionalArgValueUse.+formatDate + Live (external ref) Value +TopLevelOptionalArgValueUse.+liveEscapeCaller + deps: in=0 (live=0 dead=0) out=2 + -> +TopLevelOptionalArgValueUse.+formatDateEscapes + -> +TopLevelOptionalArgValueUse.+takesFn + Live (external ref) Value +TopLevelOptionalArgValueUse.+liveReturnCaller + deps: in=0 (live=0 dead=0) out=1 + -> +TopLevelOptionalArgValueUse.+formatDateReturn + Live (external ref) Value +TopLevelOptionalArgValueUse.+liveTupleCaller + deps: in=0 (live=0 dead=0) out=1 + -> +TopLevelOptionalArgValueUse.+formatDateTuple + Live (external ref) Value +TopLevelOptionalArgValueUse.+liveForwardingCaller + deps: in=0 (live=0 dead=0) out=1 + -> +TopLevelOptionalArgValueUse.+formatDateForwarded + Live (propagated) Value +TopLevelOptionalArgValueUse.+formatDateAlias2 + deps: in=1 (live=1 dead=0) out=1 + <- +TopLevelOptionalArgValueUse.+liveAliasCaller (live) + -> +TopLevelOptionalArgValueUse.+formatDateAlias + Live (external ref) Value +TopLevelOptionalArgValueUse.+liveAliasCaller + deps: in=0 (live=0 dead=0) out=1 + -> +TopLevelOptionalArgValueUse.+formatDateAlias2 + Live (external ref) Value +TopLevelOptionalArgValueUse.+mutuallyRecursiveCaller + deps: in=0 (live=0 dead=0) out=1 + -> +TopLevelOptionalArgValueUse.+mutuallyRecursiveTarget + Live (propagated) Value +TopLevelOptionalArgValueUse.+mutuallyRecursiveTarget + deps: in=1 (live=1 dead=0) out=0 + <- +TopLevelOptionalArgValueUse.+mutuallyRecursiveCaller (live) + Live (propagated) Value +TopLevelOptionalArgValueUse.+returnsFunction + deps: in=1 (live=1 dead=0) out=0 + <- +TopLevelOptionalArgValueUse.+returnedFunction (live) + Live (propagated) Value +TopLevelOptionalArgValueUse.+returnedFunction + deps: in=1 (live=1 dead=0) out=1 + <- +TopLevelOptionalArgValueUse.+liveReturnedFunctionCaller (live) + -> +TopLevelOptionalArgValueUse.+returnsFunction + Live (external ref) Value +TopLevelOptionalArgValueUse.+liveReturnedFunctionCaller + deps: in=0 (live=0 dead=0) out=1 + -> +TopLevelOptionalArgValueUse.+returnedFunction Live (annotated) Value +TransitiveType1.+convert Live (annotated) Value +TransitiveType1.+convertAlias Dead Value +TransitiveType2.+convertT2 @@ -5024,6 +5376,10 @@ Forward Liveness Analysis TestPromise.res:11:19-32 toPayload.result is a record label never used to read a value + Warning Dead Value + TopLevelOptionalArgValueUse.res:16:1-42 + deadEscape is never used + Warning Dead Module TransitiveType2.res:0:1 TransitiveType2 is a dead module as all its items are dead. @@ -5228,6 +5584,10 @@ Forward Liveness Analysis OptArg.res:3:1-38 optional argument x of function bar is never used + Warning Unused Argument + ReturnedOptionalSignature.resi:1:1-80 + optional argument outer of function returnedOptional is never used + Warning Unused Argument OptionalArgsLiveDead.res:1:1-33 optional argument fmt of function formatDate is never used @@ -5240,6 +5600,14 @@ Forward Liveness Analysis OptArg.res:9:1-54 optional argument a of function threeArgs is always supplied (2 calls) + Warning Unused Argument + ReturnedOptionalSignatureUse.res:5:3-82 + optional argument outer of function InlineSignature.returnedOptional is never used + + Warning Unused Argument + ReturnedOptionalSignature.res:1:1-63 + optional argument outer of function returnedOptional is never used + Warning Redundant Optional Argument OptArg.res:20:1-51 optional argument a of function wrapOneArg is always supplied (1 calls) @@ -5260,6 +5628,22 @@ Forward Liveness Analysis Unison.res:17:1-55 optional argument break_ of function group is always supplied (2 calls) + Warning Redundant Optional Argument + TopLevelOptionalArgValueUse.res:41:1-46 + optional argument fmt of function mutuallyRecursiveTarget is always supplied (1 calls) + + Warning Unused Argument + TopLevelOptionalArgValueUse.res:4:1-33 + optional argument fmt of function formatDate is never used + + Warning Unused Argument + TopLevelOptionalArgValueUse.res:33:1-85 + optional argument fmt of function liveForwardingCaller is never used + + Warning Unused Argument + ReturnedOptionalSignatureUse.res:7:3-65 + optional argument outer of function InlineSignature.returnedOptional is never used + Warning Unused Argument OptArg.res:14:1-42 optional argument a of function twoArgs is never used @@ -5268,4 +5652,4 @@ Forward Liveness Analysis OptArg.res:14:1-42 optional argument b of function twoArgs is never used - Analysis reported 319 issues (Incorrect Dead Annotation:1, Warning Dead Exception:2, Warning Dead Module:22, Warning Dead Type:94, Warning Dead Value:177, Warning Dead Value With Side Effects:5, Warning Redundant Optional Argument:6, Warning Unused Argument:12) + Analysis reported 327 issues (Incorrect Dead Annotation:1, Warning Dead Exception:2, Warning Dead Module:22, Warning Dead Type:94, Warning Dead Value:178, Warning Dead Value With Side Effects:5, Warning Redundant Optional Argument:7, Warning Unused Argument:18) diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/ContextOptionalArgs.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/ContextOptionalArgs.res new file mode 100644 index 0000000000..f9c4075e9d --- /dev/null +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/ContextOptionalArgs.res @@ -0,0 +1,60 @@ +module NotificationProvider = { + let dispatchNotificationContext = React.createContext(( + ~action as _: option=?, + _message: string, + ) => ()) + + module Provider = { + let make = React.Context.provider(dispatchNotificationContext) + } + + @react.component + let make = (~children) => { + let dispatchNotification = (~action=?, message) => + switch action { + | Some(action) => Console.log2(message, action) + | None => Console.log(message) + } + + {children} + } + + let useNotification = () => React.useContext(dispatchNotificationContext) +} + +module ComponentUsingAction = { + @react.component + let make = () => { + let dispatchNotification = NotificationProvider.useNotification() + + React.useEffect(() => { + dispatchNotification(~action="Some action", "This is a notification message") + None + }, []) + + React.null + } +} + +module ComponentNotUsingAction = { + @react.component + let make = () => { + let dispatchNotification = NotificationProvider.useNotification() + + React.useEffect(() => { + dispatchNotification("This is a notification message") + None + }, []) + + React.null + } +} + +@live +@react.component +let make = () => { + + + + +} diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/CrossFileOptionalArgProvider.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/CrossFileOptionalArgProvider.res new file mode 100644 index 0000000000..7119d158f0 --- /dev/null +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/CrossFileOptionalArgProvider.res @@ -0,0 +1 @@ +let formatDate = (~fmt=?, s) => s diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/CrossFileOptionalArgValueUse.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/CrossFileOptionalArgValueUse.res new file mode 100644 index 0000000000..ad4d73f0d9 --- /dev/null +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/CrossFileOptionalArgValueUse.res @@ -0,0 +1,5 @@ +let liveReturnCaller = () => { + CrossFileOptionalArgProvider.formatDate +} + +let _ = liveReturnCaller() diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/InterfaceOptionalArgEscape.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/InterfaceOptionalArgEscape.res new file mode 100644 index 0000000000..1505469975 --- /dev/null +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/InterfaceOptionalArgEscape.res @@ -0,0 +1,5 @@ +let escaped = (~fmt=?, value) => value + +let takesFn = _ => () + +takesFn(escaped) diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/InterfaceOptionalArgEscape.resi b/tests/analysis_tests/tests-reanalyze/deadcode/src/InterfaceOptionalArgEscape.resi new file mode 100644 index 0000000000..de0b5900d0 --- /dev/null +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/InterfaceOptionalArgEscape.resi @@ -0,0 +1 @@ +let escaped: (~fmt: string=?, string) => string diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/InterfaceOptionalArgEscapeUse.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/InterfaceOptionalArgEscapeUse.res new file mode 100644 index 0000000000..8c69690a4d --- /dev/null +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/InterfaceOptionalArgEscapeUse.res @@ -0,0 +1,3 @@ +let use = () => InterfaceOptionalArgEscape.escaped("value") + +let _ = use() diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/ReturnedOptionalSignature.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/ReturnedOptionalSignature.res new file mode 100644 index 0000000000..8e5eea08e0 --- /dev/null +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/ReturnedOptionalSignature.res @@ -0,0 +1 @@ +let returnedOptional = (~outer=?, value) => (~inner=?) => value diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/ReturnedOptionalSignature.resi b/tests/analysis_tests/tests-reanalyze/deadcode/src/ReturnedOptionalSignature.resi new file mode 100644 index 0000000000..1b06663d3b --- /dev/null +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/ReturnedOptionalSignature.resi @@ -0,0 +1 @@ +let returnedOptional: (~outer: string=?, string) => (~inner: string=?) => string diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/ReturnedOptionalSignatureUse.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/ReturnedOptionalSignatureUse.res new file mode 100644 index 0000000000..327a374484 --- /dev/null +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/ReturnedOptionalSignatureUse.res @@ -0,0 +1,14 @@ +let useInterfaceDeclaration = () => + ReturnedOptionalSignature.returnedOptional("value")(~inner="used") + +module InlineSignature: { + let returnedOptional: (~outer: string=?, string) => (~inner: string=?) => string +} = { + let returnedOptional = (~outer=?, value) => (~inner=?) => value +} + +let useInlineSignature = () => + InlineSignature.returnedOptional("value")(~inner="used") + +let _ = useInterfaceDeclaration() +let _ = useInlineSignature() diff --git a/tests/analysis_tests/tests-reanalyze/deadcode/src/TopLevelOptionalArgValueUse.res b/tests/analysis_tests/tests-reanalyze/deadcode/src/TopLevelOptionalArgValueUse.res new file mode 100644 index 0000000000..32aba79370 --- /dev/null +++ b/tests/analysis_tests/tests-reanalyze/deadcode/src/TopLevelOptionalArgValueUse.res @@ -0,0 +1,54 @@ +/* Dead first-class escapes should not suppress optional-arg warnings, but live + first-class escapes should suppress them even when there is also a direct call. */ + +let formatDate = (~fmt=?, s) => s +let formatDateEscapes = (~fmt=?, s) => s +let formatDateReturn = (~fmt=?, s) => s +let formatDateTuple = (~fmt=?, s) => s +let formatDateForwarded = (~fmt=?, s) => s +let formatDateTopLevelEscape = (~fmt=?, s) => s +let formatDateAlias = (~fmt=?, s) => s + +let takesFn = _ => () + +takesFn(formatDateTopLevelEscape) + +let deadEscape = () => takesFn(formatDate) + +let liveCaller = () => formatDate("2024-01-01") + +let liveEscapeCaller = () => { + takesFn(formatDateEscapes) + formatDateEscapes("2024-01-01") +} + +let liveReturnCaller = () => { + formatDateReturn +} + +let liveTupleCaller = () => { + (formatDateTuple, "tuple") +} + +let liveForwardingCaller = (~fmt=?) => { + formatDateForwarded(~fmt?, "2024-01-01") +} + +let formatDateAlias2 = formatDateAlias +let liveAliasCaller = () => formatDateAlias2("2024-01-01") + +let rec mutuallyRecursiveCaller = () => mutuallyRecursiveTarget(~fmt="ISO", "2024-01-01") +and mutuallyRecursiveTarget = (~fmt=?, s) => s + +let returnsFunction = value => (~inner: option=?) => value +let returnedFunction = returnsFunction("value") +let liveReturnedFunctionCaller = () => returnedFunction() + +let _ = liveCaller() +let _ = liveEscapeCaller() +let _ = liveReturnCaller() +let _ = liveTupleCaller() +let _ = liveForwardingCaller() +let _ = liveAliasCaller() +let _ = mutuallyRecursiveCaller() +let _ = liveReturnedFunctionCaller()