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

Defer processing generic functions returning intersected functions #58875

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Andarist
Copy link
Contributor

fixes #58833

@typescript-bot typescript-bot added the For Backlog Bug PRs that fix a backlog bug label Jun 15, 2024
return false;
}
const returnType = getReturnTypeOfSignature(signature);
return returnType.flags & TypeFlags.Intersection ? some((returnType as IntersectionType).types, isFunctionType) : isFunctionType(returnType);
Copy link
Member

Choose a reason for hiding this comment

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

Not just someType?

Copy link
Member

Choose a reason for hiding this comment

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

(or whatever that helper is called that walks intersections and maybe unions)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

someType handles "single" types and unions, not intersections. There is everyContainedType that works for unions and intersections but I'd need someContainedType here. It can be done here, I just didn't bother.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe not in this PR, I guess, but isUnitLikeType, isTypeDerivedFrom, isGenericTypeWithUnionConstraint, isGenericTypeWithoutNullableConstraint all do this same thing. (isEmptyObjectType copies/pastes the every variant` too.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just pushed out a change introducing someContainedType

return false;
}
const returnType = getReturnTypeOfSignature(signature);
return returnType.flags & TypeFlags.Intersection ? someContainedType(returnType, isFunctionType) : isFunctionType(returnType);
Copy link
Member

Choose a reason for hiding this comment

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

Isn't the point of the someContainedType helper that this can just be

Suggested change
return returnType.flags & TypeFlags.Intersection ? someContainedType(returnType, isFunctionType) : isFunctionType(returnType);
return someContainedType(returnType, isFunctionType);

?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I intentionally dont want to run this for unions here. Not because I know we shouldnt but because I dont know if we should. Changing the behavior for unions would increase the likelihood of this breaking something for some project

@weswigham
Copy link
Member

Guess that means we should
@typescript-bot test it
but honestly, if that comes back clean, we should probably try handling the union case, too.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 20, 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

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

Everything looks the same!

You can check the log here.

@typescript-bot
Copy link
Collaborator

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

Everything looks good!

@typescript-bot
Copy link
Collaborator

@weswigham
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,153 62,153 ~ ~ ~ p=1.000 n=6
Types 50,242 50,242 ~ ~ ~ p=1.000 n=6
Memory used 192,753k (± 0.77%) 194,045k (± 0.94%) ~ 192,159k 195,793k p=0.066 n=6
Parse Time 1.31s (± 0.75%) 1.31s (± 0.79%) ~ 1.29s 1.32s p=0.591 n=6
Bind Time 0.71s 0.71s (± 0.58%) ~ 0.70s 0.71s p=0.405 n=6
Check Time 9.43s (± 0.33%) 9.43s (± 0.28%) ~ 9.40s 9.48s p=1.000 n=6
Emit Time 2.76s (± 0.37%) 2.75s (± 0.81%) ~ 2.72s 2.78s p=0.805 n=6
Total Time 14.20s (± 0.22%) 14.20s (± 0.29%) ~ 14.15s 14.27s p=0.936 n=6
angular-1 - node (v18.15.0, x64)
Errors 5 5 ~ ~ ~ p=1.000 n=6
Symbols 944,114 944,114 ~ ~ ~ p=1.000 n=6
Types 407,051 407,051 ~ ~ ~ p=1.000 n=6
Memory used 1,218,315k (± 0.00%) 1,218,332k (± 0.00%) ~ 1,218,265k 1,218,387k p=0.423 n=6
Parse Time 7.93s (± 0.27%) 7.95s (± 0.54%) ~ 7.90s 8.01s p=0.373 n=6
Bind Time 2.23s (± 0.40%) 2.23s (± 0.67%) ~ 2.21s 2.25s p=0.557 n=6
Check Time 35.71s (± 0.28%) 35.80s (± 0.31%) ~ 35.68s 35.96s p=0.520 n=6
Emit Time 16.11s (± 0.85%) 16.13s (± 0.72%) ~ 15.92s 16.24s p=0.810 n=6
Total Time 61.98s (± 0.36%) 62.12s (± 0.37%) ~ 61.77s 62.36s p=0.298 n=6
mui-docs - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 2,134,309 2,134,309 ~ ~ ~ p=1.000 n=6
Types 927,039 927,039 ~ ~ ~ p=1.000 n=6
Memory used 2,115,942k (± 0.01%) 2,115,928k (± 0.01%) ~ 2,115,773k 2,116,087k p=0.810 n=6
Parse Time 7.86s (± 0.26%) 7.88s (± 0.39%) ~ 7.82s 7.91s p=0.195 n=6
Bind Time 2.74s (± 0.64%) 2.76s (± 0.65%) ~ 2.74s 2.79s p=0.190 n=6
Check Time 83.90s (± 0.25%) 83.62s (± 0.42%) ~ 83.08s 84.01s p=0.173 n=6
Emit Time 0.16s (± 2.58%) 0.15s (± 3.53%) ~ 0.15s 0.16s p=0.282 n=6
Total Time 94.67s (± 0.23%) 94.41s (± 0.39%) ~ 93.85s 94.84s p=0.199 n=6
self-build-src - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 1,230,692 1,230,696 +4 (+ 0.00%) ~ ~ p=0.001 n=6
Types 261,165 261,167 +2 (+ 0.00%) ~ ~ p=0.001 n=6
Memory used 2,345,449k (± 0.04%) 2,345,327k (± 0.03%) ~ 2,344,392k 2,345,955k p=0.810 n=6
Parse Time 4.97s (± 0.90%) 4.98s (± 1.32%) ~ 4.88s 5.08s p=0.629 n=6
Bind Time 1.91s (± 0.61%) 1.90s (± 0.52%) ~ 1.89s 1.91s p=0.314 n=6
Check Time 33.74s (± 0.32%) 33.75s (± 0.36%) ~ 33.52s 33.85s p=0.748 n=6
Emit Time 2.71s (± 2.67%) 2.75s (± 1.82%) ~ 2.70s 2.82s p=0.199 n=6
Total Time 43.35s (± 0.31%) 43.41s (± 0.40%) ~ 43.14s 43.66s p=0.378 n=6
self-build-src-public-api - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 1,230,692 1,230,696 +4 (+ 0.00%) ~ ~ p=0.001 n=6
Types 261,165 261,167 +2 (+ 0.00%) ~ ~ p=0.001 n=6
Memory used 2,421,678k (± 0.03%) 2,421,197k (± 0.04%) ~ 2,419,523k 2,422,336k p=0.575 n=6
Parse Time 5.18s (± 1.09%) 5.14s (± 0.94%) ~ 5.08s 5.20s p=0.173 n=6
Bind Time 1.70s (± 1.05%) 1.69s (± 0.87%) ~ 1.68s 1.72s p=0.357 n=6
Check Time 34.03s (± 0.22%) 34.08s (± 0.47%) ~ 33.79s 34.26s p=0.298 n=6
Emit Time 2.73s (± 1.78%) 2.77s (± 3.53%) ~ 2.61s 2.86s p=0.336 n=6
Total Time 43.67s (± 0.18%) 43.72s (± 0.66%) ~ 43.18s 44.05s p=0.128 n=6
self-compiler - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 258,573 258,577 +4 (+ 0.00%) ~ ~ p=0.001 n=6
Types 104,819 104,821 +2 (+ 0.00%) ~ ~ p=0.001 n=6
Memory used 428,162k (± 0.01%) 428,254k (± 0.02%) ~ 428,163k 428,371k p=0.128 n=6
Parse Time 2.75s (± 1.04%) 2.77s (± 1.02%) ~ 2.73s 2.81s p=0.806 n=6
Bind Time 1.10s (± 1.37%) 1.11s (± 1.80%) ~ 1.07s 1.12s p=0.180 n=6
Check Time 15.12s (± 0.40%) 15.05s (± 0.36%) ~ 14.96s 15.11s p=0.092 n=6
Emit Time 1.15s (± 1.18%) 1.15s (± 0.71%) ~ 1.13s 1.15s p=0.209 n=6
Total Time 20.13s (± 0.50%) 20.08s (± 0.34%) ~ 19.97s 20.16s p=0.470 n=6
ts-pre-modules - node (v18.15.0, x64)
Errors 35 35 ~ ~ ~ p=1.000 n=6
Symbols 224,565 224,565 ~ ~ ~ p=1.000 n=6
Types 93,734 93,734 ~ ~ ~ p=1.000 n=6
Memory used 369,484k (± 0.02%) 369,489k (± 0.02%) ~ 369,421k 369,589k p=0.936 n=6
Parse Time 2.76s (± 1.57%) 2.76s (± 1.06%) ~ 2.73s 2.81s p=0.466 n=6
Bind Time 1.58s (± 0.74%) 1.58s (± 1.03%) ~ 1.57s 1.61s p=0.731 n=6
Check Time 15.41s (± 0.49%) 15.42s (± 0.37%) ~ 15.36s 15.51s p=0.873 n=6
Emit Time 0.00s 0.00s ~ ~ ~ p=1.000 n=6
Total Time 19.74s (± 0.44%) 19.77s (± 0.28%) ~ 19.68s 19.83s p=0.810 n=6
vscode - node (v18.15.0, x64)
Errors 139 139 ~ ~ ~ p=1.000 n=6
Symbols 2,847,449 2,847,449 ~ ~ ~ p=1.000 n=6
Types 974,045 974,045 ~ ~ ~ p=1.000 n=6
Memory used 3,040,044k (± 0.00%) 3,040,095k (± 0.00%) ~ 3,040,056k 3,040,157k p=0.066 n=6
Parse Time 13.56s (± 0.23%) 13.55s (± 0.42%) ~ 13.47s 13.64s p=0.936 n=6
Bind Time 4.23s (± 2.20%) 4.18s (± 0.46%) ~ 4.15s 4.21s p=0.183 n=6
Check Time 75.38s (± 2.66%) 74.05s (± 0.24%) ~ 73.70s 74.22s p=0.470 n=6
Emit Time 22.68s (± 8.46%) 24.00s (± 0.39%) ~ 23.87s 24.12s p=0.065 n=6
Total Time 115.86s (± 0.12%) 115.79s (± 0.21%) ~ 115.33s 116.01s p=0.873 n=6
webpack - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 267,116 267,116 ~ ~ ~ p=1.000 n=6
Types 108,758 108,758 ~ ~ ~ p=1.000 n=6
Memory used 411,662k (± 0.02%) 411,573k (± 0.02%) ~ 411,467k 411,636k p=0.109 n=6
Parse Time 4.70s (± 0.43%) 4.71s (± 0.68%) ~ 4.68s 4.77s p=0.808 n=6
Bind Time 2.07s (± 1.35%) 2.09s (± 0.84%) ~ 2.07s 2.12s p=1.000 n=6
Check Time 20.82s (± 0.29%) 20.73s (± 0.41%) ~ 20.57s 20.79s p=0.064 n=6
Emit Time 0.00s 0.00s ~ ~ ~ p=1.000 n=6
Total Time 27.60s (± 0.22%) 27.53s (± 0.37%) ~ 27.33s 27.61s p=0.170 n=6
xstate-main - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 523,765 523,765 ~ ~ ~ p=1.000 n=6
Types 178,055 178,055 ~ ~ ~ p=1.000 n=6
Memory used 461,922k (± 0.07%) 461,712k (± 0.09%) ~ 461,304k 462,203k p=0.575 n=6
Parse Time 3.16s (± 0.59%) 3.17s (± 0.52%) ~ 3.14s 3.19s p=0.934 n=6
Bind Time 1.18s (± 1.49%) 1.18s (± 0.44%) ~ 1.17s 1.18s p=0.557 n=6
Check Time 17.93s (± 0.40%) 17.95s (± 0.46%) ~ 17.80s 18.05s p=0.630 n=6
Emit Time 0.00s 0.00s ~ ~ ~ p=1.000 n=6
Total Time 22.27s (± 0.39%) 22.29s (± 0.44%) ~ 22.12s 22.42s p=0.630 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

@typescript-bot
Copy link
Collaborator

@weswigham Here are the results of running the top 400 repos with tsc comparing main and refs/pull/58875/merge:

Something interesting changed - please have a look.

Details

reduxjs/reselect

typescript_test/tsconfig.json

type-tests/tsconfig.json

@Andarist
Copy link
Contributor Author

The above is just a single break (a single type-level test case from reselect). It can be simplified to this playground

The break is related to this comment. There is no way to know if deferring will lead to better or worse results. It turns out that in this specific case, it leads to worse.

This test case lucked out heavily though. OutputSelector is a function type, it happens to have some extra properties on it but they are not essential to reselect's API. If this would be a plain function then this test case wouldn't pass.

Similarly, it just happens to use an intersection to add extra properties. And that (without this PR) prevents this deferred processing. It similarly wouldn't work if it would be declared as a single type.

I think this break is acceptable. It's not great that it breaks something in the wild but it doesn't make sense to have functions with extra properties to behave differently based on how those extra properties are declared.

There is a simple workaround for this case, one can move the nested createSelector call, assign its result to variable, and use that in place of the original nested call. This fixes the problem because the problem is related to how nested calls are resolved. Moving to a variable sidesteps the problem as the variable's type will settle before the compiler get to computing "outer" call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Backlog Bug PRs that fix a backlog bug
Projects
Status: Waiting on reviewers
4 participants