How does EK9 detect unused parameters?

← Code Quality · Ref: Q319

EK9 detects parameters and closure captures that are declared but never used in the function body.

UNUSED PARAMETERS (E08091)

If a function declares a parameter but never reads it, the parameter is dead code. It increases the function signature complexity without contributing to the result. This usually means the implementation is incomplete or the parameter was left over from a refactoring.

UNUSED CAPTURES (E11018)

Dynamic functions can capture variables from their enclosing scope. If a captured variable is never used inside the dynamic function, the capture is unnecessary. Unused captures waste memory and obscure the function's actual dependencies.

EXEMPT CONTEXTS

Some parameters are legitimately unused:
- Abstract methods: parameters define the contract but have no body.
- Override methods: the overriding method must match the parent signature even if it does not use all parameters.
- Dispatcher methods: the parameter type drives dispatch but may not be used in the base method.
- Operators: operator signatures are fixed by convention.
- Parameterised types: generic type parameters define the shape.

GO AND RUST ANALOGY

Go requires all variables to be used (unused variable is a compilation error). Rust warns on unused variables with _ prefix convention. EK9 follows Go's philosophy of treating unused code as an error, but is more nuanced with exemptions for abstract, override, and dispatcher contexts.

See Q311 for the full quality checks catalog. See Q49 for function basics. See Q53 for closure captures.

Example

defines module qa.codequality.unused

  defines function

    <?-
      Every parameter is used in the function body.
      Removing any parameter would change the behaviour.
    -?>
    calculateArea() as pure
      ->
        width as Float
        height as Float
      <-
        rtn as Float: width * height

    <?-
      Both parameters contribute to the output.
    -?>
    greetPerson() as pure
      ->
        title as String
        surname as String
      <-
        greeting as String: `Hello, ${title} ${surname}`

  defines program

    UnusedParametersDemo()
      stdout <- Stdout()

      roomWidth <- 5.5
      roomHeight <- 3.2
      roomArea <- calculateArea(roomWidth, roomHeight)
      stdout.println(`Room area: ${roomArea} sq metres`)

      personalGreeting <- greetPerson("Dr", "Watson")
      stdout.println(personalGreeting)

Common mistakes

E50001 — Renaming the variable means later references to 'roomArea' become unresolved, triggering E50001. See ek9 -h E50001 for details.

Incorrect:

roomAreaXYZ <- calculateArea(roomWidth, roomHeight)

Correct:

roomArea <- calculateArea(roomWidth, roomHeight)
Other ways to ask this
  • What does E08091 unused parameter mean?
  • Why does EK9 flag unused function arguments?
  • How does EK9 detect unused closure captures?

Coming from another language?

Java: no unused parameter detection in the compiler, relies on IDE inspections or SonarQube. Rust: warns on unused variables, _ prefix suppresses. Go: unused variables are compilation errors, unused function parameters are not checked. Python: no unused parameter detection in standard tools. C++: -Wunused-parameter warns but can be suppressed. Kotlin: IDE inspection only, not a compilation error. EK9: unused parameters and captures are mandatory compiler errors with intelligent exemptions.

Keywords: code, metric, quality, migrate, argument, incomplete, E08091, refactor, dead, parameter, clean-code, unused, capture, E11018