Skip to content

Improve logic that chooses co- vs. contra-variant inferences - #57909

Merged
Jake Bailey (jakebailey) merged 11 commits into
microsoft:mainfrom
Andarist:tweak-co-contra-inference
Jun 17, 2024
Merged

Improve logic that chooses co- vs. contra-variant inferences#57909
Jake Bailey (jakebailey) merged 11 commits into
microsoft:mainfrom
Andarist:tweak-co-contra-inference

Conversation

@Andarist

@AndaristMateusz Burzyński (Andarist) commented Mar 22, 2024

Copy link
Copy Markdown
Contributor

To review this it might be helpful to see how this evolved over time:
#27028
#46392
#52123
#52180
#54072

The reason why this inference fails today is that isTypeSubtypeOf leads to requireOptionalProperties === true. This has such inferences:

inferredCovariantType// { query: string }inferredContravariantType// { query?: unknown; body?: unknown; }

So the covariant inference lacks body property and thus it fails the check and the contravariant inference gets chosen at the end.

fixes#57908
fixes#58468

@typescript-botTypeScript Bot (typescript-bot) added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Mar 22, 2024
@typescript-bot

Copy link
Copy Markdown
Contributor

This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise.

@jakebailey

Copy link
Copy Markdown
Member

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 22, 2024

Copy link
Copy Markdown
Contributor

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

CommandStatusResults
test top800✅ Started
user test this✅ Started👀 Results
run dt✅ Started👀 Results
perf test this faster✅ Started👀 Results

const preferCovariantType = inferredCovariantType && (!inferredContravariantType ||
!(inferredCovariantType.flags & TypeFlags.Never) &&
some(inference.contraCandidates, t => isTypeSubtypeOf(inferredCovariantType, t)) &&
some(inference.contraCandidates, t => isTypeAssignableTo(inferredCovariantType, t)) &&

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is not the correct change then at the very least a test case should be proposed that shows how the isTypeSubtypeOf is better.

When this check was originally introduced by Anders Hejlsberg (@ahejlsberg)here it was states that:

Furthermore, knowing that an error will result when the co-variant inference is not a subtype of the contra-variant inference, we now prefer the contra-variant inference because it is likely to have come from an explicit type annotation on a function. This improves our error reporting.

An alternative idea to fix this example would be to keep coAndContraRelationCheck on inferenceContext. From what I understand, the subtypeRelation in this context is mainly used when dealing with multiple overloads - a single signature case uses assignableRelation with chooseOverload. So perhaps the used relation should determine what is being used here.

@typescript-bot

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:

Package: react
Error:

Error: /mnt/vss/_work/1/DefinitelyTyped/types/react/test/index.ts
794:5 error TypeScript@local compile error: Unused '@ts-expect-error' directive @definitelytyped/expect
✖ 1 problem (1 error, 0 warnings)
at combineErrorsAndWarnings (/mnt/vss/_work/1/DefinitelyTyped/node_modules/.pnpm/@definitelytyped+dtslint@0.2.18_typescript@5.5.0-dev.20240322/node_modules/@definitelytyped/dtslint/dist/index.js:194:28)
at runTests (/mnt/vss/_work/1/DefinitelyTyped/node_modules/.pnpm/@definitelytyped+dtslint@0.2.18_typescript@5.5.0-dev.20240322/node_modules/@definitelytyped/dtslint/dist/index.js:186:20)

Package: styled-theming
Error:

Error: /mnt/vss/_work/1/DefinitelyTyped/types/styled-theming/styled-theming-tests.tsx
72:47 error TypeScript@local compile error: No overload matches this call.
The last overload gave the following error.
Type '"wrong variant"' is not assignable to type '"primary" | "secondary" | undefined' @definitelytyped/expect
✖ 1 problem (1 error, 0 warnings)
at combineErrorsAndWarnings (/mnt/vss/_work/1/DefinitelyTyped/node_modules/.pnpm/@definitelytyped+dtslint@0.2.18_typescript@5.5.0-dev.20240322/node_modules/@definitelytyped/dtslint/dist/index.js:194:28)
at runTests (/mnt/vss/_work/1/DefinitelyTyped/node_modules/.pnpm/@definitelytyped+dtslint@0.2.18_typescript@5.5.0-dev.20240322/node_modules/@definitelytyped/dtslint/dist/index.js:186:20)

You can check the log here.

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the user tests comparing main and refs/pull/57909/merge:

Something interesting changed - please have a look.

Details

uglify-js

/mnt/ts_downloads/_/m/uglify-js/tsconfig.json

  • [NEW] error TS2684: The 'this' context of type '(...items: never[]) => number' is not assignable to method's 'this' of type '(this: any[], ...args: any) => number'.
    • /mnt/ts_downloads/_/m/uglify-js/node_modules/uglify-js/lib/compress.js(293,17)
    • /mnt/ts_downloads/_/m/uglify-js/node_modules/uglify-js/lib/compress.js(2472,29)
    • /mnt/ts_downloads/_/m/uglify-js/node_modules/uglify-js/lib/compress.js(7469,47)
    • /mnt/ts_downloads/_/m/uglify-js/node_modules/uglify-js/lib/compress.js(14005,13)
  • [NEW] error TS2684: The 'this' context of type '(...items: never[]) => number' is not assignable to method's 'this' of type '(this: any, ...args: any) => number'.
    • /mnt/ts_downloads/_/m/uglify-js/node_modules/uglify-js/lib/compress.js(1867,13)
    • /mnt/ts_downloads/_/m/uglify-js/node_modules/uglify-js/lib/compress.js(7298,64)
    • /mnt/ts_downloads/_/m/uglify-js/node_modules/uglify-js/lib/compress.js(7981,33)
    • /mnt/ts_downloads/_/m/uglify-js/node_modules/uglify-js/lib/compress.js(8012,29)
    • /mnt/ts_downloads/_/m/uglify-js/node_modules/uglify-js/lib/compress.js(14002,17)
    • /mnt/ts_downloads/_/m/uglify-js/node_modules/uglify-js/lib/parse.js(1863,17)

@typescript-bot

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
MetricbaselineprDeltaBestWorstp-value
Angular - node (v18.15.0, x64)
Memory used295,529k (± 0.00%)295,524k (± 0.00%)~295,506k295,544kp=0.423 n=6
Parse Time2.66s (± 0.31%)2.66s (± 0.28%)~2.65s2.67sp=0.209 n=6
Bind Time0.83s (± 0.66%)0.82s (± 0.99%)~0.81s0.83sp=0.859 n=6
Check Time8.20s (± 0.37%)8.20s (± 0.15%)~8.18s8.21sp=0.809 n=6
Emit Time7.04s (± 0.20%)7.09s (± 0.88%)~7.00s7.18sp=0.107 n=6
Total Time18.72s (± 0.16%)18.76s (± 0.32%)~18.69s18.86sp=0.225 n=6
Compiler-Unions - node (v18.15.0, x64)
Memory used191,964k (± 0.06%)193,733k (± 0.95%)~191,878k195,497kp=0.128 n=6
Parse Time1.36s (± 0.89%)1.36s (± 1.21%)~1.33s1.38sp=1.000 n=6
Bind Time0.72s (± 0.00%)0.72s (± 0.00%)~0.72s0.72sp=1.000 n=6
Check Time9.56s (± 0.60%)9.49s (± 0.37%)-0.08s (- 0.80%)9.44s9.54sp=0.045 n=6
Emit Time2.62s (± 0.51%)2.63s (± 0.64%)~2.61s2.65sp=0.227 n=6
Total Time14.26s (± 0.40%)14.19s (± 0.39%)~14.11s14.28sp=0.090 n=6
Monaco - node (v18.15.0, x64)
Memory used347,372k (± 0.01%)347,374k (± 0.01%)~347,324k347,407kp=0.873 n=6
Parse Time2.47s (± 0.33%)2.48s (± 0.40%)~2.47s2.49sp=0.498 n=6
Bind Time0.93s (± 0.44%)0.92s (± 0.59%)~0.92s0.93sp=0.282 n=6
Check Time7.00s (± 0.41%)7.02s (± 0.49%)~6.97s7.07sp=0.465 n=6
Emit Time4.08s (± 0.37%)4.07s (± 0.40%)~4.04s4.08sp=0.157 n=6
Total Time14.49s (± 0.26%)14.49s (± 0.23%)~14.45s14.55sp=0.872 n=6
TFS - node (v18.15.0, x64)
Memory used302,726k (± 0.02%)302,708k (± 0.01%)~302,678k302,760kp=0.575 n=6
Parse Time2.41s (± 0.68%)2.39s (± 1.72%)~2.34s2.44sp=0.571 n=6
Bind Time1.19s (± 0.53%)1.19s (± 1.02%)~1.17s1.20sp=0.673 n=6
Check Time7.44s (± 0.56%)7.45s (± 0.46%)~7.41s7.50sp=0.376 n=6
Emit Time4.28s (± 0.41%)4.29s (± 0.58%)~4.26s4.33sp=1.000 n=6
Total Time15.33s (± 0.34%)15.32s (± 0.48%)~15.24s15.42sp=0.688 n=6
material-ui - node (v18.15.0, x64)
Memory used509,876k (± 0.01%)509,895k (± 0.00%)~509,875k509,907kp=0.125 n=6
Parse Time2.64s (± 0.37%)2.65s (± 0.65%)~2.63s2.67sp=0.215 n=6
Bind Time0.99s (± 0.99%)0.98s (± 0.56%)~0.98s0.99sp=0.322 n=6
Check Time17.23s (± 0.22%)17.23s (± 0.37%)~17.15s17.32sp=1.000 n=6
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)~0.00s0.00sp=1.000 n=6
Total Time20.86s (± 0.19%)20.87s (± 0.29%)~20.81s20.98sp=0.746 n=6
mui-docs - node (v18.15.0, x64)
Memory used1,737,544k (± 0.00%)1,737,524k (± 0.00%)~1,737,491k1,737,554kp=0.230 n=6
Parse Time7.78s (± 0.38%)7.80s (± 0.61%)~7.74s7.88sp=0.373 n=6
Bind Time2.80s (± 0.32%)2.81s (± 0.83%)~2.78s2.84sp=0.806 n=6
Check Time66.38s (± 0.34%)66.49s (± 0.45%)~66.11s66.91sp=0.521 n=6
Emit Time0.15s (± 3.53%)0.16s (± 3.29%)~0.15s0.16sp=0.640 n=6
Total Time77.12s (± 0.32%)77.25s (± 0.34%)~76.98s77.63sp=0.471 n=6
self-build-src - node (v18.15.0, x64)
Memory used2,394,217k (± 0.02%)2,393,952k (± 0.04%)~2,392,566k2,394,786kp=0.471 n=6
Parse Time6.07s (± 0.90%)6.07s (± 0.68%)~6.02s6.11sp=0.688 n=6
Bind Time2.26s (± 0.52%)2.24s (± 1.68%)~2.17s2.28sp=0.415 n=6
Check Time39.48s (± 0.29%)39.61s (± 0.22%)+0.14s (+ 0.34%)39.48s39.73sp=0.045 n=6
Emit Time3.12s (± 0.48%)3.15s (± 1.61%)~3.08s3.21sp=0.520 n=6
Total Time50.94s (± 0.22%)51.08s (± 0.20%)+0.14s (+ 0.27%)50.89s51.20sp=0.045 n=6
self-compiler - node (v18.15.0, x64)
Memory used415,185k (± 0.01%)415,193k (± 0.01%)~415,144k415,226kp=0.936 n=6
Parse Time3.43s (± 0.96%)3.42s (± 0.75%)~3.39s3.45sp=0.807 n=6
Bind Time1.29s (± 0.76%)1.29s (± 0.82%)~1.27s1.30sp=0.547 n=6
Check Time18.02s (± 0.35%)18.01s (± 0.43%)~17.89s18.11sp=0.872 n=6
Emit Time1.31s (± 1.12%)1.32s (± 0.88%)~1.31s1.34sp=0.324 n=6
Total Time24.06s (± 0.35%)24.04s (± 0.30%)~23.94s24.16sp=0.806 n=6
vscode - node (v18.15.0, x64)
Memory used2,889,942k (± 0.00%)2,889,412k (± 0.00%)-531k (- 0.02%)2,889,325k2,889,479kp=0.005 n=6
Parse Time12.95s (± 0.27%)12.94s (± 0.27%)~12.91s13.00sp=0.683 n=6
Bind Time4.13s (± 0.82%)4.14s (± 0.64%)~4.10s4.17sp=0.746 n=6
Check Time71.13s (± 0.24%)71.45s (± 0.31%)+0.32s (+ 0.45%)71.14s71.74sp=0.045 n=6
Emit Time19.50s (± 0.88%)19.40s (± 0.79%)~19.18s19.60sp=0.336 n=6
Total Time107.71s (± 0.35%)107.93s (± 0.32%)~107.57s108.40sp=0.378 n=6
webpack - node (v18.15.0, x64)
Memory used408,193k (± 0.03%)408,153k (± 0.01%)~408,080k408,221kp=0.810 n=6
Parse Time3.89s (± 0.72%)3.90s (± 0.67%)~3.86s3.94sp=0.623 n=6
Bind Time1.67s (± 0.49%)1.69s (± 0.89%)+0.02s (+ 1.20%)1.67s1.70sp=0.031 n=6
Check Time16.80s (± 0.32%)16.72s (± 0.20%)-0.08s (- 0.46%)16.67s16.77sp=0.037 n=6
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)~0.00s0.00sp=1.000 n=6
Total Time22.36s (± 0.18%)22.31s (± 0.20%)~22.25s22.36sp=0.077 n=6
xstate - node (v18.15.0, x64)
Memory used512,982k (± 0.01%)513,035k (± 0.02%)~512,919k513,174kp=0.471 n=6
Parse Time3.96s (± 0.43%)3.94s (± 0.42%)~3.92s3.97sp=0.052 n=6
Bind Time1.85s (± 0.90%)1.85s (± 1.15%)~1.82s1.87sp=1.000 n=6
Check Time3.37s (± 0.55%)3.37s (± 0.24%)~3.36s3.38sp=0.870 n=6
Emit Time0.08s (± 6.19%)0.09s (± 6.44%)~0.08s0.09sp=0.640 n=6
Total Time9.28s (± 0.19%)9.25s (± 0.33%)~9.22s9.30sp=0.090 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • Angular - node (v18.15.0, x64)
  • Compiler-Unions - node (v18.15.0, x64)
  • Monaco - node (v18.15.0, x64)
  • TFS - node (v18.15.0, x64)
  • material-ui - node (v18.15.0, x64)
  • mui-docs - node (v18.15.0, x64)
  • self-build-src - node (v18.15.0, x64)
  • self-compiler - node (v18.15.0, x64)
  • vscode - node (v18.15.0, x64)
  • webpack - node (v18.15.0, x64)
  • xstate - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

Developer Information:

Download Benchmarks

@jakebailey

Copy link
Copy Markdown
Member

TypeScript Bot (@typescript-bot) pack this

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 22, 2024

Copy link
Copy Markdown
Contributor

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

CommandStatusResults
pack this✅ Started✅ Results

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 22, 2024

Copy link
Copy Markdown
Contributor

Hey Jake Bailey (@jakebailey), I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
"devDependencies": {
"typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/160700/artifacts?artifactName=tgz&fileId=09532E0BDDB3EF1D0C0185CBFA531EE829D75833400D06C510FCB93118E30D0C02&fileName=/typescript-5.5.0-insiders.20240322.tgz"
}
}

and then running npm install.


There is also a playground for this build and an npm module you can use via "typescript": "npm:@typescript-deploys/pr-build@5.5.0-pr-57909-8".;

@typescript-botTypeScript Bot (typescript-bot) added For Backlog Bug PRs that fix a backlog bug and removed For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Mar 23, 2024
@Andarist

Copy link
Copy Markdown
ContributorAuthor

Jake Bailey (@jakebailey) could you rerun top800, dt and perf suites? a new playground would also be appreciated :)

@jakebailey

Copy link
Copy Markdown
Member

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 23, 2024

Copy link
Copy Markdown
Contributor

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

CommandStatusResults
test top800✅ Started✅ Results
user test this✅ Started✅ Results
run dt✅ Started👀 Results
perf test this faster✅ Started👀 Results
pack this✅ Started✅ Results

@typescript-bot

TypeScript Bot (typescript-bot) commented Mar 23, 2024

Copy link
Copy Markdown
Contributor

Hey Jake Bailey (@jakebailey), I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
"devDependencies": {
"typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/160702/artifacts?artifactName=tgz&fileId=C476EBF980531EB5F87264AF4D7EFD709FC10481D708D1A72266850B714544B902&fileName=/typescript-5.5.0-insiders.20240323.tgz"
}
}

and then running npm install.


There is also a playground for this build and an npm module you can use via "typescript": "npm:@typescript-deploys/pr-build@5.5.0-pr-57909-12".;

@typescript-bot

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:

Package: styled-theming
Error:

Error: /mnt/vss/_work/1/DefinitelyTyped/types/styled-theming/styled-theming-tests.tsx
72:47 error TypeScript@local compile error: No overload matches this call.
The last overload gave the following error.
Type '"wrong variant"' is not assignable to type '"primary" | "secondary" | undefined' @definitelytyped/expect
✖ 1 problem (1 error, 0 warnings)
at combineErrorsAndWarnings (/mnt/vss/_work/1/DefinitelyTyped/node_modules/.pnpm/@definitelytyped+dtslint@0.2.18_typescript@5.5.0-dev.20240323/node_modules/@definitelytyped/dtslint/dist/index.js:194:28)
at runTests (/mnt/vss/_work/1/DefinitelyTyped/node_modules/.pnpm/@definitelytyped+dtslint@0.2.18_typescript@5.5.0-dev.20240323/node_modules/@definitelytyped/dtslint/dist/index.js:186:20)

You can check the log here.

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the user tests comparing main and refs/pull/57909/merge:

Everything looks good!

@typescript-bot

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
MetricbaselineprDeltaBestWorstp-value
Angular - node (v18.15.0, x64)
Memory used295,530k (± 0.01%)295,537k (± 0.01%)~295,512k295,555kp=1.000 n=6
Parse Time2.66s (± 0.37%)2.66s (± 0.28%)~2.65s2.67sp=0.652 n=6
Bind Time0.82s (± 0.66%)0.83s (± 0.49%)~0.83s0.84sp=0.054 n=6
Check Time8.20s (± 0.32%)8.22s (± 0.60%)~8.17s8.29sp=0.872 n=6
Emit Time7.07s (± 0.35%)7.05s (± 0.64%)~7.02s7.14sp=0.222 n=6
Total Time18.76s (± 0.19%)18.76s (± 0.33%)~18.68s18.84sp=1.000 n=6
Compiler-Unions - node (v18.15.0, x64)
Memory used192,468k (± 0.73%)194,259k (± 0.94%)~191,886k195,602kp=0.093 n=6
Parse Time1.37s (± 0.97%)1.36s (± 1.52%)~1.33s1.39sp=0.250 n=6
Bind Time0.72s (± 0.00%)0.72s (± 0.00%)~0.72s0.72sp=1.000 n=6
Check Time9.51s (± 0.66%)9.52s (± 0.57%)~9.43s9.59sp=1.000 n=6
Emit Time2.63s (± 0.95%)2.62s (± 0.96%)~2.58s2.64sp=0.461 n=6
Total Time14.23s (± 0.53%)14.21s (± 0.41%)~14.11s14.26sp=0.573 n=6
Monaco - node (v18.15.0, x64)
Memory used347,373k (± 0.01%)347,383k (± 0.00%)~347,358k347,402kp=0.575 n=6
Parse Time2.48s (± 0.33%)2.48s (± 0.30%)~2.47s2.49sp=0.729 n=6
Bind Time0.93s (± 0.88%)0.93s (± 0.56%)~0.92s0.93sp=0.929 n=6
Check Time7.00s (± 0.49%)7.00s (± 0.38%)~6.97s7.04sp=0.686 n=6
Emit Time4.07s (± 0.34%)4.07s (± 0.26%)~4.05s4.08sp=1.000 n=6
Total Time14.48s (± 0.28%)14.48s (± 0.18%)~14.45s14.52sp=0.808 n=6
TFS - node (v18.15.0, x64)
Memory used302,725k (± 0.01%)302,715k (± 0.02%)~302,659k302,798kp=0.575 n=6
Parse Time2.40s (± 1.41%)2.51s (± 8.80%)~2.39s2.96sp=0.260 n=6
Bind Time1.21s (± 0.68%)1.24s (±10.13%)~1.18s1.50sp=0.230 n=6
Check Time7.46s (± 0.50%)7.75s (± 9.17%)~7.43s9.20sp=0.574 n=6
Emit Time4.29s (± 0.54%)4.45s (± 9.53%)~4.25s5.31sp=0.571 n=6
Total Time15.35s (± 0.38%)15.95s (± 9.29%)~15.32s18.97sp=0.748 n=6
material-ui - node (v18.15.0, x64)
Memory used509,900k (± 0.00%)509,884k (± 0.00%)~509,859k509,917kp=0.128 n=6
Parse Time2.66s (± 0.63%)2.65s (± 0.70%)~2.62s2.67sp=0.325 n=6
Bind Time0.99s (± 1.05%)0.99s (± 0.82%)~0.98s1.00sp=0.270 n=6
Check Time17.22s (± 0.44%)17.23s (± 0.53%)~17.17s17.41sp=0.936 n=6
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)~0.00s0.00sp=1.000 n=6
Total Time20.86s (± 0.41%)20.87s (± 0.48%)~20.81s21.07sp=0.936 n=6
mui-docs - node (v18.15.0, x64)
Memory used1,737,562k (± 0.00%)1,737,442k (± 0.00%)-120k (- 0.01%)1,737,418k1,737,479kp=0.005 n=6
Parse Time7.77s (± 0.27%)7.79s (± 0.86%)~7.73s7.92sp=0.746 n=6
Bind Time2.80s (± 0.27%)2.80s (± 0.42%)~2.79s2.82sp=0.933 n=6
Check Time66.67s (± 0.41%)66.46s (± 0.27%)~66.19s66.65sp=0.229 n=6
Emit Time0.15s (± 2.69%)0.15s (± 3.36%)~0.15s0.16sp=0.595 n=6
Total Time77.40s (± 0.34%)77.21s (± 0.22%)~76.94s77.36sp=0.173 n=6
self-build-src - node (v18.15.0, x64)
Memory used2,393,895k (± 0.05%)2,393,977k (± 0.02%)~2,393,272k2,394,910kp=0.471 n=6
Parse Time6.10s (± 0.95%)6.05s (± 1.13%)~5.96s6.14sp=0.261 n=6
Bind Time2.26s (± 0.78%)2.25s (± 1.21%)~2.20s2.27sp=1.000 n=6
Check Time39.45s (± 0.41%)39.49s (± 0.41%)~39.38s39.81sp=0.810 n=6
Emit Time3.10s (± 2.12%)3.11s (± 1.39%)~3.04s3.17sp=0.936 n=6
Total Time50.90s (± 0.36%)50.93s (± 0.40%)~50.74s51.30sp=0.936 n=6
self-compiler - node (v18.15.0, x64)
Memory used415,116k (± 0.01%)415,122k (± 0.01%)~415,083k415,153kp=0.936 n=6
Parse Time4.19s (± 0.63%)4.20s (± 0.53%)~4.17s4.23sp=0.864 n=6
Bind Time1.58s (± 1.36%)1.60s (± 1.62%)~1.56s1.63sp=0.421 n=6
Check Time22.33s (± 0.38%)22.27s (± 0.47%)~22.16s22.46sp=0.228 n=6
Emit Time1.65s (± 0.99%)1.66s (± 0.62%)~1.65s1.67sp=0.242 n=6
Total Time29.76s (± 0.35%)29.72s (± 0.32%)~29.62s29.88sp=0.575 n=6
vscode - node (v18.15.0, x64)
Memory used2,891,049k (± 0.00%)2,891,279k (± 0.00%)+230k (+ 0.01%)2,891,226k2,891,343kp=0.005 n=6
Parse Time12.93s (± 0.35%)12.92s (± 0.26%)~12.88s12.98sp=1.000 n=6
Bind Time4.13s (± 0.54%)4.13s (± 0.32%)~4.12s4.15sp=0.807 n=6
Check Time71.47s (± 0.29%)71.67s (± 0.34%)~71.32s71.99sp=0.230 n=6
Emit Time19.43s (± 0.95%)19.41s (± 0.84%)~19.25s19.64sp=0.872 n=6
Total Time107.96s (± 0.27%)108.12s (± 0.24%)~107.85s108.59sp=0.575 n=6
webpack - node (v18.15.0, x64)
Memory used408,129k (± 0.01%)408,163k (± 0.01%)~408,104k408,215kp=0.173 n=6
Parse Time3.90s (± 0.70%)3.89s (± 0.23%)~3.88s3.90sp=0.934 n=6
Bind Time1.68s (± 0.58%)1.67s (± 0.76%)~1.65s1.69sp=0.116 n=6
Check Time16.78s (± 0.24%)16.74s (± 0.20%)~16.69s16.77sp=0.086 n=6
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)~0.00s0.00sp=1.000 n=6
Total Time22.36s (± 0.24%)22.31s (± 0.19%)~22.25s22.36sp=0.064 n=6
xstate - node (v18.15.0, x64)
Memory used513,044k (± 0.02%)513,043k (± 0.02%)~512,923k513,149kp=0.936 n=6
Parse Time3.95s (± 0.55%)3.94s (± 0.30%)~3.92s3.95sp=0.747 n=6
Bind Time1.84s (± 0.95%)1.85s (± 0.99%)~1.83s1.87sp=0.508 n=6
Check Time3.37s (± 0.99%)3.37s (± 0.55%)~3.35s3.40sp=0.515 n=6
Emit Time0.09s (± 6.44%)0.08s (± 4.99%)~0.08s0.09sp=0.282 n=6
Total Time9.24s (± 0.61%)9.25s (± 0.38%)~9.19s9.29sp=0.688 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • Angular - node (v18.15.0, x64)
  • Compiler-Unions - node (v18.15.0, x64)
  • Monaco - node (v18.15.0, x64)
  • TFS - node (v18.15.0, x64)
  • material-ui - node (v18.15.0, x64)
  • mui-docs - node (v18.15.0, x64)
  • self-build-src - node (v18.15.0, x64)
  • self-compiler - node (v18.15.0, x64)
  • vscode - node (v18.15.0, x64)
  • webpack - node (v18.15.0, x64)
  • xstate - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

Developer Information:

Download Benchmarks

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the top 800 repos comparing main and refs/pull/57909/merge:

Everything looks good!

@Andarist

Mateusz Burzyński (Andarist) commented Mar 23, 2024

Copy link
Copy Markdown
ContributorAuthor

The only reported error here is actually desired! See the comment here. I didn't look into this one before because of that and because it just involves multiple libraries with complicated type. I plan to reduce it to a test case now and add it here.

EDIT:// From this initial repro: TS playground to this TS playground. It's pretty lengthy but I already have problems with removing from it just about anything.

@Andarist

Copy link
Copy Markdown
ContributorAuthor

Still just one error :p and I have commented on it already here

@typescript-bot

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
MetricbaselineprDeltaBestWorstp-value
Compiler-Unions - node (v18.15.0, x64)
Errors3030~~~p=1.000 n=6
Symbols62,15462,154~~~p=1.000 n=6
Types50,24850,248~~~p=1.000 n=6
Memory used192,795k (± 0.76%)192,759k (± 0.78%)~192,109k195,825kp=0.378 n=6
Parse Time1.29s (± 1.74%)1.30s (± 1.16%)~1.28s1.31sp=0.864 n=6
Bind Time0.72s0.72s~~~p=1.000 n=6
Check Time9.52s (± 0.32%)9.51s (± 0.19%)~9.49s9.54sp=0.419 n=6
Emit Time2.65s (± 0.19%)2.64s (± 0.31%)-0.01s (- 0.38%)2.63s2.65sp=0.050 n=6
Total Time14.19s (± 0.36%)14.16s (± 0.13%)~14.13s14.18sp=0.294 n=6
angular-1 - node (v18.15.0, x64)
Errors55~~~p=1.000 n=6
Symbols944,110944,120+10 (+ 0.00%)~~p=0.001 n=6
Types407,141407,148+7 (+ 0.00%)~~p=0.001 n=6
Memory used1,221,999k (± 0.00%)1,222,003k (± 0.00%)~1,221,955k1,222,042kp=1.000 n=6
Parse Time6.80s (± 0.71%)6.81s (± 0.66%)~6.75s6.87sp=0.810 n=6
Bind Time1.88s (± 0.48%)1.88s (± 0.88%)~1.85s1.89sp=0.803 n=6
Check Time31.09s (± 0.34%)31.15s (± 0.53%)~31.03s31.47sp=0.630 n=6
Emit Time14.72s (± 0.66%)14.78s (± 0.29%)~14.72s14.84sp=0.377 n=6
Total Time54.49s (± 0.17%)54.61s (± 0.34%)~54.42s54.93sp=0.173 n=6
mui-docs - node (v18.15.0, x64)
Errors55~~~p=1.000 n=6
Symbols1,961,2901,961,274-16 (- 0.00%)~~p=0.001 n=6
Types696,905696,860-45 (- 0.01%)~~p=0.001 n=6
Memory used1,778,074k (± 0.00%)1,778,019k (± 0.00%)-56k (- 0.00%)1,778,006k1,778,038kp=0.005 n=6
Parse Time6.77s (± 0.38%)6.78s (± 0.24%)~6.76s6.81sp=0.332 n=6
Bind Time2.31s (± 1.11%)2.31s (± 0.22%)~2.31s2.32sp=0.928 n=6
Check Time57.01s (± 0.32%)56.97s (± 0.34%)~56.74s57.28sp=0.575 n=6
Emit Time0.14s0.14s~~~p=1.000 n=6
Total Time66.23s (± 0.29%)66.20s (± 0.28%)~65.97s66.49sp=0.575 n=6
self-build-src - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,220,2471,220,280+33 (+ 0.00%)~~p=0.001 n=6
Types258,932258,941+9 (+ 0.00%)~~p=0.001 n=6
Memory used2,334,478k (± 0.04%)2,334,608k (± 0.03%)~2,333,545k2,335,230kp=0.936 n=6
Parse Time4.99s (± 1.79%)4.96s (± 1.57%)~4.85s5.07sp=0.810 n=6
Bind Time1.86s (± 0.63%)1.88s (± 1.00%)~1.86s1.91sp=0.187 n=6
Check Time33.48s (± 0.32%)33.37s (± 0.32%)~33.26s33.54sp=0.109 n=6
Emit Time2.61s (± 2.40%)2.64s (± 1.82%)~2.55s2.68sp=0.228 n=6
Total Time42.94s (± 0.46%)42.86s (± 0.41%)~42.72s43.20sp=0.630 n=6
self-build-src-public-api - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,220,2471,220,280+33 (+ 0.00%)~~p=0.001 n=6
Types258,932258,941+9 (+ 0.00%)~~p=0.001 n=6
Memory used2,410,887k (± 0.02%)2,411,704k (± 0.03%)+817k (+ 0.03%)2,410,948k2,412,348kp=0.045 n=6
Parse Time7.68s (± 0.84%)7.73s (± 1.46%)~7.58s7.91sp=0.378 n=6
Bind Time2.50s (± 1.87%)2.50s (± 0.93%)~2.46s2.53sp=0.575 n=6
Check Time49.26s (± 0.48%)49.38s (± 0.34%)~49.07s49.57sp=0.336 n=6
Emit Time3.85s (± 3.34%)3.81s (± 1.33%)~3.74s3.86sp=0.810 n=6
Total Time63.28s (± 0.39%)63.42s (± 0.43%)~62.89s63.64sp=0.173 n=6
self-compiler - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols256,476256,479+3 (+ 0.00%)~~p=0.001 n=6
Types104,239104,238-1 (- 0.00%)~~p=0.001 n=6
Memory used425,330k (± 0.00%)425,345k (± 0.01%)~425,313k425,384kp=0.471 n=6
Parse Time3.38s (± 0.16%)3.35s (± 0.82%)~3.32s3.39sp=0.250 n=6
Bind Time1.30s (± 0.90%)1.31s (± 0.89%)~1.29s1.32sp=0.185 n=6
Check Time17.79s (± 0.23%)17.75s (± 0.58%)~17.56s17.86sp=0.630 n=6
Emit Time1.35s (± 0.89%)1.36s (± 2.18%)~1.33s1.41sp=1.000 n=6
Total Time23.82s (± 0.21%)23.78s (± 0.48%)~23.58s23.91sp=0.521 n=6
ts-pre-modules - node (v18.15.0, x64)
Errors3535~~~p=1.000 n=6
Symbols224,575224,575~~~p=1.000 n=6
Types93,78593,785~~~p=1.000 n=6
Memory used369,747k (± 0.02%)369,852k (± 0.03%)~369,702k370,016kp=0.093 n=6
Parse Time2.83s (± 0.86%)2.82s (± 1.47%)~2.77s2.88sp=0.686 n=6
Bind Time1.58s (± 0.66%)1.60s (± 0.94%)~1.57s1.61sp=0.142 n=6
Check Time15.57s (± 0.36%)15.57s (± 0.42%)~15.47s15.67sp=0.571 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time19.98s (± 0.41%)19.99s (± 0.41%)~19.88s20.13sp=0.687 n=6
vscode - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols2,809,6532,809,890+237 (+ 0.01%)~~p=0.001 n=6
Types953,438953,461+23 (+ 0.00%)~~p=0.001 n=6
Memory used2,981,399k (± 0.00%)2,981,559k (± 0.00%)~2,981,474k2,981,687kp=0.054 n=6
Parse Time13.69s (± 0.41%)13.72s (± 0.61%)~13.60s13.83sp=0.575 n=6
Bind Time4.10s (± 2.02%)4.14s (± 2.62%)~4.06s4.28sp=0.570 n=6
Check Time72.99s (± 2.66%)72.30s (± 0.56%)~71.85s73.03sp=0.575 n=6
Emit Time22.97s (± 7.08%)23.57s (± 0.88%)~23.37s23.84sp=0.936 n=6
Total Time113.75s (± 0.44%)113.72s (± 0.49%)~113.04s114.32sp=1.000 n=6
webpack - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols265,866265,866~~~p=1.000 n=6
Types108,424108,424~~~p=1.000 n=6
Memory used410,525k (± 0.02%)410,556k (± 0.01%)~410,483k410,640kp=0.575 n=6
Parse Time4.75s (± 0.74%)4.73s (± 0.80%)~4.68s4.79sp=0.198 n=6
Bind Time2.07s (± 0.61%)2.05s (± 1.33%)~2.01s2.08sp=0.285 n=6
Check Time20.89s (± 0.18%)20.91s (± 0.51%)~20.73s21.03sp=0.471 n=6
Emit Time0.00s (±244.70%)0.00s~~~p=0.405 n=6
Total Time27.72s (± 0.16%)27.69s (± 0.50%)~27.49s27.85sp=0.872 n=6
xstate-main - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols524,576524,841+265 (+ 0.05%)~~p=0.001 n=6
Types178,847178,899+52 (+ 0.03%)~~p=0.001 n=6
Memory used462,531k (± 0.01%)462,674k (± 0.02%)+144k (+ 0.03%)462,549k462,824kp=0.031 n=6
Parse Time3.89s (± 0.41%)3.89s (± 0.25%)~3.88s3.90sp=1.000 n=6
Bind Time1.45s (± 1.40%)1.44s (± 1.16%)~1.42s1.46sp=0.367 n=6
Check Time22.46s (± 0.63%)22.41s (± 0.56%)~22.27s22.57sp=0.521 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time27.80s (± 0.49%)27.74s (± 0.42%)~27.62s27.89sp=0.423 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • Compiler-Unions - node (v18.15.0, x64)
  • angular-1 - node (v18.15.0, x64)
  • mui-docs - node (v18.15.0, x64)
  • self-build-src - node (v18.15.0, x64)
  • self-build-src-public-api - node (v18.15.0, x64)
  • self-compiler - node (v18.15.0, x64)
  • ts-pre-modules - node (v18.15.0, x64)
  • vscode - node (v18.15.0, x64)
  • webpack - node (v18.15.0, x64)
  • xstate-main - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

Developer Information:

Download Benchmarks

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the top 400 repos comparing main and refs/pull/57909/merge:

Everything looks good!

@jakebailey

Copy link
Copy Markdown
Member

Indeed, just rechecking since this is old and also we have new perf benchmarks / stats.

@weswighamWesley Wigham (weswigham) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the tests are good, I'm fine with this (nice cheeky PR title that copies the title given to two other PRs that have edited this), but I do want to take a moment to write about this function at a conceptual level. The comment in the code does a poor job of this - it's literally restating what the code below does, rather than really expounding on the why it's doing what it does.

We're trying to pick between the covariant position inference result and the contravariant position inference result. Strictly speaking, when the results differ, you can easily be in a situation where there simply is no correct inference. For example, if we're inferring from (x: number) => string to (x: T) => T. Picking either number or string instead is basically just a choice of which error to produce at the argument site - there is no single T that the input type will be assignable to (except any). However, if you're a bit lucky, one of the two results will work in both positions and produce a type for which the overall argument is assignable. For example, if you have (x: number) => 0, 0 will work for T in both positions. So will number. Ideally, we'd just note all the possible inferences and try them all to see if any choice results in a valid assignment of the argument, then pick that one. Instead we hem and haw a bit because we don't really want to do all that backtracking (it's costly), and try to find a local heuristic to pick one or the other for each type argument. And, moreover, when multiple results are valid, determining a useful "ranking" of them for the "best" match is helpful, since users typically have an intent or expectation for how we bias our choices in situations like these.

As of this PR, that ranking is:

  1. Covariant result if not never or any, assignable to all contravariant candidates, and the variable being inferred isn't referred to by another variable's constraint directly and every covariant inference candidate is assignable to the chosen covariant inference result
  2. Contravariant result, if present
  3. Covariant result

Why is this the ranking? Uh... I dunno. Mostly just empirical testing of "this gives good results". I really wish I could point to more rigor here. Certainly, I cannot point to an algebra from which this algorithm arises. Heck, I'd argue it's kinda wrong and bad - in the (x: number) => 0 example above, it picks 0, but number would be a more reasonable pick. By what metric? Feels. Literals are constraining, and I'd feel you should only pick them as a last resort.

But at least over our current implementation, assignability over subtyping makes sense, since arguments are ultimately compared via assignability and not subtyping (though using the compareTypes on the inference context may be better still, since that would allow the subtype overload pass to use subtypes for its heuristic as those arguments are compared via subtype, while the second pass can use assignment), and excepting Any in the same way as Never from the ranking also tracks (since they're basically the same on the source side of a relationship, as is compared in the first step here).

Comment threadsrc/compiler/checker.ts Outdated
@jakebailey

Copy link
Copy Markdown
Member

Hm, baselines don't seem to be fully up to date.

@Andarist

Copy link
Copy Markdown
ContributorAuthor

Jake Bailey (@jakebailey) fixed that :)

@Andarist

Copy link
Copy Markdown
ContributorAuthor

though using the compareTypes on the inference context may be better still, since that would allow the subtype overload pass to use subtypes for its heuristic as those arguments are compared via subtype, while the second pass can use assignment

I see why you mention this but I failed to create a reasonable test case showing this is better in practice. I could apply this change blindly as it doesn't make a difference for the existing test suite. I also don't think it would surface anything in the extended test suite since that would essentially move the needle closer to the state before this PR for some cases. So I'm hesitant to make this change as I'd prefer to do it with a test case at hand.

At the same time, I see a risk in introducing this change (and funny enough I failed to create a test case showing this too, even a contrived one) since contextual parameter types (cached!) would be assigned based on the proposed subtyped check from the first overload pass. This could potentially yield worse results for them when the secondary pass (using assignableRelation) could still succeed.

@trevorade

Copy link
Copy Markdown

Should this PR be mentioned in the 5.6 Announcements under Notable Behavioral Changes?

I realize the Beta and RC announcements have already gone out.

@microsoftMicrosoft (microsoft) locked as resolved and limited conversation to collaborators Oct 16, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

For Backlog BugPRs that fix a backlog bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.call on an union with different arguments counts fails when passing any Contravariant inference gets picked when a a better covariant candidate exists

6 participants

@Andarist@typescript-bot@jakebailey@trevorade@weswigham@sandersn