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

Add missing relationship allowing a type to be assignable to a conditional when assignable to both branches #30639

Merged
merged 12 commits into from
Mar 11, 2021

Conversation

weswigham
Copy link
Member

@weswigham weswigham commented Mar 29, 2019

Fixes #29505
Fixes #29662
Fixes #26933
Fixes #25413 (with the caveat that the conditional in the example needs to be non-distributive)

This is super simple compared to #27932. To account for distributivity, we simply instantiate the distributed type with a replacement mapper so we're always comparing with "some arbitrary subtype" of it. Combined with our newer conditional type simplification rules, this seems to handle all the common cases people have submitted. ❤️

The place where this differs from #27932 is the never-case handling for distributive conditionals. Unlike that PR, this PR chooses to say that even for distributive conditionals, so long as you're assignable to all possible types for both branches, you're assignable to the conditional. Nothing is assignable to never other than never, so that case of the distributive type really stands out. It almost feels like T extends R ? A : B when T=never should actually reduce to A&B rather than never - for most conditionals this does end up essentially being never anyway (since most conditionals "filter" types), but for a certain class of "dumb" conditionals which map rather than filer, that type is still useful, and actually seems to be the real bound of the type (unlike never, which is too far down the matrix, as it were).

@weswigham weswigham force-pushed the conditional-both-branch-relation branch from 7344f40 to 346d1f9 Compare March 29, 2019 22:37
@jack-williams
Copy link
Collaborator

jack-williams commented Apr 2, 2019

Edit: I don’t think there is anything serious going on here; I’m just thinking that this is a new manifestation of the behaviour in #30020.

Can you check this example on your branch?

function foo<T>(x: T, y: ([T] extends [string] ? string : boolean) extends boolean ? 1 : 2, z: 2) {
    y = z; // should error, might not.
}
foo(true, 1, 2)

@weswigham
Copy link
Member Author

weswigham commented Apr 3, 2019

It in fact does not error like it should at present - I started looking into it this afternoon, and fixing #30708 (and its extension in this PR to generic conditionals) looks like it's going to need some revisions to how we measure "permissive" instantiations (a specially-handled any is, as pointed out by many, often not quite right). I think I'm mostly done (making a separate "reading" permissive type and "writing" permissive type and swapping between them as positional variance during instantiation calls for seems to do the trick), but I've been a little overzealous in my refactors along the way (had to check for some mapper identities during conditional type instantiation so refactored some things to remove some needless mapper remappings and secondary caching, and broke some stuff along the way), so I need to take a bit to revert some of it - hopefully I'll have an update ready sometime tomorrow, but it will greatly complicate this PR; I may split it off into a separate one. ❤️

@jack-williams
Copy link
Collaborator

I think I'm mostly done (making a separate "reading" permissive type and "writing" permissive type and swapping between them as positional variance during instantiation calls for seems to do the trick)

Awesome stuff! This work here also breaks stuff down into positive and negative occurrences of ?/any in certain cases, so that approach feels like it's on the right track.

Copy link
Member

@andrewbranch andrewbranch left a comment

Choose a reason for hiding this comment

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

I noticed a while back that you can’t make a React element with a generic TagName due to a conditional type in LibraryManagedAttributes (a pattern which, by the way, I do not particularly condone, but was looking into as, say, “opposition research” for an alternative approach), so I tested this to see if it helps with that problem. It does get one step closer, but on second look, clearly components are not going to be assignable to both sides of that large nested conditional.

Nonetheless, this seems like a win—any reason we shouldn’t merge it? Is there still interest in #27932 (which IIUC would supersede the changes here)?

By the way, there aren’t merge conflicts but it doesn’t build as-is as trueType and falseType have been renamed.

@andrewbranch
Copy link
Member

image

👏 👏

@jack-williams
Copy link
Collaborator

Cross-posting from #31277. Might be worth running user tests and DT on this.

@sandersn sandersn added the For Milestone Bug PRs that fix a bug with a specific milestone label Feb 1, 2020
@sandersn
Copy link
Member

@weswigham
I think this PR needs:

  1. user/docker/DT/RWC runs (probably docker and DT have the most conditional types right now?)
  2. a review from @ahejlsberg
  3. a perf test of a codebase with conditional types, either added to the perf suite, or an ad-hoc series of average runs of Popular Conditional-Heavy Project.

Does that sound right to you?

src/compiler/checker.ts Outdated Show resolved Hide resolved
@sandersn
Copy link
Member

@weswigham now that the perf test suite has material-ui, can you merge from master and summarise the results of the perf test?

@weswigham weswigham force-pushed the conditional-both-branch-relation branch from 80226c8 to 1024ad1 Compare March 30, 2020 23:08
@weswigham weswigham force-pushed the conditional-both-branch-relation branch from 1024ad1 to 786e5a4 Compare March 30, 2020 23:12
@sandersn
Copy link
Member

@weswigham would you be able to get this up-to-date with master? Let's take this for 4.3 -- early so that we have a chance to shake out any subtle problems.

@sandersn
Copy link
Member

@typescript-bot perf test this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 11, 2021

Heya @sandersn, I've started to run the perf test suite on this PR at 8642a5f. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

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

Here they are:

Comparison Report - master..30639

Metric master 30639 Delta Best Worst
Angular - node (v10.16.3, x64)
Memory used 348,560k (± 0.01%) 348,605k (± 0.03%) +44k (+ 0.01%) 348,410k 348,911k
Parse Time 1.92s (± 0.92%) 1.92s (± 0.50%) +0.00s (+ 0.05%) 1.89s 1.94s
Bind Time 0.83s (± 0.91%) 0.83s (± 0.67%) -0.00s (- 0.24%) 0.82s 0.85s
Check Time 5.06s (± 0.57%) 5.07s (± 0.34%) +0.01s (+ 0.10%) 5.04s 5.11s
Emit Time 5.93s (± 0.68%) 5.91s (± 0.34%) -0.02s (- 0.39%) 5.87s 5.95s
Total Time 13.75s (± 0.41%) 13.73s (± 0.22%) -0.02s (- 0.13%) 13.66s 13.80s
Compiler-Unions - node (v10.16.3, x64)
Memory used 204,639k (± 0.15%) 204,732k (± 0.12%) +93k (+ 0.05%) 203,852k 205,103k
Parse Time 0.78s (± 0.79%) 0.78s (± 0.77%) -0.00s (- 0.64%) 0.76s 0.79s
Bind Time 0.52s (± 0.85%) 0.52s (± 1.35%) -0.00s (- 0.57%) 0.50s 0.53s
Check Time 7.42s (± 0.82%) 7.39s (± 0.62%) -0.03s (- 0.35%) 7.31s 7.51s
Emit Time 2.58s (± 0.79%) 2.58s (± 0.64%) -0.00s (- 0.08%) 2.55s 2.62s
Total Time 11.30s (± 0.67%) 11.26s (± 0.46%) -0.04s (- 0.32%) 11.17s 11.42s
Monaco - node (v10.16.3, x64)
Memory used 356,687k (± 0.01%) 356,674k (± 0.02%) -13k (- 0.00%) 356,536k 356,856k
Parse Time 1.55s (± 0.61%) 1.55s (± 0.42%) -0.00s (- 0.06%) 1.53s 1.56s
Bind Time 0.73s (± 0.81%) 0.74s (± 0.88%) +0.00s (+ 0.41%) 0.73s 0.76s
Check Time 5.24s (± 0.66%) 5.22s (± 0.55%) -0.02s (- 0.36%) 5.16s 5.26s
Emit Time 3.15s (± 1.10%) 3.13s (± 1.06%) -0.02s (- 0.48%) 3.07s 3.24s
Total Time 10.67s (± 0.61%) 10.64s (± 0.57%) -0.03s (- 0.29%) 10.54s 10.79s
TFS - node (v10.16.3, x64)
Memory used 308,970k (± 0.02%) 308,990k (± 0.02%) +21k (+ 0.01%) 308,872k 309,091k
Parse Time 1.21s (± 0.46%) 1.21s (± 0.33%) +0.00s (+ 0.25%) 1.20s 1.22s
Bind Time 0.70s (± 0.85%) 0.69s (± 0.52%) -0.00s (- 0.29%) 0.69s 0.70s
Check Time 4.69s (± 0.24%) 4.69s (± 0.51%) +0.00s (+ 0.02%) 4.64s 4.76s
Emit Time 3.24s (± 0.80%) 3.24s (± 1.19%) -0.01s (- 0.22%) 3.16s 3.32s
Total Time 9.83s (± 0.27%) 9.82s (± 0.44%) -0.01s (- 0.05%) 9.74s 9.94s
material-ui - node (v10.16.3, x64)
Memory used 501,639k (± 0.01%) 502,348k (± 0.02%) +710k (+ 0.14%) 502,110k 502,471k
Parse Time 1.99s (± 0.70%) 2.00s (± 0.72%) +0.01s (+ 0.65%) 1.97s 2.04s
Bind Time 0.65s (± 1.43%) 0.64s (± 1.57%) -0.00s (- 0.46%) 0.63s 0.67s
Check Time 14.30s (± 0.90%) 14.34s (± 0.60%) +0.04s (+ 0.27%) 14.23s 14.59s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 16.93s (± 0.79%) 16.98s (± 0.50%) +0.05s (+ 0.28%) 16.88s 17.25s
Angular - node (v12.1.0, x64)
Memory used 326,127k (± 0.09%) 326,159k (± 0.07%) +32k (+ 0.01%) 325,214k 326,390k
Parse Time 1.90s (± 0.56%) 1.89s (± 0.53%) -0.01s (- 0.37%) 1.86s 1.91s
Bind Time 0.81s (± 0.76%) 0.81s (± 0.72%) -0.00s (- 0.25%) 0.80s 0.82s
Check Time 4.97s (± 0.68%) 4.97s (± 0.59%) -0.00s (- 0.02%) 4.91s 5.05s
Emit Time 6.01s (± 0.72%) 6.00s (± 1.09%) -0.00s (- 0.08%) 5.91s 6.24s
Total Time 13.68s (± 0.49%) 13.67s (± 0.63%) -0.02s (- 0.13%) 13.54s 13.99s
Compiler-Unions - node (v12.1.0, x64)
Memory used 191,458k (± 0.03%) 191,339k (± 0.14%) -119k (- 0.06%) 190,738k 192,125k
Parse Time 0.77s (± 0.76%) 0.77s (± 0.80%) +0.00s (+ 0.26%) 0.76s 0.79s
Bind Time 0.53s (± 0.71%) 0.52s (± 1.62%) -0.00s (- 0.76%) 0.51s 0.54s
Check Time 6.96s (± 0.51%) 6.98s (± 0.66%) +0.02s (+ 0.36%) 6.91s 7.10s
Emit Time 2.58s (± 1.22%) 2.59s (± 1.06%) +0.01s (+ 0.27%) 2.53s 2.65s
Total Time 10.83s (± 0.43%) 10.86s (± 0.43%) +0.03s (+ 0.27%) 10.77s 10.98s
Monaco - node (v12.1.0, x64)
Memory used 339,115k (± 0.01%) 339,143k (± 0.04%) +28k (+ 0.01%) 338,887k 339,553k
Parse Time 1.54s (± 1.00%) 1.52s (± 0.39%) -0.01s (- 0.72%) 1.51s 1.54s
Bind Time 0.72s (± 0.62%) 0.72s (± 0.90%) +0.00s (+ 0.00%) 0.70s 0.73s
Check Time 5.05s (± 0.27%) 5.03s (± 0.78%) -0.02s (- 0.48%) 4.96s 5.14s
Emit Time 3.14s (± 1.17%) 3.10s (± 0.78%) -0.04s (- 1.18%) 3.04s 3.15s
Total Time 10.45s (± 0.47%) 10.37s (± 0.43%) -0.07s (- 0.69%) 10.25s 10.49s
TFS - node (v12.1.0, x64)
Memory used 293,112k (± 0.02%) 293,112k (± 0.02%) +1k (+ 0.00%) 293,012k 293,231k
Parse Time 1.22s (± 0.63%) 1.21s (± 0.62%) -0.00s (- 0.16%) 1.19s 1.22s
Bind Time 0.69s (± 0.83%) 0.68s (± 1.11%) -0.01s (- 0.87%) 0.67s 0.70s
Check Time 4.61s (± 0.76%) 4.59s (± 0.44%) -0.01s (- 0.24%) 4.56s 4.65s
Emit Time 3.16s (± 1.40%) 3.15s (± 0.63%) -0.01s (- 0.35%) 3.11s 3.19s
Total Time 9.67s (± 0.77%) 9.64s (± 0.32%) -0.03s (- 0.30%) 9.57s 9.72s
material-ui - node (v12.1.0, x64)
Memory used 479,455k (± 0.05%) 480,209k (± 0.05%) +754k (+ 0.16%) 479,183k 480,450k
Parse Time 1.99s (± 0.62%) 1.99s (± 0.66%) -0.00s (- 0.25%) 1.96s 2.03s
Bind Time 0.64s (± 1.01%) 0.64s (± 0.91%) -0.00s (- 0.16%) 0.62s 0.65s
Check Time 12.90s (± 0.75%) 12.91s (± 0.58%) +0.01s (+ 0.09%) 12.77s 13.13s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.53s (± 0.66%) 15.54s (± 0.43%) +0.01s (+ 0.03%) 15.40s 15.72s
Angular - node (v14.15.1, x64)
Memory used 324,976k (± 0.01%) 324,968k (± 0.01%) -8k (- 0.00%) 324,933k 324,996k
Parse Time 1.90s (± 0.62%) 1.91s (± 0.58%) +0.01s (+ 0.26%) 1.89s 1.94s
Bind Time 0.85s (± 0.68%) 0.85s (± 0.68%) -0.00s (- 0.35%) 0.83s 0.86s
Check Time 4.93s (± 0.42%) 4.94s (± 0.59%) +0.01s (+ 0.20%) 4.90s 5.04s
Emit Time 6.26s (± 0.30%) 6.27s (± 0.36%) +0.01s (+ 0.24%) 6.21s 6.32s
Total Time 13.94s (± 0.26%) 13.97s (± 0.39%) +0.03s (+ 0.22%) 13.86s 14.12s
Compiler-Unions - node (v14.15.1, x64)
Memory used 191,077k (± 0.02%) 191,080k (± 0.02%) +4k (+ 0.00%) 190,992k 191,141k
Parse Time 0.80s (± 0.46%) 0.79s (± 0.46%) -0.00s (- 0.25%) 0.79s 0.80s
Bind Time 0.55s (± 0.40%) 0.55s (± 0.54%) +0.00s (+ 0.18%) 0.55s 0.56s
Check Time 6.99s (± 0.56%) 6.99s (± 0.49%) -0.00s (- 0.01%) 6.92s 7.06s
Emit Time 2.54s (± 0.76%) 2.54s (± 0.93%) +0.00s (+ 0.12%) 2.51s 2.61s
Total Time 10.87s (± 0.40%) 10.88s (± 0.44%) +0.00s (+ 0.03%) 10.81s 10.99s
Monaco - node (v14.15.1, x64)
Memory used 338,046k (± 0.00%) 338,064k (± 0.00%) +18k (+ 0.01%) 338,041k 338,083k
Parse Time 1.56s (± 0.69%) 1.55s (± 0.29%) -0.01s (- 0.83%) 1.54s 1.56s
Bind Time 0.74s (± 0.46%) 0.74s (± 0.40%) -0.00s (- 0.13%) 0.74s 0.75s
Check Time 4.95s (± 0.52%) 4.97s (± 0.44%) +0.02s (+ 0.30%) 4.92s 5.02s
Emit Time 3.15s (± 0.83%) 3.16s (± 0.27%) +0.01s (+ 0.29%) 3.14s 3.18s
Total Time 10.41s (± 0.34%) 10.42s (± 0.27%) +0.01s (+ 0.10%) 10.35s 10.47s
TFS - node (v14.15.1, x64)
Memory used 292,251k (± 0.01%) 292,315k (± 0.01%) +64k (+ 0.02%) 292,241k 292,378k
Parse Time 1.26s (± 1.83%) 1.24s (± 0.66%) -0.01s (- 1.11%) 1.22s 1.26s
Bind Time 0.71s (± 0.42%) 0.71s (± 0.56%) -0.00s (- 0.42%) 0.70s 0.72s
Check Time 4.58s (± 0.54%) 4.60s (± 0.36%) +0.02s (+ 0.46%) 4.56s 4.63s
Emit Time 3.25s (± 0.85%) 3.24s (± 0.44%) -0.00s (- 0.06%) 3.20s 3.26s
Total Time 9.79s (± 0.43%) 9.79s (± 0.27%) +0.00s (+ 0.01%) 9.73s 9.84s
material-ui - node (v14.15.1, x64)
Memory used 477,992k (± 0.01%) 478,616k (± 0.00%) +623k (+ 0.13%) 478,571k 478,659k
Parse Time 2.06s (± 0.57%) 2.05s (± 0.41%) -0.01s (- 0.58%) 2.02s 2.06s
Bind Time 0.70s (± 0.74%) 0.69s (± 0.72%) -0.00s (- 0.57%) 0.68s 0.70s
Check Time 12.93s (± 0.37%) 12.94s (± 0.68%) +0.01s (+ 0.10%) 12.83s 13.23s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.69s (± 0.27%) 15.69s (± 0.59%) -0.00s (- 0.01%) 15.56s 15.98s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-198-generic
Architecturex64
Available Memory16 GB
Available Memory5 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 30639 10
Baseline master 10

Developer Information:

Download Benchmark

@sandersn
Copy link
Member

Performance still looks fine. I'm going to merge this since it's ready.

@sandersn sandersn merged commit 2643e65 into microsoft:master Mar 11, 2021
@sandersn sandersn deleted the conditional-both-branch-relation branch March 11, 2021 19:57
@jcalz
Copy link
Contributor

jcalz commented Aug 29, 2024

Anyone coming back here wondering why this doesn't work for distributive conditional types: it was reverted in #46429 (which is of course linked above)

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
Archived in project
9 participants