E08264: this constructor leaves properties without a value - it can only be used through this() from a constructor that sets them; construct through a constructor that sets every property

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

What went wrong

This call constructs the object through a private constructor that leaves properties without a value. The message names them, for example "'private Label <- Label()' leaves 'text' without a value". A private constructor may leave properties unset - the 'default private Label()' idiom - only because it is meant to be reached through this() from a constructor that then sets them. Reaching it any other way, such as the type constructing an object of itself in a method, would build an object with a property that has no value: the first read of it, or the generated '?', would fail at run time.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 1404 (Why can't my class construct an object of itself through its private ...)
  • ek9 -q 2020 (How do I write a generic type that can be parameterised w...)

Rationale

Each constructor is judged on what it leaves set: its own body plus, through this(...), whatever the constructor it delegates to sets. A private constructor that sets nothing gives nothing. In the [EXAMPLE] section below, Label's 'default private Label()' sets nothing, so after 'this()' the public constructor must still set 'text' itself; and 'blank()' building 'Label()' reaches the private constructor, so 'text' would have no value. The fix builds 'Label("")' instead.

A private constructor that DOES set every property may be used anywhere in the type, and after this(...) to it the object is complete.

How to fix it

  1. Construct through a constructor that sets every property: 'Label("")'
  2. Or write a private constructor that sets every property and construct through that
  3. Or give the property a value at declaration ('text as String: ""'), so no constructor has to set it

Common causes

  • A factory or copy method ('blank()', 'emptied()') written as 'Label()', reaching the 'default private' constructor that exists only to satisfy E07175
  • The same inside a generic type: 'Holder() of T'

See also

  • E07175: the default constructor must be private when properties have no value
  • E08060: a property used before it is initialised (also reported at a property that some accessible constructor, through its this() chain, leaves unset)
  • E08061: the object used before it is fully constructed

https://ek9.io/classes.html

Examples

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

Fails with E08264: this constructor leaves properties without a value - it can only be used through this() from a constructor that sets them; construct through a constructor that sets every property

#!ek9
defines module error.e08264.bad

  defines class

    Label
      text as String?

      default private Label()

      Label()
        -> initial as String
        this()
        text: initial

      blank()
        <- rtn as Label: Label()

      default operator ?

Fixed: Construct through a constructor that sets every property

#!ek9
defines module error.e08264.good

  defines class

    Label
      text as String?

      default private Label()

      Label()
        -> initial as String
        text: initial

      blank()
        <- rtn as Label: Label("")

      default operator ?

Questions and answers

These Q&A entries show E08264 and its fix: