E08130: is not marked 'pure', but call is made in a scope that is marked as 'pure'

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

What went wrong

You're calling a NON-PURE function from within a PURE context. Pure contexts can only call other pure functions.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 690 (How do pure function call chains work and what restrictio...)
  • ek9 -q 678 (How do pure and non-pure methods coexist in an override h...)
  • ek9 -q 87 (What operations and callbacks does Result support?)

Rationale

Pure functions guarantee no side effects - calling non-pure breaks this.

How to fix it

Decide which way the pure boundary should move: widen it to take in the callee, or narrow it so the caller is no longer pure. Both are legitimate. The question is whether the callee's body is genuinely free of side effects - if it is, widen; if it does real I/O, narrow.

With tooling, ek9_query_purity_impact (the file and the error line) gauges both directions read-only before you commit: 'availableDirections' lists the valid ones, the efferent axis names every callee that must become pure if you widen, and the afferent axis names every pure caller that breaks if you narrow. ek9_fix_purity_contract then applies the direction you chose - mode 'make-callee-pure' to widen, 'remove-pure-from-caller' to narrow - with dryRun:true first.

Two refusals are worth knowing. Past a threshold either direction is refused as 'cascade-too-large': that is a signal the purity boundary is in the wrong place, not an obstacle to work around. On an override the fix is refused with 'override-cascade-blocks-fix' naming the contract root - change purity there, never on the override.

By hand:

  1. Mark the called function as pure if it genuinely has no side effects
  2. Or restructure so the pure context no longer needs that call
  3. If I/O is genuinely needed, remove 'pure' from the calling function

Common causes

  • Function not marked as pure but could be
  • Calling I/O function in pure context

See also

  • E08130: non-pure call in pure context (this error)
  • E08120: mutating operation in pure context

Examples

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

Fails with E08130: is not marked 'pure', but call is made in a scope that is marked as 'pure'

#!ek9
defines module error.e08130.bad

  defines function

    shout()
      -> message as String
      <- rtn as String: message.upperCase()

    announce() as pure
      -> message as String
      <- rtn as String: shout(message)

Fixed: Call only pure functions from a pure one - mark the helper pure

#!ek9
defines module error.e08130.good

  defines function

    shout() as pure
      -> message as String
      <- rtn as String: message.upperCase()

    announce() as pure
      -> message as String
      <- rtn as String: shout(message)

Questions and answers

These Q&A entries show E08130 and its fix: