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 Support for Using Aliased Discriminants in Conditional Statements #56173

Merged
merged 3 commits into from
Nov 8, 2023

Conversation

Zzzen
Copy link
Contributor

@Zzzen Zzzen commented Oct 22, 2023

Fixes #55577

@typescript-bot typescript-bot added the For Backlog Bug PRs that fix a backlog bug label Oct 22, 2023
Comment on lines 27163 to 27165
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
return isVariableDeclaration(node.parent) && isVarConstLike(node.parent);
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't this lead to calling isConstantReference recursively (perhaps accompanied by some other checks but still)? What about nested binding patterns (const { a: { b: b2 } } = ...)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you for bringing this to my attention! I was surprised to discover that TypeScript currently lacks support for nested binding patterns during cross symbol analysis. I don't know if it is intended though.

playground

type Nested = {
    type: 'string';
    resp: {
        data: string
    }
} | {
    type: 'number';
    resp: {
        data: number;
    }
}

{
    let resp!: Nested;
    const { resp: { data }, type } = resp;
    if (type === 'string') {
        data satisfies string;  // should not error
    }
    if (resp.type === 'string') {
        resp.resp.data satisfies string;
    }
}

Copy link
Contributor

Choose a reason for hiding this comment

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

This sounds like #38839 (comment)

I was more thinking about cases like this:

type Nested =
  | {
      resp: {
        type: "string";
        data: string;
      };
    }
  | {
      resp: {
        type: "number";
        data: number;
      };
    };

declare const nested: Nested;

const {
  resp: { type, data },
} = nested;
if (type === "string") {
  data satisfies string; // should be OK
}

This keeps the dependency between the discriminant and another property "at the same level" but at the same time both are coming from a nested binding pattern.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that I might have accidentally fixed this in this PR. When I sat down to it I totally forgot about the conversation here 😅

@@ -27160,6 +27160,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
case SyntaxKind.ElementAccessExpression:
// The resolvedSymbol property is initialized by checkPropertyAccess or checkElementAccess before we get here.
return isConstantReference((node as AccessExpression).expression) && isReadonlySymbol(getNodeLinks(node).resolvedSymbol || unknownSymbol);
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
return isBindingElement(node.parent) ? isConstantReference(node.parent.parent) : isVariableDeclaration(node.parent) && isVarConstLike(node.parent);
Copy link
Contributor

Choose a reason for hiding this comment

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

an alternative solution for this could look smth like this:

Suggested change
return isBindingElement(node.parent) ? isConstantReference(node.parent.parent) : isVariableDeclaration(node.parent) && isVarConstLike(node.parent);
const rootDeclaration = getRootDeclaration(node.parent);
return isVariableDeclaration(rootDeclaration) && isVarConstLike(rootDeclaration);

Copy link
Contributor

@Andarist Andarist Nov 5, 2023

Choose a reason for hiding this comment

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

I believe that this should work as well: TS playground but the problem is that we are dealing with a pseudo-reference here. At this point, we can't easily check if the original symbol for which we are performing the narrowing is a non-reassigned parameter.

This could easily be seen as a separate issue though. I only mention it here since I was touching the nearby code and I noticed this now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wish there was a 'const' modifier available for parameters and we could just check that!

Copy link
Contributor

Choose a reason for hiding this comment

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

This should make that possible: #56313

@gabritto

This comment was marked as duplicate.

@gabritto
Copy link
Member

gabritto commented Nov 8, 2023

@typescript-bot run DT
@typescript-bot user test this
@typescript-bot test top100
@typescript-bot perf test this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Nov 8, 2023

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

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented Nov 8, 2023

Heya @gabritto, I've started to run the diff-based top-repos suite on this PR at 9ff723c. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented Nov 8, 2023

Heya @gabritto, I've started to run the regular perf test suite on this PR at 9ff723c. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented Nov 8, 2023

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

Update: The results are in!

@typescript-bot
Copy link
Collaborator

@gabritto Here are the results of running the user test suite comparing main and refs/pull/56173/merge:

There were infrastructure failures potentially unrelated to your change:

  • 3 instances of "Package install failed"

Otherwise...

Everything looks good!

@typescript-bot
Copy link
Collaborator

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

Here they are:

Compiler

Comparison Report - baseline..pr
Metric baseline pr Delta Best Worst p-value
Angular - node (v18.15.0, x64)
Memory used 295,159k (± 0.01%) 295,154k (± 0.01%) ~ 295,109k 295,212k p=0.748 n=6
Parse Time 2.63s (± 0.34%) 2.63s (± 0.56%) ~ 2.61s 2.65s p=0.804 n=6
Bind Time 0.83s (± 1.00%) 0.83s (± 1.00%) ~ 0.83s 0.85s p=1.000 n=6
Check Time 8.04s (± 0.42%) 8.05s (± 0.32%) ~ 8.03s 8.09s p=0.258 n=6
Emit Time 7.08s (± 0.39%) 7.09s (± 0.24%) ~ 7.07s 7.12s p=0.256 n=6
Total Time 18.58s (± 0.28%) 18.61s (± 0.23%) ~ 18.56s 18.67s p=0.172 n=6
Compiler-Unions - node (v18.15.0, x64)
Memory used 194,600k (± 1.56%) 191,675k (± 1.24%) ~ 190,671k 196,523k p=0.298 n=6
Parse Time 1.36s (± 1.21%) 1.35s (± 1.19%) ~ 1.32s 1.37s p=0.864 n=6
Bind Time 0.73s (± 0.00%) 0.73s (± 0.56%) ~ 0.73s 0.74s p=0.405 n=6
Check Time 9.18s (± 0.27%) 9.15s (± 0.35%) ~ 9.09s 9.18s p=0.073 n=6
Emit Time 2.63s (± 0.65%) 2.63s (± 0.42%) ~ 2.62s 2.65s p=1.000 n=6
Total Time 13.90s (± 0.28%) 13.87s (± 0.23%) ~ 13.82s 13.90s p=0.294 n=6
Monaco - node (v18.15.0, x64)
Memory used 347,353k (± 0.01%) 347,355k (± 0.00%) ~ 347,337k 347,381k p=1.000 n=6
Parse Time 2.46s (± 0.21%) 2.47s (± 0.42%) ~ 2.45s 2.48s p=0.077 n=6
Bind Time 0.95s (± 0.86%) 0.94s (± 0.43%) ~ 0.94s 0.95s p=0.248 n=6
Check Time 6.91s (± 0.30%) 6.92s (± 0.22%) ~ 6.89s 6.93s p=0.732 n=6
Emit Time 4.04s (± 0.19%) 4.05s (± 0.48%) ~ 4.03s 4.08s p=0.249 n=6
Total Time 14.35s (± 0.15%) 14.38s (± 0.13%) +0.03s (+ 0.21%) 14.35s 14.40s p=0.036 n=6
TFS - node (v18.15.0, x64)
Memory used 302,593k (± 0.00%) 302,609k (± 0.01%) ~ 302,580k 302,653k p=0.378 n=6
Parse Time 1.99s (± 0.69%) 2.00s (± 1.16%) ~ 1.98s 2.04s p=0.871 n=6
Bind Time 1.00s (± 0.89%) 1.01s (± 1.16%) ~ 0.99s 1.02s p=0.214 n=6
Check Time 6.24s (± 0.41%) 6.25s (± 0.26%) ~ 6.24s 6.28s p=0.678 n=6
Emit Time 3.58s (± 0.73%) 3.57s (± 0.49%) ~ 3.55s 3.60s p=0.870 n=6
Total Time 12.81s (± 0.23%) 12.84s (± 0.28%) ~ 12.79s 12.89s p=0.293 n=6
material-ui - node (v18.15.0, x64)
Memory used 470,530k (± 0.00%) 470,557k (± 0.01%) ~ 470,520k 470,610k p=0.128 n=6
Parse Time 2.57s (± 0.53%) 2.56s (± 0.33%) ~ 2.55s 2.57s p=0.210 n=6
Bind Time 0.98s (± 0.56%) 0.99s (± 1.89%) ~ 0.96s 1.01s p=0.676 n=6
Check Time 16.62s (± 0.33%) 16.62s (± 0.21%) ~ 16.58s 16.66s p=0.809 n=6
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) ~ 0.00s 0.00s p=1.000 n=6
Total Time 20.18s (± 0.31%) 20.18s (± 0.25%) ~ 20.13s 20.24s p=0.936 n=6
xstate - node (v18.15.0, x64)
Memory used 512,830k (± 0.01%) 512,822k (± 0.01%) ~ 512,759k 512,903k p=0.936 n=6
Parse Time 3.27s (± 0.16%) 3.27s (± 0.36%) ~ 3.25s 3.28s p=0.929 n=6
Bind Time 1.54s (± 0.33%) 1.54s (± 0.49%) ~ 1.53s 1.55s p=0.784 n=6
Check Time 2.85s (± 0.48%) 2.85s (± 0.53%) ~ 2.82s 2.86s p=0.462 n=6
Emit Time 0.08s (± 0.00%) 0.08s (± 0.00%) ~ 0.08s 0.08s p=1.000 n=6
Total Time 7.75s (± 0.10%) 7.74s (± 0.24%) ~ 7.71s 7.76s p=0.867 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)
  • xstate - node (v18.15.0, x64)
Benchmark Name Iterations
Current pr 6
Baseline baseline 6

tsserver

Comparison Report - baseline..pr
Metric baseline pr Delta Best Worst p-value
Compiler-UnionsTSServer - node (v18.15.0, x64)
Req 1 - updateOpen 2,389ms (± 0.67%) 2,386ms (± 0.84%) ~ 2,351ms 2,411ms p=1.000 n=6
Req 2 - geterr 5,390ms (± 1.40%) 5,335ms (± 1.16%) ~ 5,296ms 5,460ms p=0.092 n=6
Req 3 - references 325ms (± 0.75%) 328ms (± 1.23%) ~ 324ms 335ms p=0.250 n=6
Req 4 - navto 276ms (± 1.26%) 279ms (± 0.70%) ~ 275ms 281ms p=0.263 n=6
Req 5 - completionInfo count 1,356 (± 0.00%) 1,356 (± 0.00%) ~ 1,356 1,356 p=1.000 n=6
Req 5 - completionInfo 85ms (± 5.15%) 79ms (± 7.49%) ~ 75ms 90ms p=0.099 n=6
CompilerTSServer - node (v18.15.0, x64)
Req 1 - updateOpen 2,503ms (± 0.79%) 2,497ms (± 0.83%) ~ 2,476ms 2,524ms p=0.873 n=6
Req 2 - geterr 4,066ms (± 1.31%) 4,060ms (± 1.56%) ~ 4,021ms 4,188ms p=0.298 n=6
Req 3 - references 343ms (± 1.30%) 342ms (± 1.38%) ~ 333ms 345ms p=0.803 n=6
Req 4 - navto 283ms (± 0.29%) 282ms (± 0.43%) ~ 280ms 283ms p=0.599 n=6
Req 5 - completionInfo count 1,518 (± 0.00%) 1,518 (± 0.00%) ~ 1,518 1,518 p=1.000 n=6
Req 5 - completionInfo 88ms (± 5.03%) 88ms (± 5.01%) ~ 79ms 90ms p=1.000 n=6
xstateTSServer - node (v18.15.0, x64)
Req 1 - updateOpen 2,589ms (± 0.44%) 2,597ms (± 0.44%) ~ 2,588ms 2,617ms p=0.128 n=6
Req 2 - geterr 1,702ms (± 2.94%) 1,727ms (± 2.08%) ~ 1,678ms 1,772ms p=0.378 n=6
Req 3 - references 113ms (± 9.21%) 112ms (±10.41%) ~ 101ms 124ms p=0.627 n=6
Req 4 - navto 367ms (± 0.57%) 366ms (± 0.56%) ~ 364ms 368ms p=0.673 n=6
Req 5 - completionInfo count 2,073 (± 0.00%) 2,073 (± 0.00%) ~ 2,073 2,073 p=1.000 n=6
Req 5 - completionInfo 310ms (± 1.83%) 309ms (± 2.09%) ~ 298ms 315ms p=1.000 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • CompilerTSServer - node (v18.15.0, x64)
  • Compiler-UnionsTSServer - node (v18.15.0, x64)
  • xstateTSServer - node (v18.15.0, x64)
Benchmark Name Iterations
Current pr 6
Baseline baseline 6

Startup

Comparison Report - baseline..pr
Metric baseline pr Delta Best Worst p-value
tsc-startup - node (v18.15.0, x64)
Execution time 152.75ms (± 0.21%) 152.56ms (± 0.19%) -0.20ms (- 0.13%) 151.38ms 155.44ms p=0.000 n=600
tsserver-startup - node (v18.15.0, x64)
Execution time 227.90ms (± 0.14%) 227.79ms (± 0.15%) -0.11ms (- 0.05%) 226.18ms 231.75ms p=0.000 n=600
tsserverlibrary-startup - node (v18.15.0, x64)
Execution time 229.11ms (± 0.16%) 229.06ms (± 0.18%) -0.05ms (- 0.02%) 227.58ms 235.55ms p=0.035 n=600
typescript-startup - node (v18.15.0, x64)
Execution time 229.65ms (± 0.16%) 229.00ms (± 0.24%) -0.65ms (- 0.28%) 227.37ms 236.03ms p=0.000 n=600
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • tsc-startup - node (v18.15.0, x64)
  • tsserver-startup - node (v18.15.0, x64)
  • tsserverlibrary-startup - node (v18.15.0, x64)
  • typescript-startup - node (v18.15.0, x64)
Benchmark Name Iterations
Current pr 6
Baseline baseline 6

Developer Information:

Download Benchmarks

@typescript-bot
Copy link
Collaborator

Hey @gabritto, the results of running the DT tests are ready.
Everything looks the same!
You can check the log here.

@typescript-bot
Copy link
Collaborator

@gabritto Here are the results of running the top-repos suite comparing main and refs/pull/56173/merge:

Everything looks good!

@gabritto gabritto merged commit 7b96c28 into microsoft:main Nov 8, 2023
19 checks passed
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
Archived in project
Development

Successfully merging this pull request may close these issues.

Type inference fails when using combined boolean variable in if condition
4 participants