Why can't I add 'as pure' to an override when the parent method isn't pure?
← Purity Contracts · Ref: Q562
You cannot add 'as pure' to an override when the parent method is not pure. The compiler reports E05160.
WHY YOU CANNOT ADD PURE
Callers using the parent type expect the method MAY have side effects. If the child adds purity, code using a parent reference cannot rely on it because another child might not be pure. Purity is a contract from the top of the hierarchy, not something added partway down.
THE ERROR: E05160
If you mark an override 'as pure' but the parent method is not pure, the compiler reports E05160: the parent method is not pure so you cannot add purity.
CORRECT APPROACH
Option 1: Remove 'as pure' from the override. The child matches the parent contract.
Option 2: If you control the parent, make the parent method pure. Then all children must follow.
DESIGN PRINCIPLE
Purity flows DOWN the hierarchy, not UP. The root type decides whether the contract is pure. Children honour it; they cannot change it in either direction.
See Q561 for the reverse rule (must keep pure). See Q560 for pure method basics. See Q567 for purity through inheritance chains.
Example
defines module qa.purity.cannotaddpure defines class //Parent is NOT pure: children must match Logger as open logMessage() -> message as String <- formatted as String: "[LOG] " + message default operator ? //Correct: child does NOT add pure TimestampLogger extends Logger override logMessage() -> message as String <- formatted as String: "[LOG:TS] " + message default operator ? //Separate pure hierarchy: designed pure from the start Formatter as abstract format() as pure abstract -> text as String <- rtn as String? default operator ? UpperFormatter extends Formatter override format() as pure -> text as String <- rtn as String: text.upperCase() default operator ? defines program CannotAddPureDemo() stdout <- Stdout() //Non-pure hierarchy logger <- TimestampLogger() stdout.println(logger.logMessage("system started")) //Pure hierarchy (designed pure from the start) formatter <- UpperFormatter() stdout.println(formatter.format("hello"))
Common mistakes
E05160 — The parent Logger.logMessage is not pure. Adding as pure to the override is forbidden because purity flows down from the top of the hierarchy, not up. See ek9 -h E05160 for details.
Incorrect:
override logMessage() as pure
Correct:
override logMessage()
E05150 — The parent Formatter.format is declared pure abstract. Overriding without as pure would violate the purity contract. See ek9 -h E05150 for details.
Incorrect:
override format()
Correct:
override format() as pure
Other ways to ask this
- What is E05160 SUPER_IS_NOT_PURE?
- Can I make a child method pure if the parent is not?
- Why does EK9 prevent adding purity in an override?
Coming from another language?
Java: no purity concept, no enforcement. Kotlin: no purity. Rust: no purity on trait methods. Go: no purity. EK9: purity is a hierarchical contract enforced by E05160 (cannot add) and E05150 (cannot remove).
Keywords: open, hierarchy, function, purity, override, parent, abstract, immutable, add, pure, contract, E05160, forbidden, side-effect, virtual