Skip to content

Commit 78e6a46

Browse files
committed
Merge branch 2.1.x into 2.2.x
2 parents 042c4a1 + 82fb419 commit 78e6a46

3 files changed

Lines changed: 51 additions & 3 deletions

File tree

src/Analyser/TypeSpecifier.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,8 +1849,12 @@ private function specifyTypesFromAsserts(TypeSpecifierContext $context, Expr\Cal
18491849
if ($type instanceof ConditionalTypeForParameter) {
18501850
$parameterName = substr($type->getParameterName(), 1);
18511851
if (array_key_exists($parameterName, $argsMap)) {
1852-
$argType = TypeCombinator::union(...array_map(static fn (Expr $expr) => $scope->getType($expr), $argsMap[$parameterName]));
1853-
$type = $type->toConditional($argType);
1852+
$type = $traverse($type);
1853+
if ($type instanceof ConditionalTypeForParameter) {
1854+
$argType = TypeCombinator::union(...array_map(static fn (Expr $expr) => $scope->getType($expr), $argsMap[substr($type->getParameterName(), 1)]));
1855+
return $type->toConditional($argType);
1856+
}
1857+
return $type;
18541858
}
18551859
}
18561860

src/Reflection/ResolvedFunctionVariantWithOriginal.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,13 @@ private function resolveConditionalTypesForParameter(Type $type): Type
291291
{
292292
return TypeTraverser::map($type, function (Type $type, callable $traverse): Type {
293293
if ($type instanceof ConditionalTypeForParameter && array_key_exists($type->getParameterName(), $this->passedArgs)) {
294-
$type = $type->toConditional($this->passedArgs[$type->getParameterName()]);
294+
// Traverse children first, then convert — avoids infinite loop when
295+
// the passed argument contains ConditionalTypeForParameter with a colliding parameter name.
296+
$type = $traverse($type);
297+
if ($type instanceof ConditionalTypeForParameter) {
298+
return $type->toConditional($this->passedArgs[$type->getParameterName()]);
299+
}
300+
return $type;
295301
}
296302

297303
return $traverse($type);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace Bug13872;
4+
5+
use function is_array;
6+
use function is_bool;
7+
use function is_callable;
8+
use function is_countable;
9+
use function is_float;
10+
use function is_int;
11+
use function is_iterable;
12+
use function is_null;
13+
use function is_numeric;
14+
use function is_object;
15+
use function is_resource;
16+
use function is_scalar;
17+
use function is_string;
18+
use function PHPStan\Testing\assertType;
19+
20+
class Foo
21+
{
22+
public function check(): void
23+
{
24+
assertType('true', is_callable(is_callable(...)));
25+
assertType('true', is_callable(is_array(...)));
26+
assertType('false', is_array(is_string(...)));
27+
assertType('false', is_string(is_int(...)));
28+
assertType('false', is_int(is_callable(...)));
29+
assertType('true', is_object(is_callable(...)));
30+
assertType('true', is_callable(is_bool(...)));
31+
assertType('false', is_null(is_string(...)));
32+
assertType('false', is_float(is_int(...)));
33+
assertType('false', is_scalar(is_numeric(...)));
34+
assertType('false', is_countable(is_array(...)));
35+
assertType('false', is_iterable(is_string(...)));
36+
assertType('false', is_resource(is_callable(...)));
37+
}
38+
}

0 commit comments

Comments
 (0)