E08278: cannot be the target of '>' because '>' replaces the target with a fresh value and this type cannot make one (it must be concrete, have an accessible constructor with no arguments and have a ':=:' operator); use '>>' to add to it instead, or give the type those

Category: E08xxx Pre-IR checks (flow analysis) · Reported in phase: PRE_IR_CHECKS · Classification: STREAM_REPLACE_NEEDS_FRESH_VALUE · All error codes

What went wrong

A '>' at the end of a stream REPLACES its target: the stream is poured into a fresh value of the target's type and, only when the stream has finished, that value is swapped in with ':='. That is the Unix meaning of '>' and it is the same for a List, a Set, an Integer, a String or a type you wrote - the old value takes no part in the result, and a stream that fails part-way leaves the target as it was. To do that the target's type has to be able to make a fresh value: it must be a concrete type, with a constructor that takes no arguments and that is not private, and it must have a ':=:'. Here the target's type cannot, so '>' has nothing to start from. Rather than quietly add to the target, which is what '>>' says, the compiler stops and names '>>':

cat [1, 2, 3] > tally

The built-in output channels are different and are never reported: Stdout, Stderr, a file output, a UDP or TCP connection and anything else that is an IO. '>' into one of them clears it first (it empties a file, and does nothing where there is nothing to clear) and '>>' leaves what is there.

Worked examples

Each of these is fine:

  • //'>>' adds to the Tally that is there: 10 + 1 + 2 + 3.
  • cat [1, 2, 3] >> tally
  • //'>' makes a fresh Tally with the constructor with no arguments and swaps it in with ':=:': 1 + 2 + 3.
  • cat [1, 2, 3] > tally

How to fix it

  1. If you meant to add the stream's items to what the target already holds, write '>>'.
  2. If you meant to replace it, give the type 'default operator :=:' (or your own ':='), and keep a constructor with no arguments that is not private, so a fresh value can be made and swapped in.
  3. A target that is a trait or an abstract type can never make a fresh value: use '>>', or a variable of a concrete type.

Common causes

  • A class that collects what is piped into it ('operator |') being the target of '>' rather than '>>'
  • A target declared as a trait or an abstract class
  • A type that declares its no-argument constructor 'private'
  • A type with no ':=:' (neither written nor 'default operator :=:')

See also

  • E08277: another stream-sink check, a stream that appends to the very variable it reads

Examples

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

Fails with E08278: cannot be the target of '>' because '>' replaces the target with a fresh value and this type cannot make one (it must be concrete, have an accessible constructor with no arguments and have a ':=:' operator); use '>>' to add to it instead, or give the type those

#!ek9
defines module error.e08278.bad

  defines class

    Tally
      count as Integer: 0

      Tally()
        ->
          start as Integer

        count :=: start

      default operator ?

      operator $ as pure
        <- rtn as String: `Tally(${count})`

      operator |
        -> item as Integer
        if item?
          count += item

  defines function

    addUp()
      stdout <- Stdout()
      tally <- Tally(10)
      cat [1, 2, 3] > tally
      stdout.println($tally)

Fixed: Give the Tally a constructor with no arguments and a ':=:', or add to it with '>>'

#!ek9
defines module error.e08278.good

  defines class

    Tally
      count as Integer: 0

      Tally()
        count :=: 0

      Tally()
        ->
          start as Integer

        count :=: start

      default operator ?

      operator $ as pure
        <- rtn as String: `Tally(${count})`

      default operator :=:

      operator |
        -> item as Integer
        if item?
          count += item

  defines function

    addUp()
      stdout <- Stdout()
      tally <- Tally(10)
      //'>>' adds to the Tally that is there: 10 + 1 + 2 + 3.
      cat [1, 2, 3] >> tally

      //'>' makes a fresh Tally with the constructor with no arguments and swaps it in with ':=:': 1 + 2 + 3.
      cat [1, 2, 3] > tally
      stdout.println($tally)

Fixed: Use '>>' to add to the Tally that is there

#!ek9
defines module error.e08278.good.fix

  defines class

    Tally
      count as Integer: 0

      Tally()
        ->
          start as Integer

        count :=: start

      default operator ?

      operator $ as pure
        <- rtn as String: `Tally(${count})`

      operator |
        -> item as Integer
        if item?
          count += item

  defines function

    addUp()
      stdout <- Stdout()
      tally <- Tally(10)
      cat [1, 2, 3] >> tally
      stdout.println($tally)