E05290: parents disagree on 'pure' - one method cannot honour both a pure and a non-pure contract

Category: E05xxx Explicit type symbol definition · Reported in phase: FULL_RESOLUTION · Classification: PURE_CONTRACTS_CONFLICT · All error codes

What went wrong

A method stands in for several parent declarations - a super class and a trait, or two traits - and those parents DISAGREE on 'pure': at least one declares the method 'pure' and at least one does not. 'pure' is always part of the contract, so an override must match every parent that declares the method. When the parents disagree, no single method can honour both contracts.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 1401 (What happens when a method comes from both a pure parent...)

Rationale

A caller holding the pure parent relies on the method having no side effects. A caller holding the non-pure parent relies on it being free to have them. One body cannot be both, so combining these parents on one type is rejected - whichever parent is listed first. In the [EXAMPLE] section below, a Circle extends a Base whose 'describe()' is not pure and has the trait Strict whose 'describe()' is pure: Circle's override, pure or not, breaks one of them. The fix makes both parents declare it 'pure'.

How to fix it

  1. Make the parents agree: mark both declarations 'pure', or neither
  2. Or stop combining them - implement the pure trait on a different type

Common causes

  • Adding a pure trait to a class whose super already declares the same method without 'pure'
  • Two traits written independently that declare the same method differently

See also

  • E05150: override missing purity the parents require
  • E05160: override adds purity the parents do not have
  • E07940: 'sanitized' - which, unlike 'pure', an override may ADD (never drop)

https://ek9.io/functions.html

Examples

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

Fails with E05290: parents disagree on 'pure' - one method cannot honour both a pure and a non-pure contract

#!ek9
defines module error.e05290.bad

  defines trait

    Strict
      describe() as pure abstract
        <- rtn as String?

  defines class

    Base as open
      describe()
        <- rtn as String: "base"

      default operator ?

    Circle extends Base with trait of Strict
      override describe()
        <- rtn as String: "circle"

      default operator ?

Fixed: Make the parents agree: here both declare describe() pure, so the override is pure

#!ek9
defines module error.e05290.good

  defines trait

    Strict
      describe() as pure abstract
        <- rtn as String?

  defines class

    Base as open
      describe() as pure
        <- rtn as String: "base"

      default operator ?

    Circle extends Base with trait of Strict
      override describe() as pure
        <- rtn as String: "circle"

      default operator ?

Questions and answers

These Q&A entries show E05290 and its fix: