Skip to content

An array literal in a ternary is an array, and Android builds own - #624

Merged
ASDAlexander77 merged 1 commit into
mainfrom
own-ternary-android
Oct 20, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
own-ternary-android

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Closes the last two open items in the own markers spec.

Ternary of an array literal or null. return i < 3 ? ["a"] : null failed MLIR verification ("operand #0 does not dominate this use") under every model, gc included. The cause:

  • The ternary's type was const_array<string,1> | null.
  • The generated ___cast function that makes it a string[] | null narrows t in its else branch. Narrowing a const_array gives the narrowed name storage of its own: a heap copy that it owns.
  • That copy was released at the end of the function, outside the branch it was made in.

Now a literal array in a branch of ?: is widened to an array in that branch, as TypeScript types it. Each branch also hands its array out with a reference of its own, as new C() is (Retain plus __owned_result). That lets consumeConditionalResults settle the merge, so -mm=own accepts array ternaries. Before, own rejected even c ? ["a"] : ["b"]. rc passes --verify-ownership on the new test.

if (a) of a string[] | null didn't narrow a, because truthiness narrowing required a tagged union. An array keeps null in its own pointer, so a[0] indexed the union. Truthiness narrowing now also covers untagged unions of arrays and null. It deliberately leaves Shared<T> | null alone: own reads a counted handle through the variable itself, and own_shared_graph breaks otherwise.

Test: tests/00narrow_array_null.ts, under gc, rc, none and own, compiled and JIT. It covers ternaries over if, while and for, and push after churn.

Android own. android-link.cmake now links an executable and a shared library under own as well as gc. This needs the own Android default library from ASDAlexander77/TypeScriptCompilerDefaultLib#38. I ran an own executable on the API 29 x86_64 emulator: matchAll, padStart, repeat, arrays and classes all gave correct output. The README and the spec are updated.

Full suite: 4834/4834 (Release, Windows).

🤖 Generated with Claude Code

- `i < 3 ? ["a"] : null` failed MLIR verification under every model: the
  ternary was a `const_array | null`, and the generated function casting it
  to `string[] | null` narrowed the literal to a copy that its narrowed name
  owned, released outside the branch. A literal array in a branch of `?:` is
  now an array there, handed out with a reference of its own as `new C()`
  is, so -mm=own accepts array ternaries too.
- `if (a)` of a `string[] | null` narrows it (an untagged union of arrays and
  null); `a[0]` indexed the union before.
- The Android link test links an executable and a shared library under own
  as well as gc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit ae7db08 into main Oct 20, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the own-ternary-android branch October 20, 2026 06:50
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.

1 participant