E08094: coalescing expression has a predetermined result - both operands are literals, or a literal on the left of '?:' is always set and so always chosen

Category: E08xxx Pre-IR checks (flow analysis) · Reported in phase: PRE_IR_CHECKS · Classification: CONSTANT_COALESCING · All error codes

What went wrong

This coalescing expression has a result that is predetermined at compile time. Either both sides of a comparison coalescing operator ('<?', '>?') are literal values, or the left of the coalescing operator (Elvis) '?:' is a literal - a literal is always set, so it is always the result and the right is never used. '5 <? 3' is always 3; '7 ?: fallback' is always 7, and 'fallback' is never evaluated. The other way round, 'fallback ?: 7', is fine: the literal is the fallback for an unset 'fallback'. The [EXAMPLE] section below shows each operator with literals, and the same operators over variables.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 1333 (Why does EK9 reject a coalescing expression where both...)
  • ek9 -q 2061 (What type does 'a ?: b' have when a and b are different types?)

How to fix it

  1. Replace one literal with a variable or named constant
  2. For '?:', put the value that may be unset on the LEFT and the literal default on the right
  3. If the result is intentional, assign the known value directly
  4. Check for copy-paste errors in the operands

Common causes

  • Copy-paste error (forgot to change one operand)
  • Operands of '?:' written the wrong way round ('0 ?: count' for 'count ?: 0')
  • Placeholder code that was never completed
  • Debugging remnant

See also

  • E08082: constant comparison (same issue with comparison operators)
  • E08083: constant arithmetic
  • E08269: a coalescing operator mixed with another operator without parentheses

Examples

Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.

Fails with E08094: coalescing expression has a predetermined result - both operands are literals, or a literal on the left of '?:' is always set and so always chosen

#!ek9
defines module error.e08094.bad

  defines function

    checkIntegerCoalescingLT()
      <- result as Integer?

      result: 5 <? 3

    checkIntegerCoalescingGT()
      <- result as Integer?

      result: 5 >? 3

    checkIntegerCoalescingLE()
      <- result as Integer?

      result: 5 <? 3

    checkIntegerCoalescingGE()
      <- result as Integer?

      result: 5 >? 3

    checkFloatCoalescingLT()
      <- result as Float?

      result: 1.0 <? 2.0

    checkStringCoalescingLT()
      <- result as String?

      result: "alpha" <? "beta"

    //A literal on the LEFT of '?:' is always set, so it is always the result and the right is never used.
    checkElvisIntegerLiteralLeft()
      -> fallback as Integer
      <- result as Integer?

      result: 7 ?: fallback

    checkElvisPromotedLiteralLeft()
      <- result as Float?

      result: 7 ?: 2.5

    checkElvisStringLiteralLeft()
      -> fallback as String
      <- result as String?

      result: "text" ?: fallback

Fixed: Coalesce a variable; a literal only as the fallback

#!ek9
defines module error.e08094.good

  defines function

    coalesceVariableWithLiteral()
      -> amount as Integer
      <- result as Integer?

      result: amount <? 100

    coalesceTwoVariables()
      ->
        first as Integer
        second as Integer
      <- result as Integer?

      result: first >? second

    coalesceVariableLE()
      ->
        first as Integer
        second as Integer
      <- result as Integer?

      result: first <? second

    coalesceVariableGE()
      -> amount as Integer
      <- result as Integer?

      result: amount >? 50

    //A literal on the RIGHT of '?:' is the fallback - the left decides.
    elvisVariableLeftLiteralRight()
      -> amount as Integer
      <- result as Integer?

      result: amount ?: 0

    //Inside require/assert a literal on the left is deliberate (as for the comparison family).
    elvisLiteralLeftInRequire()
      -> amount as Integer
      require (7 ?: amount) > 0

Questions and answers

These Q&A entries show E08094 and its fix: