From 856040e9182f2c7acd136de724c0f9c93e33891f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Sat, 18 Jun 2022 12:54:51 +0200 Subject: [PATCH 1/4] Add test for phpstan issue 7396 --- ...icReturnTypeExtensionTypeInferenceTest.php | 1 + .../data/TestDynamicReturnTypeExtensions.php | 36 +++++++++++++++++++ tests/PHPStan/Analyser/data/bug-7385.php | 24 +++++++++++++ .../PHPStan/Analyser/dynamic-return-type.neon | 4 +++ 4 files changed, 65 insertions(+) create mode 100644 tests/PHPStan/Analyser/data/bug-7385.php diff --git a/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php b/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php index 59ebef356e..572ec5921e 100644 --- a/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php +++ b/tests/PHPStan/Analyser/DynamicReturnTypeExtensionTypeInferenceTest.php @@ -20,6 +20,7 @@ public function dataAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/dynamic-method-return-getsingle-conditional.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7344.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7391b.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7385.php'); } /** diff --git a/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php b/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php index 446e478cd0..d24bc484c9 100644 --- a/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php +++ b/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php @@ -7,6 +7,10 @@ use PhpParser\Node\Expr\New_; use PhpParser\Node\Expr\StaticCall; use PHPStan\Analyser\Scope; +use PHPStan\Analyser\SpecifiedTypes; +use PHPStan\Analyser\TypeSpecifier; +use PHPStan\Analyser\TypeSpecifierAwareExtension; +use PHPStan\Analyser\TypeSpecifierContext; use PHPStan\Reflection\Dummy\ChangedTypeMethodReflection; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ParametersAcceptorSelector; @@ -18,6 +22,7 @@ use PHPStan\Type\DynamicStaticMethodReturnTypeExtension; use PHPStan\Type\IntegerType; use PHPStan\Type\IntersectionType; +use PHPStan\Type\MethodTypeSpecifyingExtension; use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\ObjectWithoutClassType; @@ -263,3 +268,34 @@ public function getTypeFromStaticMethodCall( return $scope->getType(new New_($methodCall->class)); } } + +class Bug7385MethodTypeSpecifyingExtension implements TypeSpecifierAwareExtension, MethodTypeSpecifyingExtension +{ + public function getClass(): string + { + return \Bug7385\Model::class; + } + + public function isMethodSupported(MethodReflection $methodReflection, MethodCall $methodCall = null, TypeSpecifierContext $context = null): bool + { + return $methodReflection->getName() === 'assertHasIface'; + } + + /** @var TypeSpecifier */ + protected $typeSpecifier; + + public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void + { + $this->typeSpecifier = $typeSpecifier; + } + + public function specifyTypes(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes + { + $type = TypeCombinator::intersect( + $scope->getType($methodCall->var), + new ObjectType(\Bug7385\Iface::class) + ); + + return $this->typeSpecifier->create($methodCall->var, $type, TypeSpecifierContext::createNull()); + } +} diff --git a/tests/PHPStan/Analyser/data/bug-7385.php b/tests/PHPStan/Analyser/data/bug-7385.php new file mode 100644 index 0000000000..0190b1e736 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-7385.php @@ -0,0 +1,24 @@ +assertHasIface(); + assertType('Bug7385\Model&Bug7391\Iface', $m); +}; diff --git a/tests/PHPStan/Analyser/dynamic-return-type.neon b/tests/PHPStan/Analyser/dynamic-return-type.neon index e80f2018a0..038a84da54 100644 --- a/tests/PHPStan/Analyser/dynamic-return-type.neon +++ b/tests/PHPStan/Analyser/dynamic-return-type.neon @@ -39,3 +39,7 @@ services: class: PHPStan\Tests\Bug7391BDynamicStaticMethodReturnTypeExtension tags: - phpstan.broker.dynamicStaticMethodReturnTypeExtension + - + class: PHPStan\Tests\Bug7385MethodTypeSpecifyingExtension + tags: + - phpstan.typeSpecifier.methodTypeSpecifyingExtension From 2f5a3baa3ce8598643eb22c48bd712e402e7e72b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Sat, 18 Jun 2022 13:11:02 +0200 Subject: [PATCH 2/4] TEST --- tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php b/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php index d24bc484c9..c3f226e25e 100644 --- a/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php +++ b/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php @@ -296,6 +296,8 @@ public function specifyTypes(MethodReflection $methodReflection, MethodCall $met new ObjectType(\Bug7385\Iface::class) ); + throw new \Error('reached: ' . $type->describe(\PHPStan\Type\VerbosityLevel::precise())); + return $this->typeSpecifier->create($methodCall->var, $type, TypeSpecifierContext::createNull()); } } From 253aa2ea72101eb2231e4e980e79eae15db48adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Sat, 18 Jun 2022 13:13:48 +0200 Subject: [PATCH 3/4] fix test --- tests/PHPStan/Analyser/data/bug-7385.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Analyser/data/bug-7385.php b/tests/PHPStan/Analyser/data/bug-7385.php index 0190b1e736..b41d53fbd2 100644 --- a/tests/PHPStan/Analyser/data/bug-7385.php +++ b/tests/PHPStan/Analyser/data/bug-7385.php @@ -20,5 +20,5 @@ function () { $m = random_int(0, 1) === 0 ? new Model() : new class() extends Model implements Iface {}; assertType('Bug7385\Model', $m); $m->assertHasIface(); - assertType('Bug7385\Model&Bug7391\Iface', $m); + assertType('Bug7385\Iface&Bug7385\Model', $m); }; From d90bc0a25f31aac9ad896a1c00559dfe1064ef51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Sat, 18 Jun 2022 13:11:02 +0200 Subject: [PATCH 4/4] Revert "TEST" This reverts commit e89b50a2b03e2f635eb6b2a2e0c0cf61a54692f8. --- tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php b/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php index c3f226e25e..d24bc484c9 100644 --- a/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php +++ b/tests/PHPStan/Analyser/data/TestDynamicReturnTypeExtensions.php @@ -296,8 +296,6 @@ public function specifyTypes(MethodReflection $methodReflection, MethodCall $met new ObjectType(\Bug7385\Iface::class) ); - throw new \Error('reached: ' . $type->describe(\PHPStan\Type\VerbosityLevel::precise())); - return $this->typeSpecifier->create($methodCall->var, $type, TypeSpecifierContext::createNull()); } }