Skip to content

Commit d528228

Browse files
Fix get_debug_type produces wrong type for anonymous classes with parent
1 parent 1968aa9 commit d528228

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

Diff for: src/Type/Php/GetDebugTypeFunctionReturnTypeExtension.php

+12-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use PHPStan\Type\StringType;
1212
use PHPStan\Type\Type;
1313
use PHPStan\Type\UnionType;
14+
use function array_key_first;
1415
use function array_map;
1516
use function count;
1617

@@ -37,6 +38,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
3738

3839
/**
3940
* @see https://www.php.net/manual/en/function.get-debug-type.php#refsect1-function.get-debug-type-returnvalues
41+
* @see https://github.com/php/php-src/commit/ef0e4478c51540510b67f7781ad240f5e0592ee4
4042
*/
4143
private static function resolveOneType(Type $type): Type
4244
{
@@ -71,7 +73,16 @@ private static function resolveOneType(Type $type): Type
7173
}
7274

7375
if ($reflection->isAnonymous()) { // phpcs:ignore
74-
$types[] = new ConstantStringType('class@anonymous');
76+
$parentClass = $reflection->getParentClass();
77+
$implementedInterfaces = $reflection->getImmediateInterfaces();
78+
if ($parentClass !== null) {
79+
$types[] = new ConstantStringType($parentClass->getName() . '@anonymous');
80+
} elseif ($implementedInterfaces !== []) {
81+
$firstInterface = $implementedInterfaces[array_key_first($implementedInterfaces)];
82+
$types[] = new ConstantStringType($firstInterface->getName() . '@anonymous');
83+
} else {
84+
$types[] = new ConstantStringType('class@anonymous');
85+
}
7586
}
7687
}
7788

Diff for: tests/PHPStan/Analyser/nsrt/get-debug-type.php

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
use function PHPStan\Testing\assertType;
66

77
final class A {}
8+
interface B {}
9+
interface C {}
10+
class D {}
811

912
/**
1013
* @param double $d
@@ -18,6 +21,9 @@ function doFoo(bool $b, int $i, float $f, $d, $r, string $s, array $a, $intOrStr
1821
$o = new \stdClass();
1922
$A = new A();
2023
$anonymous = new class {};
24+
$anonymousImplements = new class implements B, C {};
25+
$anonymousExtends = new class extends D {};
26+
$anonymousExtendsImplements = new class extends D implements B, C {};
2127

2228
assertType("'bool'", get_debug_type($b));
2329
assertType("'bool'", get_debug_type(true));
@@ -35,6 +41,9 @@ function doFoo(bool $b, int $i, float $f, $d, $r, string $s, array $a, $intOrStr
3541
assertType("'int'|'string'", get_debug_type($intOrString));
3642
assertType("'array'|'GetDebugType\\\\A'", get_debug_type($arrayOrObject));
3743
assertType("'class@anonymous'", get_debug_type($anonymous));
44+
assertType("'GetDebugType\\\\B@anonymous'", get_debug_type($anonymousImplements));
45+
assertType("'GetDebugType\\\\D@anonymous'", get_debug_type($anonymousExtends));
46+
assertType("'GetDebugType\\\\D@anonymous'", get_debug_type($anonymousExtendsImplements));
3847
}
3948

4049
/**

0 commit comments

Comments
 (0)