Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate the error any type in union and intersection construction #58610

Merged
merged 3 commits into from
May 23, 2024

Conversation

weswigham
Copy link
Member

You might not think this is the obvious fix for the issue, but it is! Type parameter constraints, when they see a non-error any, remap it to unknown (there are historical reasons for this). So by swallowing the error-any (and replacing it with a normal any), union and intersection construction resulted in the constraint calculation logic not witnessing the error type, and thus remapping the constraint (and, thus, making the constraint from the type node not match the cached constraint on the type parameter itself!)

This should also just behave a bit better with respect to follow on errors in some other cases, too.

Fixes #58598

@typescript-bot typescript-bot added Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels May 21, 2024
@jakebailey
Copy link
Member

Is this at all related to #56429?

@weswigham
Copy link
Member Author

It's related insofar as better error-type propagation often creates better behaviors for follow-on locations for us.

@weswigham weswigham marked this pull request as ready for review May 21, 2024 22:25
Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

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

Looks good, some quibbles with formatting. And we should see how DT/top400 tests look.

@@ -17303,7 +17304,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (unionReduction !== UnionReduction.None) {
if (includes & TypeFlags.AnyOrUnknown) {
return includes & TypeFlags.Any ?
includes & TypeFlags.IncludesWildcard ? wildcardType : anyType :
includes & TypeFlags.IncludesWildcard ? wildcardType :
includes & TypeFlags.IncludesError ? errorType : anyType :
unknownType;
Copy link
Member

Choose a reason for hiding this comment

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

These ternaries are officially off the chain now.

Copy link
Member Author

Choose a reason for hiding this comment

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

🤷‍♀️ I just write the ternaries, I let the formatter figure out how it wants to indent them.

@@ -17637,7 +17640,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return neverType;
}
if (includes & TypeFlags.Any) {
return includes & TypeFlags.IncludesWildcard ? wildcardType : anyType;
return includes & TypeFlags.IncludesWildcard ? wildcardType : includes & TypeFlags.IncludesError ? errorType : anyType;
Copy link
Member

Choose a reason for hiding this comment

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

it would be nice to have multiple lines here

@@ -6185,6 +6185,8 @@ export const enum TypeFlags {
StringMapping = 1 << 28, // Uppercase/Lowercase type
/** @internal */
Reserved1 = 1 << 29, // Used by union/intersection type construction
/** @internal */
Reserved2 = 1 << 30, // Used by union/intersection type construction
Copy link
Member

Choose a reason for hiding this comment

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

remind me, do we have 31 bits available?

Copy link
Member

Choose a reason for hiding this comment

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

In modern Node, yep, we do.

@jakebailey
Copy link
Member

@typescript-bot test it

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 22, 2024

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-bot
Copy link
Collaborator

@jakebailey Here are the results of running the user tests comparing main and refs/pull/58610/merge:

Something interesting changed - please have a look.

Details

effect

tsconfig.json

tsconfig.base.json

puppeteer

test/tsconfig.json

@typescript-bot
Copy link
Collaborator

Hey @jakebailey, the results of running the DT tests are ready.

Everything looks the same!

You can check the log here.

@typescript-bot
Copy link
Collaborator

@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 - node (v18.15.0, x64)
Errors 30 30 ~ ~ ~ p=1.000 n=6
Symbols 62,154 62,154 ~ ~ ~ p=1.000 n=6
Types 50,248 50,248 ~ ~ ~ p=1.000 n=6
Memory used 194,058k (± 1.03%) 192,252k (± 0.03%) ~ 192,187k 192,365k p=0.230 n=6
Parse Time 1.29s (± 1.27%) 1.30s (± 1.26%) ~ 1.27s 1.31s p=0.321 n=6
Bind Time 0.72s 0.72s ~ ~ ~ p=1.000 n=6
Check Time 9.55s (± 0.37%) 9.57s (± 0.21%) ~ 9.55s 9.59s p=0.374 n=6
Emit Time 2.63s (± 0.46%) 2.63s (± 0.46%) ~ 2.61s 2.64s p=0.406 n=6
Total Time 14.20s (± 0.30%) 14.21s (± 0.28%) ~ 14.16s 14.26s p=0.468 n=6
angular-1 - node (v18.15.0, x64)
Errors 5 5 ~ ~ ~ p=1.000 n=6
Symbols 944,110 944,110 ~ ~ ~ p=1.000 n=6
Types 407,140 407,140 ~ ~ ~ p=1.000 n=6
Memory used 1,222,050k (± 0.00%) 1,222,075k (± 0.00%) ~ 1,221,989k 1,222,120k p=0.575 n=6
Parse Time 6.79s (± 0.74%) 6.82s (± 0.26%) ~ 6.80s 6.85s p=0.171 n=6
Bind Time 1.88s (± 0.62%) 1.88s (± 0.52%) ~ 1.87s 1.89s p=0.555 n=6
Check Time 31.25s (± 0.25%) 31.32s (± 0.49%) ~ 31.11s 31.50s p=0.471 n=6
Emit Time 14.71s (± 0.38%) 14.76s (± 0.33%) ~ 14.71s 14.83s p=0.296 n=6
Total Time 54.64s (± 0.23%) 54.78s (± 0.35%) ~ 54.54s 54.98s p=0.173 n=6
mui-docs - node (v18.15.0, x64)
Errors 5 5 ~ ~ ~ p=1.000 n=6
Symbols 1,978,404 1,978,450 +46 (+ 0.00%) ~ ~ p=0.001 n=6
Types 882,046 882,062 +16 (+ 0.00%) ~ ~ p=0.001 n=6
Memory used 1,884,924k (± 0.00%) 1,884,982k (± 0.00%) +58k (+ 0.00%) 1,884,962k 1,885,013k p=0.030 n=6
Parse Time 6.77s (± 0.33%) 6.76s (± 0.20%) ~ 6.74s 6.78s p=0.163 n=6
Bind Time 2.29s (± 0.18%) 2.24s (± 5.67%) ~ 1.98s 2.30s p=0.929 n=6
Check Time 60.37s (± 0.60%) 60.40s (± 0.24%) ~ 60.21s 60.59s p=0.336 n=6
Emit Time 0.14s (± 2.88%) 0.15s (± 3.52%) ~ 0.14s 0.15s p=0.112 n=6
Total Time 69.57s (± 0.52%) 69.53s (± 0.29%) ~ 69.25s 69.78s p=0.873 n=6
self-build-src - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 1,223,262 1,223,286 +24 (+ 0.00%) ~ ~ p=0.001 n=6
Types 260,177 260,185 +8 (+ 0.00%) ~ ~ p=0.001 n=6
Memory used 2,339,410k (± 0.03%) 2,339,735k (± 0.04%) ~ 2,338,837k 2,341,091k p=0.630 n=6
Parse Time 5.01s (± 1.07%) 4.98s (± 0.78%) ~ 4.93s 5.04s p=0.261 n=6
Bind Time 1.90s (± 0.80%) 1.89s (± 1.09%) ~ 1.86s 1.91s p=0.511 n=6
Check Time 33.86s (± 0.27%) 33.84s (± 0.25%) ~ 33.73s 33.97s p=0.689 n=6
Emit Time 2.68s (± 2.22%) 2.65s (± 1.27%) ~ 2.59s 2.69s p=0.296 n=6
Total Time 43.46s (± 0.27%) 43.37s (± 0.30%) ~ 43.21s 43.53s p=0.298 n=6
self-build-src-public-api - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 1,223,262 1,223,286 +24 (+ 0.00%) ~ ~ p=0.001 n=6
Types 260,177 260,185 +8 (+ 0.00%) ~ ~ p=0.001 n=6
Memory used 2,415,130k (± 0.05%) 2,440,419k (± 2.49%) ~ 2,414,014k 2,564,802k p=0.378 n=6
Parse Time 6.29s (± 0.79%) 6.23s (± 0.98%) ~ 6.16s 6.34s p=0.173 n=6
Bind Time 2.05s (± 1.37%) 2.05s (± 1.94%) ~ 2.01s 2.10s p=0.936 n=6
Check Time 40.24s (± 0.27%) 40.37s (± 0.47%) ~ 40.13s 40.62s p=0.298 n=6
Emit Time 3.26s (± 3.08%) 3.19s (± 1.64%) ~ 3.13s 3.26s p=0.229 n=6
Total Time 51.83s (± 0.21%) 51.86s (± 0.27%) ~ 51.69s 52.05s p=1.000 n=6
self-compiler - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 257,714 257,716 +2 (+ 0.00%) ~ ~ p=0.001 n=6
Types 104,904 104,906 +2 (+ 0.00%) ~ ~ p=0.001 n=6
Memory used 426,487k (± 0.01%) 426,460k (± 0.01%) ~ 426,412k 426,522k p=0.229 n=6
Parse Time 3.35s (± 0.70%) 3.36s (± 0.64%) ~ 3.33s 3.39s p=0.803 n=6
Bind Time 1.33s (± 0.39%) 1.32s (± 0.48%) ~ 1.31s 1.33s p=0.091 n=6
Check Time 17.93s (± 0.24%) 17.95s (± 0.21%) ~ 17.90s 17.99s p=0.470 n=6
Emit Time 1.36s (± 1.20%) 1.37s (± 0.97%) ~ 1.36s 1.39s p=0.676 n=6
Total Time 23.98s (± 0.16%) 24.00s (± 0.19%) ~ 23.93s 24.05s p=0.520 n=6
ts-pre-modules - node (v18.15.0, x64)
Errors 35 35 ~ ~ ~ p=1.000 n=6
Symbols 224,575 224,575 ~ ~ ~ p=1.000 n=6
Types 93,785 93,785 ~ ~ ~ p=1.000 n=6
Memory used 369,852k (± 0.03%) 369,928k (± 0.02%) ~ 369,822k 370,036k p=0.173 n=6
Parse Time 3.51s (± 0.95%) 3.50s (± 1.09%) ~ 3.47s 3.56s p=0.687 n=6
Bind Time 1.94s (± 0.65%) 1.94s (± 0.73%) ~ 1.92s 1.96s p=1.000 n=6
Check Time 19.35s (± 0.31%) 19.35s (± 0.28%) ~ 19.30s 19.45s p=0.936 n=6
Emit Time 0.00s 0.00s ~ ~ ~ p=1.000 n=6
Total Time 24.80s (± 0.30%) 24.79s (± 0.39%) ~ 24.69s 24.94s p=0.810 n=6
vscode - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 2,834,818 2,834,818 ~ ~ ~ p=1.000 n=6
Types 960,647 960,647 ~ ~ ~ p=1.000 n=6
Memory used 3,006,755k (± 0.00%) 3,006,791k (± 0.00%) ~ 3,006,729k 3,006,862k p=0.336 n=6
Parse Time 13.82s (± 0.21%) 13.81s (± 0.21%) ~ 13.77s 13.85s p=0.808 n=6
Bind Time 4.17s (± 0.38%) 4.26s (± 2.71%) ~ 4.14s 4.38s p=0.625 n=6
Check Time 76.46s (± 1.99%) 75.26s (± 2.95%) ~ 73.10s 77.62s p=0.575 n=6
Emit Time 20.21s (± 7.55%) 21.62s (± 9.75%) ~ 19.56s 23.81s p=0.092 n=6
Total Time 114.66s (± 0.07%) 114.95s (± 0.26%) +0.29s (+ 0.26%) 114.61s 115.47s p=0.045 n=6
webpack - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 266,087 266,087 ~ ~ ~ p=1.000 n=6
Types 108,518 108,518 ~ ~ ~ p=1.000 n=6
Memory used 410,844k (± 0.01%) 410,861k (± 0.03%) ~ 410,770k 411,095k p=0.810 n=6
Parse Time 3.84s (± 0.92%) 3.83s (± 0.71%) ~ 3.79s 3.86s p=0.871 n=6
Bind Time 1.66s (± 1.30%) 1.66s (± 0.89%) ~ 1.64s 1.68s p=0.684 n=6
Check Time 16.89s (± 0.35%) 16.94s (± 0.29%) ~ 16.87s 16.99s p=0.107 n=6
Emit Time 0.00s 0.00s ~ ~ ~ p=1.000 n=6
Total Time 22.39s (± 0.30%) 22.44s (± 0.20%) ~ 22.36s 22.49s p=0.298 n=6
xstate-main - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 524,654 524,654 ~ ~ ~ p=1.000 n=6
Types 178,920 178,920 ~ ~ ~ p=1.000 n=6
Memory used 462,683k (± 0.01%) 462,685k (± 0.02%) ~ 462,582k 462,891k p=0.810 n=6
Parse Time 3.88s (± 0.53%) 3.89s (± 0.68%) ~ 3.86s 3.92s p=0.870 n=6
Bind Time 1.44s (± 1.16%) 1.44s (± 1.13%) ~ 1.42s 1.46s p=0.743 n=6
Check Time 22.54s (± 0.77%) 22.44s (± 0.70%) ~ 22.23s 22.60s p=0.226 n=6
Emit Time 0.00s 0.00s ~ ~ ~ p=1.000 n=6
Total Time 27.87s (± 0.59%) 27.77s (± 0.45%) ~ 27.60s 27.92s p=0.173 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)
Benchmark Name Iterations
Current pr 6
Baseline baseline 6

Developer Information:

Download Benchmarks

@weswigham
Copy link
Member Author

@typescript-bot pack this

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 22, 2024

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

Command Status Results
pack this ✅ Started ✅ Results

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 22, 2024

Hey @weswigham, 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/161864/artifacts?artifactName=tgz&fileId=BF2ED1BFDABF4FEABBEC62B88D698F99B6AF1D9CAF9649FC65736C9D6381C1D002&fileName=/typescript-5.5.0-insiders.20240522.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-58610-9".;

@typescript-bot
Copy link
Collaborator

@jakebailey Here are the results of running the top 400 repos comparing main and refs/pull/58610/merge:

Something interesting changed - please have a look.

Details

nextauthjs/next-auth

18 of 40 projects failed to build with the old tsc and were ignored

docs/tsconfig.json

@weswigham
Copy link
Member Author

weswigham commented May 22, 2024

@typescript-bot user test this

@typescript-bot
Copy link
Collaborator

typescript-bot commented May 22, 2024

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

Command Status Results
user test this ✅ Started 👀 Results

@typescript-bot
Copy link
Collaborator

@weswigham Here are the results of running the user tests comparing main and refs/pull/58610/merge:

Something interesting changed - please have a look.

Details

effect

tsconfig.json

tsconfig.base.json

puppeteer

test/tsconfig.json

@weswigham
Copy link
Member Author

weswigham commented May 22, 2024

Something is funky with Effect-TS in the user harness - the runner shows thousands of errors in the log (Error counts for https://github.com/Effect-TS/effect/blob/e3766411b60ebb45d31e9c9d94efa099121d4d58/tsconfig.json: new = 4804, old = 4775). When you download, install, and build it locally (the same version linked in the log), even with this PR, it's not nearly that bad - 13 errors across all projects, none of them are the ones listed here.

@jakebailey is the runner silently failing to install/link dependencies correctly for that user test or something? That's the only thing I could think of, which is why I reran the test. And it would make sense - these kinda of errors are what I'd expect to see if some intersections in class base types contained unresolved types that now get propagated out (instead of quietly any'd). Error types in class base types make the class's base types get set to nothing, rather than any.

@jakebailey
Copy link
Member

The test thing infers packages and tsconfigs and attempts to install them and run on each of them, so it's possible that it's just doing things "wrong" for that repo. We can convert it to a script test or something where it more clearly tries to run things, but we'll lose the inference of configs and such. I'm not sure I have the time to try and fix the root problem, though.

@weswigham
Copy link
Member Author

weswigham commented May 22, 2024

The project does have one diff in the real output - a new error - but it's a follow-on caused by what I said above - a class has an error type intersected into its' base types, so all its' base types get erased now, rather than any'd (which is what should happen and would happen if the error was the single base type rather than an intersection member already). And the root error is creeping in because the project has skipLibCheck on, so isn't aware that the types for one of its' transitive deps is just straight up missing. (Specifically, packages/sql-mysql2 depends on an external mysql2, which depends on events and stream, which are presumably supposed to be provided by @types/node, but aren't because the project doesn't include @types/node!)

Big downside of using skipLibCheck - you don't get any errors for a missing environment! Though I can see why they enable it - they have a metric ton of straight up broken deps.

@weswigham
Copy link
Member Author

Useful investigation regardless, even if there wasn't really much related to this issue, disabling skipLibCheck in it pointed out this regression that I've opened an issue for.

@weswigham weswigham merged commit b3f3bb3 into microsoft:main May 23, 2024
28 checks passed
@weswigham weswigham deleted the propagate-error-type branch May 23, 2024 16:39
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.

[transpileDeclaration API][5.5] Self referencing generic type constraint with union gets emitted as unknown
4 participants