From a4a7992982288b9e9aa0ec96faba89e8f044ac8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 20 Dec 2024 10:39:40 +0100 Subject: [PATCH 1/2] Compute more precise syntactic truthy semantics for comma expressions --- src/compiler/checker.ts | 5 +++ .../reference/predicateSemantics.errors.txt | 10 ++++- .../baselines/reference/predicateSemantics.js | 7 ++++ .../reference/predicateSemantics.symbols | 13 +++++++ .../reference/predicateSemantics.types | 37 +++++++++++++++++++ tests/cases/compiler/predicateSemantics.ts | 5 +++ 6 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 80b61edd3657a..1baca6f7f3070 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -44715,6 +44715,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !!(node as StringLiteral | NoSubstitutionTemplateLiteral).text ? PredicateSemantics.Always : PredicateSemantics.Never; case SyntaxKind.ConditionalExpression: return getSyntacticTruthySemantics((node as ConditionalExpression).whenTrue) | getSyntacticTruthySemantics((node as ConditionalExpression).whenFalse); + case SyntaxKind.BinaryExpression: + if ((node as BinaryExpression).operatorToken.kind !== SyntaxKind.CommaToken) { + break; + } + return getSyntacticTruthySemantics((node as BinaryExpression).right); case SyntaxKind.Identifier: if (getResolvedSymbol(node as Identifier) === undefinedSymbol) { return PredicateSemantics.Never; diff --git a/tests/baselines/reference/predicateSemantics.errors.txt b/tests/baselines/reference/predicateSemantics.errors.txt index c80dd47d19357..244560be93c55 100644 --- a/tests/baselines/reference/predicateSemantics.errors.txt +++ b/tests/baselines/reference/predicateSemantics.errors.txt @@ -14,9 +14,10 @@ predicateSemantics.ts(52,14): error TS2695: Left side of comma operator is unuse predicateSemantics.ts(52,14): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish. predicateSemantics.ts(70,1): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish. predicateSemantics.ts(71,1): error TS2869: Right operand of ?? is unreachable because the left operand is never nullish. +predicateSemantics.ts(75,5): error TS2872: This kind of expression is always truthy. -==== predicateSemantics.ts (16 errors) ==== +==== predicateSemantics.ts (17 errors) ==== declare let cond: any; // OK: One or other operand is possibly nullish @@ -120,4 +121,11 @@ predicateSemantics.ts(71,1): error TS2869: Right operand of ?? is unreachable be `foo` ?? 32; // error ~~~~~ !!! error TS2869: Right operand of ?? is unreachable because the left operand is never nullish. + + // https://github.com/microsoft/TypeScript/issues/60822 + declare function test60822(arg: string, arg2?: string): string | null; + if (test60822("foo"), "bar") {} // error + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2872: This kind of expression is always truthy. + if (test60822("foo"), test60822("bar")) {} // ok \ No newline at end of file diff --git a/tests/baselines/reference/predicateSemantics.js b/tests/baselines/reference/predicateSemantics.js index 30ada0d514d02..71b433fc031b6 100644 --- a/tests/baselines/reference/predicateSemantics.js +++ b/tests/baselines/reference/predicateSemantics.js @@ -72,6 +72,11 @@ tag`foo${1}` ?? 32; // ok `foo${1}` ?? 32; // error `foo` ?? 32; // error + +// https://github.com/microsoft/TypeScript/issues/60822 +declare function test60822(arg: string, arg2?: string): string | null; +if (test60822("foo"), "bar") {} // error +if (test60822("foo"), test60822("bar")) {} // ok //// [predicateSemantics.js] @@ -140,3 +145,5 @@ var X = /** @class */ (function () { (_k = tag(__makeTemplateObject(["foo", ""], ["foo", ""]), 1)) !== null && _k !== void 0 ? _k : 32; // ok (_l = "foo".concat(1)) !== null && _l !== void 0 ? _l : 32; // error "foo" !== null && "foo" !== void 0 ? "foo" : 32; // error +if (test60822("foo"), "bar") { } // error +if (test60822("foo"), test60822("bar")) { } // ok diff --git a/tests/baselines/reference/predicateSemantics.symbols b/tests/baselines/reference/predicateSemantics.symbols index f8ddf0fe5db87..66016b41dd882 100644 --- a/tests/baselines/reference/predicateSemantics.symbols +++ b/tests/baselines/reference/predicateSemantics.symbols @@ -137,3 +137,16 @@ tag`foo${1}` ?? 32; // ok `foo${1}` ?? 32; // error `foo` ?? 32; // error +// https://github.com/microsoft/TypeScript/issues/60822 +declare function test60822(arg: string, arg2?: string): string | null; +>test60822 : Symbol(test60822, Decl(predicateSemantics.ts, 70, 12)) +>arg : Symbol(arg, Decl(predicateSemantics.ts, 73, 27)) +>arg2 : Symbol(arg2, Decl(predicateSemantics.ts, 73, 39)) + +if (test60822("foo"), "bar") {} // error +>test60822 : Symbol(test60822, Decl(predicateSemantics.ts, 70, 12)) + +if (test60822("foo"), test60822("bar")) {} // ok +>test60822 : Symbol(test60822, Decl(predicateSemantics.ts, 70, 12)) +>test60822 : Symbol(test60822, Decl(predicateSemantics.ts, 70, 12)) + diff --git a/tests/baselines/reference/predicateSemantics.types b/tests/baselines/reference/predicateSemantics.types index b054c66ad43e7..54382f8a32f12 100644 --- a/tests/baselines/reference/predicateSemantics.types +++ b/tests/baselines/reference/predicateSemantics.types @@ -375,3 +375,40 @@ tag`foo${1}` ?? 32; // ok >32 : 32 > : ^^ +// https://github.com/microsoft/TypeScript/issues/60822 +declare function test60822(arg: string, arg2?: string): string | null; +>test60822 : (arg: string, arg2?: string) => string | null +> : ^ ^^ ^^ ^^^ ^^^^^ +>arg : string +> : ^^^^^^ +>arg2 : string +> : ^^^^^^ + +if (test60822("foo"), "bar") {} // error +>test60822("foo"), "bar" : "bar" +> : ^^^^^ +>test60822("foo") : string +> : ^^^^^^ +>test60822 : (arg: string, arg2?: string) => string | null +> : ^ ^^ ^^ ^^^ ^^^^^ +>"foo" : "foo" +> : ^^^^^ +>"bar" : "bar" +> : ^^^^^ + +if (test60822("foo"), test60822("bar")) {} // ok +>test60822("foo"), test60822("bar") : string +> : ^^^^^^ +>test60822("foo") : string +> : ^^^^^^ +>test60822 : (arg: string, arg2?: string) => string | null +> : ^ ^^ ^^ ^^^ ^^^^^ +>"foo" : "foo" +> : ^^^^^ +>test60822("bar") : string +> : ^^^^^^ +>test60822 : (arg: string, arg2?: string) => string | null +> : ^ ^^ ^^ ^^^ ^^^^^ +>"bar" : "bar" +> : ^^^^^ + diff --git a/tests/cases/compiler/predicateSemantics.ts b/tests/cases/compiler/predicateSemantics.ts index a22b34341e7d5..ea595cf540154 100644 --- a/tests/cases/compiler/predicateSemantics.ts +++ b/tests/cases/compiler/predicateSemantics.ts @@ -69,3 +69,8 @@ tag`foo${1}` ?? 32; // ok `foo${1}` ?? 32; // error `foo` ?? 32; // error + +// https://github.com/microsoft/TypeScript/issues/60822 +declare function test60822(arg: string, arg2?: string): string | null; +if (test60822("foo"), "bar") {} // error +if (test60822("foo"), test60822("bar")) {} // ok From 170e0aa938b92718728c004c8f32ab7dd0617d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 20 Dec 2024 11:06:29 +0100 Subject: [PATCH 2/2] update baselines --- .../reference/invalidLetInForOfAndForIn_ES5.errors.txt | 5 ++++- .../reference/invalidLetInForOfAndForIn_ES6.errors.txt | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/invalidLetInForOfAndForIn_ES5.errors.txt b/tests/baselines/reference/invalidLetInForOfAndForIn_ES5.errors.txt index 2445ba63c7631..d6dc2b24611fa 100644 --- a/tests/baselines/reference/invalidLetInForOfAndForIn_ES5.errors.txt +++ b/tests/baselines/reference/invalidLetInForOfAndForIn_ES5.errors.txt @@ -2,11 +2,12 @@ invalidLetInForOfAndForIn_ES5.ts(5,13): error TS1005: ',' expected. invalidLetInForOfAndForIn_ES5.ts(5,14): error TS1181: Array element destructuring pattern expected. invalidLetInForOfAndForIn_ES5.ts(5,14): error TS2695: Left side of comma operator is unused and has no side effects. invalidLetInForOfAndForIn_ES5.ts(5,14): error TS2695: Left side of comma operator is unused and has no side effects. +invalidLetInForOfAndForIn_ES5.ts(5,14): error TS2872: This kind of expression is always truthy. invalidLetInForOfAndForIn_ES5.ts(5,19): error TS1005: ';' expected. invalidLetInForOfAndForIn_ES5.ts(5,20): error TS1128: Declaration or statement expected. -==== invalidLetInForOfAndForIn_ES5.ts (6 errors) ==== +==== invalidLetInForOfAndForIn_ES5.ts (7 errors) ==== // This should be an error // More details: http://www.ecma-international.org/ecma-262/6.0/#sec-iteration-statements @@ -20,6 +21,8 @@ invalidLetInForOfAndForIn_ES5.ts(5,20): error TS1128: Declaration or statement e !!! error TS2695: Left side of comma operator is unused and has no side effects. ~~~ !!! error TS2695: Left side of comma operator is unused and has no side effects. + ~~~~~ +!!! error TS2872: This kind of expression is always truthy. ~ !!! error TS1005: ';' expected. ~ diff --git a/tests/baselines/reference/invalidLetInForOfAndForIn_ES6.errors.txt b/tests/baselines/reference/invalidLetInForOfAndForIn_ES6.errors.txt index cf35e02b1661e..7730b8e3b10fb 100644 --- a/tests/baselines/reference/invalidLetInForOfAndForIn_ES6.errors.txt +++ b/tests/baselines/reference/invalidLetInForOfAndForIn_ES6.errors.txt @@ -2,11 +2,12 @@ invalidLetInForOfAndForIn_ES6.ts(5,13): error TS1005: ',' expected. invalidLetInForOfAndForIn_ES6.ts(5,14): error TS1181: Array element destructuring pattern expected. invalidLetInForOfAndForIn_ES6.ts(5,14): error TS2695: Left side of comma operator is unused and has no side effects. invalidLetInForOfAndForIn_ES6.ts(5,14): error TS2695: Left side of comma operator is unused and has no side effects. +invalidLetInForOfAndForIn_ES6.ts(5,14): error TS2872: This kind of expression is always truthy. invalidLetInForOfAndForIn_ES6.ts(5,19): error TS1005: ';' expected. invalidLetInForOfAndForIn_ES6.ts(5,20): error TS1128: Declaration or statement expected. -==== invalidLetInForOfAndForIn_ES6.ts (6 errors) ==== +==== invalidLetInForOfAndForIn_ES6.ts (7 errors) ==== // This should be an error // More details: http://www.ecma-international.org/ecma-262/6.0/#sec-iteration-statements @@ -20,6 +21,8 @@ invalidLetInForOfAndForIn_ES6.ts(5,20): error TS1128: Declaration or statement e !!! error TS2695: Left side of comma operator is unused and has no side effects. ~~~ !!! error TS2695: Left side of comma operator is unused and has no side effects. + ~~~~~ +!!! error TS2872: This kind of expression is always truthy. ~ !!! error TS1005: ';' expected. ~