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

Fixed type predicate inference for discriminated union parameters #57952

Conversation

Andarist
Copy link
Contributor

fixes #57947

@typescript-bot typescript-bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Mar 27, 2024
@RyanCavanaugh
Copy link
Member

@typescript-bot test it

@typescript-bot
Copy link
Collaborator

typescript-bot commented Mar 27, 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 @RyanCavanaugh, the results of running the DT tests are ready.

Everything looks the same!

You can check the log here.

@typescript-bot
Copy link
Collaborator

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

Everything looks good!

@typescript-bot
Copy link
Collaborator

@RyanCavanaugh
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
Angular - node (v18.15.0, x64)
Memory used 295,552k (± 0.00%) 295,546k (± 0.00%) ~ 295,537k 295,560k p=0.149 n=6
Parse Time 2.66s (± 0.31%) 2.66s (± 0.15%) ~ 2.66s 2.67s p=0.206 n=6
Bind Time 0.83s (± 0.49%) 0.83s (± 0.00%) ~ 0.83s 0.83s p=0.405 n=6
Check Time 8.20s (± 0.54%) 8.20s (± 0.34%) ~ 8.17s 8.24s p=0.871 n=6
Emit Time 7.03s (± 0.19%) 7.03s (± 0.23%) ~ 7.02s 7.06s p=0.554 n=6
Total Time 18.71s (± 0.21%) 18.72s (± 0.20%) ~ 18.68s 18.77s p=1.000 n=6
Compiler-Unions - node (v18.15.0, x64)
Memory used 192,641k (± 0.78%) 191,950k (± 0.08%) ~ 191,800k 192,216k p=0.128 n=6
Parse Time 1.36s (± 0.89%) 1.36s (± 0.98%) ~ 1.34s 1.38s p=0.360 n=6
Bind Time 0.72s (± 0.75%) 0.73s (± 0.56%) ~ 0.72s 0.73s p=0.282 n=6
Check Time 9.48s (± 0.58%) 9.48s (± 0.72%) ~ 9.41s 9.60s p=0.936 n=6
Emit Time 2.64s (± 0.61%) 2.62s (± 0.86%) ~ 2.59s 2.66s p=0.079 n=6
Total Time 14.20s (± 0.42%) 14.19s (± 0.45%) ~ 14.10s 14.28s p=0.806 n=6
Monaco - node (v18.15.0, x64)
Memory used 347,414k (± 0.01%) 347,407k (± 0.01%) ~ 347,381k 347,440k p=0.936 n=6
Parse Time 2.49s (± 0.30%) 2.48s (± 0.72%) ~ 2.46s 2.51s p=0.164 n=6
Bind Time 0.93s (± 0.44%) 0.93s (± 0.56%) ~ 0.92s 0.93s p=0.595 n=6
Check Time 7.01s (± 0.55%) 7.00s (± 0.28%) ~ 6.98s 7.04s p=0.493 n=6
Emit Time 4.08s (± 0.30%) 4.06s (± 0.26%) ~ 4.05s 4.08s p=0.209 n=6
Total Time 14.51s (± 0.23%) 14.48s (± 0.21%) ~ 14.45s 14.53s p=0.226 n=6
TFS - node (v18.15.0, x64)
Memory used 302,758k (± 0.01%) 302,794k (± 0.01%) ~ 302,755k 302,864k p=0.149 n=6
Parse Time 2.40s (± 1.13%) 2.39s (± 1.32%) ~ 2.34s 2.43s p=0.373 n=6
Bind Time 1.20s (± 2.33%) 1.20s (± 0.68%) ~ 1.19s 1.21s p=0.787 n=6
Check Time 7.47s (± 0.54%) 7.49s (± 0.36%) ~ 7.46s 7.53s p=0.191 n=6
Emit Time 4.27s (± 0.54%) 4.26s (± 0.45%) ~ 4.23s 4.29s p=0.365 n=6
Total Time 15.34s (± 0.52%) 15.34s (± 0.25%) ~ 15.28s 15.40s p=0.688 n=6
material-ui - node (v18.15.0, x64)
Memory used 509,924k (± 0.00%) 509,923k (± 0.01%) ~ 509,898k 509,970k p=0.810 n=6
Parse Time 2.66s (± 0.31%) 2.67s (± 0.21%) ~ 2.66s 2.67s p=0.859 n=6
Bind Time 0.99s (± 0.52%) 0.98s (± 0.56%) ~ 0.98s 0.99s p=0.640 n=6
Check Time 17.21s (± 0.16%) 17.27s (± 0.49%) ~ 17.12s 17.34s p=0.107 n=6
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) ~ 0.00s 0.00s p=1.000 n=6
Total Time 20.86s (± 0.13%) 20.92s (± 0.42%) ~ 20.76s 20.99s p=0.126 n=6
mui-docs - node (v18.15.0, x64)
Memory used 1,737,791k (± 0.00%) 1,737,820k (± 0.00%) ~ 1,737,781k 1,737,870k p=0.092 n=6
Parse Time 7.79s (± 0.27%) 7.98s (± 5.53%) ~ 7.77s 8.88s p=0.935 n=6
Bind Time 2.80s (± 0.45%) 2.80s (± 0.62%) ~ 2.78s 2.83s p=0.867 n=6
Check Time 66.57s (± 0.63%) 66.60s (± 0.36%) ~ 66.31s 66.94s p=0.936 n=6
Emit Time 0.15s (± 3.53%) 0.16s (± 3.29%) ~ 0.15s 0.16s p=0.640 n=6
Total Time 77.33s (± 0.52%) 77.54s (± 0.48%) ~ 77.18s 78.17s p=0.575 n=6
self-build-src - node (v18.15.0, x64)
Memory used 2,392,037k (± 0.02%) 2,391,958k (± 0.03%) ~ 2,390,496k 2,392,638k p=0.575 n=6
Parse Time 6.05s (± 0.49%) 6.04s (± 0.51%) ~ 6.01s 6.09s p=0.511 n=6
Bind Time 2.26s (± 0.96%) 2.25s (± 1.07%) ~ 2.22s 2.27s p=0.622 n=6
Check Time 39.56s (± 0.27%) 39.37s (± 0.24%) -0.19s (- 0.48%) 39.20s 39.46s p=0.016 n=6
Emit Time 3.10s (± 1.41%) 3.13s (± 1.02%) ~ 3.11s 3.19s p=0.261 n=6
Total Time 51.00s (± 0.23%) 50.82s (± 0.22%) -0.19s (- 0.37%) 50.65s 50.94s p=0.045 n=6
self-compiler - node (v18.15.0, x64)
Memory used 415,091k (± 0.02%) 414,979k (± 0.01%) -112k (- 0.03%) 414,947k 415,026k p=0.020 n=6
Parse Time 4.18s (± 0.80%) 4.18s (± 0.48%) ~ 4.16s 4.21s p=1.000 n=6
Bind Time 1.60s (± 0.94%) 1.59s (± 1.36%) ~ 1.55s 1.61s p=0.514 n=6
Check Time 22.43s (± 0.32%) 22.34s (± 0.23%) ~ 22.27s 22.41s p=0.054 n=6
Emit Time 1.68s (± 1.29%) 1.71s (± 0.71%) +0.03s (+ 1.79%) 1.69s 1.72s p=0.018 n=6
Total Time 29.88s (± 0.22%) 29.81s (± 0.24%) ~ 29.69s 29.88s p=0.148 n=6
vscode - node (v18.15.0, x64)
Memory used 2,892,654k (± 0.00%) 2,892,663k (± 0.00%) ~ 2,892,548k 2,892,743k p=0.936 n=6
Parse Time 15.92s (± 0.29%) 15.91s (± 0.29%) ~ 15.88s 16.00s p=0.466 n=6
Bind Time 5.05s (± 0.34%) 5.03s (± 0.34%) -0.02s (- 0.46%) 5.01s 5.05s p=0.035 n=6
Check Time 87.05s (± 0.45%) 86.82s (± 0.20%) ~ 86.51s 87.00s p=0.335 n=6
Emit Time 23.65s (± 0.60%) 23.58s (± 0.35%) ~ 23.51s 23.71s p=0.575 n=6
Total Time 131.66s (± 0.38%) 131.34s (± 0.14%) ~ 131.03s 131.57s p=0.297 n=6
webpack - node (v18.15.0, x64)
Memory used 408,453k (± 0.02%) 408,423k (± 0.01%) ~ 408,337k 408,479k p=0.471 n=6
Parse Time 4.79s (± 0.66%) 4.79s (± 0.67%) ~ 4.75s 4.83s p=1.000 n=6
Bind Time 2.07s (± 0.25%) 2.06s (± 1.12%) ~ 2.02s 2.09s p=0.352 n=6
Check Time 20.71s (± 0.30%) 20.70s (± 0.33%) ~ 20.62s 20.79s p=0.936 n=6
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) ~ 0.00s 0.00s p=1.000 n=6
Total Time 27.56s (± 0.26%) 27.55s (± 0.37%) ~ 27.44s 27.70s p=0.630 n=6
xstate - node (v18.15.0, x64)
Memory used 513,130k (± 0.01%) 513,164k (± 0.01%) ~ 513,065k 513,263k p=0.298 n=6
Parse Time 3.95s (± 0.44%) 3.98s (± 0.61%) +0.04s (+ 0.93%) 3.95s 4.01s p=0.030 n=6
Bind Time 1.88s (± 1.04%) 1.88s (± 1.09%) ~ 1.86s 1.90s p=0.564 n=6
Check Time 3.37s (± 0.37%) 3.38s (± 0.52%) ~ 3.35s 3.40s p=0.806 n=6
Emit Time 0.09s (± 5.95%) 0.08s (± 4.99%) ~ 0.08s 0.09s p=0.112 n=6
Total Time 9.28s (± 0.26%) 9.32s (± 0.37%) ~ 9.27s 9.36s p=0.052 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • Angular - node (v18.15.0, x64)
  • Compiler-Unions - node (v18.15.0, x64)
  • Monaco - node (v18.15.0, x64)
  • TFS - node (v18.15.0, x64)
  • material-ui - node (v18.15.0, x64)
  • mui-docs - node (v18.15.0, x64)
  • self-build-src - node (v18.15.0, x64)
  • self-compiler - node (v18.15.0, x64)
  • vscode - node (v18.15.0, x64)
  • webpack - node (v18.15.0, x64)
  • xstate - node (v18.15.0, x64)
Benchmark Name Iterations
Current pr 6
Baseline baseline 6

Developer Information:

Download Benchmarks

@typescript-bot
Copy link
Collaborator

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

Something interesting changed - please have a look.

Details

vitest-dev/vitest

37 of 43 projects failed to build with the old tsc and were ignored

packages/runner/tsconfig.json

  • error TS2345: Argument of type '(Suite | File)[] | Test<{}>[]' is not assignable to parameter of type '(Suite | File)[]'.

@RyanCavanaugh
Copy link
Member

              const suites = tasksGroup.filter(group => group.type === 'suite')
              const tests = tasksGroup.filter(group => group.type === 'test')
              const groups = shuffle([suites, tests], sequence.seed)
              tasksGroup = groups.flatMap(group => shuffle(group, sequence.seed))

Seems like an expected break

@Andarist
Copy link
Contributor Author

Full TS playground for the above: TS playground

@jakebailey jakebailey closed this Mar 27, 2024
@jakebailey jakebailey reopened this Mar 27, 2024
@RyanCavanaugh
Copy link
Member

@danvk look right to you?

Copy link
Contributor

@danvk danvk left a comment

Choose a reason for hiding this comment

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

LGTM

I'd wondered what the right value for declaredType in the false check was but didn't have a test case that showed it making a difference. Now we do! Thanks for tracking this down, @Andarist.

Not relevant to merging this PR, but I am curious why declaredType matters in this case but not most others. Presumably there are other, unreported bugs that this fixed.

antecedent,
node: expr,
Copy link
Contributor

Choose a reason for hiding this comment

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

any particular reason for this change?

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 tried to follow the structure used by the ones created in the binder to keep functions receiving this monomorphic. I'm not sure if my change prompted this further experiment but it certainly looked like it to me since it was open soon after I opened this one here ;p

TLDR: this was meant as an optimization for the engine. I didn't measure it at all since I don't have time for it but it's usually better to create structures in the same way (order of keys etc matters for the engine)

Copy link
Contributor

Choose a reason for hiding this comment

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

👍 Makes sense. The calls to getFlowTypeOfReference are so expensive compared to everything else in getTypePredicateFromBody that I doubt micro-optimizations matter (see #57465 (comment) and #57660). But I can't imagine they hurt!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

once u apply micro-optimizations at scale there are some good wins to be had :P #57977 (comment)

@Andarist
Copy link
Contributor Author

Andarist commented Apr 2, 2024

Not relevant to merging this PR, but I am curious why declaredType matters in this case but not most others. Presumably there are other, unreported bugs that this fixed.

Without this TS won't attempt to discriminate the union since unions are not involved, see the condition here.

The fix relies on the fact that the assigned type might be different than the declared type and it's still "preserved":

type U = { type: "foo" } | { type: "bar" };

const item: U = { type: "foo" };

item;
// ^? const item: { type: "foo"; }

@RyanCavanaugh RyanCavanaugh merged commit 42a215c into microsoft:main Apr 2, 2024
25 checks passed
@Andarist Andarist deleted the fix/type-predicate-inference-discriminated-union branch April 2, 2024 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Uncommitted Bug PR for untriaged, rejected, closed or missing bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Type predicate not inferred for discriminated union?
5 participants