← board

DECIDE: constructor-exception-cleanup semantics (auto-Destroy on failed Create?)

Upstream (FPC/Delphi) behavior

Every constructor body is implicitly wrapped by the compiler in a try/except: if an exception escapes the constructor, the runtime calls Destroy on the partially-constructed instance (memory is already live — NewInstance ran before the constructor body), then re-raises to the caller. This is unconditional — every constructor gets the wrapper whether the class needs it or not. Its corollary: a destructor written against this contract must tolerate being invoked on a half-initialized object (nil fields it never got to set), which is why idiomatic Pascal destructors guard every free/dispose with if Assigned(...).

Position recorded (2026-07-04 discussion)

Options on the table

  1. Match FPC exactly: implicit try/except-call-Destroy-reraise wrapper on every constructor. Needed only if source/binary compat with existing Pascal code that leans on this (rare — old libs doing multi-stage resource alloc across one constructor) matters.
  2. No wrapper (current lean): constructor exception propagates raw, no auto-Destroy. Cheaper codegen, matches the project's no-implicit-safety-net stance. Breaks compat with the rare upstream code relying on the cleanup contract.
  3. Opt-in wrapper: directive/switch to request FPC-parity behavior per unit or per class, defaulting off.

Acceptance (of the decision, not code)

A written choice (2, almost certainly, per the discussion) recorded here; if anything ever surfaces requiring FPC-parity cleanup semantics, revisit before implementing rather than assuming option 2 forever.

DECIDED 2026-07-20 — Option 2, no wrapper

User's call: 2. A constructor that raises propagates the exception raw. No implicit try/except, no auto-Destroy, no reraise.

Matches the project's no-implicit-safety-net stance and keeps constructor codegen free of a wrapper nobody asked for. The compat cost is real but narrow: upstream Pascal code doing multi-stage resource allocation across a single constructor and leaning on FPC's cleanup contract will leak instead of being destroyed. That is rare, and it is loud rather than silent.

Option 3 (opt-in directive) stays available if a corpus program ever actually needs FPC parity here — it can be added later without breaking anything decided now, since the default would remain off.

Log