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, or stores it into another object, 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)`, or storing it in a collection owned by someone else, lets the not-yet-finished object be used. EK9 rejects `this` as an argument inside a constructor body, and also a local that holds `this` (`other <- this` then `reg.register(other)` is E08250 on `other`), and so does an own property the constructor stored `this` into (`me: this` then `reg.register(me)`). So is a dynamic function or dynamic class that captures `this` (`(me: this) is Callback`) when it is passed out, directly or through a local: the captured object is just as half-built. Calling such a dynamic function inside the constructor is allowed.
STORING IS THE SAME ESCAPE
Storing any of these into ANOTHER object is E08250 too, because the other object can call back into the half-built one: a property of another instance (`p.parent: this`), a collection another object holds or returns (`p.kids += this`, `reg.members() += this`), another object's mutating operator (`reg += this`), or a collection passed in (`others += this`). Storing `this` in the object's OWN property is a self-reference and is allowed (`kids += this`, `this.kids += this`); a chain through an own property (`this.me.parent: this`) reaches another object and is not.
HOW TO FIX
Complete construction first, then register or link (`child <- Child(); parent.adopt(child)`). 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 rejects it at compile time, so `this` cannot be passed out of a constructor or stored into another object, directly or through a local that holds it.
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: passing `this` (or a local holding `this`, or a dynamic function/class capturing it) as an argument, or storing it into another object's property or collection, inside a constructor body is a compile-time error (E08250); storing it in the object's own property is allowed.
Keywords: half-built, safe, escapes, register, unsafe, initialisation, constructor, E08250, race, publication, this