How does EK9 track variable initialization across control flow branches?

← Data Flow Safety · Ref: Q633

EK9 tracks the initialization state of every variable through all control flow paths. If a variable might be uninitialized on any reachable path where it is used, the compiler raises E08020.

BRANCH INITIALIZATION

When a variable is assigned in both the if and else branches, the compiler knows it is initialized after the if-else regardless of which branch executes. If only one branch initializes the variable, the compiler considers it potentially uninitialized after the conditional.

RETURN VARIABLE DEFAULTS

Return variables declared with a default value (e.g., '<- rtn as String: unknown') are always initialized. The default ensures the variable has a value even if no branch explicitly sets it.

SAFE PATTERN

Either provide a default value at declaration time, or ensure every branch of every conditional initializes the variable before it is used.

See Q632 for definition order. See Q634 for guard-based safe access. See Q251 for debugging unset variable errors.

Example

defines module qa.dataflow.branchinit

  defines constant

    EXCELLENT_THRESHOLD <- 90

    GOOD_THRESHOLD <- 70

    POOR_THRESHOLD <- 50

  defines function

    <?-
      Correct: the return variable has a default value,
      so it is always initialized regardless of branch taken.
    -?>
    classifyScore() as pure
      -> score as Integer
      <- category as String: "average"

      if score >= EXCELLENT_THRESHOLD
        category: "excellent"
      else if score >= GOOD_THRESHOLD
        category: "good"
      else if score < POOR_THRESHOLD
        category: "poor"

    <?-
      Correct: both branches explicitly set the return variable.
      The compiler can verify both paths initialize it.
    -?>
    describeSign() as pure
      -> number as Integer
      <- description as String: "zero"

      if number > 0
        description: "positive"
      else if number < 0
        description: "negative"

    <?-
      Correct: intermediate variables are initialized at declaration
      and used after initialization in both branches.
    -?>
    formatAmount() as pure
      ->
        amount as Float
        showDecimals as Boolean
      <- formatted as String: `${amount}`

      rounded <- amount + 0.5
      label <- "Amount"

      if showDecimals
        formatted: `${label}: ${amount}`
      else
        formatted: `${label}: ${rounded}`

  defines program

    BranchInitDemo()
      stdout <- Stdout()

      cat1 <- classifyScore(95)
      stdout.println(`Score 95: ${cat1}`)

      cat2 <- classifyScore(42)
      stdout.println(`Score 42: ${cat2}`)

      sign1 <- describeSign(5)
      stdout.println(`5 is ${sign1}`)

      sign2 <- describeSign(-3)
      stdout.println(`-3 is ${sign2}`)

      fmt1 <- formatAmount(19.99, true)
      stdout.println(fmt1)

      fmt2 <- formatAmount(19.99, false)
      stdout.println(fmt2)

Common mistakes

E50001 — If category is only initialized in one branch, it may be uninitialized when used later. Provide a default value at declaration or initialize on all paths. See ek9 -h E50001 for details.

Incorrect:

category as String: String()
      if score >= EXCELLENT_THRESHOLD
        category: "excellent"
      stdout.println(category)

Correct:

category as String: "average"
Other ways to ask this
  • What happens if a variable is only initialized in one branch?
  • How does EK9 check initialization in if-else?
  • What is E08020 used before initialized?

Coming from another language?

Java: definite assignment analysis requires variables to be assigned before use, similar concept. Rust: borrow checker ensures initialization on all paths. Go: zero-value initialization means variables are always initialized (but may have wrong value). Python: runtime NameError if variable not assigned on taken path. C: undefined behavior for uninitialized variables. EK9: compile error E08020 for potentially uninitialized variables on any reachable path.

Keywords: safety, else, initialize, uninitialized, variable, flow, if, path, E08020, control, data-flow, initialization, branch