Skip to content

instanceof asks a union or an optional that may hold a class at run time - #451

Merged
ASDAlexander77 merged 1 commit into
mainfrom
fix-instanceof-union
Oct 2, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
fix-instanceof-union

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Fixes #450.

x instanceof C with x: C | null, C | D, C | number or C | undefined was always false, under every memory model, even after narrowing (if (e) e instanceof C). mlirGenInstanceOfLogic dispatched on the left operand's type: a class, any, opaque or an interface. A union or an optional fell through to the compile-time comparison of the two types, which emitted the constant false.

Now a union or an optional with a class among its members is asked at run time, through the instance's own vtable (slot 0, .instanceOf), as an any already is:

  • an optional, when it has a value;
  • C | null, which needs no tag, when the pointer is set;
  • a tagged union, when its tag is "class" (every class member's tag is), its payload read as the first class member's pointer. The vtable then decides which class it is, so C | D holding a D gives instanceof D true and instanceof C false.

Anything else it may hold (null, undefined, a number) is an instance of nothing.

Tests

  • New tests/00instanceof_union.ts: each shape holding a class and holding something else, a subclass held as its nullable base, a C | D parameter, a narrowed value, and a plain class for comparison. It failed at its first assert before the change. Registered as compile and JIT tests, and in the rc/none corpus list.
  • It passes under gc, rc, none and own (AOT and JIT) and with -noopt.
  • Full Release ctest: 3444/3445. The one failure is test-compile-gc-defaultlib-collector, the known local LNK2005 against the stale installed default library (fails on main the same way).
  • GCC build in WSL; the test passes there under JIT.
  • -mm=own corpus: unchanged except the new file, which compiles under own too.

🤖 Generated with Claude Code

…ime (#450)

`x instanceof C` with `x: C | null`, `C | D`, `C | number` or `C | undefined` was always false,
under every memory model, even after narrowing. mlirGenInstanceOfLogic dispatched on the left
operand's type - a class, `any`, opaque or an interface - and a union or an optional fell through
to the compile-time comparison of the two types, which emitted the constant `false`.

Now such a value is asked at run time, through the instance's own vtable (slot 0, `.instanceOf`),
as an `any` is:
- an optional, when it has a value;
- `C | null`, which needs no tag, when the pointer is set;
- a tagged union, when its tag is "class" (every class member's tag is), its payload read as the
  first class member's pointer.

Anything else it may hold is an instance of nothing.

Test: 00instanceof_union (compile and JIT, and in the rc/none corpus).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 9d92dc8 into main Oct 2, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-instanceof-union branch October 2, 2026 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

instanceof is always false for a class value held in a union or an optional

1 participant