E08055: return value is initialised before a 'require' precondition; declare it 'as Type?' and assign it after the require(s)

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

What went wrong

A construct (function/method/operator/program operation) declares a returning variable with an INLINE INITIALISER while its body OPENS WITH a 'require' precondition (a require at the head of the body, before the first ordinary statement). The return's initialiser runs BEFORE the body, so a leading require written to guard the return computation is dead code that reads like protection. Only a leading precondition is at fault: a 'require' that comes after real work is a post-condition that legitimately sees the already-computed return.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 304 (What is the require statement and when should I use it?)

[THE FOOT-GUN] In the failing source in the [EXAMPLE] section below, 'unitPrice' declares '<- rtn as Integer: total / quantity' and then 'require quantity <> 0'. The division runs FIRST, so running unitPrice(10, 0) panics on the division - the 'require quantity <> 0' never executed.

How to fix it

Declare the return UNINITIALISED ('as Type?') and assign it only AFTER the require(s) - guard first, then compute (the fix in the [EXAMPLE] section below).

Common causes

  • An inline-initialised return (<- rtn as T: expr / := expr / <- expr) with a leading 'require' precondition
  • A magic placeholder default (<- rtn as T: 0) kept above a leading require
  • A precondition that tests the return itself - forcing 'as Type?' turns that into a use-before-initialised error (E08060) too, for free

Not at fault

  • A 'require' that appears after other statements (a post-condition/assertion) with an inline-initialised return - the return is already computed, so nothing is dodged
  • A 'require' nested inside an if/switch/loop or a dynamic function

See also

  • E08055: return initialised before a 'require' (this error)
  • E08050: return not initialised on all paths
  • E08060: variable might be used before initialised

Examples

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

Fails with E08055: return value is initialised before a 'require' precondition; declare it 'as Type?' and assign it after the require(s)

#!ek9
defines module error.e08055.bad

  defines function

    unitPrice()
      ->
        total as Integer
        quantity as Integer
      <- rtn as Integer: total / quantity

      require quantity <> 0

Fixed: Declare it unset, require first, then compute

#!ek9
defines module error.e08055.good

  defines function

    unitPrice()
      ->
        total as Integer
        quantity as Integer
      <- rtn as Integer?

      require quantity <> 0
      rtn: total / quantity