E07440: return types are incompatible (covariance required)

Category: E07xxx Full resolution · Reported in phase: FULL_RESOLUTION · Classification: COVARIANCE_MISMATCH · All error codes

What went wrong

An overriding method returns a type that's incompatible with the base method's return type. The return type must be the same as, or a subtype of, the return type of EVERY parent that declares the method - the super class and each trait. When two parents promise types no single type satisfies (Integer and String), no override can honour both.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 699 (What are the return type and parameter type rules for met...)

How to fix it

  1. Use same return type as base
  2. Or use covariant (subtype) return

Common causes

  • Different return type than parent
  • Non-covariant return

See also

  • E07440: override return type mismatch (this error)
  • E07410: constructor return mismatch

Examples

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

Fails with E07440: return types are incompatible (covariance required)

#!ek9
defines module error.e07440.bad

  <?-
    Just use these for valid covariance checks.
  -?>
  defines record

    R1 as open
      someField <- "Field1"

      default operator ?

    R2 extends R1
      anotherField <- "Field2"

      default operator ?

    <?-
      Something that is unrelated to R1 or R2.
      To be used later in tests.
    -?>
    R3
      unrelatedField <- "Field3"

      default operator ?

  defines class

    C1 as open
      someMethod1()
        -> text as String
        <- rtn as Float: 1.0

      someMethod2()
        -> text as String
        <- rtn as R1: R1()

      someMethod3()
        -> text as String
        <- rtn as R1: R1()

      //Something that has no return mainValue to be used in covariance checks later
      someMethod4()
        -> text as String
        require text?

    <?-
      Extend an override the C1 someMethod1 method but alter the return type
      so that it incompatible with the class C1
    -?>
    C2 extends C1
      override someMethod1()
        -> text as String
        <- rtn as String: "Test"

      <?-
        just a normal override no covariance issues or use.
      -?>
      override someMethod2()
        -> text as String
        <- rtn as R1: R1()

      <?-
        Again override and should be OK because this is valid as it is a 'R1'.
        But this does not test covariance!
      -?>
      override someMethod3()
        -> text as String
        <- rtn as R1: R2()

      <?-
        A valid override of a method
      -?>
      override someMethod4()
        -> text as String
        require text?

    <?-
      Now even though an Integer can be coerced to a Float - it is not 'covariant'.
    -?>
    C3 extends C1
      override someMethod1()
        -> text as String
        <- rtn as Integer: 1

      <?-
        Again override and should be OK because this is valid covariance.
        Note that we have altered the return type.
      -?>
      override someMethod2()
        -> text as String
        <- rtn as R2: R2()

      <?-
        But R3 is not a 'R1' and therefore this is not valid covariance.
      -?>
      override someMethod3()
        -> text as String
        <- rtn as R3: R3()

      <?-
        Cannot start adding return types when super is not returning anything.
      -?>
      override someMethod4()
        -> text as String
        <- rtn as R3: R3()
        require text?

    C4 extends C1
      <?-
        Normal valid override
      -?>
      override someMethod1()
        -> text as String
        <- rtn as Float: 1.0

      <?-
        Must return a covariant compatible type.
      -?>
      override someMethod2()
        -> text as String
        require text?

      <?-
        But Integer '9' is not a 'R1' and therefore this is not valid covariance.
      -?>
      override someMethod3()
        -> text as String
        <- rtn <- 9

      <?-
        Another valid override
      -?>
      override someMethod4()
        -> text as String
        require text?

Fixed: Return the super's type, or a sub-type of it

#!ek9
defines module error.e07440.good

  defines record

    Shape as open
      name <- "shape"
      default operator ?

    Square extends Shape
      side <- 2
      default operator ?

  defines class

    Factory as open
      make()
        <- rtn as Shape: Shape()

    //Covariant: a Square IS a Shape
    SquareFactory extends Factory
      override make()
        <- rtn as Square: Square()

Questions and answers

These Q&A entries show E07440 and its fix: