How should I compare two similar variables to avoid self-comparison errors?

← Comparison Patterns · Ref: Q637

EK9 detects when both sides of a comparison operator resolve to the same variable and raises E08081. This is always a copy-paste error.

THE PROBLEM

When duplicating comparison code, it is easy to write 'priceA == priceA' instead of 'priceA == priceB'. The result is a constant (always true for ==, always false for <>) and the intended comparison never happens. This bug is silent in most languages.

FLAGGED OPERATORS

Self-comparison is detected for: ==, <>, <, >, <=, >=, <=>, <~>, contains, and matches. All produce constant results when both operands are the same variable.

CORRECT PATTERN

Always compare two DIFFERENT variables. Use distinct meaningful names that make the intent clear:

  if currentPrice < previousPrice
  if scoreA == scoreB
  if leftValue <=> rightValue

COMMON MISTAKE

Copy-pasting a line like 'if priceA < priceB' and accidentally getting 'if priceA < priceA' when modifying. EK9 catches this immediately.

See Q318 for self-assignment detection. See Q558 for tautological conditions. See Q638 for named constant patterns. See Q639 for Boolean usage without literals.

Example

defines module qa.comparison.safecompare

  defines function

    <?-
      Correct: compares two different variables (priceA vs priceB).
      Renaming one operand to match the other would trigger E08081.
    -?>
    findCheaperItem() as pure
      ->
        priceA as Float
        priceB as Float
      <- cheaperPrice as Float: priceA

      if priceB < priceA
        cheaperPrice: priceB

    <?-
      Correct: compares two distinct score variables.
      Each operand is a different parameter.
    -?>
    scoresMatch() as pure
      ->
        scoreA as Integer
        scoreB as Integer
      <- matched as Boolean: scoreA == scoreB

    <?-
      Correct: compares left and right boundary values.
      Distinct names make the intent clear.
    -?>
    isOverlapping() as pure
      ->
        leftStart as Integer
        leftEnd as Integer
        rightStart as Integer
        rightEnd as Integer
      <- overlapping as Boolean: leftStart <= rightEnd

      if leftEnd < rightStart
        overlapping: false
      else if rightEnd < leftStart
        overlapping: false

    <?-
      Correct: three-way comparison between distinct amounts.
    -?>
    findMiddleValue() as pure
      ->
        firstAmount as Float
        secondAmount as Float
        thirdAmount as Float
      <- middleAmount as Float: firstAmount

      if firstAmount >= secondAmount and firstAmount <= thirdAmount
        middleAmount: firstAmount
      else if secondAmount >= firstAmount and secondAmount <= thirdAmount
        middleAmount: secondAmount
      else
        middleAmount: thirdAmount

  defines program

    SafeComparisonDemo()
      stdout <- Stdout()

      cheaper <- findCheaperItem(29.99, 19.99)
      stdout.println(`Cheaper: ${cheaper}`)

      matched <- scoresMatch(85, 85)
      stdout.println(`Scores match: ${matched}`)

      overlap <- isOverlapping(leftStart: 1, leftEnd: 5, rightStart: 3, rightEnd: 8)
      stdout.println(`Overlapping: ${overlap}`)

      mid <- findMiddleValue(3.0, 1.0, 2.0)
      stdout.println(`Middle: ${mid}`)

Common mistakes

E08081 — Comparing a variable to itself always produces a constant result. This is a copy-paste error where both operands resolve to the same variable. See ek9 -h E08081 for details.

Incorrect:

if priceA < priceA

Correct:

if priceB < priceA

E08081 — Self-comparison with == always produces true. Use two different variables to make a meaningful comparison. See ek9 -h E08081 for details.

Incorrect:

matched as Boolean: scoreA == scoreA

Correct:

matched as Boolean: scoreA == scoreB
Other ways to ask this
  • What is self-comparison and how does EK9 detect it?
  • Why does EK9 reject comparing a variable to itself?
  • How do I fix E08081 self-comparison?

Coming from another language?

Java: no self-comparison detection in javac. SpotBugs has limited checks. SonarQube detects some patterns. Rust: clippy eq_op lint warns on self-comparison. Go: go vet detects some self-assignments. Python: no built-in detection. C++: -Wtautological-compare warns on some patterns. EK9: mandatory compiler error E08081 for all comparison and containment operators.

Keywords: detect, pair, copy, variable, debug, different, comparison, equal, E08081, paste, pattern, self