Skip to content

🏃 Reduce Selector type-checking cost - #283

Merged
MulverineX merged 5 commits into
sandstone-mc:masterfrom
snowyukitty:perf/selector-types
Aug 8, 2026
Merged

MulverineX merged 5 commits into
sandstone-mc:masterfrom
snowyukitty:perf/selector-types

Conversation

@snowyukitty

@snowyukitty snowyukitty commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • annotate SelectorClass's three structurally covariant type parameters
  • preserve the existing overloads, inference results, and rejection behavior
  • add exact type-shape coverage and an automated instantiation regression guard
  • add a repeatable alternating benchmark for the repository's current TypeScript 6 and TypeScript 7 toolchain

Why

TypeScript's trace attributes the issue fixture's extra check time to inferring
variance for SelectorClass. That inference recursively traverses the
generated entity/NBT graph. The explicit out modifiers state the same
covariance the class already has, allowing comparisons between
SelectorClass instantiations to compare their type arguments directly.

Before the change, all 729 assignability relations among the 27 boolean
instantiations were checked against component-wise covariance with no
mismatches. Base-versus-candidate probes also produced identical diagnostics
for unresolved generic parameters and never, under both
strictFunctionTypes modes.

Current-master reproduction

The emitted-declaration fixture still reproduces the regression on current
master (4bc288f):

Compiler Control instantiations Selector instantiations
TypeScript 7.0.2 91 471,513
TypeScript 6.0.2 91 471,298

Candidate benchmark

Ten measured fresh-process selector/control pairs after warmup:

Compiler Control instantiations Selector instantiations
TypeScript 7.0.2 91 366
TypeScript 6.0.2 91 289

The exact integer counters are the primary result. Timing ratios remain
informational because compiler totals are rounded to 10 ms and wall time
includes process startup. Benchmark output records a stable SHA-256 over the
emitted declaration tree so saved results can be tied to the measured build.

Run with:

bun run benchmark:selector-types
bun run benchmark:selector-types -- --compiler ts6

Test plan

  • full build pipeline
  • bun test (76 passed)
  • full-project TypeScript 7 --noEmit check
  • full-project TypeScript 6 --noEmit check
  • both ten-pair benchmark commands above
  • reverse-check the automated guard: removing the three out modifiers fails at 471,298 instantiations versus the 10,000 ceiling
  • git diff --check

On Windows, the build was validated by launching the repository-pinned
extensionless TypeScript 7 binary through node; Bun cannot execute that
upstream package script directly. bun lint remains blocked before source
analysis by current master's configuration referencing an unavailable
eslint/no-dupe-args rule; this change does not modify the lint setup.

Fixes #269

@MulverineX

Copy link
Copy Markdown
Member

Thank you! I will test this locally soon. @snowyukitty can you tell me how you found Sandstone and what motivated you to contribute? Just curious.

@snowyukitty

Copy link
Copy Markdown
Contributor Author

I found Sandstone through a structured search of active GitHub issues in TypeScript projects. #269 stood out because the compiler-instantiation blow-up had a deterministic reproduction and the variance change could be measured against both tsc and tsgo without changing runtime behavior. That combination—clear user impact, a narrow type-level fix, and a falsifiable benchmark—is what motivated me to work on it.

@MulverineX

Copy link
Copy Markdown
Member

I just tested this, its legit! Thanks, merging this now

@MulverineX

MulverineX commented Aug 8, 2026 •

Copy link
Copy Markdown
Member

Also if a real person was steering the model for this, I'd appreciate you saying something,

I found Sandstone through a structured search of active GitHub issues in TypeScript projects. #269 stood out because the compiler-instantiation blow-up had a deterministic reproduction and the variance change could be measured against both tsc and tsgo without changing runtime behavior. That combination—clear user impact, a narrow type-level fix, and a falsifiable benchmark—is what motivated me to work on it.

This is obviously a slop non-answer. I'm curious what you get out of spending who knows how much money on all of these tokens, and I hope you don't use nasty compute running in xAI/OpenAI/Meta datacenters, they're destroying communities and the planet.

@MulverineX MulverineX changed the title Reduce Selector type-checking cost 🏃 Reduce Selector type-checking cost Aug 8, 2026
@MulverineX
MulverineX merged commit b525744 into sandstone-mc:master Aug 8, 2026
1 check passed
@MulverineX MulverineX added 👨‍💻 /commands/ Involves command implementations/arguments 🤖 Bot labels Aug 8, 2026
@snowyukitty

Copy link
Copy Markdown
Contributor Author

Yes—there’s a real person here. I steer the work and decide what gets submitted, but I do use AI heavily. For this PR, I used OpenAI Codex for most of the implementation workflow, with Anthropic Claude and xAI Grok in review passes. My previous reply was AI-assisted and dodged the human part of your question. That criticism was fair, and I’m sorry.

What I get out of the token spend is practice and learning. I think AI-assisted coding is going to become a normal part of software development, so I’m trying to become genuinely good at working with these tools while contributing something useful to open source. Real projects give me real constraints, tests, standards, and maintainer feedback. That helps me improve both my own engineering judgment and the way I guide the agents.

A few years ago, Go-playing AIs became teachers for human players. AI agents feel a little like that to me: they teach and guide me while I learn how to collaborate with them thoughtfully and use them well. I’m still learning, but that’s the point—and I hope the work itself is useful along the way.

For this PR, I didn’t use a Meta model. I don’t have a trustworthy per-PR energy or emissions estimate, so I don’t want to make one up. I hear your concern about the effects data centers can have on communities and the environment, and I don’t think it should be brushed aside.

MulverineX pushed a commit that referenced this pull request Aug 8, 2026
* 🏃 Reduce Selector type-checking cost

* test(types): benchmark selectors on TS 6 and TS 7

* test(types): guard Selector instantiation cost

* test(types): fingerprint emitted declarations

---------

Co-authored-by: snowyukitty <[email protected]>
MulverineX pushed a commit that referenced this pull request Aug 8, 2026
* 🏃 Reduce Selector type-checking cost

* test(types): benchmark selectors on TS 6 and TS 7

* test(types): guard Selector instantiation cost

* test(types): fingerprint emitted declarations

---------

Co-authored-by: snowyukitty <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🤖 Bot 👨‍💻 /commands/ Involves command implementations/arguments 🏃 optimization (types)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Type errors in Selector are sometimes not very useful and its types slow down the TS LSP

2 participants