You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An optional argument that is not explicitly declared (i.e. does not appear in code) may be reported as always/never used. However, because it does not appear in the code, the report is not trivially actionable.
In particular, those reports may be tautological : the optional argument is inferred because it is required and is considered always used because it is required. This is not fixable.
Example and reproduction
(* /tmp/implicit_opt_arg.ml *)letg (f: ?opt:_ -> unit -> unit) = f ()letinferredf= g f
type'a with_opt = ?opt:'a -> unit -> unitlettype_defd (f: 'a with_opt) = f ()
$ ocamlopt -bin-annot implicit_opt_arg.ml
$ dead_code_analyzer -a -Oa all -On all implicit_opt_arg.cmt
Scanning files...
[DONE]
.> OPTIONAL ARGUMENTS: ALWAYS:
=============================
/tmp/implicit_opt_arg.ml:3: ?opt
Nothing else to report in this section
--------------------------------------------------------------------------------
.> OPTIONAL ARGUMENTS: NEVER:
============================
/tmp/implicit_opt_arg.ml:2: ?opt
/tmp/implicit_opt_arg.ml:6: ?opt
Nothing else to report in this section
--------------------------------------------------------------------------------
All the reports are coherent. However, 2 of them feel like false positives and should probably be discarded:
The optional argument of inferred's parameter f (line 3) is reported as always used. This is the tautological case: it exists because g requires it, and it is used because g requires it. If g's signature changed, then inferred's type would as well. Because the optional argument is not actually defined by inferred's f but "inherited" from g's f, the report cannot be fixed.
optional argument of type_defd's parameter f (line 6) is reported as never used. The optional argument is actually defined by the type 'a with_opt, so fixing the report means replacing f's type by another annotation rather than cleaning it up. This echoes the module type limitation (see Reports with locations in module types are inconsistent #50).
Note
The examples use higher-order functions.
I don't think the tautological case exists in other situations because aliases are resolved (i.e. let g = f would identify that g's arguments are actually f's).
The type def example could be reproduced with first order functions by having an explicit .mli
Context
An optional argument that is not explicitly declared (i.e. does not appear in code) may be reported as always/never used. However, because it does not appear in the code, the report is not trivially actionable.
In particular, those reports may be tautological : the optional argument is inferred because it is required and is considered always used because it is required. This is not fixable.
Example and reproduction
All the reports are coherent. However, 2 of them feel like false positives and should probably be discarded:
The optional argument of
inferred's parameterf(line 3) is reported as always used. This is the tautological case: it exists becausegrequires it, and it is used becausegrequires it. Ifg's signature changed, theninferred's type would as well. Because the optional argument is not actually defined byinferred'sfbut "inherited" fromg'sf, the report cannot be fixed.optional argument of
type_defd's parameterf(line 6) is reported as never used. The optional argument is actually defined by the type'a with_opt, so fixing the report means replacingf'stype by another annotation rather than cleaning it up. This echoes the module type limitation (see Reports with locations in module types are inconsistent #50).Note
The examples use higher-order functions.
I don't think the tautological case exists in other situations because aliases are resolved (i.e.
let g = fwould identify thatg's arguments are actuallyf's).The type def example could be reproduced with first order functions by having an explicit
.mli