How does EK9 detect redundant empty and isSet checks?

← Code Quality · Ref: Q736

EK9 tracks variable state through data flow and detects three categories of redundant checks.

ISSET ALWAYS FALSE (E08089)

If a variable is declared unset (with ?) and never assigned a value, checking it with ? is always false. The code inside the if block is dead code.

EMPTY ALWAYS TRUE (E08092)

If a collection is created with no elements and not modified before an empty check, the check is always true. An empty Optional is also always empty.

EMPTY ALWAYS FALSE (E08093)

If a collection is created from a literal with elements, an empty check is always false. An Optional created with a value is never empty.

CORRECT PATTERNS

Assign a value before checking isSet. Populate collections before checking empty. Use function returns where the state is genuinely unknown.

See Q559 for redundant isSet overview. See Q640 for collection isSet patterns.

Example

defines module qa.codequality.emptyissetflow

  defines function

    findName()
      -> key as String
      <- result as String: String()

      if key == "admin"
        result: "Administrator"

    describeItems()
      -> items as List of String
      <- description as String: "empty"

      if not items empty
        description: `${length items} items`

  defines program

    EmptyIsSetFlowDemo()
      stdout <- Stdout()

      //isSet check on function return - genuinely needed
      name <- findName("admin")
      if name?
        stdout.println(`Found: ${name}`)

      //empty check on function return - genuinely needed
      items <- ["alpha", "beta"]
      stdout.println(describeItems(items))

      emptyList <- List() of String
      stdout.println(describeItems(emptyList))

Common mistakes

E50060 — String has no toUpperCase() method in EK9. Use upperCase() instead. See ek9 -h E50060 for details.

Incorrect:

name <- findName("admin").toUpperCase()

Correct:

name <- findName("admin")

E50060 — String has no getValue() method. findName() already returns a String. See ek9 -h E50060 for details.

Incorrect:

name <- findName("admin").getValue()

Correct:

name <- findName("admin")

E50060 — List has no toString() method. Use string interpolation or the $ operator. See ek9 -h E50060 for details.

Incorrect:

stdout.println(items.toString())

Correct:

stdout.println(describeItems(items))
Other ways to ask this
  • What is E08089 isSet always false in EK9?
  • What is E08092 empty always true in EK9?
  • What is E08093 empty always false in EK9?

Coming from another language?

Java: no built-in detection, optional IDE inspections. Rust: clippy detects some redundant Option checks. Python: pylint detects some unreachable code. Go: go vet detects some unreachable code. EK9: mandatory compiler error with full data flow tracking for isSet and empty checks.

Keywords: code, never, flow, quality, E08089, empty, collection, always, optional, E08093, E08092, dead, redundant, isset