Skip to content

Commit 9435151

Browse files
committed
Allow ReflectionClass<covariant X> even on PHP 8.3-
1 parent 02116b7 commit 9435151

File tree

3 files changed

+47
-11
lines changed

3 files changed

+47
-11
lines changed

src/Rules/Generics/GenericObjectTypeCheck.php

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use PHPStan\Type\Type;
1717
use PHPStan\Type\TypeTraverser;
1818
use PHPStan\Type\VerbosityLevel;
19+
use ReflectionClass;
1920
use function array_filter;
2021
use function array_keys;
2122
use function array_values;
@@ -105,17 +106,24 @@ public function check(
105106
$genericTypeVariance = $genericTypeVariances[$i] ?? TemplateTypeVariance::createInvariant();
106107
if ($templateType instanceof TemplateType && !$genericTypeVariance->invariant()) {
107108
if ($genericTypeVariance->equals($templateType->getVariance())) {
108-
$messages[] = RuleErrorBuilder::message(sprintf(
109-
$typeProjectionIsRedundantMessage,
110-
TypeProjectionHelper::describe($genericTypeType, $genericTypeVariance, VerbosityLevel::typeOnly()),
111-
$genericType->describe(VerbosityLevel::typeOnly()),
112-
$templateType->describe(VerbosityLevel::typeOnly()),
113-
$classLikeDescription,
114-
$classReflection->getDisplayName(false),
115-
))
116-
->identifier('generics.callSiteVarianceRedundant')
117-
->tip('You can safely remove the call-site variance annotation.')
118-
->build();
109+
if (
110+
// allow ReflectionClass<covariant X>
111+
// so that same code works for PHP 8.3 and 8.4+
112+
$classReflection->getName() !== ReflectionClass::class
113+
|| $templateType->getName() !== 'T'
114+
) {
115+
$messages[] = RuleErrorBuilder::message(sprintf(
116+
$typeProjectionIsRedundantMessage,
117+
TypeProjectionHelper::describe($genericTypeType, $genericTypeVariance, VerbosityLevel::typeOnly()),
118+
$genericType->describe(VerbosityLevel::typeOnly()),
119+
$templateType->describe(VerbosityLevel::typeOnly()),
120+
$classLikeDescription,
121+
$classReflection->getDisplayName(false),
122+
))
123+
->identifier('generics.callSiteVarianceRedundant')
124+
->tip('You can safely remove the call-site variance annotation.')
125+
->build();
126+
}
119127
} elseif (!$genericTypeVariance->validPosition($templateType->getVariance())) {
120128
$messages[] = RuleErrorBuilder::message(sprintf(
121129
$typeProjectionHasConflictingVarianceMessage,

tests/PHPStan/Rules/PhpDoc/IncompatiblePhpDocTypeRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,9 @@ public function testGenericStatic(): void
461461
]);
462462
}
463463

464+
public function testBug13452(): void
465+
{
466+
$this->analyse([__DIR__ . '/data/bug-13452.php'], []);
467+
}
468+
464469
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Bug13452;
4+
5+
use ReflectionClass;
6+
7+
class Event
8+
{
9+
10+
}
11+
12+
class HelloWorld
13+
{
14+
15+
/**
16+
* @param ReflectionClass<covariant Event> $ref
17+
*/
18+
public function doFoo(ReflectionClass $ref): void
19+
{
20+
21+
}
22+
23+
}

0 commit comments

Comments
 (0)