From 161c40db25652a7e0991940cdcbd8089e02270a4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 28 Jul 2026 18:52:43 +0200 Subject: [PATCH] Read operand types from ExpressionResults in Throw/BooleanAnd/Coalesce handlers Where the handler already holds the child's ExpressionResult, read the type off the result instead of re-asking the scope: the throw point's thrown type and the two right-side explicit-never checks. First batch of converting handler Scope::getType() reads to ExpressionResult reads - the call sites then match the single-pass engine, which answers them from the result without a scope walk. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_019wqGgaD7iqL44t1KgpJS7b --- src/Analyser/ExprHandler/BooleanAndHandler.php | 2 +- src/Analyser/ExprHandler/CoalesceHandler.php | 2 +- src/Analyser/ExprHandler/ThrowHandler.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Analyser/ExprHandler/BooleanAndHandler.php b/src/Analyser/ExprHandler/BooleanAndHandler.php index 80b7c2672ba..cad60960e80 100644 --- a/src/Analyser/ExprHandler/BooleanAndHandler.php +++ b/src/Analyser/ExprHandler/BooleanAndHandler.php @@ -265,7 +265,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex $leftResult = $nodeScopeResolver->processExprNode($stmt, $expr->left, $scope, $storage, $nodeCallback, $context->enterDeep()); $leftTruthyScope = $leftResult->getTruthyScope(); $rightResult = $nodeScopeResolver->processExprNode($stmt, $expr->right, $leftTruthyScope, $storage, $nodeCallback, $context); - $rightExprType = $rightResult->getScope()->getType($expr->right); + $rightExprType = $rightResult->getType(); if ($rightExprType instanceof NeverType && $rightExprType->isExplicit()) { $leftMergedWithRightScope = $leftResult->getFalseyScope(); } else { diff --git a/src/Analyser/ExprHandler/CoalesceHandler.php b/src/Analyser/ExprHandler/CoalesceHandler.php index 8323d307c36..d7b0fa53571 100644 --- a/src/Analyser/ExprHandler/CoalesceHandler.php +++ b/src/Analyser/ExprHandler/CoalesceHandler.php @@ -128,7 +128,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex $rightScope = $scope->filterByFalseyValue($expr); $rightResult = $nodeScopeResolver->processExprNode($stmt, $expr->right, $rightScope, $storage, $nodeCallback, $context->enterDeep()); - $rightExprType = $scope->getType($expr->right); + $rightExprType = $rightResult->getType(); if ($rightExprType instanceof NeverType && $rightExprType->isExplicit()) { $scope = $scope->filterByTruthyValue(new Expr\Isset_([$expr->left])); } else { diff --git a/src/Analyser/ExprHandler/ThrowHandler.php b/src/Analyser/ExprHandler/ThrowHandler.php index 05bda29ec2d..e9b1ce7d37a 100644 --- a/src/Analyser/ExprHandler/ThrowHandler.php +++ b/src/Analyser/ExprHandler/ThrowHandler.php @@ -48,7 +48,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex expr: $expr, hasYield: false, isAlwaysTerminating: true, - throwPoints: array_merge($exprResult->getThrowPoints(), [InternalThrowPoint::createExplicit($scope, $scope->getType($expr->expr), $expr, false)]), + throwPoints: array_merge($exprResult->getThrowPoints(), [InternalThrowPoint::createExplicit($scope, $exprResult->getType(), $expr, false)]), impurePoints: $exprResult->getImpurePoints(), ); }