E08050: return value is not always initialised
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
- Initialize return parameter at declaration: <- rtn <- defaultValue
- Or use simple assignment (:) instead of mutating operators
- 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
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:
- Q50: How do function returns work without a return statement in EK9?
- Q688: How does EK9 enforce variable initialization order?
- Q837: Can I use a guard (including ':=?') inside a switch or loop expression in EK9?
- Q1240: Write me a pure function categorise that takes an Integer score and returns a String category ('high', 'medium' or 'low'), proving the return variable is initialised on every branch.
- Q1249: Write me a pure function classifyTemperature that takes a Float celsius and returns a String label, declaring the return variable WITHOUT a default and proving the compiler that every branch of the if/else chain initialises it.
- Q1354: How do I use a guard in the expression form of a while loop?
- Q1355: How do guards work in a do/while loop, in both statement and expression form?
- Q1356: How do I use a guard in a for-range loop, including the expression form?
- Q1357: How do I use a guard in a for-in loop, including the expression form?
- Q1358: How do I use a <- or :=? guard in a try, in both statement and expression form?
- Q1359: How do I use a :=? assign-if-unset guard in a switch expression?
- Q1361: Do guard variables work the same way in every expression-form control-flow construct?