Why does 'default operator' fail when a property's type has no operators?

← Operators and Expressions · Ref: Q1315

'default operator' generates field-by-field implementations by calling the SAME operator on each property's type. So if a class uses 'default operator', EVERY property type must support the operators being generated (==, <>, <=>, $, #?, ? and so on). When a property's type is a custom class or record that defines no operators, the generated code has nothing to call and compilation fails with E07200.

Two fixes:
1. Give the property's type its own operators - the simplest is to add 'default operator' to that type too, so it gains the full field-by-field set.
2. Or implement the outer operators manually instead of using 'default', e.g. 'override operator ? as pure' returning a hand-written expression.

Built-in types (Integer, Float, String, Boolean, Date, Time, DateTime, Duration, Money) already have all operators, so properties of those types never trigger E07200.

See Q949 for the full default operator rules. See Q245 for implementing operators by hand.

Example

defines module qa.operators.propertytypeoperator

  defines class

    <?-
      The property TYPE must itself support the operators that 'default'
      generates. Coordinate gets 'default operator' so it gains the full
      field-by-field set (==, <>, <=>, $, #?, ?), satisfying Place below.
    -?>
    Coordinate
      x <- Integer()
      y <- Integer()

      Coordinate() as pure
        ->
          x as Integer
          y as Integer
        this.x :=: x
        this.y :=: y

      default operator

    <?-
      Place uses 'default operator'. Because its property 'where' is a
      Coordinate that now supports all operators, the generated
      field-by-field code compiles cleanly - no E07200.
    -?>
    Place
      name <- String()
      where <- Coordinate()

      Place() as pure
        ->
          name as String
          where as Coordinate
        this.name :=: name
        this.where :=: where

      default operator

  defines program

    PropertyTypeOperatorDemo()
      stdout <- Stdout()

      origin <- Coordinate(0, 0)
      target <- Coordinate(3, 4)

      home <- Place("home", origin)
      away <- Place("away", target)

      stdout.println(`home == away: ${home == away}`)
      stdout.println(`home: ${home}`)
      stdout.println(`home set: ${home?}`)

Common mistakes

E07200 — 'default operator' on Place generates field-by-field code that calls operators (such as $ and ?) on the type of every property. The property 'where' is a Coordinate, but Coordinate defines no operators, so the generated implementation has nothing to call and E07200 is raised for the missing operator. The fix is to give Coordinate its own operators - adding 'default operator' to Coordinate is the simplest, or implement Place's operators manually instead of using 'default'. See ek9 -h E07200 for details.

Incorrect:

Coordinate
  x <- Integer()
  y <- Integer()
  // no operators

Place
  where <- Coordinate()
  default operator

Correct:

    Coordinate
      x <- Integer()
      y <- Integer()

      Coordinate() as pure
        ->
          x as Integer
          y as Integer
Other ways to ask this
  • What triggers E07200 PROPERTY_TYPE_MISSING_OPERATOR?
  • Why does my class with 'default operator' say a field type lacks an operator?
  • How do I use default operator when a property is a custom class?

Coming from another language?

Java: IDE-generated equals/hashCode silently compiles even if a field type has no usable equals (falling back to Object identity) - a latent bug. Kotlin data class / Rust derive(Eq, Hash) / Python dataclass all require contained types to themselves support the derived behaviour, but the failure modes differ (Rust errors at derive, Java does not). EK9 makes the requirement explicit at compile time: every property type must provide the operator that 'default' generates, or E07200 is raised.

Keywords: property, field, default, operator, E07200, generate, E07235, missing, auto, type