diff --git a/src/Reflection/Php/PhpClassReflectionExtension.php b/src/Reflection/Php/PhpClassReflectionExtension.php index 2c15cf3e99..321ee288ee 100644 --- a/src/Reflection/Php/PhpClassReflectionExtension.php +++ b/src/Reflection/Php/PhpClassReflectionExtension.php @@ -618,12 +618,16 @@ private function createMethod( ); } - return $this->createUserlandMethodReflection($declaringClass, $declaringClass, $methodReflection); + return $this->createUserlandMethodReflection( + $declaringClass, + $declaringClass, + $methodReflection, + $this->findMethodTrait($methodReflection), + ); } - public function createUserlandMethodReflection(ClassReflection $fileDeclaringClass, ClassReflection $actualDeclaringClass, BuiltinMethodReflection $methodReflection): PhpMethodReflection + public function createUserlandMethodReflection(ClassReflection $fileDeclaringClass, ClassReflection $actualDeclaringClass, BuiltinMethodReflection $methodReflection, ?string $declaringTraitName): PhpMethodReflection { - $declaringTraitName = $this->findMethodTrait($methodReflection); $resolvedPhpDoc = null; $stubPhpDocPair = $this->findMethodPhpDocIncludingAncestors($fileDeclaringClass, $methodReflection->getName(), array_map(static fn (ReflectionParameter $parameter): string => $parameter->getName(), $methodReflection->getParameters())); $phpDocBlockClassReflection = $fileDeclaringClass; diff --git a/src/Rules/Methods/MethodSignatureRule.php b/src/Rules/Methods/MethodSignatureRule.php index 3de09b7ca6..dda585bf52 100644 --- a/src/Rules/Methods/MethodSignatureRule.php +++ b/src/Rules/Methods/MethodSignatureRule.php @@ -150,13 +150,15 @@ private function collectParentMethods(string $methodName, ClassReflection $class continue; } + $declaringTrait = $trait->getNativeMethod($methodName)->getDeclaringClass(); $parentMethods[] = [ $this->phpClassReflectionExtension->createUserlandMethodReflection( $trait, $class, new NativeBuiltinMethodReflection($methodReflection), + $declaringTrait->getName(), ), - $trait->getNativeMethod($methodName)->getDeclaringClass(), + $declaringTrait, ]; } } diff --git a/src/Rules/Methods/OverridingMethodRule.php b/src/Rules/Methods/OverridingMethodRule.php index aa22a9cab9..686d04918f 100644 --- a/src/Rules/Methods/OverridingMethodRule.php +++ b/src/Rules/Methods/OverridingMethodRule.php @@ -334,13 +334,15 @@ private function findPrototype(ClassReflection $classReflection, string $methodN $methodReflection = $nativeTraitReflection->getMethod($methodName); $isAbstract = $methodReflection->isAbstract(); if ($isAbstract) { + $declaringTrait = $trait->getNativeMethod($methodName)->getDeclaringClass(); return [ $this->phpClassReflectionExtension->createUserlandMethodReflection( $trait, $classReflection, new NativeBuiltinMethodReflection($methodReflection), + $declaringTrait->getName(), ), - $trait->getNativeMethod($methodName)->getDeclaringClass(), + $declaringTrait, false, ]; } diff --git a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php index 58342f5ce3..ca62a9401a 100644 --- a/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php +++ b/tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php @@ -462,4 +462,16 @@ public function testBug10166(): void ]); } + public function testBug10184(): void + { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Test requires PHP 8.0.'); + } + + $this->reportMaybes = true; + $this->reportStatic = true; + + $this->analyse([__DIR__ . '/data/bug-10184.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Methods/data/bug-10184.php b/tests/PHPStan/Rules/Methods/data/bug-10184.php new file mode 100644 index 0000000000..16446d830d --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-10184.php @@ -0,0 +1,29 @@ + */ + abstract public function foo(): Collection; +} + +class Baz +{ + /** @use FooTrait */ + use FooTrait; + + /** @return Collection */ + public function foo(): Collection + { + /** @var Collection */ + return new Collection(); + } +}