diff --git a/internal/checker/checker.go b/internal/checker/checker.go index a6b3a684c5..4532fef085 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -12399,17 +12399,32 @@ func (c *Checker) checkNullishCoalesceOperands(left *ast.Node, right *ast.Node) if ast.IsBinaryExpression(right) && ast.IsLogicalBinaryOperator(right.AsBinaryExpression().OperatorToken.Kind) { c.grammarErrorOnNode(right, diagnostics.X_0_and_1_operations_cannot_be_mixed_without_parentheses, scanner.TokenToString(right.AsBinaryExpression().OperatorToken.Kind), scanner.TokenToString(ast.KindQuestionQuestionToken)) } + c.checkNullishCoalesceOperandLeft(left) + c.checkNullishCoalesceOperandRight(right) +} + +func (c *Checker) checkNullishCoalesceOperandLeft(left *ast.Node) { leftTarget := ast.SkipOuterExpressions(left, ast.OEKAll) nullishSemantics := c.getSyntacticNullishnessSemantics(leftTarget) if nullishSemantics != PredicateSemanticsSometimes { - if left.Parent.Parent.Kind == ast.KindBinaryExpression { - c.error(leftTarget, diagnostics.This_binary_expression_is_never_nullish_Are_you_missing_parentheses) + if nullishSemantics == PredicateSemanticsAlways { + c.error(leftTarget, diagnostics.This_expression_is_always_nullish) } else { - if nullishSemantics == PredicateSemanticsAlways { - c.error(leftTarget, diagnostics.This_expression_is_always_nullish) - } else { - c.error(leftTarget, diagnostics.Right_operand_of_is_unreachable_because_the_left_operand_is_never_nullish) - } + c.error(leftTarget, diagnostics.Right_operand_of_is_unreachable_because_the_left_operand_is_never_nullish) + } + } +} + +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) } } } diff --git a/testdata/baselines/reference/submodule/compiler/predicateSemantics.errors.txt b/testdata/baselines/reference/submodule/compiler/predicateSemantics.errors.txt index 8b9b243bad..cf503611a4 100644 --- a/testdata/baselines/reference/submodule/compiler/predicateSemantics.errors.txt +++ b/testdata/baselines/reference/submodule/compiler/predicateSemantics.errors.txt @@ -6,15 +6,27 @@ predicateSemantics.ts(28,13): error TS2871: This expression is always nullish. 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 TS2870: This binary expression is never nullish. Are you missing parentheses? -predicateSemantics.ts(33,13): error TS2870: This binary expression is never nullish. Are you missing parentheses? -predicateSemantics.ts(34,13): error TS2870: This binary expression is never nullish. Are you missing parentheses? +predicateSemantics.ts(32,13): error TS2871: This expression is always nullish. +predicateSemantics.ts(32,21): 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(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 TS2870: This binary expression is never nullish. Are you missing parentheses? -predicateSemantics.ts(45,13): error TS2870: This binary expression is never nullish. Are you missing parentheses? -predicateSemantics.ts(46,13): error TS2870: This binary expression is never nullish. Are you missing parentheses? -predicateSemantics.ts(47,13): error TS2870: This binary expression is never nullish. Are you missing parentheses? +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(46,13): error TS2871: This expression is always nullish. +predicateSemantics.ts(46,21): error TS2881: This expression 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(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. @@ -26,7 +38,7 @@ predicateSemantics.ts(89,1): error TS2869: Right operand of ?? is unreachable be predicateSemantics.ts(90,1): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish. -==== predicateSemantics.ts (26 errors) ==== +==== predicateSemantics.ts (38 errors) ==== declare let opt: number | undefined; // OK: One or other operand is possibly nullish @@ -76,16 +88,24 @@ predicateSemantics.ts(90,1): error TS2869: Right operand of ?? is unreachable be !!! error TS2872: This kind of expression is always truthy. const p07 = null ?? null ?? null; ~~~~ -!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? +!!! error TS2871: This expression is always nullish. + ~~~~ +!!! error TS2871: This expression is always nullish. const p08 = null ?? opt ?? null; ~~~~ -!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? +!!! error TS2871: This expression is always nullish. const p09 = null ?? (opt ? null : undefined) ?? null; ~~~~ -!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? +!!! 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); ~~~~ !!! error TS2871: This expression is always nullish. @@ -94,20 +114,36 @@ predicateSemantics.ts(90,1): error TS2869: Right operand of ?? is unreachable be !!! error TS2871: This expression is always nullish. const p14 = opt ?? (null ?? null ?? null); ~~~~ -!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? +!!! 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. const p17 = opt ?? (opt ? 1 : 2) ?? 3; + ~~~~~~~~~~~ +!!! error TS2881: This expression is never nullish. const p21 = null ?? null ?? null ?? null; ~~~~ -!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? +!!! 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 TS2870: This binary expression is never nullish. Are you missing parentheses? +!!! error TS2871: This expression is always nullish. + ~ +!!! error TS2881: This expression is never nullish. const p23 = null ?? (opt ? 1 : 2) ?? 1; ~~~~ -!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? +!!! error TS2871: This expression is always nullish. + ~~~~~~~~~~~ +!!! error TS2881: This expression is never nullish. // Outer expression tests while ({} as any) { } diff --git a/testdata/baselines/reference/submodule/compiler/predicateSemantics.errors.txt.diff b/testdata/baselines/reference/submodule/compiler/predicateSemantics.errors.txt.diff deleted file mode 100644 index 5f593741f5..0000000000 --- a/testdata/baselines/reference/submodule/compiler/predicateSemantics.errors.txt.diff +++ /dev/null @@ -1,115 +0,0 @@ ---- old.predicateSemantics.errors.txt -+++ new.predicateSemantics.errors.txt -@@= skipped -5, +5 lines =@@ - 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(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(32,13): error TS2870: This binary expression is never nullish. Are you missing parentheses? -+predicateSemantics.ts(33,13): error TS2870: This binary expression is never nullish. Are you missing parentheses? -+predicateSemantics.ts(34,13): error TS2870: This binary expression is never nullish. Are you missing parentheses? - 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(46,13): error TS2871: This expression is always nullish. --predicateSemantics.ts(46,21): error TS2881: This expression 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(40,21): error TS2870: This binary expression is never nullish. Are you missing parentheses? -+predicateSemantics.ts(45,13): error TS2870: This binary expression is never nullish. Are you missing parentheses? -+predicateSemantics.ts(46,13): error TS2870: This binary expression is never nullish. Are you missing parentheses? -+predicateSemantics.ts(47,13): error TS2870: This binary expression is never nullish. Are you missing parentheses? - 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 -32, +20 lines =@@ - predicateSemantics.ts(90,1): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish. - - --==== predicateSemantics.ts (38 errors) ==== -+==== predicateSemantics.ts (26 errors) ==== - declare let opt: number | undefined; - - // OK: One or other operand is possibly nullish -@@= skipped -50, +50 lines =@@ - !!! error TS2872: This kind of expression is always truthy. - const p07 = null ?? null ?? null; - ~~~~ --!!! error TS2871: This expression is always nullish. -- ~~~~ --!!! error TS2871: This expression is always nullish. -+!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? - const p08 = null ?? opt ?? null; - ~~~~ --!!! error TS2871: This expression is always nullish. -+!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? - const p09 = null ?? (opt ? null : undefined) ?? null; - ~~~~ --!!! error TS2871: This expression is always nullish. -- ~~~~~~~~~~~~~~~~~~~~~~ --!!! error TS2871: This expression is always nullish. -+!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? - - 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); - ~~~~ - !!! error TS2871: This expression is always nullish. -@@= skipped -26, +18 lines =@@ - !!! error TS2871: This expression is always nullish. - const p14 = opt ?? (null ?? null ?? null); - ~~~~ --!!! error TS2871: This expression is always nullish. -- ~~~~ --!!! error TS2871: This expression is always nullish. -+!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? - 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. - const p17 = opt ?? (opt ? 1 : 2) ?? 3; -- ~~~~~~~~~~~ --!!! error TS2881: This expression 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. -+!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? - const p22 = null ?? 1 ?? 1; - ~~~~ --!!! error TS2871: This expression is always nullish. -- ~ --!!! error TS2881: This expression is never nullish. -+!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? - const p23 = null ?? (opt ? 1 : 2) ?? 1; - ~~~~ --!!! error TS2871: This expression is always nullish. -- ~~~~~~~~~~~ --!!! error TS2881: This expression is never nullish. -+!!! error TS2870: This binary expression is never nullish. Are you missing parentheses? - - // Outer expression tests - while ({} as any) { } \ No newline at end of file