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

Simplify relationship check for conditional type on target side #46429

Merged
merged 5 commits into from
Oct 22, 2021

Conversation

ahejlsberg
Copy link
Member

@ahejlsberg ahejlsberg commented Oct 19, 2021

This PR simplifies our relationship checking logic for conditional types on the target side. With this PR, a source type S is assignable to a target type A extends B ? C : D when

  • The conditional type is not distributive, or is distributive but A is never referenced in C or D, and
  • B has no infer positions, and
  • S is assignable to C (except if A never assignable to B for any instantiation), and
  • S is assignable to D (except if A is always assignable to B for any instantiation).

The PR revises some of the logic that was added in #30639, specifically the logic that determines if A is referenced in C or D in a distributive conditional type. There are no baseline changes as a result of this PR, but it fixes the performance degradation reported in #44851.

Fixes #44851.

@ahejlsberg
Copy link
Member Author

ahejlsberg commented Oct 19, 2021

I should mention that with this PR, the check time for this repro drops from ~10s to about 0.4s.

@andrewbranch
Copy link
Member

@typescript-bot test this
@typescript-bot user test this inline
@typescript-bot run DT
@typescript-bot perf test this
@typescript-bot pack this
@typescript-bot all the things please

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 19, 2021

Heya @andrewbranch, I've started to run the inline community code test suite on this PR at 75ab347. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 19, 2021

Heya @andrewbranch, I've started to run the extended test suite on this PR at 75ab347. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 19, 2021

Heya @andrewbranch, I've started to run the parallelized Definitely Typed test suite on this PR at 75ab347. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 19, 2021

Heya @andrewbranch, I've started to run the tarball bundle task on this PR at 75ab347. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 19, 2021

Heya @andrewbranch, I've started to run the perf test suite on this PR at 75ab347. You can monitor the build here.

Update: The results are in!

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Oct 19, 2021

Hurray, I helped find something maybe useful!

@typescript-bot
Copy link
Collaborator

@andrewbranch
Great news! no new errors were found between main..refs/pull/46429/merge

@@ -48,7 +55,13 @@ tests/cases/compiler/conditionalTypeAssignabilityWhenDeferred.ts(116,3): error T
function f<T>(t: T) {
var x: T | null = Math.random() > 0.5 ? null : t;
onlyNullablePlease(x); // should work
~
!!! error TS2345: Argument of type 'T | null' is not assignable to parameter of type 'null extends T | null ? any : never'.
Copy link
Member

Choose a reason for hiding this comment

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

This one is interesting - is this actually a distributive conditional type? Why is it deferred?

Copy link
Member Author

Choose a reason for hiding this comment

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

We always defer if either of the check and extends types contains generics. This is somewhat of a blunt instrument, and we could possibly do better in cases like this.

Copy link
Member Author

Choose a reason for hiding this comment

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

And by "contains generics" I mean we defer when isGenericType returns true for either of the check and extends types.

@weswigham
Copy link
Member

weswigham commented Oct 19, 2021

If we're going to attempt to fix those, the fix really should be to have the conditional type construction logic decide to resolve the types instead of deferring them--but I think that has lower priority.

This is impossible in the general case - any condition with an infer has to be deferred so the infer can be instantiated with every possible input (since an infer result can't stand on its own) - if we don't reason about branch reachability in relationship checking, we can never handle conditional types that both filter and transform simultaneously like T extends () => infer I ? I : never. We knew that adding constraint checks on branch reachability would be expensive - but it's the typespace equivalent of doing control flow on genetics, which we also do wherever we can now.

@typescript-bot
Copy link
Collaborator

@andrewbranch
The results of the perf run you requested are in!

Here they are:

Comparison Report - main..46429

Metric main 46429 Delta Best Worst
Angular - node (v10.16.3, x64)
Memory used 354,063k (± 0.01%) 354,012k (± 0.02%) -51k (- 0.01%) 353,868k 354,166k
Parse Time 1.96s (± 0.58%) 1.95s (± 0.50%) -0.01s (- 0.46%) 1.93s 1.97s
Bind Time 0.84s (± 0.66%) 0.84s (± 0.81%) +0.00s (+ 0.36%) 0.83s 0.86s
Check Time 5.47s (± 0.36%) 5.48s (± 0.81%) +0.01s (+ 0.22%) 5.42s 5.61s
Emit Time 5.86s (± 0.67%) 5.88s (± 0.70%) +0.01s (+ 0.20%) 5.78s 5.98s
Total Time 14.13s (± 0.34%) 14.15s (± 0.46%) +0.02s (+ 0.12%) 14.04s 14.31s
Compiler-Unions - node (v10.16.3, x64)
Memory used 203,871k (± 0.03%) 203,893k (± 0.03%) +22k (+ 0.01%) 203,721k 203,980k
Parse Time 0.78s (± 0.67%) 0.78s (± 0.63%) +0.00s (+ 0.38%) 0.78s 0.80s
Bind Time 0.53s (± 1.13%) 0.52s (± 1.28%) -0.01s (- 1.14%) 0.50s 0.53s
Check Time 7.95s (± 0.67%) 7.90s (± 0.45%) -0.05s (- 0.62%) 7.83s 7.97s
Emit Time 2.45s (± 0.80%) 2.44s (± 0.65%) -0.01s (- 0.45%) 2.40s 2.48s
Total Time 11.71s (± 0.46%) 11.65s (± 0.29%) -0.06s (- 0.51%) 11.56s 11.72s
Monaco - node (v10.16.3, x64)
Memory used 342,091k (± 0.01%) 342,060k (± 0.03%) -32k (- 0.01%) 341,822k 342,213k
Parse Time 1.48s (± 0.78%) 1.49s (± 0.46%) +0.00s (+ 0.13%) 1.47s 1.50s
Bind Time 0.75s (± 0.82%) 0.75s (± 0.67%) -0.00s (- 0.53%) 0.74s 0.76s
Check Time 5.46s (± 0.55%) 5.42s (± 0.83%) -0.03s (- 0.59%) 5.33s 5.51s
Emit Time 3.17s (± 0.70%) 3.17s (± 0.83%) +0.00s (+ 0.00%) 3.12s 3.25s
Total Time 10.86s (± 0.31%) 10.82s (± 0.31%) -0.04s (- 0.33%) 10.74s 10.88s
TFS - node (v10.16.3, x64)
Memory used 304,751k (± 0.01%) 304,803k (± 0.02%) +52k (+ 0.02%) 304,682k 304,886k
Parse Time 1.20s (± 0.68%) 1.19s (± 0.25%) -0.01s (- 0.42%) 1.19s 1.20s
Bind Time 0.71s (± 0.70%) 0.71s (± 0.56%) +0.00s (+ 0.71%) 0.70s 0.72s
Check Time 4.97s (± 0.51%) 4.95s (± 0.67%) -0.02s (- 0.38%) 4.88s 5.03s
Emit Time 3.30s (± 1.07%) 3.32s (± 1.02%) +0.02s (+ 0.45%) 3.26s 3.40s
Total Time 10.17s (± 0.45%) 10.17s (± 0.44%) -0.01s (- 0.06%) 10.10s 10.28s
material-ui - node (v10.16.3, x64)
Memory used 471,094k (± 0.02%) 469,960k (± 0.01%) -1,134k (- 0.24%) 469,861k 470,042k
Parse Time 1.77s (± 0.56%) 1.77s (± 0.42%) -0.00s (- 0.17%) 1.76s 1.79s
Bind Time 0.66s (± 1.23%) 0.66s (± 1.22%) -0.00s (- 0.30%) 0.64s 0.68s
Check Time 14.38s (± 0.41%) 14.34s (± 0.56%) -0.04s (- 0.31%) 14.18s 14.58s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 16.82s (± 0.39%) 16.77s (± 0.52%) -0.05s (- 0.32%) 16.59s 17.02s
Angular - node (v12.1.0, x64)
Memory used 331,719k (± 0.08%) 331,897k (± 0.02%) +178k (+ 0.05%) 331,749k 332,046k
Parse Time 1.96s (± 0.67%) 1.94s (± 0.51%) -0.02s (- 1.02%) 1.92s 1.97s
Bind Time 0.82s (± 1.34%) 0.82s (± 1.15%) 0.00s ( 0.00%) 0.80s 0.84s
Check Time 5.33s (± 0.81%) 5.31s (± 0.38%) -0.02s (- 0.41%) 5.27s 5.36s
Emit Time 6.15s (± 0.82%) 6.09s (± 0.44%) -0.06s (- 0.99%) 6.05s 6.18s
Total Time 14.26s (± 0.59%) 14.16s (± 0.28%) -0.10s (- 0.72%) 14.08s 14.26s
Compiler-Unions - node (v12.1.0, x64)
Memory used 191,425k (± 0.04%) 191,331k (± 0.07%) -94k (- 0.05%) 190,906k 191,583k
Parse Time 0.78s (± 0.67%) 0.78s (± 0.93%) +0.00s (+ 0.13%) 0.77s 0.80s
Bind Time 0.53s (± 0.89%) 0.53s (± 0.71%) -0.01s (- 0.94%) 0.52s 0.53s
Check Time 7.40s (± 0.55%) 7.41s (± 0.71%) +0.00s (+ 0.07%) 7.32s 7.56s
Emit Time 2.46s (± 0.85%) 2.46s (± 1.46%) +0.00s (+ 0.12%) 2.39s 2.55s
Total Time 11.17s (± 0.48%) 11.17s (± 0.72%) +0.00s (+ 0.01%) 11.02s 11.36s
Monaco - node (v12.1.0, x64)
Memory used 325,197k (± 0.02%) 325,207k (± 0.02%) +11k (+ 0.00%) 325,051k 325,336k
Parse Time 1.48s (± 0.91%) 1.46s (± 0.55%) -0.02s (- 1.15%) 1.45s 1.49s
Bind Time 0.73s (± 0.85%) 0.73s (± 1.23%) -0.00s (- 0.41%) 0.72s 0.76s
Check Time 5.32s (± 0.81%) 5.33s (± 0.38%) +0.01s (+ 0.23%) 5.28s 5.39s
Emit Time 3.20s (± 0.72%) 3.18s (± 0.71%) -0.02s (- 0.69%) 3.14s 3.23s
Total Time 10.73s (± 0.57%) 10.70s (± 0.34%) -0.03s (- 0.25%) 10.63s 10.78s
TFS - node (v12.1.0, x64)
Memory used 289,506k (± 0.02%) 289,475k (± 0.02%) -31k (- 0.01%) 289,342k 289,574k
Parse Time 1.22s (± 0.82%) 1.21s (± 0.87%) -0.01s (- 0.90%) 1.20s 1.24s
Bind Time 0.70s (± 0.86%) 0.69s (± 1.06%) -0.01s (- 1.01%) 0.68s 0.71s
Check Time 4.92s (± 0.26%) 4.90s (± 0.56%) -0.02s (- 0.39%) 4.84s 4.96s
Emit Time 3.39s (± 0.99%) 3.37s (± 0.65%) -0.02s (- 0.53%) 3.33s 3.42s
Total Time 10.23s (± 0.41%) 10.17s (± 0.47%) -0.06s (- 0.57%) 10.08s 10.30s
material-ui - node (v12.1.0, x64)
Memory used 449,723k (± 0.06%) 448,617k (± 0.06%) -1,106k (- 0.25%) 447,464k 448,866k
Parse Time 1.79s (± 0.91%) 1.78s (± 0.72%) -0.01s (- 0.45%) 1.76s 1.82s
Bind Time 0.65s (± 1.03%) 0.64s (± 0.76%) -0.00s (- 0.46%) 0.63s 0.65s
Check Time 13.01s (± 0.85%) 12.97s (± 0.73%) -0.04s (- 0.28%) 12.83s 13.15s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.45s (± 0.73%) 15.40s (± 0.64%) -0.05s (- 0.30%) 15.23s 15.58s
Angular - node (v14.15.1, x64)
Memory used 330,294k (± 0.01%) 330,303k (± 0.01%) +9k (+ 0.00%) 330,268k 330,340k
Parse Time 1.96s (± 0.48%) 1.94s (± 0.48%) -0.02s (- 1.27%) 1.91s 1.95s
Bind Time 0.87s (± 0.54%) 0.86s (± 0.39%) -0.01s (- 0.80%) 0.86s 0.87s
Check Time 5.37s (± 0.44%) 5.37s (± 0.37%) -0.00s (- 0.07%) 5.32s 5.40s
Emit Time 6.19s (± 0.98%) 6.19s (± 0.63%) -0.01s (- 0.10%) 6.08s 6.26s
Total Time 14.39s (± 0.54%) 14.35s (± 0.37%) -0.04s (- 0.29%) 14.18s 14.43s
Compiler-Unions - node (v14.15.1, x64)
Memory used 192,554k (± 0.49%) 192,879k (± 0.37%) +325k (+ 0.17%) 189,971k 193,279k
Parse Time 0.81s (± 0.72%) 0.81s (± 1.17%) +0.01s (+ 0.87%) 0.80s 0.84s
Bind Time 0.56s (± 0.53%) 0.55s (± 0.62%) -0.01s (- 0.90%) 0.55s 0.56s
Check Time 7.60s (± 0.38%) 7.56s (± 0.47%) -0.05s (- 0.63%) 7.48s 7.65s
Emit Time 2.45s (± 0.92%) 2.44s (± 0.82%) -0.01s (- 0.57%) 2.41s 2.50s
Total Time 11.42s (± 0.33%) 11.36s (± 0.35%) -0.06s (- 0.49%) 11.29s 11.46s
Monaco - node (v14.15.1, x64)
Memory used 323,999k (± 0.01%) 323,990k (± 0.01%) -9k (- 0.00%) 323,951k 324,030k
Parse Time 1.51s (± 0.88%) 1.51s (± 0.72%) -0.01s (- 0.46%) 1.49s 1.53s
Bind Time 0.76s (± 0.48%) 0.76s (± 0.48%) 0.00s ( 0.00%) 0.75s 0.76s
Check Time 5.33s (± 0.50%) 5.30s (± 0.42%) -0.03s (- 0.53%) 5.27s 5.38s
Emit Time 3.23s (± 0.47%) 3.23s (± 0.68%) -0.00s (- 0.03%) 3.18s 3.27s
Total Time 10.83s (± 0.36%) 10.79s (± 0.24%) -0.04s (- 0.37%) 10.73s 10.87s
TFS - node (v14.15.1, x64)
Memory used 288,354k (± 0.01%) 288,339k (± 0.01%) -15k (- 0.01%) 288,308k 288,377k
Parse Time 1.24s (± 0.63%) 1.23s (± 0.53%) -0.01s (- 0.89%) 1.21s 1.24s
Bind Time 0.74s (± 0.46%) 0.73s (± 0.71%) -0.01s (- 1.09%) 0.72s 0.74s
Check Time 4.94s (± 0.31%) 4.91s (± 0.48%) -0.03s (- 0.57%) 4.87s 4.97s
Emit Time 3.49s (± 0.35%) 3.49s (± 0.82%) +0.01s (+ 0.17%) 3.43s 3.55s
Total Time 10.40s (± 0.24%) 10.36s (± 0.31%) -0.04s (- 0.38%) 10.28s 10.45s
material-ui - node (v14.15.1, x64)
Memory used 447,964k (± 0.06%) 446,820k (± 0.08%) -1,143k (- 0.26%) 445,818k 447,128k
Parse Time 1.83s (± 0.42%) 1.82s (± 0.49%) -0.01s (- 0.33%) 1.80s 1.85s
Bind Time 0.68s (± 0.70%) 0.68s (± 0.44%) +0.00s (+ 0.15%) 0.67s 0.68s
Check Time 13.19s (± 0.94%) 13.10s (± 0.46%) -0.09s (- 0.68%) 12.97s 13.25s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.70s (± 0.82%) 15.61s (± 0.38%) -0.09s (- 0.59%) 15.48s 15.75s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-210-generic
Architecturex64
Available Memory16 GB
Available Memory6 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v10.16.3, x64)
  • node (v12.1.0, x64)
  • node (v14.15.1, x64)
Scenarios
  • Angular - node (v10.16.3, x64)
  • Angular - node (v12.1.0, x64)
  • Angular - node (v14.15.1, x64)
  • Compiler-Unions - node (v10.16.3, x64)
  • Compiler-Unions - node (v12.1.0, x64)
  • Compiler-Unions - node (v14.15.1, x64)
  • Monaco - node (v10.16.3, x64)
  • Monaco - node (v12.1.0, x64)
  • Monaco - node (v14.15.1, x64)
  • TFS - node (v10.16.3, x64)
  • TFS - node (v12.1.0, x64)
  • TFS - node (v14.15.1, x64)
  • material-ui - node (v10.16.3, x64)
  • material-ui - node (v12.1.0, x64)
  • material-ui - node (v14.15.1, x64)
Benchmark Name Iterations
Current 46429 10
Baseline main 10

Developer Information:

Download Benchmark

@ahejlsberg
Copy link
Member Author

@typescript-bot test this
@typescript-bot user test this
@typescript-bot run dt
@typescript-bot pack this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 19, 2021

Heya @ahejlsberg, I've started to run the extended test suite on this PR at 75ab347. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 19, 2021

Heya @ahejlsberg, I've started to run the parallelized community code test suite on this PR at 75ab347. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 19, 2021

Heya @ahejlsberg, I've started to run the tarball bundle task on this PR at 75ab347. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 19, 2021

Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at 75ab347. You can monitor the build here.

@ahejlsberg
Copy link
Member Author

This is impossible in the general case

Agreed, and so be it. But it does seem like there are classes of cases where we ought to do better in conditional type construction. Both of the test cases that revert back to failing with this PR seem quite trivial--for example, checking if the check and extends types are identical, or if the extends type is a union that contains the check type, would cause us to resolve the conditional type to the true case.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 19, 2021

Hey @ahejlsberg, 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/113306/artifacts?artifactName=tgz&fileId=A263304AC84860808E706B7F5590B0AA3616661B50F7CE35CED050B21FF1B0C802&fileName=/typescript-4.5.0-insiders.20211019.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/[email protected]".;

@amcasey
Copy link
Member

amcasey commented Oct 21, 2021

I'll reiterate that I'm with ignoring my repro since I probably made nonsense out of the logic while tinkering with it. Obviously, never being slow is the ideal, but it's more important to focus on code people might actually write. Alternatively, we could call this good and file a separate bug to go investigate that repro.

@ahejlsberg
Copy link
Member Author

I think I can say with a high degree of certainty that whatever is going on in @amcasey's example is unrelated. I removed all of the logic having to do with assignability to conditional types (i.e. both #30639 and this PR), and the example still blows up with an instantiation depth error.

@DanielRosenwasser
Copy link
Member

Please, no more plot twists, my heart can't handle it anymore.

@andrewbranch
Copy link
Member

Yeah, if the real world code is fast then I’m happy. Just wanted to make sure it was checked against the latest changes.

@DetachHead
Copy link
Contributor

is there an example of a type that is no longer allowed as of this PR? the typescript 4.5 blog post mentions this PR

TypeScript no longer allows types to be assignable to conditional types that use infer, or that are distributive. Doing so previously often ended up causing major performance issues. For more information, see the specific change on GitHub.

but i can't seem to find a minimal example of what this means exactly

@RyanCavanaugh
Copy link
Member

@DetachHead good news (??), we found one: #47127 (comment)

@iahu
Copy link

iahu commented Dec 14, 2021

@DetachHead good news (??), we found one: #47127 (comment)

This is a BAD news for me. I deeply dependency this feature. Because of this breaking change, I cant update TypeScript, it's so bad for me, could you add a compiler option to support it as a migrate plan?

mprobst pushed a commit to mprobst/TypeScript that referenced this pull request Jan 10, 2022
…osoft#46429)

* Simplify relationship check for conditional type on target side

* Accept new baselines

* Better support for non-distribution-dependent types

* Accept new API baselines

* Accept new baselines
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team For Milestone Bug PRs that fix a bug with a specific milestone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Semantic highlighting (encodedSemanticClassifications-full) extremely slow
9 participants