diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 412a3ae77c..3e50294c94 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -1849,8 +1849,12 @@ private function specifyTypesFromAsserts(TypeSpecifierContext $context, Expr\Cal if ($type instanceof ConditionalTypeForParameter) { $parameterName = substr($type->getParameterName(), 1); if (array_key_exists($parameterName, $argsMap)) { - $argType = TypeCombinator::union(...array_map(static fn (Expr $expr) => $scope->getType($expr), $argsMap[$parameterName])); - $type = $type->toConditional($argType); + $type = $traverse($type); + if ($type instanceof ConditionalTypeForParameter) { + $argType = TypeCombinator::union(...array_map(static fn (Expr $expr) => $scope->getType($expr), $argsMap[substr($type->getParameterName(), 1)])); + return $type->toConditional($argType); + } + return $type; } } diff --git a/src/Reflection/ResolvedFunctionVariantWithOriginal.php b/src/Reflection/ResolvedFunctionVariantWithOriginal.php index 21108d658e..b29a897c45 100644 --- a/src/Reflection/ResolvedFunctionVariantWithOriginal.php +++ b/src/Reflection/ResolvedFunctionVariantWithOriginal.php @@ -290,7 +290,13 @@ private function resolveConditionalTypesForParameter(Type $type): Type { return TypeTraverser::map($type, function (Type $type, callable $traverse): Type { if ($type instanceof ConditionalTypeForParameter && array_key_exists($type->getParameterName(), $this->passedArgs)) { - $type = $type->toConditional($this->passedArgs[$type->getParameterName()]); + // Traverse children first, then convert — avoids infinite loop when + // the passed argument contains ConditionalTypeForParameter with a colliding parameter name. + $type = $traverse($type); + if ($type instanceof ConditionalTypeForParameter) { + return $type->toConditional($this->passedArgs[$type->getParameterName()]); + } + return $type; } return $traverse($type); diff --git a/tests/PHPStan/Analyser/nsrt/bug-13872.php b/tests/PHPStan/Analyser/nsrt/bug-13872.php new file mode 100644 index 0000000000..57bf2daded --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-13872.php @@ -0,0 +1,38 @@ +