E81065: 'default operator :=:' cannot copy a closeable property - the copy would share the resource and both objects would close it

Category: E81xxx-E83xxx Test configuration, execution and coverage · Reported in phase: PRE_IR_CHECKS · Classification: DEFAULT_COPY_OF_CLOSEABLE · All error codes

What went wrong

'default operator :=:' - written alone, or by the bare 'default operator', which includes it - is asked for on a type that holds a closeable property (its type has an 'operator close').

The generated copy is shallow: it copies each property by reference. After 'a :=: b', 'a' and 'b' would hold the SAME resource. Both objects would close it, and 'a's own resource would never be closed. No generated copy can be right for a resource, so it is refused.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 1843 (Can a type that holds a closeable resource use 'default operator :=:'?)

How to fix it

Ask only for the operators the type needs, without ':=:' - replace the bare 'default operator' with one 'default operator' line per operator wanted ('?', '$').

If the type really must be copied, write the copy yourself and copy only the values that are not resources - a closeable property keeps the resource its own object acquired (the [EXAMPLE] section below: a HandWrittenCopy whose copy takes the label and leaves its own Res alone).

Common causes

  • A bare 'default operator' on a class that later gained a resource property.
  • Copying a holder to "share" its connection: lend the connection as a parameter instead.

See also

  • E81065: 'default operator :=:' on a type that holds a closeable (this error)
  • E81062: Closeable slot given a value that is not new
  • E81061: Closeable type as a type argument

Examples

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

Fails with E81065: 'default operator :=:' cannot copy a closeable property - the copy would share the resource and both objects would close it

#!ek9
defines module error.e81065.bad

  defines class

    Res
      name as String?

      default private Res()

      Res()
        -> label as String
        name: label

      operator close as pure
        require name?

      default operator

    <?- BAD: the copy operator asked for explicitly -?>
    ExplicitCopy
      held as Res?

      default private ExplicitCopy()

      ExplicitCopy()
        -> label as String
        held: Res(label)

      default operator ?

      default operator :=:

      default operator close

    <?- BAD: the bare 'default operator' includes the copy operator -?>
    BareDefaults
      label as String?
      held as Res?

      default private BareDefaults()

      BareDefaults()
        -> text as String
        label: text
        held: Res(text)

      default operator close

      default operator

    <?- OK: a hand-written copy that copies only what is not a resource -?>
    HandWrittenCopy
      label as String?
      held as Res?

      default private HandWrittenCopy()

      HandWrittenCopy()
        -> text as String
        label: text
        held: Res(text)

      default operator ?

      operator :=:
        -> other as HandWrittenCopy
        label :=: other.label

      default operator close

Fixed: Ask only for the operators the type needs, or write a copy that leaves the resource alone

#!ek9
defines module error.e81065.good

  defines class

    Res
      name as String?

      default private Res()

      Res()
        -> label as String
        name: label

      read() as pure
        <- rtn as String: `read ${name}`

      default operator ?

      operator close as pure
        stdout <- Stdout()
        stdout.println(`closed ${name}`)

    HandWrittenCopy
      label as String?
      held as Res?

      default private HandWrittenCopy()

      HandWrittenCopy()
        -> text as String
        label: text
        held: Res(text)

      default operator ?

      operator :=:
        -> other as HandWrittenCopy
        label :=: other.label

      default operator close

Questions and answers

These Q&A entries show E81065 and its fix: