← board

pasmith: widen OOP beyond the single inheritance chain

What the OOP rung tests today (and tests well)

--classes N builds a linear chain TC0 < TC1 < ... < TCn. Every class overrides its parent's Calc / Name / Create / Destroy and calls inherited, so a single call through a base-typed reference walks the whole chain. Objects are declared as the base type and instantiated as random derived types, so no call site is statically resolvable — a devirtualising optimiser that gets it wrong surfaces as an -O-level self-contradiction. Destructors fold into the checksum, making dtor count and order observable. Fields include an ansistring, so refcount/COW interacts with object lifetime.

So: virtual dispatch, vtable construction, inherited chains, ctor/dtor ordering. Real coverage, and the part Csmith structurally cannot reach. It is just one shape.

The holes, ranked by expected yield

The ranking is not arbitrary: the top three are all silently-wrong-pointer classes — the program keeps running and produces a plausible number — which is exactly what a checksum oracle catches and what a hand-written suite misses.

  1. Interfaces. No IUnknown, no refcounted interface lifetime, no interface-vs-class dispatch, no class implementing two interfaces (which forces distinct interface vtables and an offset-adjusting thunk). Interface refcounting is a lifetime system as tricky as ansistring's, and nothing tests it at all. Biggest single hole.
  2. is / as. No type tests, no checked downcasts. A wrong as yields the wrong object, silently. Needs a branching hierarchy (below) to be worth anything — casting down a linear chain barely exercises the check.
  3. Method pointers (procedure of object). A two-word closure: code pointer + Self. Mispairing the halves is a classic ABI bug, and it is invisible today.
  4. Properties. No getters/setters, no indexed or default properties. A property read that bypasses its getter is silent — the value is just stale.
  5. Branching hierarchies. The chain is linear, so there are no sibling classes and no case where two subclasses of a common base must get distinct vtables. This one is also a prerequisite for is/as being meaningful.
  6. Class methods, class vars, abstract methods, virtual class methods.
  7. Objects in containers / polymorphic collections. Only fixed o0..oN slots exist; an array of base-typed refs holding mixed derived types is the ordinary real shape.
  8. Exceptions crossing a method or a destructor. The exception rung and the class rung never interact today: a raise inside a virtual call, with a live object needing cleanup, is untested — and that intersection is where b339-shaped bugs live.
  9. Overloads / operator overloading, generics, class helpers, nested classes, visibility (private is reportedly not enforced at all — 13 of 17 conformance reds, per [[feature-pasmith-widen-grammar]]).

Invariants any of this must keep

Non-negotiable, and they are what makes a finding believable (see the generator's four invariants):

Acceptance

Each rung ships independently and is gated the same way the last widening was:

Note on order

Do interfaces and the branching hierarchy first: the hierarchy is a prerequisite for is/as and for polymorphic containers being worth anything, and interfaces are the one lifetime system in the dialect that has zero fuzz coverage today.

Log