Skip to content

[experiment] fully order independent type checking - #65064

Draft
Jake Bailey (jakebailey) wants to merge 174 commits into
microsoft:mainfrom
jakebailey:checker-db
Draft

Jake Bailey (jakebailey) wants to merge 174 commits into
microsoft:mainfrom
jakebailey:checker-db

Conversation

@jakebailey

@jakebailey Jake Bailey (jakebailey) commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

There's too much here to explain, but at a high level, this is a massive change which aims to make the checker entirely order independent, that is, it doesn't matter when you call the checker, which nodes you walk first, if you do or do not pull something, check some other file, helicopter into the wrong part of a cycle, etc, the behavior, diagnostics, everything, will be the same.

Looking at individual commits is my suggested way to look inside, not the entire diff, which will surely crash your browser.

This is all AI driven, so it's a bit hard to unbox (I plan to break this apart since some stuff can be done early), but some interesting tidbits (handwritten by me!)


There's a new checkOrder test option, which makes certain tests variant on interesting orderings, like "what if we visit every single node before checking" or "what if we reverse the order of the files" or even "what if we use PRNG to randomly walk nodes and then check". This up front found on the order of 500 failing tests we already had that were secretly order dependent. These were all fuzzed out and kept.

There are a significant number of new tests which all show various ordering bugs never before discovered.

The first chunk of the PR are fixing places where code peeked at caches that "happened to be filled" instead of calling the actual function to pull on them.

Then, all of the ID-using code gets removed. At the end everything now has an ID independent ordering based on content, flags, the works. This caught a bunch of places where we were not caching things and ending up with types that were by all rights identical but had different IDs and then were unstable.

The big and scary change is the introduction of a new state management type dubbed "memo". Every single piece of checker state was moved into memos on a sidecar object on the checker (maybe for future sharing??). This memo system keeps track of the current computation, what depends on what else, eliminating basically all flags/bools that track "computed" or "resolved"-ness. This tracking also records side effects, including diagnostics, "referenced" marks, deferred checks, emit helper checks. The result is that if you query via the API and that calculates some error, those same errors will appear later if the checker runs.

With those data structures in place, now all of the cycles can be handled. Once a cycle is discovered, the checker starts logging what it's doing, and throws all of that info away assuming it's been poisoned.

All of the different recursion stacks get pulled into a single memo stack, which is a cool simplification too.

Variance is now a fixpoint algorithm, proceeding in rounds until stability. In practice, it doesn't iterate much.

Instantiation limits also stop being global numbers (since of course, that is order dependent side effect stuff). Instead, things get limited by the amount of work that's been done, and if you then pull on caches related to work, it tallies that work up to error consistently when needed. (I don't think this is fully done yet, though, since there are depth limits that are really hard to get right. Still thinking about that.)

In some cases, cycles still can't be fixed up, and so they're made consistent by doing what we've done previously for these cases, which is to pick a canonical place to restart to at least get it consistent.


Unfortunately, this all has a cost; the end of the PR tries to claw back perf, but at the end of the day, if we do more work tracking, we spend more CPU and memory tracking. It's still an open question whether this can be cheapened any more. But, my hope is that this idea is minimal enough that we could then optimize TS as a whole assuming this order-independence, e.g. work stealing, checker recycling, shared state, maybe even using LRU caches, or dumping data to disk.

But, it could also well be that this is slop and impossible to manage. But I don't want to sit on it anymore and want to see some real world effects.

Also, this is really meant to be rebased, so expect this all to be nasty nasty force pushes all the time as this gets tweaked. Unfortunately right now that's like 125+ commits, so that sucks.

However, I think that this will fix countless issues on the tracker. I have no idea how to evaluate all 5k issues to see if this PR fixes them. But it's gotta be a lot.

@typescript-automation typescript-automation Bot added Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Oct 30, 2026
@jakebailey

Copy link
Copy Markdown
Member Author

TypeScript Bot (@typescript-bot) test it

@typescript-automation

typescript-automation Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Starting jobs; this comment will be updated as builds start and complete.

Command Status Results
test top400 ✅ Started
user test this ✅ Started 👀 Results
run dt ✅ Started 👀 Results
perf test this faster ✅ Started 👀 Results

@typescript-automation

Copy link
Copy Markdown
Contributor

Hey Jake Bailey (@jakebailey), the results of running the DT tests are ready.

There were interesting changes:

Branch only errors: d3-selection

Package: d3-selection

Branch error:

Project scope: tsconfig.json

Error: types/d3-selection/d3-selection-tests.ts:1502:9
TypeScript@local compile error TS2769:
No overload matches this call.
The last overload gave the following error.
Argument of type '(enter: Selection<EnterElement, number, HTMLElement, unknown>) => TransitionLike<HTMLParagraphElement, number>' is not assignable to parameter of type 'string | ((elem: Selection<EnterElement, number, HTMLElement, unknown>) => Selection<BaseType, number, HTMLElement, unknown> | TransitionLike<...>)'.
Type '(enter: Selection<EnterElement, number, HTMLElement, unknown>) => TransitionLike<HTMLParagraphElement, number>' is not assignable to type '(elem: Selection<EnterElement, number, HTMLElement, unknown>) => Selection<BaseType, number, HTMLElement, unknown> | TransitionLike<...>'.
Type 'TransitionLike<HTMLParagraphElement, number>' is not assignable to type 'Selection<BaseType, number, HTMLElement, unknown> | TransitionLike<HTMLElement, number>'.
Type 'TransitionLike<HTMLParagraphElement, number>' is not assignable to type 'TransitionLike<HTMLElement, number>'.
The types returned by 'selection().selectAll(...)' are incompatible between these types.
Type 'Selection<null, undefined, HTMLParagraphElement, number>' is not assignable to type 'Selection<null, undefined, HTMLElement, number>'.
Property 'align' is missing in type 'HTMLElement' but required in type 'HTMLParagraphElement'.
    at combineErrorsAndWarnings (/mnt/vss/_work/1/s/DefinitelyTyped-tools/packages/dtslint/dist/index.js:200:28)
    at runTests (/mnt/vss/_work/1/s/DefinitelyTyped-tools/packages/dtslint/dist/index.js:192:20)
Branch only errors: absinthe__socket

Package: absinthe__socket

Branch error:

Project scope: tsconfig.json

Error: types/absinthe__socket/absinthe__socket-tests.ts:29:47
TypeScript@local compile error TS2345:
Argument of type 'Notifier<{ userId: number; }, {}>' is not assignable to parameter of type 'Notifier<{}, {}>'.
Types of property 'activeObservers' are incompatible.
Type 'readonly Observer<{ userId: number; }, {}>[]' is not assignable to type 'readonly Observer<{}, {}>[]'.
Type 'Observer<{ userId: number; }, {}>' is not assignable to type 'Observer<{}, {}>'.
Types of property 'onStart' are incompatible.
Type '((notifier: Notifier<{ userId: number; }, {}>) => any) | undefined' is not assignable to type '((notifier: Notifier<{}, {}>) => any) | undefined'.
Type '(notifier: Notifier<{ userId: number; }, {}>) => any' is not assignable to type '(notifier: Notifier<{}, {}>) => any'.
Types of parameters 'notifier' and 'notifier' are incompatible.
Type 'Notifier<{}, {}>' is not assignable to type 'Notifier<{ userId: number; }, {}>'.
Types of property 'activeObservers' are incompatible.
Type 'readonly Observer<{}, {}>[]' is not assignable to type 'readonly Observer<{ userId: number; }, {}>[]'.
Type 'Observer<{}, {}>' is not assignable to type 'Observer<{ userId: number; }, {}>'.
Property 'userId' is missing in type '{}' but required in type '{ userId: number; }'.
    at combineErrorsAndWarnings (/mnt/vss/_work/1/s/DefinitelyTyped-tools/packages/dtslint/dist/index.js:200:28)
    at runTests (/mnt/vss/_work/1/s/DefinitelyTyped-tools/packages/dtslint/dist/index.js:192:20)
Branch only errors: react-relay

Package: react-relay

Branch error:

Project scope: tsconfig.json

Error: types/react-relay/test/relay-hooks-tests.tsx:987:13
TypeScript@local compile error TS2344:
Type '{ mainPanelA?: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params> | undefined; mainPanelB?: EntryPoint<...> | undefined; }' does not satisfy the constraint 'Record<string, EntryPoint<any, any> | undefined>'.
Property 'mainPanelA' is incompatible with index signature.
Type 'EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>' is not assignable to type 'InternalEntryPointRepresentation<any, Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>'.
Types of property 'root' are incompatible.
Type 'JSResourceReference<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>>' is not assignable to type 'JSResourceReference<EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>>'.
Type 'EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>' is not assignable to type 'EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>'.
Type 'ComponentClass<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>'.
Type 'ComponentClass<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'ComponentClass<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any>'.
Types of property 'getDerivedStateFromProps' are incompatible.
Type 'GetDerivedStateFromProps<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any> | undefined' is not assignable to type 'GetDerivedStateFromProps<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any> | undefined'.
Type 'GetDerivedStateFromProps<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'GetDerivedStateFromProps<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any>'.
Types of parameters 'nextProps' and 'nextProps' are incompatible.
Type 'Readonly<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>>' is not assignable to type 'Readonly<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>>'.
Types of property 'extraProps' are incompatible.
Type '{} | null' is not assignable to type '{}'.
Type 'null' is not assignable to type '{}'.

types/react-relay/test/relay-hooks-tests.tsx:1023:13
TypeScript@local compile error TS2322:
Type '(params: { route: string; }) => { entryPoints: { mainPanelA: { entryPoint: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>; entryPointParams: ...; }; mainPanelB?: undefined; } | ...; queries: ...; extraProps: ...; }' is not assignable to type '(entryPointParams: { route: string; }) => PreloadProps<{ route: string; }, {}, Record<string, EntryPoint<any, any> | undefined>, { foo: "bar"; }>'.
Type '{ entryPoints: { mainPanelA: { entryPoint: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>; entryPointParams: { slug: string; }; }; mainPanelB?: undefined; } | ...; queries: {}; extraProps: ...; }' is not assignable to type 'PreloadProps<{ route: string; }, {}, Record<string, EntryPoint<any, any> | undefined>, { foo: "bar"; }>'.
Types of property 'entryPoints' are incompatible.
Type '{ mainPanelA: { entryPoint: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>; entryPointParams: ...; }; mainPanelB?: undefined; } | ...' is not assignable to type 'ThinNestedEntryPointParamsObject<Record<string, EntryPoint<any, any> | undefined>> | undefined'.
Type '{ mainPanelA: { entryPoint: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>; entryPointParams: { slug: string; }; }; mainPanelB?: undefined; }' is not assignable to type 'ThinNestedEntryPointParamsObject<Record<string, EntryPoint<any, any> | undefined>>'.
Property 'mainPanelA' is incompatible with index signature.
Type '{ entryPoint: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>; entryPointParams: { slug: string; }; }' is not assignable to type 'ThinNestedEntryPointParams<EntryPoint<any, any> | undefined>'.
The types of 'entryPoint.root' are incompatible between these types.
Type 'JSResourceReference<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>>' is not assignable to type 'JSResourceReference<EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>>'.
Type 'EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>' is not assignable to type 'EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>'.
Type 'ComponentClass<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>'.
Type 'ComponentClass<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'ComponentClass<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any>'.
Types of property 'getDerivedStateFromProps' are incompatible.
Type 'GetDerivedStateFromProps<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any> | undefined' is not assignable to type 'GetDerivedStateFromProps<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any> | undefined'.
Type 'GetDerivedStateFromProps<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'GetDerivedStateFromProps<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any>'.
Types of parameters 'nextProps' and 'nextProps' are incompatible.
Type 'Readonly<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>>' is not assignable to type 'Readonly<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>>'.
Types of property 'extraProps' are incompatible.
Type '{} | null' is not assignable to type '{}'.
Type 'null' is not assignable to type '{}'.

types/react-relay/test/relay-hooks-tests.tsx:1054:15
TypeScript@local compile error TS2322:
Type 'Readonly<{ dispose: DisposeFn; entryPoints: { [x: string]: Readonly<...>; }; extraProps: {} | null; getComponent: () => any; isDisposed: boolean; queries: { [x: string]: PreloadedQuery<OperationType, Record<...>>; }; rootModuleID: string; }>' is not assignable to type 'PreloadedEntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>> | undefined'.
Type 'Readonly<{ dispose: DisposeFn; entryPoints: { [x: string]: Readonly<...>; }; extraProps: {} | null; getComponent: () => any; isDisposed: boolean; queries: { [x: string]: PreloadedQuery<OperationType, Record<...>>; }; rootModuleID: string; }>' is not assignable to type 'Readonly<{ dispose: DisposeFn; entryPoints: {}; extraProps: {}; getComponent: () => FunctionComponent<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>>; isDisposed: boolean; queries: ...; rootModuleID: string; }>'.
Types of property 'extraProps' are incompatible.
Type '{} | null' is not assignable to type '{}'.
Type 'null' is not assignable to type '{}'.
    at combineErrorsAndWarnings (/mnt/vss/_work/1/s/DefinitelyTyped-tools/packages/dtslint/dist/index.js:200:28)
    at runTests (/mnt/vss/_work/1/s/DefinitelyTyped-tools/packages/dtslint/dist/index.js:192:20)

Full output in the log.

@typescript-automation

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the user tests with tsc comparing baseline and pr:

Something interesting changed - please have a look.

Details

effect

packages/tools/ai-docgen/tsconfig.json

puppeteer

packages/puppeteer-core/tsconfig.json

uglify-js

/mnt/vss/work/1/s/ts_downloads//m/uglify-js/tsconfig.json

  • [NEW] error TS2339: Property 'last_ref' does not exist on type 'never'.
    • /mnt/vss/work/1/s/ts_downloads//m/uglify-js/node_modules/uglify-js/lib/compress.js(2544,35)
  • [MISSING] error TS2322: Type 'false' is not assignable to type 'never'.
    • /mnt/vss/work/1/s/ts_downloads//m/uglify-js/node_modules/uglify-js/lib/compress.js(2544,25)

webpack

tsconfig.json

  • [NEW] error TS2345: Argument of type '[unknown]' is not assignable to parameter of type '[] | [boldQuantity?: boolean | undefined] | [direction?: "child" | "parent" | "sibling" | undefined] | [oversize?: boolean | undefined]'.
  • [NEW] error TS2345: Argument of type 'string | number | boolean | Type' is not assignable to parameter of type 'Type'.

tsconfig.types.json

  • [NEW] error TS2345: Argument of type '[unknown]' is not assignable to parameter of type '[] | [boldQuantity?: boolean | undefined] | [direction?: "child" | "parent" | "sibling" | undefined] | [oversize?: boolean | undefined]'.

tsconfig.types.test.json

@typescript-automation

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey)
The results of the perf run you requested are in!

Here they are:

tsc

Comparison Report - baseline..pr
Metric baseline pr Delta Best Worst p-value
Compiler-Unions - native
Errors 41 41 ~ ~ ~ p=1.000 n=20
Symbols 88,466 88,464 -2 (- 0.00%) ~ ~ p=0.000 n=20
Types 79,607 79,570 -37 (- 0.05%) ~ ~ p=0.000 n=20
Memory Used 103,896k (± 0.02%) 111,077k (± 0.04%) 🔻+7,181k (+ 6.91%) 110,925k 111,227k p=0.000 n=20
Memory Allocs 1,262,232 (± 0.01%) 1,382,888 (± 0.01%) 🔻+120,657 (+ 9.56%) 1,382,595 1,383,138 p=0.000 n=20
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Parse Time 0.023s (± 2.38%) 0.024s (± 2.35%) ~ 0.022s 0.025s p=0.273 n=20
Bind Time 0.008s (± 4.19%) 0.009s (± 6.30%) ~ 0.007s 0.011s p=0.503 n=20
Check Time 0.214s (± 2.44%) 0.238s (± 0.84%) 🔻+0.023s (+10.82%) 0.232s 0.248s p=0.000 n=20
Emit Time 0.142s (± 1.09%) 0.149s (± 0.98%) 🔻+0.007s (+ 5.16%) 0.141s 0.154s p=0.000 n=20
Total Time 0.391s (± 1.34%) 0.422s (± 0.73%) 🔻+0.031s (+ 8.05%) 0.412s 0.437s p=0.000 n=20
angular-1 - native
Errors 3 3 ~ ~ ~ p=1.000 n=20
Symbols 586,461 (± 0.01%) 582,012 (± 0.03%) -4,449 (- 0.76%) 581,488 582,966 p=0.000 n=20
Types 241,684 (± 0.00%) 244,833 (± 0.04%) +3,149 (+ 1.30%) 244,649 245,409 p=0.000 n=20
Memory Used 518,997k (± 0.03%) 799,196k (± 0.04%) 🔻+280,200k (+53.99%) 798,221k 801,135k p=0.000 n=20
Memory Allocs 7,793,838 (± 0.11%) 14,777,317 (± 0.08%) 🔻+6,983,478 (+89.60%) 14,743,392 14,830,518 p=0.000 n=20
Config Time 0.009s 0.009s ~ ~ ~ p=1.000 n=20
Parse Time 0.126s (± 4.43%) 0.124s (± 2.06%) ~ 0.116s 0.136s p=0.473 n=20
Bind Time 0.042s (± 9.91%) 0.045s (±11.57%) ~ 0.036s 0.067s p=0.533 n=20
Check Time 0s 0s ~ ~ ~ p=1.000 n=20
Emit Time 0.827s (± 0.92%) 1.358s (± 1.06%) 🔻+0.531s (+64.19%) 1.297s 1.406s p=0.000 n=20
Total Time 1.015s (± 1.00%) 1.547s (± 0.75%) 🔻+0.532s (+52.46%) 1.499s 1.587s p=0.000 n=20
arktype - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 685,920 737,025 🔻+51,105 (+ 7.45%) ~ ~ p=0.000 n=20
Types 939,467 954,543 +15,076 (+ 1.60%) ~ ~ p=0.000 n=20
Memory Used 495,298k (± 0.01%) 568,199k (± 0.01%) 🔻+72,901k (+14.72%) 567,987k 568,454k p=0.000 n=20
Memory Allocs 12,061,856 (± 0.01%) 15,942,771 (± 0.01%) 🔻+3,880,915 (+32.18%) 15,938,341 15,948,882 p=0.000 n=20
Config Time 0.001s 0.001s ~ ~ ~ p=1.000 n=20
Parse Time 0.041s (± 4.12%) 0.042s (± 2.99%) ~ 0.037s 0.047s p=0.793 n=20
Bind Time 0.014s (±10.49%) 0.013s (± 8.24%) ~ 0.011s 0.019s p=0.616 n=20
Check Time 0.883s (± 0.99%) 1.199s (± 0.78%) 🔻+0.316s (+35.81%) 1.158s 1.246s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 0.966s (± 0.86%) 1.283s (± 0.66%) 🔻+0.317s (+32.79%) 1.253s 1.328s p=0.000 n=20
class-transformer - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 45,376 45,319 -57 (- 0.13%) ~ ~ p=0.000 n=20
Types 7,573 7,219 🟩-354 (- 4.67%) ~ ~ p=0.000 n=20
Memory Used 27,890k (± 0.03%) 30,925k (± 0.02%) 🔻+3,035k (+10.88%) 30,899k 30,943k p=0.000 n=20
Memory Allocs 248,137 (± 0.04%) 267,547 (± 0.05%) 🔻+19,409 (+ 7.82%) 267,126 268,373 p=0.000 n=20
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Parse Time 0.011s (± 4.90%) 0.011s (± 4.44%) ~ 0.009s 0.013s p=0.870 n=20
Bind Time 0.003s (± 4.63%) 0.003s (± 6.23%) ~ 0.002s 0.004s p=0.381 n=20
Check Time 0.008s (± 5.14%) 0.010s (± 3.52%) 🔻+0.002s (+20.50%) 0.008s 0.011s p=0.000 n=20
Emit Time 0.008s (± 5.95%) 0.010s (± 4.57%) 🔻+0.001s (+17.79%) 0.008s 0.012s p=0.000 n=20
Total Time 0.031s (± 1.77%) 0.035s (± 1.61%) 🔻+0.003s (+ 9.86%) 0.032s 0.036s p=0.000 n=20
effect - native
Errors 12 20 🔻+8 (+66.67%) ~ ~ p=0.000 n=20
Symbols 1,235,115 1,234,949 -166 (- 0.01%) ~ ~ p=0.000 n=20
Types 894,113 890,634 -3,479 (- 0.39%) ~ ~ p=0.000 n=20
Memory Used 939,429k (± 0.03%) 1,015,968k (± 0.01%) 🔻+76,539k (+ 8.15%) 1,015,553k 1,016,675k p=0.000 n=20
Memory Allocs 12,635,077 (± 0.03%) 15,907,879 (± 0.02%) 🔻+3,272,802 (+25.90%) 15,898,929 15,928,234 p=0.000 n=20
Config Time 0.002s 0.002s ~ ~ ~ p=1.000 n=20
Parse Time 0.147s (± 1.86%) 0.149s (± 2.22%) ~ 0.138s 0.174s p=0.357 n=20
Bind Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Check Time 0.865s (± 1.97%) 1.183s (± 0.59%) 🔻+0.318s (+36.79%) 1.163s 1.216s p=0.000 n=20
Emit Time 0.492s (± 1.97%) 0.509s (± 2.29%) +0.017s (+ 3.47%) 0.459s 0.547s p=0.042 n=20
Total Time 1.597s (± 0.81%) 1.934s (± 0.61%) 🔻+0.337s (+21.11%) 1.896s 2.009s p=0.000 n=20
mui-docs - native
Errors 11,405 11,405 ~ ~ ~ p=1.000 n=20
Symbols 3,784,019 3,745,693 -38,326 (- 1.01%) ~ ~ p=0.000 n=20
Types 1,355,974 1,292,461 🟩-63,513 (- 4.68%) ~ ~ p=0.000 n=20
Memory Used 1,769,157k (± 0.06%) 2,355,727k (± 0.06%) 🔻+586,570k (+33.16%) 2,350,729k 2,362,054k p=0.000 n=20
Memory Allocs 25,751,249 (± 0.13%) 46,425,057 (± 0.07%) 🔻+20,673,808 (+80.28%) 46,305,744 46,597,622 p=0.000 n=20
Config Time 0.009s (± 2.52%) 0.009s (± 2.18%) ~ 0.008s 0.009s p=0.716 n=20
Parse Time 0.301s (± 1.40%) 0.300s (± 2.37%) ~ 0.263s 0.329s p=0.836 n=20
Bind Time 0.001s 0.001s (±34.77%) ~ 0.001s 0.005s p=1.000 n=20
Check Time 3.016s (± 0.63%) 4.953s (± 0.87%) 🔻+1.937s (+64.22%) 4.775s 5.186s p=0.000 n=20
Emit Time 0.246s (± 1.33%) 0.252s (± 8.48%) +0.006s (+ 2.23%) 0.225s 0.388s p=0.014 n=20
Total Time 4.079s (± 0.56%) 6.019s (± 0.68%) 🔻+1.940s (+47.57%) 5.929s 6.305s p=0.000 n=20
sentry - native
Errors 2 3 🔻+1 (+50.00%) ~ ~ p=0.000 n=20
Symbols 4,793,245 4,780,779 -12,466 (- 0.26%) ~ ~ p=0.000 n=20
Types 2,606,905 2,536,142 -70,763 (- 2.71%) ~ ~ p=0.000 n=20
Memory Used 2,846,141k (± 0.03%) 3,074,910k (± 0.03%) 🔻+228,769k (+ 8.04%) 3,071,117k 3,078,986k p=0.000 n=20
Memory Allocs 75,140,192 (± 0.36%) 84,474,429 (± 0.31%) 🔻+9,334,237 (+12.42%) 83,951,658 85,589,151 p=0.000 n=20
Config Time 0.026s (± 0.79%) 0.026s (± 0.89%) ~ 0.026s 0.027s p=0.501 n=20
Parse Time 0.518s (± 8.15%) 0.491s (± 4.59%) ~ 0.436s 0.643s p=0.417 n=20
Bind Time 0.176s (±10.76%) 0.178s (±10.44%) ~ 0.133s 0.256s p=0.995 n=20
Check Time 7.021s (± 0.59%) 8.232s (± 0.56%) 🔻+1.211s (+17.25%) 8.060s 8.449s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 7.794s (± 0.74%) 8.984s (± 0.70%) 🔻+1.190s (+15.27%) 8.778s 9.236s p=0.000 n=20
social-app - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 1,883,074 1,905,657 +22,583 (+ 1.20%) ~ ~ p=0.000 n=20
Types 1,158,168 1,165,271 +7,103 (+ 0.61%) ~ ~ p=0.000 n=20
Memory Used 966,839k (± 0.01%) 1,075,252k (± 0.01%) 🔻+108,413k (+11.21%) 1,074,815k 1,075,931k p=0.000 n=20
Memory Allocs 13,509,034 (± 0.22%) 17,764,359 (± 0.25%) 🔻+4,255,325 (+31.50%) 17,692,748 18,046,398 p=0.000 n=20
Config Time 0.008s (± 1.82%) 0.008s (± 1.82%) ~ 0.007s 0.008s p=1.000 n=20
Parse Time 0.180s (± 5.61%) 0.179s (± 5.35%) ~ 0.153s 0.246s p=0.857 n=20
Bind Time 0.050s (±11.47%) 0.045s (± 8.92%) ~ 0.039s 0.077s p=0.118 n=20
Check Time 1.548s (± 1.99%) 2.076s (± 1.68%) 🔻+0.529s (+34.15%) 1.949s 2.238s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 1.804s (± 1.92%) 2.326s (± 1.58%) 🔻+0.522s (+28.91%) 2.198s 2.500s p=0.000 n=20
strada-build-src - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 1,184,972 1,186,616 +1,644 (+ 0.14%) ~ ~ p=0.000 n=20
Types 438,959 437,306 -1,653 (- 0.38%) ~ ~ p=0.000 n=20
Memory Used 1,168,821k (± 0.22%) 1,236,045k (± 0.27%) 🔻+67,224k (+ 5.75%) 1,219,892k 1,255,324k p=0.000 n=20
Memory Allocs 47,504,318 (± 0.08%) 54,063,076 (± 0.05%) 🔻+6,558,758 (+13.81%) 53,965,768 54,192,344 p=0.000 n=20
Config Time 0.002s (±15.67%) 0.002s (±12.34%) ~ 0.001s 0.003s p=0.418 n=20
Parse Time 0.140s (± 2.31%) 0.141s (± 1.84%) ~ 0.129s 0.150s p=0.702 n=20
Bind Time 0.000s 0.000s (±208.60%) ~ 0.000s 0.001s p=1.000 n=20
Check Time 0.799s (± 0.52%) 0.942s (± 0.47%) 🔻+0.142s (+17.81%) 0.928s 0.963s p=0.000 n=20
Emit Time 0.139s (± 1.14%) 0.137s (± 0.80%) -0.002s (- 1.47%) 0.131s 0.140s p=0.029 n=20
Total Time 9.331s (± 0.53%) 10.385s (± 0.46%) 🔻+1.055s (+11.30%) 10.236s 10.661s p=0.000 n=20
strada-compiler - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 263,511 263,733 +222 (+ 0.08%) ~ ~ p=0.000 n=20
Types 196,116 195,818 -298 (- 0.15%) ~ ~ p=0.000 n=20
Memory Used 223,533k (± 0.02%) 239,287k (± 0.01%) 🔻+15,754k (+ 7.05%) 239,129k 239,421k p=0.000 n=20
Memory Allocs 2,388,520 (± 0.01%) 2,816,004 (± 0.01%) 🔻+427,484 (+17.90%) 2,815,196 2,816,908 p=0.000 n=20
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Parse Time 0.050s (± 2.96%) 0.051s (± 3.17%) ~ 0.046s 0.058s p=0.930 n=20
Bind Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Check Time 0.368s (± 0.70%) 0.429s (± 0.58%) 🔻+0.061s (+16.54%) 0.422s 0.440s p=0.000 n=20
Emit Time 0.048s (± 5.30%) 0.051s (± 6.28%) ~ 0.042s 0.065s p=0.193 n=20
Total Time 0.494s (± 0.69%) 0.558s (± 0.53%) 🔻+0.064s (+12.93%) 0.548s 0.573s p=0.000 n=20
t3code-server - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 4,350,661 4,283,060 -67,601 (- 1.55%) ~ ~ p=0.000 n=20
Types 3,040,644 3,016,451 -24,193 (- 0.80%) ~ ~ p=0.000 n=20
Memory Used 2,417,400k (± 0.02%) 2,720,850k (± 0.02%) 🔻+303,450k (+12.55%) 2,718,807k 2,724,832k p=0.000 n=20
Memory Allocs 37,173,527 (± 0.11%) 54,364,231 (± 0.06%) 🔻+17,190,703 (+46.24%) 54,296,137 54,552,967 p=0.000 n=20
Config Time 0.003s 0.003s (± 3.54%) ~ 0.002s 0.003s p=1.000 n=20
Parse Time 0.252s (± 1.91%) 0.255s (± 1.67%) ~ 0.241s 0.274s p=0.213 n=20
Bind Time 0.083s (± 9.76%) 0.087s (± 9.44%) ~ 0.073s 0.139s p=0.439 n=20
Check Time 5.974s (± 1.72%) 8.439s (± 1.55%) 🔻+2.465s (+41.25%) 7.958s 8.722s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 6.323s (± 1.67%) 8.795s (± 1.54%) 🔻+2.472s (+39.10%) 8.285s 9.112s p=0.000 n=20
tanstack-router - native
Errors 1 1 ~ ~ ~ p=1.000 n=20
Symbols 571,756 570,271 -1,485 (- 0.26%) ~ ~ p=0.000 n=20
Types 397,689 391,059 -6,630 (- 1.67%) ~ ~ p=0.000 n=20
Memory Used 326,453k (± 0.02%) 360,984k (± 0.02%) 🔻+34,531k (+10.58%) 360,761k 361,214k p=0.000 n=20
Memory Allocs 4,339,125 (± 0.20%) 5,432,212 (± 0.14%) 🔻+1,093,088 (+25.19%) 5,414,800 5,461,739 p=0.000 n=20
Config Time 0.001s 0.001s ~ ~ ~ p=1.000 n=20
Parse Time 0.041s (± 4.12%) 0.040s (± 4.57%) ~ 0.034s 0.047s p=0.488 n=20
Bind Time 0.013s (±11.55%) 0.012s (± 8.91%) ~ 0.010s 0.019s p=0.913 n=20
Check Time 0.498s (± 0.65%) 0.647s (± 0.63%) 🔻+0.149s (+29.93%) 0.631s 0.665s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 0.570s (± 0.80%) 0.719s (± 0.56%) 🔻+0.149s (+26.12%) 0.704s 0.736s p=0.000 n=20
ts-pre-modules - native
Errors 87 87 ~ ~ ~ p=1.000 n=20
Symbols 231,616 231,759 +143 (+ 0.06%) ~ ~ p=0.000 n=20
Types 181,195 181,047 -148 (- 0.08%) ~ ~ p=0.000 n=20
Memory Used 193,023k (± 0.01%) 207,199k (± 0.01%) 🔻+14,176k (+ 7.34%) 207,099k 207,341k p=0.000 n=20
Memory Allocs 1,310,342 (± 0.02%) 1,688,280 (± 0.02%) 🔻+377,938 (+28.84%) 1,687,127 1,689,848 p=0.000 n=20
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Parse Time 0.049s (± 3.79%) 0.049s (± 3.83%) ~ 0.044s 0.058s p=0.692 n=20
Bind Time 0.024s (± 4.74%) 0.023s (± 4.89%) ~ 0.019s 0.027s p=0.138 n=20
Check Time 0.322s (± 0.94%) 0.380s (± 1.11%) 🔻+0.058s (+18.02%) 0.369s 0.405s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 0.401s (± 0.96%) 0.459s (± 1.14%) 🔻+0.058s (+14.36%) 0.441s 0.483s p=0.000 n=20
vscode - native
Errors 11 12 🔻+1 (+ 9.09%) ~ ~ p=0.000 n=20
Symbols 7,581,393 7,409,825 -171,568 (- 2.26%) ~ ~ p=0.000 n=20
Types 4,453,103 4,223,626 🟩-229,477 (- 5.15%) ~ ~ p=0.000 n=20
Memory Used 5,238,870k (± 0.01%) 5,410,766k (± 0.02%) +171,895k (+ 3.28%) 5,407,037k 5,413,361k p=0.000 n=20
Memory Allocs 57,460,124 (± 0.01%) 68,502,245 (± 0.02%) 🔻+11,042,120 (+19.22%) 68,476,208 68,590,077 p=0.000 n=20
Config Time 0.038s (± 1.78%) 0.038s (± 1.20%) ~ 0.036s 0.039s p=0.605 n=20
Parse Time 0.938s (± 1.31%) 0.947s (± 2.19%) ~ 0.844s 1.027s p=0.465 n=20
Bind Time 0.351s (± 7.68%) 0.362s (± 9.33%) ~ 0.292s 0.567s p=0.952 n=20
Check Time 7.945s (± 1.56%) 9.364s (± 1.45%) 🔻+1.419s (+17.86%) 8.645s 9.814s p=0.000 n=20
Emit Time 2.970s (± 5.87%) 3.369s (± 4.07%) 🔻+0.399s (+13.45%) 2.990s 4.186s p=0.000 n=20
Total Time 12.303s (± 1.97%) 14.143s (± 1.64%) 🔻+1.840s (+14.96%) 13.304s 15.144s p=0.000 n=20
webpack - native
Errors 612 620 +8 (+ 1.31%) ~ ~ p=0.000 n=20
Symbols 925,190 1,082,647 🔻+157,457 (+17.02%) ~ ~ p=0.000 n=20
Types 643,199 2,133,243 🔻+1,490,044 (+231.66%) ~ ~ p=0.000 n=20
Memory Used 697,711k (± 0.02%) 1,371,751k (± 0.01%) 🔻+674,040k (+96.61%) 1,371,408k 1,372,322k p=0.000 n=20
Memory Allocs 6,473,690 (± 0.05%) 47,254,840 (± 0.01%) 🔻+40,781,151 (+629.95%) 47,247,152 47,271,226 p=0.000 n=20
Config Time 0.004s 0.004s ~ ~ ~ p=1.000 n=20
Parse Time 0.143s (± 3.09%) 0.147s (± 3.62%) ~ 0.126s 0.170s p=0.298 n=20
Bind Time 0.049s (±12.18%) 0.046s (± 9.74%) ~ 0.039s 0.072s p=0.825 n=20
Check Time 0.982s (± 0.54%) 72.903s (± 1.96%) 🔻+71.921s (+7,322.82%) 66.626s 79.005s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 1.201s (± 0.76%) 73.124s (± 1.96%) 🔻+71.923s (+5,988.87%) 66.840s 79.236s p=0.000 n=20
xstate-main - native
Errors 0 1 🔻+1 (+ ∞%) ~ ~ p=0.000 n=20
Symbols 640,490 856,593 🔻+216,103 (+33.74%) ~ ~ p=0.000 n=20
Types 387,984 457,702 🔻+69,718 (+17.97%) ~ ~ p=0.000 n=20
Memory Used 350,159k (± 0.02%) 455,995k (± 0.01%) 🔻+105,835k (+30.22%) 455,690k 456,211k p=0.000 n=20
Memory Allocs 3,968,869 (± 0.10%) 11,780,642 (± 0.03%) 🔻+7,811,773 (+196.83%) 11,766,097 11,790,998 p=0.000 n=20
Config Time 0.001s 0.001s ~ ~ ~ p=1.000 n=20
Parse Time 0.064s (± 4.85%) 0.064s (± 5.34%) ~ 0.054s 0.082s p=0.835 n=20
Bind Time 0.020s (±11.79%) 0.021s (± 9.16%) ~ 0.017s 0.032s p=0.439 n=20
Check Time 0.406s (± 1.92%) 0.909s (± 1.89%) 🔻+0.503s (+123.95%) 0.875s 1.034s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 0.496s (± 1.97%) 1.000s (± 2.01%) 🔻+0.504s (+101.72%) 0.962s 1.143s p=0.000 n=20
System info unknown
Hosts
  • native
Scenarios
  • Compiler-Unions - native
  • angular-1 - native
  • arktype - native
  • class-transformer - native
  • effect - native
  • mui-docs - native
  • sentry - native
  • social-app - native
  • strada-build-src - native
  • strada-compiler - native
  • t3code-server - native
  • tanstack-router - native
  • ts-pre-modules - native
  • vscode - native
  • webpack - native
  • xstate-main - native
Benchmark Name Iterations
Current pr 20
Baseline baseline 20

Developer Information:

Download Benchmarks

@jakebailey

Copy link
Copy Markdown
Member Author

Well, that's a little bleak.

@jakebailey

Copy link
Copy Markdown
Member Author

Not sure why top400 didn't come back either

Checker results should not depend on which files were checked first,
or on which types an editor happened to ask for before diagnostics
were requested. Tests had no way to show such dependence, so fixes for
it could only be described, not demonstrated.

The harness-only checkOrder option queries the checker in a different
order: files in reverse, each file in its own program, or every
expression's type and symbol before any diagnostics. Listing several
orders produces a baseline for each, so order dependence shows up as
differing baselines.
The checkOrder option only tries a few fixed orders over whole files,
but results can depend on which single query a checker answers first,
as when an editor asks for the type of one node before anything else
is checked. Such dependence is hard to find by hand and easy to
reintroduce.

With TS_CHECK_ORDER_FUZZ=n, each test is checked again n times in fresh
programs that first answer a seeded random selection of type, symbol,
and diagnostics queries. Any change in diagnostics or in the type or
symbol of a node fails the test with the seed and a minimized list of
queries that reproduces it. The fuzzer is off by default, so it does
not slow the normal suite.
Asking the checker for types and symbols before requesting diagnostics
changes the diagnostics and types reported for these tests. Recording
them in that order too shows which later changes make the results
independent of what was asked first.
These tests exercise checker results that can depend on the order in
which declarations, files, and relations are checked: variance
measurement cycles, relation caching under recursion and depth
limits, instantiation limits, contextual re-checks, and deferred type
reference cycles.

Recording the current baselines makes later changes to make checking
order independent show up as reviewable baseline diffs.
Variance measured through a cycle of recursive references used to
depend on which type in the cycle was measured first, so reordering
declarations or assignments changed which assignments were errors.
These cases cover cycles through interfaces, type aliases, callbacks,
and nested compositions, alongside annotated and structurally measured
types whose results should not change.
The errors for a getter and setter that disagree on abstractness or
accessibility were reported on both names by whichever accessor was
checked first, guarded by a flag on the getter. When that happened
during a query rather than a full check, the flag was set without the
errors being reported. Since the errors only depend on the modifiers,
each accessor now reports the error on its own name with no state,
which yields the same set of errors in any order.
The type parameters of a type alias are resolved along with its
declared type, but some readers took them from the links without
resolving the declared type first, relying on it having been resolved
earlier. Reading them through an accessor that resolves the declared
type makes the dependency explicit, so the result does not depend on
what was resolved before.
checkAssertion runs in several check modes, such as when a call is
first checked without its context sensitive arguments, and each run
overwrote the operand type kept for the deferred comparability check.
That check used whichever was stored last, so its result depended on
the order in which the assertion was checked.

The deferred check now uses the cached normal type of the operand. The
assertion itself only needs the operand type for `as const`, and the
operand of a non-const assertion is contextually typed by the asserted
type alone, so in any check mode the assertion computes the cached
type the deferred check will read, with inference for an enclosing
call hidden from the operand. This is the result the deferred check
would produce on its own, and checks each operand once rather than
again with fresh flow analysis in the deferred check.
The type of a destructured parameter's binding elements depended on
whether the parameter's type happened to be cached already. For
example, in non-strict mode

    (({ [a()?.d]: c = "" }) => {})();

reported TS2537 when 'c' was queried before the IIFE call resolved
the parameter (its declared type is the undefined widening type),
but not otherwise. Conversely, in

    f7({ a: {} });
    function f7({ a: { x = 0, y = 0 } } = { a: {} }) {}

calling f7 first made 'x' and 'y' errors of type any.

Make the choice depend only on the declaration. Parameters of
context-sensitive functions take their type from contextual
assignment, so ask for the parameter's type. Everything else uses
the type derived from the declaration, as it did when nothing was
cached. Asking for the parameter's type unconditionally instead
introduces circularities in patterns whose initializers reference
sibling elements.
Asking for the type of a context-sensitive function's parameter can
resolve the enclosing call, which assigns the parameter its
contextual type from the inference in progress. The first query
nevertheless returned the type it computed itself from the final
signature, while every later query returned the assigned type. In

    declare function fun<T>(g: (x: T) => T, h: (y: T) => T, x: T): T;
    fun((Math.random() < 0.5 ? (x => x) : (x => undefined)), x => x, 10);

the last 'x' was number when the call was checked first, but any
when 'x' was queried first and its result was cached.

Return the assigned type whenever one exists, so that the first
query agrees with the rest, as the original comment intended.
When resolving a function expression's members reaches the function
again through its enclosing call, the contextual check sees an empty
signature list and gives up, yet it left the node marked as context
checked. Whichever query got there first therefore decided whether the
function's parameters were ever contextually typed, and diagnostics
such as implicit any errors could be lost depending on check order.

Leave the node unchecked in that case so a later request performs the
check, and have the deferred function check request it, so that the
check is performed at least once whichever query reached it first.
Generic calls nested in the arguments of other generic calls, or in
context sensitive functions passed to them, depend on the enclosing
call for their contextual type and parameter types, and the enclosing
call infers from them in turn. When the inner call was queried first,
it was already marked as resolving by the time its contextual type
resolved the enclosing call, so the enclosing inference saw a
placeholder and both calls cached results that a check in source order
never produces.

Computing the contextual type of a call nested in an argument of an
enclosing call before resolving it resolves the enclosing call first,
as source order does. Other contexts are not resolved ahead of time,
since computing them may evaluate expressions that checking does not,
such as the target of a destructuring assignment.
Asking for the symbol of a property access that hits an index signature
stored the index symbol as the access's resolved symbol. Checking a
delete expression reads that link to decide whether the operand must be
optional, so a prior symbol query turned `delete a.x` on an index
signature into an error that a plain check does not report.

The type of the index symbol at such an access, which hovers show, is
found by comparing it to the symbol the access resolved to, so that
comparison now looks the index symbol up again rather than reading it
from links.
A context-sensitive function's signature takes the type parameters of
a generic contextual signature, and its parameters their types, when
the function is contextually checked. Anything reading the signature
before then saw it incomplete and cached what it derived from it. Type
aliases in the body read the type parameters as outer type parameters,
so querying such an alias first resolved its conditional types eagerly.
In

    declare function f(fun: <T>(t: T) => void): void
    f(function self(t) {
        const s = self;
        type P = Parameters<typeof s>;
    });

P was [t: unknown] when the call was checked first, but [t: T] when P
was asked for first, since s then had the uncontextual signature.

Split out assigning the contextual parameter types, which completes
the signature, from the rest of the contextual check, and have every
way to obtain the signature request it: the type of the function's
symbol, before anything resolves its members, and the signature of its
declaration. The rest of the check, inferring the return type and
checking the signature, remains for checking the function itself.

Contextual typing can reach the enclosing call while the signature is
being created, so keep the signature created there rather than replace
the one that was contextually typed. This also makes it unnecessary to
leave a function unchecked when its members are found being resolved.
A single signature type produced by higher order inference is
instantiated with the full mapper combined in, since its signature can
reference type parameters other than the outer type parameters of its
declaration. The instantiation cache was keyed only by the mapped outer
type parameters, so two instantiations differing in another type
parameter (here the this type) shared whichever result was computed
first. Which property access was checked first therefore decided the
type of both, and checking `outer.log` gave it the type of `inner.log`
contrary to the test's expectation.
Explaining why a name failed to resolve looks up other symbols, for
example to find a spelling suggestion, and that can resolve aliases.
When the failed name was the target of an alias, the suggestion lookup
re-entered the alias being resolved, or skipped it, depending on which
aliases were already in progress. In declarationEmitUnknownImport that
decided whether two "Circular definition of import alias" errors were
reported: they appeared when the import was checked first, and not
when the export specifier was resolved first.

Defer the explanation until no resolution is in progress, so it only
observes finished results. The circularity errors that were artifacts
of the suggestion lookup are no longer reported.
When one reference hit the flow analysis depth limit, flow analysis
was disabled for every later reference in the same function or module
body. The type of a reference then depended on whether another
reference in the body had been analyzed before it.

Each reference now gives up only when its own analysis hits the limit,
so its type is the one it would get if it were analyzed first.
This is a port of Anders Hejlsberg's "Allow accessing named declared
members during a type's resolution", which is expected to land in main
first, and replaces this branch's earlier approach to the same problem.

Resolving the members of a class or interface reference resolves those
of its base types with this bound to the reference, and a this-dependent
member of a base may need a named member of the reference itself.
Previously this branch installed a layout of only the declared members
while inherited ones were resolved, then replaced it with the full
layout, so a member read during resolution could be a different symbol
from the final one.

Instead, as in that PR, the type is pushed on a stack of types whose
layout is being built, and a named property lookup on it finds the
declared member instantiated by its mapper, or else the member of a base
type. Members found that way are written into the property slots of the
final layout, so a property is the same symbol however it is read.
Nothing partial is ever installed on the type. The lookup also observes
the resolution in progress, so results derived from it are discarded
with the cycle like any other.

Also as in that PR, class and interface types are no longer treated as
string index signature only types when simplifying indexed accesses, as
whether they are depends on whether their members were resolved yet.

keyofGenericExtendingClassDoubleLayer now reports the infinitely
circular instantiation error at both places that reach it, where main
reports it once and Strada not at all: keyof needs every property, which
a named lookup cannot provide. This may be worth revisiting.
The flag marked members whose resolution was in progress, so that the
fast path would not read members published before they were complete.
That duplicates what the resolution stack already records: the
resolution of the members is in Checker.resolving, or shadowed by a
cycle yield. The flag also let a type carry a "resolved" bit for
members that were not yet final, which is the install-then-replace
pattern Anders Hejlsberg objected to in the review of "Allow accessing
named declared members during a type's resolution".

ObjectFlagsMembersResolved now means only that the outermost
resolution of the members completed. Whether partial members are
available to a computation re-entering the resolution is recorded on
the resolution itself (membersPublished), and a re-entry finds it even
when hidden by a cycle yield. Members are marked published before their
properties are listed, since listing them may re-enter the resolution,
which then sees the members as it did before.

Types created with their members, rather than resolved, still set the
flag directly through setStructuredTypeMembers; resolvers use
setStructuredTypeData or publishStructuredTypeMembers.
@jakebailey

Copy link
Copy Markdown
Member Author

TypeScript Bot (@typescript-bot) test it

@typescript-automation

typescript-automation Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Starting jobs; this comment will be updated as builds start and complete.

Command Status Results
test top400 ✅ Started 👀 Results
user test this ✅ Started 👀 Results
run dt ✅ Started 👀 Results
perf test this faster ✅ Started 👀 Results

@typescript-automation

Copy link
Copy Markdown
Contributor

Hey Jake Bailey (@jakebailey), the results of running the DT tests are ready.

There were interesting changes:

Branch only errors: d3-selection

Package: d3-selection

Branch error:

Project scope: tsconfig.json

Error: types/d3-selection/d3-selection-tests.ts:1502:9
TypeScript@local compile error TS2769:
No overload matches this call.
The last overload gave the following error.
Argument of type '(enter: Selection<EnterElement, number, HTMLElement, unknown>) => TransitionLike<HTMLParagraphElement, number>' is not assignable to parameter of type 'string | ((elem: Selection<EnterElement, number, HTMLElement, unknown>) => Selection<BaseType, number, HTMLElement, unknown> | TransitionLike<...>)'.
Type '(enter: Selection<EnterElement, number, HTMLElement, unknown>) => TransitionLike<HTMLParagraphElement, number>' is not assignable to type '(elem: Selection<EnterElement, number, HTMLElement, unknown>) => Selection<BaseType, number, HTMLElement, unknown> | TransitionLike<...>'.
Type 'TransitionLike<HTMLParagraphElement, number>' is not assignable to type 'Selection<BaseType, number, HTMLElement, unknown> | TransitionLike<HTMLElement, number>'.
Type 'TransitionLike<HTMLParagraphElement, number>' is not assignable to type 'TransitionLike<HTMLElement, number>'.
The types returned by 'selection().merge' are incompatible between these types.
Type '(other: Selection<HTMLParagraphElement, number, any, any> | TransitionLike<HTMLParagraphElement, number>) => Selection<...>' is not assignable to type '(other: Selection<HTMLElement, number, any, any> | TransitionLike<HTMLElement, number>) => Selection<HTMLElement, number, any, any>'.
Types of parameters 'other' and 'other' are incompatible.
Type 'Selection<HTMLElement, number, any, any> | TransitionLike<HTMLElement, number>' is not assignable to type 'Selection<HTMLParagraphElement, number, any, any> | TransitionLike<HTMLParagraphElement, number>'.
Type 'Selection<HTMLElement, number, any, any>' is not assignable to type 'Selection<HTMLParagraphElement, number, any, any> | TransitionLike<HTMLParagraphElement, number>'.
Type 'Selection<HTMLElement, number, any, any>' is not assignable to type 'Selection<HTMLParagraphElement, number, any, any>'.
Types of property 'select' are incompatible.
Type '{ <DescElement extends BaseType>(selector: string): import("/mnt/vss/_work/1/s/DefinitelyTyped/types/d3-selection/index").Selection<DescElement, number, any, any>; <DescElement extends BaseType>(selector: null): import("/mnt/vss/_work/1/s/DefinitelyTyped/types/d3-selection/index").Selection<...>; <DescElement extend...' is not assignable to type '{ <DescElement extends BaseType>(selector: string): import("/mnt/vss/_work/1/s/DefinitelyTyped/types/d3-selection/index").Selection<DescElement, number, any, any>; <DescElement extends BaseType>(selector: null): import("/mnt/vss/_work/1/s/DefinitelyTyped/types/d3-selection/index").Selection<...>; <DescElement extend...'. Two different types with this name exist, but they are unrelated.
Types of parameters 'selector' and 'selector' are incompatible.
Types of parameters 'groups' and 'groups' are incompatible.
Type 'HTMLElement[] | ArrayLike<HTMLElement>' is not assignable to type 'HTMLParagraphElement[] | ArrayLike<HTMLParagraphElement>'.
Type 'HTMLElement[]' is not assignable to type 'HTMLParagraphElement[] | ArrayLike<HTMLParagraphElement>'.
Type 'HTMLElement[]' is not assignable to type 'HTMLParagraphElement[]'.
Property 'align' is missing in type 'HTMLElement' but required in type 'HTMLParagraphElement'.
    at combineErrorsAndWarnings (/mnt/vss/_work/1/s/DefinitelyTyped-tools/packages/dtslint/dist/index.js:200:28)
    at runTests (/mnt/vss/_work/1/s/DefinitelyTyped-tools/packages/dtslint/dist/index.js:192:20)
Branch only errors: react-relay

Package: react-relay

Branch error:

Project scope: tsconfig.json

Error: types/react-relay/test/relay-hooks-tests.tsx:987:13
TypeScript@local compile error TS2344:
Type '{ mainPanelA?: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params> | undefined; mainPanelB?: EntryPoint<...> | undefined; }' does not satisfy the constraint 'Record<string, EntryPoint<any, any> | undefined>'.
Property 'mainPanelA' is incompatible with index signature.
Type 'EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>' is not assignable to type 'InternalEntryPointRepresentation<any, Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>'.
Types of property 'root' are incompatible.
Type 'JSResourceReference<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>>' is not assignable to type 'JSResourceReference<EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>>'.
Type 'EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>' is not assignable to type 'EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>'.
Type 'ComponentClass<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>'.
Type 'ComponentClass<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'ComponentClass<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any>'.
Types of property 'getDerivedStateFromProps' are incompatible.
Type 'GetDerivedStateFromProps<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any> | undefined' is not assignable to type 'GetDerivedStateFromProps<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any> | undefined'.
Type 'GetDerivedStateFromProps<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'GetDerivedStateFromProps<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any>'.
Types of parameters 'nextProps' and 'nextProps' are incompatible.
Type 'Readonly<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>>' is not assignable to type 'Readonly<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>>'.
Types of property 'extraProps' are incompatible.
Type '{} | null' is not assignable to type '{}'.
Type 'null' is not assignable to type '{}'.

types/react-relay/test/relay-hooks-tests.tsx:1023:13
TypeScript@local compile error TS2322:
Type '(params: { route: string; }) => { entryPoints: { mainPanelA: { entryPoint: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>; entryPointParams: ...; }; mainPanelB?: undefined; } | ...; queries: ...; extraProps: ...; }' is not assignable to type '(entryPointParams: { route: string; }) => PreloadProps<{ route: string; }, {}, Record<string, EntryPoint<any, any> | undefined>, { foo: "bar"; }>'.
Type '{ entryPoints: { mainPanelA: { entryPoint: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>; entryPointParams: { slug: string; }; }; mainPanelB?: undefined; } | ...; queries: {}; extraProps: ...; }' is not assignable to type 'PreloadProps<{ route: string; }, {}, Record<string, EntryPoint<any, any> | undefined>, { foo: "bar"; }>'.
Types of property 'entryPoints' are incompatible.
Type '{ mainPanelA: { entryPoint: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>; entryPointParams: ...; }; mainPanelB?: undefined; } | ...' is not assignable to type 'ThinNestedEntryPointParamsObject<Record<string, EntryPoint<any, any> | undefined>> | undefined'.
Type '{ mainPanelA: { entryPoint: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>; entryPointParams: { slug: string; }; }; mainPanelB?: undefined; }' is not assignable to type 'ThinNestedEntryPointParamsObject<Record<string, EntryPoint<any, any> | undefined>>'.
Property 'mainPanelA' is incompatible with index signature.
Type '{ entryPoint: EntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>, Params>; entryPointParams: { slug: string; }; }' is not assignable to type 'ThinNestedEntryPointParams<EntryPoint<any, any> | undefined>'.
The types of 'entryPoint.root' are incompatible between these types.
Type 'JSResourceReference<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>>' is not assignable to type 'JSResourceReference<EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>>'.
Type 'EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>' is not assignable to type 'EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>'.
Type 'ComponentClass<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'EntryPointComponent<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>'.
Type 'ComponentClass<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'ComponentClass<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any>'.
Types of property 'getDerivedStateFromProps' are incompatible.
Type 'GetDerivedStateFromProps<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any> | undefined' is not assignable to type 'GetDerivedStateFromProps<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any> | undefined'.
Type 'GetDerivedStateFromProps<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>, any>' is not assignable to type 'GetDerivedStateFromProps<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>, any>'.
Types of parameters 'nextProps' and 'nextProps' are incompatible.
Type 'Readonly<EntryPointProps<Record<string, OperationType>, Record<string, EntryPoint<any, any> | undefined>, {}, {} | null>>' is not assignable to type 'Readonly<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>>'.
Types of property 'extraProps' are incompatible.
Type '{} | null' is not assignable to type '{}'.
Type 'null' is not assignable to type '{}'.

types/react-relay/test/relay-hooks-tests.tsx:1054:15
TypeScript@local compile error TS2322:
Type 'Readonly<{ dispose: DisposeFn; entryPoints: { [x: string]: Readonly<...>; }; extraProps: {} | null; getComponent: () => any; isDisposed: boolean; queries: { [x: string]: PreloadedQuery<OperationType, Record<...>>; }; rootModuleID: string; }>' is not assignable to type 'PreloadedEntryPoint<EntryPointComponent<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }>> | undefined'.
Type 'Readonly<{ dispose: DisposeFn; entryPoints: { [x: string]: Readonly<...>; }; extraProps: {} | null; getComponent: () => any; isDisposed: boolean; queries: { [x: string]: PreloadedQuery<OperationType, Record<...>>; }; rootModuleID: string; }>' is not assignable to type 'Readonly<{ dispose: DisposeFn; entryPoints: {}; extraProps: {}; getComponent: () => FunctionComponent<EntryPointProps<{ someQueryRef: SomeQuery; }, {}, { onClick: () => void; }, {}>>; isDisposed: boolean; queries: ...; rootModuleID: string; }>'.
Types of property 'extraProps' are incompatible.
Type '{} | null' is not assignable to type '{}'.
Type 'null' is not assignable to type '{}'.
    at combineErrorsAndWarnings (/mnt/vss/_work/1/s/DefinitelyTyped-tools/packages/dtslint/dist/index.js:200:28)
    at runTests (/mnt/vss/_work/1/s/DefinitelyTyped-tools/packages/dtslint/dist/index.js:192:20)

Full output in the log.

@typescript-automation

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the user tests with tsc comparing baseline and pr:

Something interesting changed - please have a look.

Details

effect

packages/tools/ai-docgen/tsconfig.json

uglify-js

/mnt/vss/work/1/s/ts_downloads//m/uglify-js/tsconfig.json

  • [NEW] error TS2339: Property 'last_ref' does not exist on type 'never'.
    • /mnt/vss/work/1/s/ts_downloads//m/uglify-js/node_modules/uglify-js/lib/compress.js(2544,35)
  • [MISSING] error TS2322: Type 'false' is not assignable to type 'never'.
    • /mnt/vss/work/1/s/ts_downloads//m/uglify-js/node_modules/uglify-js/lib/compress.js(2544,25)

webpack

tsconfig.json

  • [NEW] error TS2345: Argument of type '[unknown]' is not assignable to parameter of type '[] | [boldQuantity?: boolean | undefined] | [direction?: "child" | "parent" | "sibling" | undefined] | [oversize?: boolean | undefined]'.
  • [NEW] error TS2345: Argument of type 'string | number | boolean | Type' is not assignable to parameter of type 'Type'.

tsconfig.types.json

  • [NEW] error TS2345: Argument of type '[unknown]' is not assignable to parameter of type '[] | [boldQuantity?: boolean | undefined] | [direction?: "child" | "parent" | "sibling" | undefined] | [oversize?: boolean | undefined]'.

tsconfig.types.test.json

@typescript-automation

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey)
The results of the perf run you requested are in!

Here they are:

tsc

Comparison Report - baseline..pr
Metric baseline pr Delta Best Worst p-value
Compiler-Unions - native
Errors 41 41 ~ ~ ~ p=1.000 n=20
Symbols 88,466 88,464 -2 (- 0.00%) ~ ~ p=0.000 n=20
Types 79,607 79,569 -38 (- 0.05%) ~ ~ p=0.000 n=20
Memory Used 107,502k (± 0.02%) 109,575k (± 0.03%) +2,072k (+ 1.93%) 109,454k 109,693k p=0.000 n=20
Memory Allocs 1,262,200 (± 0.01%) 1,297,565 (± 0.01%) +35,365 (+ 2.80%) 1,297,305 1,297,943 p=0.000 n=20
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Parse Time 0.023s (± 2.64%) 0.023s (± 2.83%) ~ 0.019s 0.025s p=0.966 n=20
Bind Time 0.008s (± 3.69%) 0.008s (± 6.64%) ~ 0.007s 0.010s p=0.166 n=20
Check Time 0.207s (± 0.69%) 0.226s (± 0.59%) 🔻+0.018s (+ 8.81%) 0.220s 0.230s p=0.000 n=20
Emit Time 0.133s (± 1.70%) 0.135s (± 1.13%) +0.002s (+ 1.58%) 0.131s 0.143s p=0.016 n=20
Total Time 0.374s (± 0.58%) 0.395s (± 0.57%) 🔻+0.020s (+ 5.44%) 0.384s 0.408s p=0.000 n=20
angular-1 - native
Errors 3 3 ~ ~ ~ p=1.000 n=20
Symbols 586,553 580,825 -5,728 (- 0.98%) ~ ~ p=0.000 n=20
Types 241,682 238,891 -2,791 (- 1.15%) ~ ~ p=0.000 n=20
Memory Used 519,802k (± 0.02%) 834,242k (± 0.01%) 🔻+314,440k (+60.49%) 833,968k 834,507k p=0.000 n=20
Memory Allocs 7,794,702 (± 0.17%) 14,362,449 (± 0.04%) 🔻+6,567,747 (+84.26%) 14,355,366 14,408,139 p=0.000 n=20
Config Time 0.009s 0.009s ~ ~ ~ p=1.000 n=20
Parse Time 0.122s (± 2.70%) 0.117s (± 2.28%) ~ 0.107s 0.125s p=0.089 n=20
Bind Time 0.041s (± 7.76%) 0.045s (±11.91%) ~ 0.037s 0.070s p=0.258 n=20
Check Time 0s 0s ~ ~ ~ p=1.000 n=20
Emit Time 0.646s (± 1.12%) 1.135s (± 0.81%) 🔻+0.489s (+75.76%) 1.107s 1.177s p=0.000 n=20
Total Time 0.828s (± 0.89%) 1.316s (± 0.88%) 🔻+0.488s (+58.88%) 1.283s 1.352s p=0.000 n=20
arktype - native
Errors 0 4 🔻+4 (+ ∞%) ~ ~ p=0.000 n=20
Symbols 685,920 693,349 +7,429 (+ 1.08%) ~ ~ p=0.000 n=20
Types 939,467 921,165 -18,302 (- 1.95%) ~ ~ p=0.000 n=20
Memory Used 495,347k (± 0.01%) 514,865k (± 0.01%) +19,518k (+ 3.94%) 514,631k 515,252k p=0.000 n=20
Memory Allocs 12,062,425 (± 0.01%) 12,433,424 (± 0.01%) +371,000 (+ 3.08%) 12,430,754 12,443,969 p=0.000 n=20
Config Time 0.001s 0.001s ~ ~ ~ p=1.000 n=20
Parse Time 0.041s (± 3.84%) 0.041s (± 3.23%) ~ 0.036s 0.047s p=0.421 n=20
Bind Time 0.014s (±10.02%) 0.013s (± 8.35%) ~ 0.011s 0.020s p=0.711 n=20
Check Time 0.877s (± 0.77%) 1.029s (± 0.47%) 🔻+0.152s (+17.30%) 1.011s 1.050s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 0.960s (± 0.51%) 1.086s (± 0.53%) 🔻+0.126s (+13.07%) 1.065s 1.106s p=0.000 n=20
class-transformer - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 45,376 45,319 -57 (- 0.13%) ~ ~ p=0.000 n=20
Types 7,573 7,219 🟩-354 (- 4.67%) ~ ~ p=0.000 n=20
Memory Used 27,890k (± 0.02%) 28,232k (± 0.02%) +342k (+ 1.23%) 28,209k 28,254k p=0.000 n=20
Memory Allocs 248,432 (± 0.05%) 253,295 (± 0.05%) +4,864 (+ 1.96%) 252,849 253,751 p=0.000 n=20
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Parse Time 0.011s (± 3.83%) 0.011s (± 4.67%) ~ 0.008s 0.013s p=0.149 n=20
Bind Time 0.003s (±12.18%) 0.003s (± 9.29%) ~ 0.003s 0.005s p=0.861 n=20
Check Time 0.008s (± 6.42%) 0.009s (± 5.45%) 🔻+0.001s (+12.50%) 0.007s 0.010s p=0.004 n=20
Emit Time 0.008s (± 7.47%) 0.008s (± 5.04%) ~ 0.007s 0.009s p=0.967 n=20
Total Time 0.031s (± 2.17%) 0.032s (± 1.79%) +0.001s (+ 3.43%) 0.029s 0.034s p=0.025 n=20
effect - native
Errors 12 20 🔻+8 (+66.67%) ~ ~ p=0.000 n=20
Symbols 1,235,115 1,232,770 -2,345 (- 0.19%) ~ ~ p=0.000 n=20
Types 894,113 887,221 -6,892 (- 0.77%) ~ ~ p=0.000 n=20
Memory Used 949,874k (± 0.02%) 969,975k (± 0.02%) +20,101k (+ 2.12%) 969,328k 970,741k p=0.000 n=20
Memory Allocs 12,635,940 (± 0.02%) 13,075,043 (± 0.07%) +439,103 (+ 3.48%) 13,063,558 13,161,490 p=0.000 n=20
Config Time 0.002s 0.002s ~ ~ ~ p=1.000 n=20
Parse Time 0.157s (± 2.99%) 0.156s (± 1.85%) ~ 0.144s 0.166s p=0.542 n=20
Bind Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Check Time 0.906s (± 1.79%) 1.018s (± 1.38%) 🔻+0.112s (+12.31%) 0.982s 1.094s p=0.000 n=20
Emit Time 0.509s (± 2.99%) 0.519s (± 2.14%) ~ 0.490s 0.578s p=0.351 n=20
Total Time 1.667s (± 1.81%) 1.786s (± 1.29%) 🔻+0.119s (+ 7.12%) 1.704s 1.881s p=0.000 n=20
mui-docs - native
Errors 11,405 11,405 ~ ~ ~ p=1.000 n=20
Symbols 3,784,019 3,713,239 -70,780 (- 1.87%) ~ ~ p=0.000 n=20
Types 1,355,974 1,262,950 🟩-93,024 (- 6.86%) ~ ~ p=0.000 n=20
Memory Used 1,768,756k (± 0.09%) 1,906,500k (± 0.05%) 🔻+137,744k (+ 7.79%) 1,902,431k 1,911,427k p=0.000 n=20
Memory Allocs 25,747,582 (± 0.14%) 25,500,783 (± 0.13%) -246,800 (- 0.96%) 25,399,458 25,639,157 p=0.000 n=20
Config Time 0.008s 0.008s ~ ~ ~ p=1.000 n=20
Parse Time 0.281s (± 2.19%) 0.280s (± 2.28%) ~ 0.235s 0.302s p=0.713 n=20
Bind Time 0.001s 0.001s ~ ~ ~ p=1.000 n=20
Check Time 2.927s (± 0.51%) 3.071s (± 0.36%) 🔻+0.144s (+ 4.90%) 3.038s 3.116s p=0.000 n=20
Emit Time 0.238s (± 1.14%) 0.240s (± 1.06%) ~ 0.230s 0.247s p=0.303 n=20
Total Time 3.934s (± 0.42%) 4.075s (± 0.27%) +0.141s (+ 3.59%) 4.011s 4.113s p=0.000 n=20
sentry - native
Errors 2 2 ~ ~ ~ p=1.000 n=20
Symbols 4,793,245 4,693,680 -99,565 (- 2.08%) ~ ~ p=0.000 n=20
Types 2,606,905 2,496,340 🟩-110,565 (- 4.24%) ~ ~ p=0.000 n=20
Memory Used 2,846,746k (± 0.03%) 2,973,537k (± 0.03%) 🔻+126,791k (+ 4.45%) 2,969,722k 2,976,277k p=0.000 n=20
Memory Allocs 75,043,909 (± 0.25%) 75,318,966 (± 0.17%) +275,056 (+ 0.37%) 74,959,266 75,940,441 p=0.001 n=20
Config Time 0.025s (± 0.92%) 0.025s (± 1.04%) ~ 0.024s 0.026s p=0.624 n=20
Parse Time 0.467s (± 4.44%) 0.460s (± 3.46%) ~ 0.420s 0.532s p=0.482 n=20
Bind Time 0.149s (±11.33%) 0.166s (± 9.32%) ~ 0.129s 0.215s p=0.062 n=20
Check Time 6.522s (± 0.78%) 7.012s (± 0.92%) 🔻+0.489s (+ 7.50%) 6.852s 7.356s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 7.210s (± 0.73%) 7.718s (± 0.75%) 🔻+0.508s (+ 7.05%) 7.563s 8.016s p=0.000 n=20
social-app - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 1,883,074 1,883,995 +921 (+ 0.05%) ~ ~ p=0.000 n=20
Types 1,158,168 1,148,768 -9,400 (- 0.81%) ~ ~ p=0.000 n=20
Memory Used 966,922k (± 0.01%) 1,009,494k (± 0.01%) 🔻+42,572k (+ 4.40%) 1,008,813k 1,010,239k p=0.000 n=20
Memory Allocs 13,521,383 (± 0.26%) 13,801,133 (± 0.27%) +279,750 (+ 2.07%) 13,744,905 14,101,853 p=0.000 n=20
Config Time 0.007s (± 2.39%) 0.007s (± 2.66%) ~ 0.007s 0.008s p=1.000 n=20
Parse Time 0.155s (± 2.40%) 0.157s (± 3.65%) ~ 0.141s 0.198s p=0.578 n=20
Bind Time 0.041s (± 8.64%) 0.043s (± 9.52%) ~ 0.035s 0.060s p=0.632 n=20
Check Time 1.407s (± 0.93%) 1.593s (± 0.66%) 🔻+0.186s (+13.24%) 1.566s 1.648s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 1.628s (± 0.76%) 1.818s (± 0.68%) 🔻+0.190s (+11.68%) 1.785s 1.874s p=0.000 n=20
strada-build-src - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 1,184,972 1,186,601 +1,629 (+ 0.14%) ~ ~ p=0.000 n=20
Types 438,959 437,226 -1,733 (- 0.39%) ~ ~ p=0.000 n=20
Memory Used 1,169,503k (± 0.25%) 1,179,387k (± 0.33%) +9,884k (+ 0.85%) 1,168,695k 1,204,029k p=0.000 n=20
Memory Allocs 47,586,666 (± 0.08%) 49,003,892 (± 0.10%) +1,417,226 (+ 2.98%) 48,858,952 49,278,060 p=0.000 n=20
Config Time 0.002s (±10.63%) 0.002s (±13.83%) ~ 0.001s 0.002s p=0.480 n=20
Parse Time 0.138s (± 1.08%) 0.137s (± 1.98%) ~ 0.130s 0.153s p=0.175 n=20
Bind Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Check Time 0.788s (± 0.55%) 0.864s (± 0.65%) 🔻+0.076s (+ 9.61%) 0.849s 0.892s p=0.000 n=20
Emit Time 0.139s (± 1.73%) 0.137s (± 1.64%) ~ 0.131s 0.153s p=0.089 n=20
Total Time 9.191s (± 0.49%) 9.824s (± 0.73%) 🔻+0.633s (+ 6.89%) 9.595s 10.099s p=0.000 n=20
strada-compiler - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 263,511 263,733 +222 (+ 0.08%) ~ ~ p=0.000 n=20
Types 196,116 195,818 -298 (- 0.15%) ~ ~ p=0.000 n=20
Memory Used 223,552k (± 0.02%) 230,107k (± 0.02%) +6,555k (+ 2.93%) 229,830k 230,220k p=0.000 n=20
Memory Allocs 2,389,670 (± 0.01%) 2,495,679 (± 0.01%) 🔻+106,009 (+ 4.44%) 2,494,328 2,497,196 p=0.000 n=20
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Parse Time 0.049s (± 3.41%) 0.049s (± 2.72%) ~ 0.044s 0.054s p=0.671 n=20
Bind Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Check Time 0.405s (± 0.37%) 0.445s (± 0.84%) 🔻+0.041s (+10.04%) 0.429s 0.468s p=0.000 n=20
Emit Time 0.051s (± 6.07%) 0.054s (± 6.58%) ~ 0.043s 0.066s p=0.179 n=20
Total Time 0.534s (± 0.75%) 0.578s (± 1.11%) 🔻+0.044s (+ 8.22%) 0.549s 0.608s p=0.000 n=20
t3code-server - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 4,350,661 4,275,656 -75,005 (- 1.72%) ~ ~ p=0.000 n=20
Types 3,040,644 3,011,289 -29,355 (- 0.97%) ~ ~ p=0.000 n=20
Memory Used 2,417,813k (± 0.05%) 2,499,686k (± 0.03%) +81,872k (+ 3.39%) 2,497,624k 2,503,166k p=0.000 n=20
Memory Allocs 37,162,703 (± 0.07%) 39,936,827 (± 0.05%) 🔻+2,774,124 (+ 7.46%) 39,867,361 40,066,053 p=0.000 n=20
Config Time 0.003s (± 6.00%) 0.003s (± 6.84%) ~ 0.002s 0.003s p=1.000 n=20
Parse Time 0.251s (± 2.05%) 0.250s (± 2.05%) ~ 0.236s 0.268s p=0.683 n=20
Bind Time 0.085s (±10.33%) 0.090s (±11.32%) ~ 0.074s 0.137s p=0.472 n=20
Check Time 5.821s (± 0.50%) 6.554s (± 0.50%) 🔻+0.733s (+12.60%) 6.429s 6.720s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 6.170s (± 0.43%) 6.909s (± 0.50%) 🔻+0.739s (+11.98%) 6.755s 7.066s p=0.000 n=20
tanstack-router - native
Errors 1 1 ~ ~ ~ p=1.000 n=20
Symbols 571,756 566,635 -5,121 (- 0.90%) ~ ~ p=0.000 n=20
Types 397,689 388,675 -9,014 (- 2.27%) ~ ~ p=0.000 n=20
Memory Used 326,441k (± 0.01%) 341,109k (± 0.01%) 🔻+14,669k (+ 4.49%) 340,953k 341,307k p=0.000 n=20
Memory Allocs 4,335,751 (± 0.29%) 4,537,255 (± 0.23%) 🔻+201,505 (+ 4.65%) 4,518,598 4,593,233 p=0.000 n=20
Config Time 0.001s 0.001s ~ ~ ~ p=1.000 n=20
Parse Time 0.040s (± 4.98%) 0.041s (± 4.70%) ~ 0.032s 0.047s p=0.558 n=20
Bind Time 0.015s (±10.48%) 0.013s (±10.95%) ~ 0.011s 0.021s p=0.051 n=20
Check Time 0.521s (± 1.75%) 0.586s (± 1.65%) 🔻+0.065s (+12.48%) 0.555s 0.630s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 0.595s (± 1.72%) 0.661s (± 1.59%) 🔻+0.066s (+11.05%) 0.627s 0.717s p=0.000 n=20
ts-pre-modules - native
Errors 87 87 ~ ~ ~ p=1.000 n=20
Symbols 231,616 231,759 +143 (+ 0.06%) ~ ~ p=0.000 n=20
Types 181,195 181,047 -148 (- 0.08%) ~ ~ p=0.000 n=20
Memory Used 193,003k (± 0.02%) 197,873k (± 0.01%) +4,870k (+ 2.52%) 197,773k 197,967k p=0.000 n=20
Memory Allocs 1,310,290 (± 0.02%) 1,395,656 (± 0.02%) 🔻+85,366 (+ 6.52%) 1,394,798 1,397,134 p=0.000 n=20
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Parse Time 0.043s (± 2.89%) 0.043s (± 2.94%) ~ 0.039s 0.048s p=0.602 n=20
Bind Time 0.019s (± 6.27%) 0.019s (± 5.14%) ~ 0.016s 0.024s p=0.412 n=20
Check Time 0.287s (± 1.03%) 0.314s (± 0.85%) 🔻+0.027s (+ 9.38%) 0.305s 0.322s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 0.355s (± 0.75%) 0.382s (± 0.73%) 🔻+0.028s (+ 7.82%) 0.372s 0.394s p=0.000 n=20
vscode - native
Errors 11 11 ~ ~ ~ p=1.000 n=20
Symbols 7,586,320 7,347,532 🟩-238,788 (- 3.15%) ~ ~ p=0.000 n=20
Types 4,457,051 4,214,558 🟩-242,493 (- 5.44%) ~ ~ p=0.000 n=20
Memory Used 5,252,899k (± 0.01%) 5,318,875k (± 0.01%) +65,976k (+ 1.26%) 5,316,277k 5,321,964k p=0.000 n=20
Memory Allocs 57,393,643 (± 0.02%) 61,340,408 (± 0.02%) 🔻+3,946,766 (+ 6.88%) 61,316,480 61,396,589 p=0.000 n=20
Config Time 0.033s (± 0.63%) 0.033s (± 1.59%) ~ 0.033s 0.038s p=0.113 n=20
Parse Time 0.879s (± 0.97%) 0.886s (± 1.76%) ~ 0.805s 0.957s p=0.417 n=20
Bind Time 0.286s (± 0.56%) 0.294s (± 6.95%) ~ 0.277s 0.479s p=0.290 n=20
Check Time 6.945s (± 0.28%) 7.570s (± 0.50%) 🔻+0.625s (+ 9.00%) 7.311s 7.653s p=0.000 n=20
Emit Time 1.910s (± 1.16%) 2.158s (± 6.36%) 🔻+0.247s (+12.94%) 1.956s 2.819s p=0.000 n=20
Total Time 10.108s (± 0.22%) 10.995s (± 1.01%) 🔻+0.887s (+ 8.78%) 10.793s 11.504s p=0.000 n=20
webpack - native
Errors 595 601 +6 (+ 1.01%) ~ ~ p=0.000 n=20
Symbols 861,433 861,788 +355 (+ 0.04%) ~ ~ p=0.000 n=20
Types 595,020 593,447 -1,573 (- 0.26%) ~ ~ p=0.000 n=20
Memory Used 632,911k (± 0.01%) 664,642k (± 0.01%) 🔻+31,731k (+ 5.01%) 664,341k 664,993k p=0.000 n=20
Memory Allocs 5,887,614 (± 0.06%) 6,464,785 (± 0.03%) 🔻+577,170 (+ 9.80%) 6,458,477 6,473,145 p=0.000 n=20
Config Time 0.004s 0.004s ~ ~ ~ p=1.000 n=20
Parse Time 0.117s (± 2.00%) 0.120s (± 2.27%) +0.002s (+ 2.14%) 0.104s 0.128s p=0.043 n=20
Bind Time 0.039s (±11.64%) 0.038s (±11.49%) ~ 0.032s 0.064s p=0.622 n=20
Check Time 0.938s (± 0.59%) 1.063s (± 0.34%) 🔻+0.125s (+13.33%) 1.049s 1.076s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 1.119s (± 0.41%) 1.245s (± 0.49%) 🔻+0.126s (+11.23%) 1.221s 1.274s p=0.000 n=20
xstate-main - native
Errors 0 0 ~ ~ ~ p=1.000 n=20
Symbols 640,490 659,984 +19,494 (+ 3.04%) ~ ~ p=0.000 n=20
Types 387,984 372,422 🟩-15,562 (- 4.01%) ~ ~ p=0.000 n=20
Memory Used 350,143k (± 0.03%) 368,495k (± 0.01%) 🔻+18,352k (+ 5.24%) 368,296k 368,790k p=0.000 n=20
Memory Allocs 3,969,092 (± 0.07%) 4,502,684 (± 0.07%) 🔻+533,593 (+13.44%) 4,492,934 4,516,926 p=0.000 n=20
Config Time 0.001s 0.001s ~ ~ ~ p=1.000 n=20
Parse Time 0.060s (± 2.89%) 0.060s (± 3.55%) ~ 0.053s 0.068s p=0.984 n=20
Bind Time 0.019s (±11.38%) 0.020s (± 9.43%) ~ 0.016s 0.028s p=0.327 n=20
Check Time 0.382s (± 0.70%) 0.448s (± 1.27%) 🔻+0.065s (+17.09%) 0.437s 0.486s p=0.000 n=20
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=20
Total Time 0.467s (± 0.92%) 0.533s (± 1.11%) 🔻+0.066s (+14.12%) 0.516s 0.572s p=0.000 n=20
System info unknown
Hosts
  • native
Scenarios
  • Compiler-Unions - native
  • angular-1 - native
  • arktype - native
  • class-transformer - native
  • effect - native
  • mui-docs - native
  • sentry - native
  • social-app - native
  • strada-build-src - native
  • strada-compiler - native
  • t3code-server - native
  • tanstack-router - native
  • ts-pre-modules - native
  • vscode - native
  • webpack - native
  • xstate-main - native
Benchmark Name Iterations
Current pr 20
Baseline baseline 20

Developer Information:

Download Benchmarks

@typescript-automation

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the top 400 repos with tsc comparing baseline and pr:

Something interesting changed - please have a look.

Details

cheaper-inference/OmniRoute

5 of 11 projects failed to build with the old tsc and were ignored

open-sse/tsconfig.json

  • error TS2322: Type 'Promise<ImageResult | MagnificImageResult | { success: boolean; data: { created: any; data: any; }; } | { success: boolean; status: number; error: unknown; } | { data?: undefined; success: boolean; status: number; error: any; }>' is not assignable to type 'Promise<ImageResult>'.

Reduced from the react-relay DefinitelyTyped tests. On main, the
variances of these mutually recursive generics are measured while the
cycle is still open and then frozen, so every parameter of
EntryPointComponent ends up "independent". Main therefore accepts the
assignment of `e` to `EntryPoint<any, any>` while rejecting the
assignment of `e.root` to that same type's `root` property.

The checker now reports both assignments, which is the consistent
answer. Recording the case keeps that behavior covered.
A function with an inferred return type that calls itself inside a
callback passed to a non-generic function forms a return type cycle
through the callback. TypeScript reports TS7023 on the function and
TS7024 on the callback, and without noImplicitAny the cycle resolves
both to any. The baselines record this branch's current output, which
misses the cycle: there are no errors under strict, and the non-strict
case reports a spurious TS2322 (seen in OmniRoute).
Contextually checking a function expression infers its return type
from its body. Since "Discard results derived from computations in
progress", that inference was pushed as a return type resolution of
the function's signature. When the body calls a function whose return
type depends on the call enclosing the function expression, resolving
that call relates the function expression's signature, which requests
its return type. Seeing it in progress, that request returned any
without detecting a cycle, so the enclosing function's return type was
inferred from a provisional any instead of reporting the circularity.

The inference now runs without marking the signature in progress, as
in TypeScript. The nested request computes the return type itself,
reaches the enclosing function, and the cycle is reported on both as
before. The result is cached only if no request has already cached
one, so whichever request finishes first decides it, the same as when
the return type is requested directly.
Inferring a method's return type as a union of the class's this type
and an interface relates the class to the interface, which needs the
return types of the other methods. When one of those calls back into
the first method, the return types form a cycle, and which members
report it depends on which return type is requested first.

TypeScript reports the cycle on both methods when the class
declaration is checked before its use. When the class is first related
to the interface, the method calling back is computed first, sees the
other in progress, and both are inferred without error. This branch
discards results that observed a computation in progress, so the
latter recomputes from the other entry and reports the cycle (seen in
effect's SchemaAST).
In JavaScript, a @type tag on a function expression gives the types of
its parameters, even where the function also has a contextual type.
The baselines record this branch's current output, which types the
parameters from the contextual type instead (seen in webpack).
Completing contextual signatures eagerly switched parameter assignment
from the signature of the function's symbol to the signature built
from its declaration. In JavaScript the symbol's signature comes from
a @type tag when one is present, and the function's parameters take
their types from that tag. Using the declaration's signature wrote the
outer contextual types onto those parameters instead, producing errors
inside the function body that the tag rules out.

Prefer the tag's signature, as before, and fall back to the
declaration's signature otherwise.
Inferring from string[][] to Iterable<Iterable<T>> passes through the
[Symbol.iterator] method types of the outer and inner arrays. Ordering
those by type id calls the inner method type newer, and so the
inference expanding recursion, only when it is first created during
the inference; iterating string[] beforehand avoids that. Ordering by
generation infers the element type in both cases (seen in webpack).
This reverts commit f871455.

Computing the contextual type of a call nested in an argument of an
enclosing call does more than resolve the enclosing call: it walks the
contextual types between them, such as the contextual return type of an
arrow function the nested call is returned from. When the enclosing
call is already resolving, that walk still decides where a cycle
through the two calls is entered. With it skipped, a cycle through a
scope object whose members are thunks referring to the scope was
entered at the nested call rather than at the thunk's return type, as
in source order, and parameters of callbacks passed to the nested call
became implicitly any (seen in arktype).
A scope object built by a generic call whose parameter is a mapped type
over the object, with a member that is a thunk calling back into the
scope, checks without error in the reference implementation under every
order tried. There, the thunk's return type is computed once, while the
scope's reverse mapping of the thunk is in progress, which cuts off the
nested resolution of the scope call, and is cached. Here it is computed
again after the scope call's nested resolution is discarded, outside
that reverse mapping, and fails as a cycle through the scope.

The baseline records the current, incorrect, circularity errors. The
case is reduced by hand from a pattern in arktype, which itself checks
without error.
The variable is narrowed to never inside the if. With && in the
loop condition, main reports only the assignment of false to never:
loop analysis creates an incomplete never placeholder (silentNever),
and that placeholder leaks into the type of the reference, so the
property access is silently allowed. With a plain loop condition,
main reports the property access instead, which is what we report
in both cases.

Reduced with creduce (seen in uglify-js).
A call resolution hides the resolutions below it, so a symbol whose
initializer reaches itself through a call argument is computed again,
nested in itself, as in main. The nested computation observes things
in progress that the outer one entered: here, a mapped property whose
contextual type is skipped, and the reverse mapping whose depth cutoff
it reaches. Those mark everything since as circular, so the nested
result was discarded, and the outer computation, reaching the same
types again outside that context, then failed with a circularity.

When everything the nested computation observed in progress was
entered by the outermost hidden resolution of the same target, the
nested computation is what that one always computes first from
scratch, whichever entry led to it, so its result is kept as a cycle
participant, as main keeps the first result set.

Main also keeps the reverse-mapped property type computed under the
depth cutoff, so it types the property as unknown. That result still
depends on the cutoff and is discarded, so the property is computed
again from scratch afterwards, giving its full type: an improvement
over main rather than a match (seen in arktype).
An instantiation stopped by the limit on the depth of the whole
instantiation names every type that recurs in it, in the order in
which they recur. Which type of the cycle the instantiation entered
first depends on what was cached before, so checkers that had checked
different files named the same cycle starting from different types,
and reported the same error twice with different messages (seen in
zod, with checkers running concurrently).

The names now start from the type declared first, so the message is
the same wherever the cycle is entered. The limit on the depth of a
single computation already names only what that computation
instantiated, which does not depend on where it was entered, so its
messages keep the order in which the types recur.
Every computation with effects keeps a memoEffects until a check
replays it, and when nothing checks again, such as when emitting after
checking, those of the whole program stay live. Few have reference
marks or cycle heads, so moving them to a side struct shrinks every
node from 128 to 80 bytes (seen in angular, about 60MB less).
linkState wrapped the effects of the computation that cached a result
in a set of deps even when it was the only one, though replaying a set
holding only f replays f the same way. The state now points at f until
a second computation caches the result, which then gets a set rather
than adding to the effects of f, shared with everything else depending
on it (seen in angular, about 30MB less).
Most results with a memo state only have pending effects, and every
state stays live until a check reads it, so storing the rare errors
list behind a pointer halves the state (seen in angular, about 20MB
less).
A computation with no effects of its own that observed only one result
computed at the same node replays exactly what that result does, so
the result keeps those effects as its own rather than a node holding
one edge to them (seen in angular, about 10MB less).
resolvingIndex scanned every in-progress entry of a memo map to find a
key, which is quadratic when many entries of one map are in progress at
once, as in deeply nested variance measurements. Past a small number of
in-progress entries, count them by key so that a lookup for a key that
is not in progress is constant time.

(seen in nested variance stress)
When a variance measurement re-entered one already in progress, the
inner measurement restarted from the canonical (smallest) type of the
cycle with the stack hidden. With cycles nested in cycles, each restart
re-measured every type still in progress, so the work multiplied with
the nesting depth.

Now re-entry instead records the lowest stack index it reached, as in
Tarjan's algorithm, and returns provisional variances. When a
measurement finishes as the root of its strongly connected component
and the component's canonical type is not the root, what was cached
since the root began is discarded and the canonical type is measured
once with the stack hidden; the root then adopts its result. The result
is what main computes when the canonical type is checked first, and
each component is measured at most about twice.

The elaboration in varianceCircularConsistency now goes through the
'queries' property again, matching main and TypeScript 6.0.

(seen in nested variance stress)
When a computation re-entered one in progress, memoCycle made every
computation above it depend on it, stopping only at one that already
depended on that same head. With cycles nested in cycles, re-entries
reach many different heads, so each walked most of the stack and every
computation gained a dependency per head.

A computation in progress above a cycle head becomes part of the head's
effects, so depending on the lowest head covers every head above it.
Record the head's index with each dependency, add one only for a lower
head than the computation already depends on, and stop the walk at the
first computation that depends on this head or one below it.

(seen in nested variance stress)
Relating type references and aliases now asks whether the target's
variances are being measured, which scanned the whole variance stack on
every comparison made during a measurement. Index the stack by symbol,
restoring a symbol's previous index when its measurement ends, so that
a measurement hidden with the rest of the stack is still not found.

(seen in nested variance stress)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant