From 33ce51f4e81abe22d2e402894deb31f14fde1ba4 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 14 Oct 2026 23:04:49 +0200 Subject: [PATCH 1/2] [CodeQuality] Speed up ExplicitNullableObjectInstanceRector with cheap bail before native type resolution --- .../ExplicitBoolConditionResolver.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/rules/CodeQuality/NodeAnalyzer/ExplicitBoolConditionResolver.php b/rules/CodeQuality/NodeAnalyzer/ExplicitBoolConditionResolver.php index d093f992dcc..b4addf4c949 100644 --- a/rules/CodeQuality/NodeAnalyzer/ExplicitBoolConditionResolver.php +++ b/rules/CodeQuality/NodeAnalyzer/ExplicitBoolConditionResolver.php @@ -5,8 +5,12 @@ namespace Rector\CodeQuality\NodeAnalyzer; use PhpParser\Node\Expr; +use PhpParser\Node\Expr\BinaryOp; use PhpParser\Node\Expr\BooleanNot; use PhpParser\Node\Expr\Cast\Bool_; +use PhpParser\Node\Expr\Empty_; +use PhpParser\Node\Expr\Instanceof_; +use PhpParser\Node\Expr\Isset_; use PhpParser\Node\Expr\Ternary; use PhpParser\Node\Stmt\ElseIf_; use PhpParser\Node\Stmt\If_; @@ -40,6 +44,11 @@ public function resolve(If_|ElseIf_|Ternary $node): ?ExplicitBoolCondition return null; } + // cheap bail - these shapes can never be a nullable object, skip costly native type resolution + if ($this->isNeverNullableObject($conditionNode)) { + return null; + } + $conditionStaticType = $this->nodeTypeResolver->getNativeType($conditionNode); if ($conditionStaticType instanceof MixedType || $conditionStaticType->isBoolean()->yes()) { return null; @@ -47,4 +56,12 @@ public function resolve(If_|ElseIf_|Ternary $node): ?ExplicitBoolCondition return new ExplicitBoolCondition($conditionNode, $isNegated); } + + private function isNeverNullableObject(Expr $expr): bool + { + return $expr instanceof BinaryOp + || $expr instanceof Instanceof_ + || $expr instanceof Empty_ + || $expr instanceof Isset_; + } } From 8f903847977a66ec1c648d292046a2e66c27e06e Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 14 Oct 2026 23:05:16 +0200 Subject: [PATCH 2/2] [DeadCode] Speed up RemoveAlwaysTrueIfConditionRector with single node traversal --- .../If_/RemoveAlwaysTrueIfConditionRector.php | 29 +++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/rules/DeadCode/Rector/If_/RemoveAlwaysTrueIfConditionRector.php b/rules/DeadCode/Rector/If_/RemoveAlwaysTrueIfConditionRector.php index 03a8f613460..01cdd4ff7d8 100644 --- a/rules/DeadCode/Rector/If_/RemoveAlwaysTrueIfConditionRector.php +++ b/rules/DeadCode/Rector/If_/RemoveAlwaysTrueIfConditionRector.php @@ -197,30 +197,17 @@ private function shouldSkipFromVariable(Expr $expr, Scope $scope): bool private function shouldSkipExpr(Expr $expr): bool { - $hasNonStaticNode = (bool) $this->betterNodeFinder->findInstancesOf( - $expr, - [ - PropertyFetch::class, - StaticPropertyFetch::class, - ArrayDimFetch::class, - MethodCall::class, - StaticCall::class, - ] - ); - - if ($hasNonStaticNode) { - return true; - } - - /** @var FuncCall[] $funcCalls */ - $funcCalls = $this->betterNodeFinder->findInstancesOf($expr, [FuncCall::class]); - foreach ($funcCalls as $funcCall) { - if ($this->isNames($funcCall, self::RUNTIME_STATE_FUNCTIONS)) { + return $this->betterNodeFinder->findFirst($expr, function (Node $node): bool { + if ($node instanceof PropertyFetch + || $node instanceof StaticPropertyFetch + || $node instanceof ArrayDimFetch + || $node instanceof MethodCall + || $node instanceof StaticCall) { return true; } - } - return false; + return $node instanceof FuncCall && $this->isNames($node, self::RUNTIME_STATE_FUNCTIONS); + }) instanceof Node; } private function refactorIfWithBooleanAnd(If_ $if): ?If_