From 71b2ba6111e934f2b4ee112bc4d8d2f47ced22f5 Mon Sep 17 00:00:00 2001 From: Joost Koehoorn Date: Sat, 27 Aug 2022 10:40:13 +0200 Subject: [PATCH] Reuse computed type of condition expressions (#49881) --- src/compiler/checker.ts | 14 ++-- ...uncalledFunctionChecksInConditionalPerf.js | 8 ++ ...ledFunctionChecksInConditionalPerf.symbols | 32 +++++++ ...alledFunctionChecksInConditionalPerf.types | 83 +++++++++++++++++++ ...uncalledFunctionChecksInConditionalPerf.ts | 5 ++ 5 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.js create mode 100644 tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.symbols create mode 100644 tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.types create mode 100644 tests/cases/compiler/uncalledFunctionChecksInConditionalPerf.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5f71335b36158..0dc5477eadb57 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -34108,7 +34108,7 @@ namespace ts { || isBinaryExpression(parent) && (parent.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || parent.operatorToken.kind === SyntaxKind.BarBarToken)) { parent = parent.parent; } - checkTestingKnownTruthyCallableOrAwaitableType(node.left, isIfStatement(parent) ? parent.thenStatement : undefined); + checkTestingKnownTruthyCallableOrAwaitableType(node.left, leftType, isIfStatement(parent) ? parent.thenStatement : undefined); } checkTruthinessOfType(leftType, node.left); } @@ -34685,8 +34685,8 @@ namespace ts { } function checkConditionalExpression(node: ConditionalExpression, checkMode?: CheckMode): Type { - checkTruthinessExpression(node.condition); - checkTestingKnownTruthyCallableOrAwaitableType(node.condition, node.whenTrue); + const type = checkTruthinessExpression(node.condition); + checkTestingKnownTruthyCallableOrAwaitableType(node.condition, type, node.whenTrue); const type1 = checkExpression(node.whenTrue, checkMode); const type2 = checkExpression(node.whenFalse, checkMode); return getUnionType([type1, type2], UnionReduction.Subtype); @@ -38391,8 +38391,8 @@ namespace ts { function checkIfStatement(node: IfStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node); - checkTruthinessExpression(node.expression); - checkTestingKnownTruthyCallableOrAwaitableType(node.expression, node.thenStatement); + const type = checkTruthinessExpression(node.expression); + checkTestingKnownTruthyCallableOrAwaitableType(node.expression, type, node.thenStatement); checkSourceElement(node.thenStatement); if (node.thenStatement.kind === SyntaxKind.EmptyStatement) { @@ -38402,7 +38402,7 @@ namespace ts { checkSourceElement(node.elseStatement); } - function checkTestingKnownTruthyCallableOrAwaitableType(condExpr: Expression, body?: Statement | Expression) { + function checkTestingKnownTruthyCallableOrAwaitableType(condExpr: Expression, condType: Type, body?: Statement | Expression) { if (!strictNullChecks) return; helper(condExpr, body); @@ -38417,7 +38417,7 @@ namespace ts { ? condExpr.right : condExpr; if (isModuleExportsAccessExpression(location)) return; - const type = checkTruthinessExpression(location); + const type = location === condExpr ? condType : checkTruthinessExpression(location); const isPropertyExpressionCast = isPropertyAccessExpression(location) && isTypeAssertion(location.expression); if (!(getTypeFacts(type) & TypeFacts.Truthy) || isPropertyExpressionCast) return; diff --git a/tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.js b/tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.js new file mode 100644 index 0000000000000..cba189cbf2f1a --- /dev/null +++ b/tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.js @@ -0,0 +1,8 @@ +//// [uncalledFunctionChecksInConditionalPerf.ts] +declare const b: boolean; + +((((((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b); + + +//// [uncalledFunctionChecksInConditionalPerf.js] +((((((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b); diff --git a/tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.symbols b/tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.symbols new file mode 100644 index 0000000000000..1e4d10c56f30a --- /dev/null +++ b/tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.symbols @@ -0,0 +1,32 @@ +=== tests/cases/compiler/uncalledFunctionChecksInConditionalPerf.ts === +declare const b: boolean; +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) + +((((((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b); +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) +>b : Symbol(b, Decl(uncalledFunctionChecksInConditionalPerf.ts, 0, 13)) + diff --git a/tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.types b/tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.types new file mode 100644 index 0000000000000..7a6b8384009a5 --- /dev/null +++ b/tests/baselines/reference/uncalledFunctionChecksInConditionalPerf.types @@ -0,0 +1,83 @@ +=== tests/cases/compiler/uncalledFunctionChecksInConditionalPerf.ts === +declare const b: boolean; +>b : boolean + +((((((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b); +>((((((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>(((((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>(((((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>((((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>((((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>(((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>(((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>(((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>(((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>(((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>(((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>(((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>(((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>(((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>(((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>(((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>(((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>(((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>(((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>(((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>(((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) : boolean +>((((((((b) && b) && b) && b) && b) && b) && b) && b) && b : boolean +>((((((((b) && b) && b) && b) && b) && b) && b) && b) : boolean +>(((((((b) && b) && b) && b) && b) && b) && b) && b : boolean +>(((((((b) && b) && b) && b) && b) && b) && b) : boolean +>((((((b) && b) && b) && b) && b) && b) && b : boolean +>((((((b) && b) && b) && b) && b) && b) : boolean +>(((((b) && b) && b) && b) && b) && b : boolean +>(((((b) && b) && b) && b) && b) : boolean +>((((b) && b) && b) && b) && b : boolean +>((((b) && b) && b) && b) : boolean +>(((b) && b) && b) && b : boolean +>(((b) && b) && b) : boolean +>((b) && b) && b : boolean +>((b) && b) : boolean +>(b) && b : boolean +>(b) : boolean +>b : boolean +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true +>b : true + diff --git a/tests/cases/compiler/uncalledFunctionChecksInConditionalPerf.ts b/tests/cases/compiler/uncalledFunctionChecksInConditionalPerf.ts new file mode 100644 index 0000000000000..d780e171a7ba1 --- /dev/null +++ b/tests/cases/compiler/uncalledFunctionChecksInConditionalPerf.ts @@ -0,0 +1,5 @@ +// @strictNullChecks: true + +declare const b: boolean; + +((((((((((((((((((((((((((b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b) && b);