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 detection of optional chains containing a reference #59144

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

Conversation

Andarist
Copy link
Contributor

@Andarist Andarist commented Jul 5, 2024

fixes #56998
fixes #60855

@typescript-bot typescript-bot added the For Backlog Bug PRs that fix a backlog bug label Jul 5, 2024
@@ -27143,7 +27143,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
function optionalChainContainsReference(source: Node, target: Node) {
while (isOptionalChain(source)) {
source = source.expression;
if (isMatchingReference(source, target)) {
if (isMatchingReference(target, source)) {
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 think an extra refactor should be made here.

isMatchingReference accepts reference as the first parameter but optionalChainContainsReference accepts it as the second one (!). That caused the issue here as both of them refer to both of the parameters as source and target - so it wasn't apparent that the reference (called a target here) is passed to isMatchingReference at the position that is used for candidate expressions (also called a target by that function).

I think it would make sense to:

  1. rename those parameters to something like expression and reference or maybe candidate and reference. isMatchingReference sometimes calls recursively itself with adjusted source (what I propose to call a reference here) but I think that doesn't impact the proposed naming
  2. use consistent order of parameters. I think what optionalChainContainsReference uses is better (reference passed as the second argument to it) but isMatchingReference is likely an older function so maybe the team would prefer that.

Copy link
Member

Choose a reason for hiding this comment

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

This function is nearly identical to containsMatchingReference aside from only supporting optional chaining. I'm not sure argument order is the issue here.

Copy link
Member

Choose a reason for hiding this comment

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

isMatchingReference walks both source and target to different extents. It may just be that some check on one side or the other is not exhaustive enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This function is nearly identical to containsMatchingReference aside from only supporting optional chaining.

Yeah, it is almost identical - and notice that source and target are passed down to isMatchingReference by them at different parameter positions. That only makes me believe more that the argument order is the issue here.

isMatchingReference walks both source and target to different extents. It may just be that some check on one side or the other is not exhaustive enough.

It may be that. But I'm not sure to what extent that function should be walking both so I'm hesitant to make changes there as previous authors haven't embed that logic related to optional chains there.


I re-read the code now and analyzed this again and I'm only more convinced that the argument order is incorrect here. Fixing this in isMatchingReference (without changing the adjusted argument order) would require fixing this at its end (in the switch/case that checks source):

            case SyntaxKind.BinaryExpression:
                return (isBinaryExpression(source) && source.operatorToken.kind === SyntaxKind.CommaToken && isMatchingReference(source.right, target));

The case here doesn't fit what is handled here at all, it does fit what is handled on the target side though:

            case SyntaxKind.BinaryExpression:
                return (isAssignmentExpression(target) && isMatchingReference(source, target.left)) ||
                    (isBinaryExpression(target) && target.operatorToken.kind === SyntaxKind.CommaToken && isMatchingReference(source, target.right));

So given that and the fact that arguments really seem to be semantically flipped when judging by other calls to isMatchingReference, I'm inclined to argue the current fix is the correct one.

@jakebailey
Copy link
Member

@typescript-bot test it

@typescript-bot
Copy link
Collaborator

typescript-bot commented Oct 14, 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 @jakebailey, the results of running the DT tests are ready.

Everything looks the same!

You can check the log here.

@typescript-bot
Copy link
Collaborator

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

Everything looks good!

@typescript-bot
Copy link
Collaborator

@jakebailey
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 31 31 ~ ~ ~ p=1.000 n=6
Symbols 62,340 62,340 ~ ~ ~ p=1.000 n=6
Types 50,379 50,379 ~ ~ ~ p=1.000 n=6
Memory used 195,864k (± 0.74%) 195,775k (± 0.83%) ~ 192,473k 196,596k p=0.689 n=6
Parse Time 1.59s (± 1.47%) 1.61s (± 0.61%) +0.02s (+ 1.58%) 1.60s 1.62s p=0.015 n=6
Bind Time 0.86s (± 0.97%) 0.87s (± 2.62%) ~ 0.83s 0.89s p=0.358 n=6
Check Time 11.73s (± 0.65%) 11.77s (± 0.40%) ~ 11.73s 11.86s p=0.126 n=6
Emit Time 3.35s (± 3.77%) 3.37s (± 4.51%) ~ 3.24s 3.59s p=0.748 n=6
Total Time 17.53s (± 0.83%) 17.63s (± 0.69%) ~ 17.53s 17.83s p=0.148 n=6
angular-1 - node (v18.15.0, x64)
Errors 33 33 ~ ~ ~ p=1.000 n=6
Symbols 947,886 947,886 ~ ~ ~ p=1.000 n=6
Types 410,840 410,840 ~ ~ ~ p=1.000 n=6
Memory used 1,224,805k (± 0.00%) 1,224,822k (± 0.00%) ~ 1,224,759k 1,224,881k p=0.689 n=6
Parse Time 8.12s (± 0.83%) 8.07s (± 1.14%) ~ 7.97s 8.18s p=0.335 n=6
Bind Time 2.27s (± 2.02%) 2.25s (± 0.83%) ~ 2.23s 2.28s p=1.000 n=6
Check Time 37.71s (± 0.29%) 37.74s (± 0.61%) ~ 37.40s 37.99s p=0.575 n=6
Emit Time 18.15s (± 0.63%) 18.22s (± 0.65%) ~ 18.08s 18.40s p=0.173 n=6
Total Time 66.25s (± 0.14%) 66.29s (± 0.51%) ~ 65.80s 66.70s p=0.689 n=6
mui-docs - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 2,530,075 2,530,075 ~ ~ ~ p=1.000 n=6
Types 916,374 916,374 ~ ~ ~ p=1.000 n=6
Memory used 2,341,552k (± 0.01%) 2,341,459k (± 0.01%) ~ 2,341,011k 2,341,660k p=1.000 n=6
Parse Time 11.25s (± 0.53%) 11.20s (± 0.93%) ~ 11.07s 11.34s p=0.421 n=6
Bind Time 2.63s (± 0.64%) 2.62s (± 0.56%) ~ 2.60s 2.64s p=0.210 n=6
Check Time 91.46s (± 1.83%) 91.96s (± 2.06%) ~ 90.72s 95.12s p=0.936 n=6
Emit Time 0.70s (±116.85%) 0.66s (±116.01%) ~ 0.33s 2.23s p=0.070 n=6
Total Time 106.03s (± 1.83%) 106.44s (± 2.18%) ~ 104.88s 109.68s p=0.810 n=6
self-build-src - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 1,258,109 1,258,109 ~ ~ ~ p=1.000 n=6
Types 266,266 266,266 ~ ~ ~ p=1.000 n=6
Memory used 3,026,423k (± 9.72%) 3,146,063k (± 0.03%) ~ 3,144,796k 3,146,953k p=0.936 n=6
Parse Time 6.56s (± 1.77%) 6.61s (± 0.61%) ~ 6.55s 6.67s p=0.296 n=6
Bind Time 2.28s (± 6.06%) 2.31s (± 1.91%) ~ 2.26s 2.39s p=0.521 n=6
Check Time 43.06s (± 0.47%) 43.09s (± 0.28%) ~ 42.86s 43.21s p=0.748 n=6
Emit Time 3.46s (± 2.00%) 3.51s (± 2.18%) ~ 3.42s 3.63s p=0.423 n=6
Total Time 55.38s (± 0.57%) 55.55s (± 0.32%) ~ 55.20s 55.67s p=0.230 n=6
self-build-src-public-api - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 1,258,109 1,258,109 ~ ~ ~ p=1.000 n=6
Types 266,266 266,266 ~ ~ ~ p=1.000 n=6
Memory used 2,552,231k (± 3.16%) 2,765,333k (±12.86%) ~ 2,499,205k 3,218,643k p=0.471 n=6
Parse Time 8.18s (± 0.82%) 8.31s (± 2.72%) ~ 8.14s 8.60s p=0.467 n=6
Bind Time 2.68s (± 0.81%) 2.65s (± 1.08%) ~ 2.61s 2.69s p=0.077 n=6
Check Time 53.32s (± 0.66%) 53.32s (± 0.28%) ~ 53.11s 53.47s p=1.000 n=6
Emit Time 4.33s (± 0.84%) 4.41s (± 2.65%) ~ 4.27s 4.60s p=0.173 n=6
Total Time 68.50s (± 0.49%) 68.69s (± 0.39%) ~ 68.40s 69.05s p=0.378 n=6
self-compiler - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 261,786 261,786 ~ ~ ~ p=1.000 n=6
Types 106,508 106,508 ~ ~ ~ p=1.000 n=6
Memory used 438,772k (± 0.01%) 438,770k (± 0.01%) ~ 438,711k 438,800k p=0.810 n=6
Parse Time 4.39s (± 1.23%) 4.39s (± 0.79%) ~ 4.34s 4.43s p=0.872 n=6
Bind Time 1.62s (± 0.78%) 1.61s (± 0.96%) ~ 1.58s 1.62s p=0.247 n=6
Check Time 23.45s (± 0.56%) 23.42s (± 0.32%) ~ 23.30s 23.50s p=1.000 n=6
Emit Time 1.91s (± 0.86%) 1.92s (± 0.51%) ~ 1.90s 1.93s p=0.210 n=6
Total Time 31.36s (± 0.41%) 31.34s (± 0.32%) ~ 31.21s 31.46s p=0.689 n=6
ts-pre-modules - node (v18.15.0, x64)
Errors 68 68 ~ ~ ~ p=1.000 n=6
Symbols 225,919 225,919 ~ ~ ~ p=1.000 n=6
Types 94,415 94,415 ~ ~ ~ p=1.000 n=6
Memory used 371,060k (± 0.01%) 371,066k (± 0.01%) ~ 370,986k 371,113k p=1.000 n=6
Parse Time 2.90s (± 1.30%) 2.88s (± 1.31%) ~ 2.83s 2.93s p=0.197 n=6
Bind Time 1.59s (± 1.08%) 1.58s (± 1.35%) ~ 1.54s 1.60s p=0.677 n=6
Check Time 16.35s (± 0.11%) 16.34s (± 0.57%) ~ 16.21s 16.45s p=0.936 n=6
Emit Time 0.00s 0.00s ~ ~ ~ p=1.000 n=6
Total Time 20.83s (± 0.19%) 20.80s (± 0.68%) ~ 20.58s 20.96s p=0.809 n=6
vscode - node (v18.15.0, x64)
Errors 3 3 ~ ~ ~ p=1.000 n=6
Symbols 3,120,293 3,120,293 ~ ~ ~ p=1.000 n=6
Types 1,075,252 1,075,252 ~ ~ ~ p=1.000 n=6
Memory used 3,212,968k (± 0.02%) 3,212,831k (± 0.01%) ~ 3,212,307k 3,213,146k p=0.471 n=6
Parse Time 14.08s (± 0.49%) 14.04s (± 0.34%) ~ 13.97s 14.10s p=0.229 n=6
Bind Time 4.46s (± 0.32%) 4.45s (± 0.88%) ~ 4.37s 4.47s p=1.000 n=6
Check Time 85.63s (± 1.49%) 86.51s (± 2.17%) ~ 84.42s 88.43s p=0.810 n=6
Emit Time 24.86s (± 7.91%) 25.25s (± 7.66%) ~ 22.68s 27.22s p=0.936 n=6
Total Time 129.03s (± 2.28%) 130.25s (± 2.14%) ~ 126.94s 134.05s p=0.471 n=6
webpack - node (v18.15.0, x64)
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 285,282 285,282 ~ ~ ~ p=1.000 n=6
Types 115,799 115,799 ~ ~ ~ p=1.000 n=6
Memory used 435,509k (± 0.01%) 435,528k (± 0.03%) ~ 435,449k 435,751k p=0.936 n=6
Parse Time 4.05s (± 0.45%) 4.07s (± 0.79%) ~ 4.04s 4.12s p=0.256 n=6
Bind Time 1.75s (± 1.39%) 1.75s (± 1.33%) ~ 1.72s 1.77s p=0.566 n=6
Check Time 18.31s (± 0.36%) 18.38s (± 0.55%) ~ 18.24s 18.54s p=0.336 n=6
Emit Time 0.00s 0.00s ~ ~ ~ p=1.000 n=6
Total Time 24.11s (± 0.37%) 24.20s (± 0.43%) ~ 24.06s 24.35s p=0.172 n=6
xstate-main - node (v18.15.0, x64)
Errors 3 3 ~ ~ ~ p=1.000 n=6
Symbols 540,222 540,222 ~ ~ ~ p=1.000 n=6
Types 181,145 181,145 ~ ~ ~ p=1.000 n=6
Memory used 483,761k (± 0.04%) 483,843k (± 0.04%) ~ 483,483k 483,995k p=0.065 n=6
Parse Time 3.36s (± 0.74%) 3.38s (± 0.63%) ~ 3.35s 3.40s p=0.412 n=6
Bind Time 1.18s (± 0.87%) 1.18s (± 1.51%) ~ 1.16s 1.21s p=0.565 n=6
Check Time 19.30s (± 2.66%) 19.22s (± 0.91%) ~ 19.02s 19.53s p=0.422 n=6
Emit Time 0.00s (±244.70%) 0.00s ~ ~ ~ p=0.405 n=6
Total Time 23.84s (± 2.16%) 23.78s (± 0.68%) ~ 23.61s 24.05s p=0.422 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

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

Everything looks good!

Copy link
Member

@rbuckton rbuckton left a comment

Choose a reason for hiding this comment

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

Argument order is likely not the culprit here.

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 author
5 participants