Skip to content

Commit 856040e

Browse files
committed
Add test for phpstan issue 7396
1 parent fd304ca commit 856040e

File tree

4 files changed

+65
-0
lines changed

4 files changed

+65
-0
lines changed

tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public function dataAsserts(): iterable
2020
yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-getsingle-conditional.php');
2121
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7344.php');
2222
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7391b.php');
23+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7385.php');
2324
}
2425

2526
/**

tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
use PhpParser\Node\Expr\New_;
88
use PhpParser\Node\Expr\StaticCall;
99
use PHPStan\Analyser\Scope;
10+
use PHPStan\Analyser\SpecifiedTypes;
11+
use PHPStan\Analyser\TypeSpecifier;
12+
use PHPStan\Analyser\TypeSpecifierAwareExtension;
13+
use PHPStan\Analyser\TypeSpecifierContext;
1014
use PHPStan\Reflection\Dummy\ChangedTypeMethodReflection;
1115
use PHPStan\Reflection\MethodReflection;
1216
use PHPStan\Reflection\ParametersAcceptorSelector;
@@ -18,6 +22,7 @@
1822
use PHPStan\Type\DynamicStaticMethodReturnTypeExtension;
1923
use PHPStan\Type\IntegerType;
2024
use PHPStan\Type\IntersectionType;
25+
use PHPStan\Type\MethodTypeSpecifyingExtension;
2126
use PHPStan\Type\NeverType;
2227
use PHPStan\Type\ObjectType;
2328
use PHPStan\Type\ObjectWithoutClassType;
@@ -263,3 +268,34 @@ public function getTypeFromStaticMethodCall(
263268
return $scope->getType(new New_($methodCall->class));
264269
}
265270
}
271+
272+
class Bug7385MethodTypeSpecifyingExtension implements TypeSpecifierAwareExtension, MethodTypeSpecifyingExtension
273+
{
274+
public function getClass(): string
275+
{
276+
return \Bug7385\Model::class;
277+
}
278+
279+
public function isMethodSupported(MethodReflection $methodReflection, MethodCall $methodCall = null, TypeSpecifierContext $context = null): bool
280+
{
281+
return $methodReflection->getName() === 'assertHasIface';
282+
}
283+
284+
/** @var TypeSpecifier */
285+
protected $typeSpecifier;
286+
287+
public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void
288+
{
289+
$this->typeSpecifier = $typeSpecifier;
290+
}
291+
292+
public function specifyTypes(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes
293+
{
294+
$type = TypeCombinator::intersect(
295+
$scope->getType($methodCall->var),
296+
new ObjectType(\Bug7385\Iface::class)
297+
);
298+
299+
return $this->typeSpecifier->create($methodCall->var, $type, TypeSpecifierContext::createNull());
300+
}
301+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug7385;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Model
8+
{
9+
public function assertHasIface(): void
10+
{
11+
throw new \Error('For static analysis only, $this type is narrowed by MethodTypeSpecifyingExtension');
12+
}
13+
}
14+
15+
interface Iface
16+
{
17+
}
18+
19+
function () {
20+
$m = random_int(0, 1) === 0 ? new Model() : new class() extends Model implements Iface {};
21+
assertType('Bug7385\Model', $m);
22+
$m->assertHasIface();
23+
assertType('Bug7385\Model&Bug7391\Iface', $m);
24+
};

tests/PHPStan/Analyser/dynamic-return-type.neon

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ services:
3939
class: PHPStan\Tests\Bug7391BDynamicStaticMethodReturnTypeExtension
4040
tags:
4141
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
42+
-
43+
class: PHPStan\Tests\Bug7385MethodTypeSpecifyingExtension
44+
tags:
45+
- phpstan.typeSpecifier.methodTypeSpecifyingExtension

0 commit comments

Comments
 (0)