E05190: if any constructor is marked pure, all constructors must be pure

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

What went wrong

Constructors in a class must have consistent purity - either ALL constructors are pure, or NONE are pure. Mixing pure and non-pure constructors is not allowed.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 564 (Why must all constructors be pure if any one is pure?)
  • ek9 -q 565 (How do I write multiple pure constructors with delegation?)
  • ek9 -q 586 (How does constructor delegation work with pure constructors?)
  • ek9 -q 564 (Why must all constructors be pure if any one is pure?)
  • ek9 -q 678 (How do pure and non-pure methods coexist in an override h...)

How to fix it

  1. Decide if class construction should be pure or not
  2. Make ALL constructors consistently pure or non-pure
  3. Remove side effects from pure constructors

Rationale

Object creation should be predictably pure or not:

  • Callers can't always choose which constructor is called
  • Factory methods might delegate to any constructor
  • Consistent purity simplifies reasoning about code

Common causes

  • Adding new constructor without matching existing purity
  • Wanting one "simple" pure constructor and one "logging" constructor
  • Forgetting to mark overloaded constructor as pure

See also

  • E05190: constructor purity inconsistency (this error)
  • E05150/E05160: method purity in override context

Examples

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

Fails with E05190: if any constructor is marked pure, all constructors must be pure

#!ek9
defines module error.e05190.bad

  defines class

    Person
      name as String: String()
      nickname as String: String()

      default Person()

      Person()
        -> name as String
        this.name :=? name

      //One pure constructor makes the others inconsistent
      Person() as pure
        ->
          name as String
          nickname as String

        this.name :=? name
        this.nickname :=? nickname

      default operator ?

Fixed: Make every constructor pure (a pure constructor sets properties with :=?)

#!ek9
defines module error.e05190.good

  defines class

    Person
      name as String: String()
      nickname as String: String()

      default Person() as pure

      Person() as pure
        -> name as String
        this.name :=? name

      Person() as pure
        ->
          name as String
          nickname as String

        this.name :=? name
        this.nickname :=? nickname

      default operator ?

Fixed: Or make none of them pure

#!ek9
defines module error.e05190.good.none

  defines class

    Person
      name as String: String()
      nickname as String: String()

      default Person()

      Person()
        -> name as String
        this.name: name

      Person()
        ->
          name as String
          nickname as String
        this.name: name
        this.nickname: nickname

      default operator ?

Questions and answers

These Q&A entries show E05190 and its fix: