E08050: return value is not always initialised

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

What went wrong

A function/method has a return variable that may not be initialized on all possible execution paths.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 688 (How does EK9 enforce variable initialization order?)

Mutating operators on return parameters

Return parameters declared without initialization (e.g., <- rtn as String?) CANNOT be used with mutating operators until initialized:

  • :=: (copy) and :~: (merge) - require existing value to copy/merge INTO
  • +=, -=, *=, /= etc. - require existing value to modify
  • ++, -- - require existing value to increment/decrement

A path that ends in a throw

A path that ends in an unconditional throw never returns, so it does not have to set the return variable - every arm of an if/else or switch that throws counts as covered. With '<- rtn as Integer?', an 'if' arm that assigns 'rtn: amount' and an 'else' arm that is just 'throw Exception("Not positive")' leave nothing unset. A throw inside an 'if' with no 'else' covers nothing (the other path still falls through), and a catch or finally that can run after the throw does not see the variable as set: reading it there is still E08020.

Dynamic functions

A dynamic function ('() extends SecurityGate as function', '() is Routine of (Boolean, Integer) as function') inherits its super's returning variable, but its body replaces the super's body - so the inherited variable starts unassigned, whatever the super declared, and every path through the body must assign it. The error is reported at the dynamic function. Assign a default first (rtn: Boolean()), or assign on every branch.

How to fix it

  1. Initialize return parameter at declaration: <- rtn <- defaultValue
  2. Or use simple assignment (:) instead of mutating operators
  3. Or initialize before using mutating operators

Common causes

  • Return only set in some if branches (and the others neither set it nor throw)
  • A dynamic function setting its inherited return on only some paths
  • Using :=: or :~: on uninitialized return parameter
  • Loop might not execute
  • Expecting mutating operator to initialize

See also

  • E08050: return not initialized on all paths (this error)
  • E08020: variable used before initialized
  • E08060: variable might not be initialized

Examples

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

Fails with E08050: return value is not always initialised

#!ek9
defines module error.e08050.bad

  defines function

    grade()
      -> passed as Boolean
      <- rtn as String?
      if passed
        rtn: "pass"

Fixed: Initialise the returning variable where it is declared

#!ek9
defines module error.e08050.good

  defines function

    grade()
      -> passed as Boolean
      <- rtn as String: "fail"
      if passed
        rtn: "pass"

Fixed: Or assign it on every path

#!ek9
defines module error.e08050.good.every.path

  defines function

    grade()
      -> passed as Boolean
      <- rtn as String?
      if passed
        rtn: "pass"
      else
        rtn: "fail"

Questions and answers

These Q&A entries show E08050 and its fix: