Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 7 additions & 21 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -12542,7 +12542,6 @@ func (c *Checker) checkNullishCoalesceOperands(left *ast.Node, right *ast.Node)
}
}
c.checkNullishCoalesceOperandLeft(left)
c.checkNullishCoalesceOperandRight(right)
}

func (c *Checker) checkNullishCoalesceOperandLeft(left *ast.Node) {
Expand All @@ -12557,20 +12556,6 @@ func (c *Checker) checkNullishCoalesceOperandLeft(left *ast.Node) {
}
}

func (c *Checker) checkNullishCoalesceOperandRight(right *ast.Node) {
binaryExpression := right.Parent
if binaryExpression.Parent != nil && ast.IsBinaryExpression(binaryExpression.Parent) && binaryExpression.Parent.AsBinaryExpression().OperatorToken.Kind == ast.KindQuestionQuestionToken {
rightTarget := ast.SkipOuterExpressions(right, ast.OEKAll)
nullishSemantics := c.getSyntacticNullishnessSemantics(rightTarget)
switch nullishSemantics {
case PredicateSemanticsAlways:
c.error(rightTarget, diagnostics.This_expression_is_always_nullish)
case PredicateSemanticsNever:
c.error(rightTarget, diagnostics.This_expression_is_never_nullish)
}
}
}

func (c *Checker) getSyntacticNullishnessSemantics(node *ast.Node) PredicateSemantics {
node = ast.SkipOuterExpressions(node, ast.OEKAll)
switch node.Kind {
Expand All @@ -12586,17 +12571,18 @@ func (c *Checker) getSyntacticNullishnessSemantics(node *ast.Node) PredicateSema
return PredicateSemanticsSometimes
case ast.KindBinaryExpression:
// List of operators that can produce null/undefined:
// = ??= ?? || ||= && &&=
// || ||= && &&=
switch node.AsBinaryExpression().OperatorToken.Kind {
case ast.KindEqualsToken,
ast.KindQuestionQuestionToken,
ast.KindQuestionQuestionEqualsToken,
ast.KindBarBarToken,
case ast.KindBarBarToken,
ast.KindBarBarEqualsToken,
ast.KindAmpersandAmpersandToken,
ast.KindAmpersandAmpersandEqualsToken:
return PredicateSemanticsSometimes
case ast.KindCommaToken:
// For these operator kinds, the right operand is effectively controlling
case ast.KindCommaToken,
ast.KindEqualsToken,
ast.KindQuestionQuestionToken,
ast.KindQuestionQuestionEqualsToken:
return c.getSyntacticNullishnessSemantics(node.AsBinaryExpression().Right)
}
return PredicateSemanticsNever
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@ predicateSemantics.ts(29,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(30,13): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(31,13): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(32,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(32,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(32,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(33,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(34,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(34,22): error TS2871: This expression is always nullish.
predicateSemantics.ts(36,20): error TS2871: This expression is always nullish.
predicateSemantics.ts(37,20): error TS2871: This expression is always nullish.
predicateSemantics.ts(34,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(36,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(37,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(38,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(39,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(40,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(40,29): error TS2871: This expression is always nullish.
predicateSemantics.ts(41,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(42,20): error TS2881: This expression is never nullish.
predicateSemantics.ts(43,21): error TS2881: This expression is never nullish.
predicateSemantics.ts(40,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(41,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(42,13): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
predicateSemantics.ts(43,13): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
predicateSemantics.ts(45,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(45,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(45,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(45,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(45,29): error TS2871: This expression is always nullish.
predicateSemantics.ts(46,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(46,21): error TS2881: This expression is never nullish.
predicateSemantics.ts(46,13): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
predicateSemantics.ts(47,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(47,22): error TS2881: This expression is never nullish.
predicateSemantics.ts(47,13): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
predicateSemantics.ts(50,8): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(51,11): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(52,8): error TS2872: This kind of expression is always truthy.
Expand Down Expand Up @@ -89,22 +89,22 @@ predicateSemantics.ts(90,1): error TS2869: Right operand of ?? is unreachable be
const p07 = null ?? null ?? null;
~~~~
!!! error TS2871: This expression is always nullish.
~~~~
~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p08 = null ?? opt ?? null;
~~~~
!!! error TS2871: This expression is always nullish.
const p09 = null ?? (opt ? null : undefined) ?? null;
~~~~
!!! error TS2871: This expression is always nullish.
~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.

const p10 = opt ?? null ?? 1;
~~~~
~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p11 = opt ?? null ?? null;
~~~~
~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p12 = opt ?? (null ?? 1);
~~~~
Expand All @@ -115,35 +115,35 @@ predicateSemantics.ts(90,1): error TS2869: Right operand of ?? is unreachable be
const p14 = opt ?? (null ?? null ?? null);
~~~~
!!! error TS2871: This expression is always nullish.
~~~~
~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p15 = opt ?? (opt ? null : undefined) ?? null;
~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p16 = opt ?? 1 ?? 2;
~
!!! error TS2881: This expression is never nullish.
~~~~~~~~
!!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
const p17 = opt ?? (opt ? 1 : 2) ?? 3;
~~~~~~~~~~~
!!! error TS2881: This expression is never nullish.
~~~~~~~~~~~~~~~~~~~~
!!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.

const p21 = null ?? null ?? null ?? null;
~~~~
!!! error TS2871: This expression is always nullish.
~~~~
~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
~~~~
~~~~~~~~~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p22 = null ?? 1 ?? 1;
~~~~
!!! error TS2871: This expression is always nullish.
~
!!! error TS2881: This expression is never nullish.
~~~~~~~~~
!!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
const p23 = null ?? (opt ? 1 : 2) ?? 1;
~~~~
!!! error TS2871: This expression is always nullish.
~~~~~~~~~~~
!!! error TS2881: This expression is never nullish.
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.

// Outer expression tests
while ({} as any) { }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
--- old.predicateSemantics.errors.txt
+++ new.predicateSemantics.errors.txt
@@= skipped -6, +6 lines =@@
predicateSemantics.ts(30,13): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(31,13): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(32,13): error TS2871: This expression is always nullish.
-predicateSemantics.ts(32,21): error TS2871: This expression is always nullish.
+predicateSemantics.ts(32,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(33,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(34,13): error TS2871: This expression is always nullish.
-predicateSemantics.ts(34,22): error TS2871: This expression is always nullish.
-predicateSemantics.ts(36,20): error TS2871: This expression is always nullish.
-predicateSemantics.ts(37,20): error TS2871: This expression is always nullish.
+predicateSemantics.ts(34,13): error TS2871: This expression is always nullish.
+predicateSemantics.ts(36,13): error TS2871: This expression is always nullish.
+predicateSemantics.ts(37,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(38,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(39,21): error TS2871: This expression is always nullish.
predicateSemantics.ts(40,21): error TS2871: This expression is always nullish.
-predicateSemantics.ts(40,29): error TS2871: This expression is always nullish.
-predicateSemantics.ts(41,21): error TS2871: This expression is always nullish.
-predicateSemantics.ts(42,20): error TS2881: This expression is never nullish.
-predicateSemantics.ts(43,21): error TS2881: This expression is never nullish.
-predicateSemantics.ts(45,13): error TS2871: This expression is always nullish.
-predicateSemantics.ts(45,21): error TS2871: This expression is always nullish.
-predicateSemantics.ts(45,29): error TS2871: This expression is always nullish.
+predicateSemantics.ts(40,21): error TS2871: This expression is always nullish.
+predicateSemantics.ts(41,13): error TS2871: This expression is always nullish.
+predicateSemantics.ts(42,13): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
+predicateSemantics.ts(43,13): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
+predicateSemantics.ts(45,13): error TS2871: This expression is always nullish.
+predicateSemantics.ts(45,13): error TS2871: This expression is always nullish.
+predicateSemantics.ts(45,13): error TS2871: This expression is always nullish.
predicateSemantics.ts(46,13): error TS2871: This expression is always nullish.
-predicateSemantics.ts(46,21): error TS2881: This expression is never nullish.
+predicateSemantics.ts(46,13): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
predicateSemantics.ts(47,13): error TS2871: This expression is always nullish.
-predicateSemantics.ts(47,22): error TS2881: This expression is never nullish.
+predicateSemantics.ts(47,13): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
predicateSemantics.ts(50,8): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(51,11): error TS2872: This kind of expression is always truthy.
predicateSemantics.ts(52,8): error TS2872: This kind of expression is always truthy.
@@= skipped -82, +82 lines =@@
const p07 = null ?? null ?? null;
~~~~
!!! error TS2871: This expression is always nullish.
- ~~~~
+ ~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p08 = null ?? opt ?? null;
~~~~
@@= skipped -8, +8 lines =@@
const p09 = null ?? (opt ? null : undefined) ?? null;
~~~~
!!! error TS2871: This expression is always nullish.
- ~~~~~~~~~~~~~~~~~~~~~~
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.

const p10 = opt ?? null ?? 1;
- ~~~~
+ ~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p11 = opt ?? null ?? null;
- ~~~~
+ ~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p12 = opt ?? (null ?? 1);
~~~~
@@= skipped -18, +18 lines =@@
const p14 = opt ?? (null ?? null ?? null);
~~~~
!!! error TS2871: This expression is always nullish.
- ~~~~
+ ~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p15 = opt ?? (opt ? null : undefined) ?? null;
- ~~~~~~~~~~~~~~~~~~~~~~
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p16 = opt ?? 1 ?? 2;
- ~
-!!! error TS2881: This expression is never nullish.
+ ~~~~~~~~
+!!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
const p17 = opt ?? (opt ? 1 : 2) ?? 3;
- ~~~~~~~~~~~
-!!! error TS2881: This expression is never nullish.
+ ~~~~~~~~~~~~~~~~~~~~
+!!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.

const p21 = null ?? null ?? null ?? null;
~~~~
!!! error TS2871: This expression is always nullish.
- ~~~~
+ ~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
- ~~~~
+ ~~~~~~~~~~~~~~~~~~~~
!!! error TS2871: This expression is always nullish.
const p22 = null ?? 1 ?? 1;
~~~~
!!! error TS2871: This expression is always nullish.
- ~
-!!! error TS2881: This expression is never nullish.
+ ~~~~~~~~~
+!!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.
const p23 = null ?? (opt ? 1 : 2) ?? 1;
~~~~
!!! error TS2871: This expression is always nullish.
- ~~~~~~~~~~~
-!!! error TS2881: This expression is never nullish.
+ ~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish.

// Outer expression tests
while ({} as any) { }
Loading