Skip to content

Ensure common supertype retains nullability in inference #49981

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

Closed
wants to merge 5 commits into from

Conversation

jakebailey
Copy link
Member

@jakebailey jakebailey commented Jul 21, 2022

Fixes #49938

Demo: Playground Link

The common supertype of a bunch of inference candidates should include null and undefined of those candidates can be null or undefined.

#49119 and #49330 changed the way this information was stored and propagated. It turns out that the old code only worked because of a fluke related to those flags. In v4.7.4, given the types in the playground link above:

  • The candidates are B and D | undefined. We declare that these are both "primary types" because neither are exactly null or undefined.
  • We look for the supertype of these, but because neither are supertypes of each other (because of the undefined), we end up picking B as it's the leftmost option.
  • But then, we would rescan the input types for the types whose falsy flags include null or undefined, but using a function that is recursive, so we find D | undefined, when the intent was to just find exactly null or undefined.
  • We union that with B to get B | D | undefined, which reduces to D | undefined, and we get the supertype that everyone had expected all along, even though that's maybe not what the code was written to do!

Instead, we can just compare the candidates without null or undefined, then add null or undefined back on again if the supertype needs it; this means that the cases we supported in 4.7.4 work (and now work the same regardless of argument order).

@typescript-bot typescript-bot added Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Jul 21, 2022
@jakebailey

This comment was marked as outdated.

@jakebailey

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@jakebailey

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@typescript-bot

This comment was marked as outdated.

@jakebailey

This comment was marked as outdated.

@jakebailey jakebailey marked this pull request as draft July 21, 2022 17:17
@jakebailey
Copy link
Member Author

Well, I narrowed this down to operate strictly on only unions and direct types, so it shouldn't have that build problem anymore (and I encoded it as a test).

@jakebailey
Copy link
Member Author

@typescript-bot test this
@typescript-bot user test this inline
@typescript-bot pack this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jul 21, 2022

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

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jul 21, 2022

Heya @jakebailey, I've started to run the diff-based user code test suite on this PR at a817435. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jul 21, 2022

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

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jul 21, 2022

Hey @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/130164/artifacts?artifactName=tgz&fileId=32A768F7B0A1960DB14C832B8F12F2972D738FB3A5CC18B69F843EBC2D78CBD902&fileName=/typescript-4.8.0-insiders.20220721.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]".;

@typescript-bot
Copy link
Collaborator

Heya @jakebailey, I've run the RWC suite on this PR - assuming you're on the TS core team, you can view the resulting diff here.

@typescript-bot
Copy link
Collaborator

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

@jakebailey
Copy link
Member Author

Demo as of this current commit: Playground Link

@jakebailey
Copy link
Member Author

jakebailey commented Jul 22, 2022

RE: the RWC tests, I think there might be one error in there that's real, but I'm having trouble understanding what's going on there because it looks like a bunch of unrelated things are showing up in the diff that shouldn't be there if the diff was running on the same version of the test codebases.

The error sort of implies that void should also be considered, though...

@jakebailey jakebailey marked this pull request as ready for review July 22, 2022 18:28
@jakebailey jakebailey requested a review from ahejlsberg July 22, 2022 18:28
@typescript-bot typescript-bot added For Milestone Bug PRs that fix a bug with a specific milestone and removed For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Jul 22, 2022
@jakebailey
Copy link
Member Author

@typescript-bot perf test this faster

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jul 22, 2022

Heya @jakebailey, I've started to run the abridged perf test suite on this PR at a817435. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

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

Here they are:

Comparison Report - main..49981

Metric main 49981 Delta Best Worst
Angular - node (v14.15.1, x64)
Memory used 335,954k (± 0.00%) 335,952k (± 0.01%) -2k (- 0.00%) 335,900k 336,022k
Parse Time 2.05s (± 0.52%) 2.07s (± 0.48%) +0.01s (+ 0.58%) 2.04s 2.09s
Bind Time 0.89s (± 0.84%) 0.90s (± 0.91%) +0.00s (+ 0.45%) 0.88s 0.92s
Check Time 5.81s (± 0.52%) 5.83s (± 0.40%) +0.02s (+ 0.34%) 5.76s 5.87s
Emit Time 6.36s (± 0.30%) 6.38s (± 0.61%) +0.02s (+ 0.31%) 6.29s 6.46s
Total Time 15.12s (± 0.28%) 15.17s (± 0.44%) +0.06s (+ 0.38%) 14.98s 15.30s
Compiler-Unions - node (v14.15.1, x64)
Memory used 193,134k (± 0.02%) 193,102k (± 0.01%) -32k (- 0.02%) 193,059k 193,144k
Parse Time 0.85s (± 0.73%) 0.85s (± 1.04%) +0.01s (+ 0.59%) 0.84s 0.88s
Bind Time 0.57s (± 0.64%) 0.57s (± 0.97%) +0.01s (+ 1.06%) 0.56s 0.58s
Check Time 6.71s (± 0.59%) 6.71s (± 0.31%) +0.00s (+ 0.06%) 6.66s 6.75s
Emit Time 2.49s (± 1.02%) 2.51s (± 1.37%) +0.02s (+ 0.76%) 2.46s 2.63s
Total Time 10.61s (± 0.41%) 10.65s (± 0.45%) +0.04s (+ 0.34%) 10.59s 10.82s
Monaco - node (v14.15.1, x64)
Memory used 325,660k (± 0.00%) 325,628k (± 0.01%) -31k (- 0.01%) 325,579k 325,675k
Parse Time 1.58s (± 0.39%) 1.58s (± 0.56%) +0.01s (+ 0.38%) 1.57s 1.61s
Bind Time 0.78s (± 0.60%) 0.78s (± 0.46%) +0.00s (+ 0.51%) 0.78s 0.79s
Check Time 5.68s (± 0.49%) 5.69s (± 0.54%) +0.02s (+ 0.30%) 5.64s 5.76s
Emit Time 3.34s (± 0.47%) 3.36s (± 0.66%) +0.01s (+ 0.45%) 3.31s 3.42s
Total Time 11.38s (± 0.22%) 11.42s (± 0.43%) +0.04s (+ 0.38%) 11.34s 11.56s
TFS - node (v14.15.1, x64)
Memory used 288,788k (± 0.01%) 288,806k (± 0.01%) +18k (+ 0.01%) 288,743k 288,856k
Parse Time 1.32s (± 1.67%) 1.34s (± 1.72%) +0.03s (+ 1.97%) 1.30s 1.41s
Bind Time 0.77s (± 4.97%) 0.77s (± 4.64%) -0.01s (- 1.16%) 0.73s 0.86s
Check Time 5.35s (± 0.38%) 5.37s (± 0.38%) +0.02s (+ 0.36%) 5.33s 5.42s
Emit Time 3.58s (± 1.99%) 3.58s (± 2.15%) -0.00s (- 0.00%) 3.42s 3.71s
Total Time 11.02s (± 0.79%) 11.05s (± 0.78%) +0.03s (+ 0.25%) 10.86s 11.19s
material-ui - node (v14.15.1, x64)
Memory used 446,695k (± 0.01%) 446,605k (± 0.05%) -90k (- 0.02%) 445,630k 446,780k
Parse Time 1.87s (± 0.37%) 1.89s (± 0.47%) +0.01s (+ 0.80%) 1.87s 1.91s
Bind Time 0.72s (± 0.80%) 0.72s (± 0.92%) -0.00s (- 0.00%) 0.71s 0.74s
Check Time 13.12s (± 0.50%) 13.30s (± 0.73%) +0.18s (+ 1.37%) 13.04s 13.57s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.72s (± 0.46%) 15.91s (± 0.64%) +0.20s (+ 1.25%) 15.64s 16.20s
xstate - node (v14.15.1, x64)
Memory used 541,302k (± 0.00%) 541,298k (± 0.01%) -4k (- 0.00%) 541,241k 541,370k
Parse Time 2.60s (± 0.40%) 2.60s (± 0.64%) +0.00s (+ 0.04%) 2.57s 2.64s
Bind Time 1.17s (± 1.43%) 1.14s (± 1.57%) -0.02s (- 1.89%) 1.11s 1.19s
Check Time 1.55s (± 0.53%) 1.55s (± 0.49%) +0.01s (+ 0.45%) 1.54s 1.57s
Emit Time 0.07s (± 0.00%) 0.07s (± 4.66%) +0.00s (+ 4.29%) 0.07s 0.08s
Total Time 5.38s (± 0.42%) 5.37s (± 0.30%) -0.01s (- 0.19%) 5.34s 5.42s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-210-generic
Architecturex64
Available Memory16 GB
Available Memory15 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v14.15.1, x64)
Scenarios
  • Angular - node (v14.15.1, x64)
  • Compiler-Unions - node (v14.15.1, x64)
  • Monaco - node (v14.15.1, x64)
  • TFS - node (v14.15.1, x64)
  • material-ui - node (v14.15.1, x64)
  • xstate - node (v14.15.1, x64)
Benchmark Name Iterations
Current 49981 10
Baseline main 10

Developer Information:

Download Benchmark

Comment on lines +21243 to +21244
function someHas(type: Type, flags: TypeFlags): boolean {
return someType(type, t => !!(t.flags & flags));
Copy link
Member

Choose a reason for hiding this comment

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

This feels common enough that I would rather us lift it up to someTypeHasFlags

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 can do that, yeah, though I think most places just entirely inline it, so I could just do that too.

@jakebailey
Copy link
Member Author

#50021 is a more complete fix than mine now, so, closing.

@jakebailey jakebailey closed this Jul 24, 2022
@jakebailey jakebailey deleted the fix-49938 branch October 20, 2022 17:24
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.

Inference doesn't find common base type for union with null or undefined - TypeScript 4.8 regression
3 participants