Skip to content

Implicit optional arguments are reported #102

Description

@fantazio

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

(* /tmp/implicit_opt_arg.ml *)
let g (f : ?opt:_ -> unit -> unit) = f ()
let inferred f = g f

type 'a with_opt = ?opt:'a -> unit -> unit
let type_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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions