I got E08250 THIS_ESCAPES_CONSTRUCTOR — why can't I pass 'this' out of a constructor?

← Concurrency · Ref: Q1349

E08250 fires when a constructor passes `this` as an argument to another method or function before construction has finished. The object is only partially built at that point — its fields may still be unset — so letting a reference escape lets other code (or another thread) observe a half-initialised object. This is the classic 'unsafe publication' bug that causes intermittent NullPointer-style failures and data races.

WHAT THE ERROR MEANS

Inside a constructor body, `this` is still being assembled. Handing it to `reg.register(this)`, storing it in a collection owned by someone else, or capturing it into a function that outlives the constructor all let the not-yet-finished object be used. EK9 rejects any `this` argument inside a constructor body.

HOW TO FIX

Complete construction first, then register. Move the escaping call OUT of the constructor into a separate step the caller performs after the object exists, or use a factory function that constructs the object fully and only then registers it.

  publisher <- Publisher("news")   //fully constructed
  registry.register(publisher)      //register afterwards — safe

WHY EK9 DETECTS THIS

Unsafe publication is invisible in most languages — Java, C#, and C++ all let `this` escape a constructor with no warning, and the resulting races only surface under load. EK9 forbids it structurally so a reference to a half-built object can never be observed.

Example

defines module qa.concurrency.this.escapes.constructor

  defines class

    Registry
      items as List of Publisher: List() of Publisher
      default Registry()
      register()
        -> p as Publisher
        items += p
      count() as pure
        <- rtn as Integer: length items
      default operator ?

    Publisher
      name as String: String()
      Publisher()
        ->
          n as String
          reg as Registry
        this.name: n
        stdout <- Stdout()
        stdout.println(`registry size ${reg.count()}`)
      default operator ?

Common mistakes

E08250 — The constructor passes `this` to `reg.register(this)` before the Publisher is fully built, letting a half-initialised object be observed (and, across threads, raced on). The fix is to finish construction and register afterwards from the caller, or via a factory. See ek9 -h E08250.

Incorrect:

reg.register(this)

Correct:

stdout <- Stdout()
        stdout.println(`registry size ${reg.count()}`)
Other ways to ask this
  • Why does EK9 reject passing this in a constructor?
  • How to register an object during construction in EK9?
  • this escapes constructor error E08250
  • Publishing this from a constructor body EK9

Coming from another language?

Java/C#/C++: `this` may escape a constructor freely; escape analysis tools flag only some cases and the resulting races are load-dependent. EK9: any `this` argument inside a constructor body is a compile-time error, eliminating unsafe publication entirely.

Keywords: initialisation, unsafe, register, escapes, safe, half-built, this, publication, race, E08250, constructor