From 2a4c938416b3794543994551558bd4bc9d6a1222 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 9 Jul 2026 23:15:06 +0200 Subject: [PATCH] Skip scope type lookup for expressions without nullsafe operators getNullsafeShortcircuitedExprRespectingScope() asked the scope for the expression's type before checking whether the expression contains a nullsafe operator at all. When it does not - the common case for the method/property/offset check rules calling this on every access - the result is the unmodified expression either way, and the type lookup (often a cache miss on the asking scope) is wasted. Do the cheap identity check first. --- src/Analyser/NullsafeOperatorHelper.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Analyser/NullsafeOperatorHelper.php b/src/Analyser/NullsafeOperatorHelper.php index 0b439191c7..dbfea0a2ec 100644 --- a/src/Analyser/NullsafeOperatorHelper.php +++ b/src/Analyser/NullsafeOperatorHelper.php @@ -10,13 +10,20 @@ final class NullsafeOperatorHelper public static function getNullsafeShortcircuitedExprRespectingScope(Scope $scope, Expr $expr): Expr { + $shortcircuitedExpr = self::getNullsafeShortcircuitedExpr($expr); + if ($shortcircuitedExpr === $expr) { + // No nullsafe operator anywhere in the expression - the result is $expr + // either way, so skip asking the scope for the expression's type. + return $expr; + } + if (!TypeCombinator::containsNull($scope->getType($expr))) { // We're in most likely in context of a null-safe operator ($scope->moreSpecificType is defined for $expr) // Modifying the expression would not bring any value or worse ruin the context information return $expr; } - return self::getNullsafeShortcircuitedExpr($expr); + return $shortcircuitedExpr; } /**