E08040: Reassignment/mutation within possible 'safe method access' scope is not allowed

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

What went wrong

You're re-pointing a variable inside a safe access block (protected by ?, or by a guard). This breaks the safety guarantee because the check was on the OLD value.

Every store counts: an assignment (':', ':=', '=', ':=?'), whether it is a statement or the pre-flow of a nested construct. Inside 'if o?', both a statement 'o := other()' and a nested 'if o := other() then o?' re-point o, and each is this error. (The [EXAMPLE] section below shows a re-point with ':' inside 'if chosen?', and the fix: check each Optional in its own branch.)

A construct's OWN head is the proof, not a re-point: 'while o :=? next() then more' is what makes o safe in that loop. It is an error only when an enclosing scope had already proven o safe.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 1960 (Can I give an Optional a new value inside the 'if o?' block that checked it?)
  • ek9 -q 86 (How do Result guard patterns and ternary access work?)
  • ek9 -q 84 (What operations does Optional support in EK9?)

How to fix it

  1. Don't re-point the checked variable inside its protection block
  2. Use a different variable for the new value: 'if replacement <- other()'
  3. Re-point after the protection block has ended

Common causes

  • Modifying Optional/Result variable inside its protection block
  • Assigning to checked variable after guard
  • A nested 'if o := other() then o?' inside 'if o?'
  • An inner loop or try whose own head re-points a variable an outer 'if o?' already checked

See also

  • E08040: reassignment in protected block (this error)
  • E08030: unprotected access

Examples

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

Fails with E08040: Reassignment/mutation within possible 'safe method access' scope is not allowed

#!ek9
defines module error.e08040.bad

  defines function

    describe()
      ->
        primary as Optional of String
        fallback as Optional of String
      <- rtn as String: "none"

      chosen <- primary
      if chosen?
        chosen: fallback
        rtn: chosen.get()

Fixed: Use the checked value; check the other one separately

#!ek9
defines module error.e08040.good

  defines function

    describe()
      ->
        primary as Optional of String
        fallback as Optional of String
      <- rtn as String: "none"

      if primary?
        rtn: primary.get()
      else if fallback?
        rtn: fallback.get()

Questions and answers

These Q&A entries show E08040 and its fix: