Skip to content

Commit c5be7a1

Browse files
committed
Fix phpstan/phpstan#14320: False positive contravariant parameter with nested trait
- Skip traits that inherited an abstract method from a sub-trait in ParentMethodHelper::collectParentMethods - The actual declaring trait is still checked separately in the same loop - New regression test in tests/PHPStan/Rules/Methods/data/bug-14320.php
1 parent f077b36 commit c5be7a1

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

src/Rules/Methods/ParentMethodHelper.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ public function collectParentMethods(string $methodName, ClassReflection $class)
5353
continue;
5454
}
5555

56+
// Skip traits that inherited the method from a sub-trait
57+
// The actual declaring trait will be processed separately
58+
if ($methodReflection->getBetterReflection()->getDeclaringClass()->getName() !== $trait->getName()) {
59+
continue;
60+
}
61+
5662
$declaringTrait = $trait->getNativeMethod($methodName)->getDeclaringClass();
5763
$parentMethods[] = [
5864
$this->phpClassReflectionExtension->createUserlandMethodReflection(

tests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,4 +558,11 @@ public function testBug12073(): void
558558
$this->analyse([__DIR__ . '/data/bug-12073.php'], []);
559559
}
560560

561+
public function testBug14320(): void
562+
{
563+
$this->reportMaybes = true;
564+
$this->reportStatic = true;
565+
$this->analyse([__DIR__ . '/data/bug-14320.php'], []);
566+
}
567+
561568
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug14320;
4+
5+
trait MyTrait
6+
{
7+
/**
8+
* @param array<string, mixed> $data
9+
* @return array<string, mixed>
10+
*/
11+
abstract protected function myFunction(array $data): array;
12+
}
13+
14+
trait MyFirstTrait
15+
{
16+
use MyTrait;
17+
}
18+
19+
abstract class MyAbstractClass
20+
{
21+
use MyFirstTrait;
22+
23+
/**
24+
* @param array<string, mixed> $data
25+
* @return array<string, mixed>
26+
*/
27+
protected function myFunction(array $data): array
28+
{
29+
return [
30+
'hello' => 'bug',
31+
];
32+
}
33+
}

0 commit comments

Comments
 (0)