Skip to content

Commit d107613

Browse files
authored
Bleeding edge - Fix position variance of static method parameters
1 parent 1d4ede1 commit d107613

10 files changed

Lines changed: 119 additions & 5 deletions

‎conf/bleedingEdge.neon‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ parameters:
3333
instanceofType: true
3434
paramOutVariance: true
3535
allInvalidPhpDocs: true
36+
strictStaticMethodTemplateTypeVariance: true

‎conf/config.neon‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ parameters:
6363
instanceofType: false
6464
paramOutVariance: false
6565
allInvalidPhpDocs: false
66+
strictStaticMethodTemplateTypeVariance: false
6667
fileExtensions:
6768
- php
6869
checkAdvancedIsset: false
@@ -296,6 +297,7 @@ parametersSchema:
296297
instanceofType: bool()
297298
paramOutVariance: bool()
298299
allInvalidPhpDocs: bool()
300+
strictStaticMethodTemplateTypeVariance: bool()
299301
])
300302
fileExtensions: listOf(string())
301303
checkAdvancedIsset: bool()
@@ -1050,6 +1052,7 @@ services:
10501052
class: PHPStan\Rules\Generics\VarianceCheck
10511053
arguments:
10521054
checkParamOutVariance: %featureToggles.paramOutVariance%
1055+
strictStaticVariance: %featureToggles.strictStaticMethodTemplateTypeVariance%
10531056

10541057
-
10551058
class: PHPStan\Rules\IssetCheck

‎src/Rules/Generics/VarianceCheck.php‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class VarianceCheck
1515

1616
public function __construct(
1717
private bool $checkParamOutVariance,
18+
private bool $strictStaticVariance,
1819
)
1920
{
2021
}
@@ -52,7 +53,7 @@ public function checkParametersAcceptor(
5253
}
5354

5455
$covariant = TemplateTypeVariance::createCovariant();
55-
$parameterVariance = $isStatic
56+
$parameterVariance = $isStatic && !$this->strictStaticVariance
5657
? TemplateTypeVariance::createStatic()
5758
: TemplateTypeVariance::createContravariant();
5859

‎tests/PHPStan/Generics/data/variance-2.json‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@
5959
"line": 124,
6060
"ignorable": true
6161
},
62+
{
63+
"message": "Template type T is declared as covariant, but occurs in contravariant position in parameter t of method PHPStan\\Generics\\Variance\\ConstructorAndStatic::create().",
64+
"line": 153,
65+
"ignorable": true
66+
},
67+
{
68+
"message": "Template type T is declared as covariant, but occurs in contravariant position in parameter w of method PHPStan\\Generics\\Variance\\ConstructorAndStatic::create().",
69+
"line": 153,
70+
"ignorable": true
71+
},
6272
{
6373
"message": "Template type T is declared as covariant, but occurs in invariant position in parameter v of method PHPStan\\Generics\\Variance\\ConstructorAndStatic::create().",
6474
"line": 153,

‎tests/PHPStan/Rules/Generics/ClassAncestorsRuleTest.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ protected function getRule(): Rule
1717
new GenericAncestorsCheck(
1818
$this->createReflectionProvider(),
1919
new GenericObjectTypeCheck(),
20-
new VarianceCheck(true),
20+
new VarianceCheck(true, true),
2121
true,
2222
[],
2323
),

‎tests/PHPStan/Rules/Generics/EnumAncestorsRuleTest.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ protected function getRule(): Rule
1818
new GenericAncestorsCheck(
1919
$this->createReflectionProvider(),
2020
new GenericObjectTypeCheck(),
21-
new VarianceCheck(true),
21+
new VarianceCheck(true, true),
2222
true,
2323
[],
2424
),

‎tests/PHPStan/Rules/Generics/InterfaceAncestorsRuleTest.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ protected function getRule(): Rule
1717
new GenericAncestorsCheck(
1818
$this->createReflectionProvider(),
1919
new GenericObjectTypeCheck(),
20-
new VarianceCheck(true),
20+
new VarianceCheck(true, true),
2121
true,
2222
[],
2323
),

‎tests/PHPStan/Rules/Generics/MethodSignatureVarianceRuleTest.php‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,33 @@ public function testRule(): void
180180
]);
181181

182182
$this->analyse([__DIR__ . '/data/method-signature-variance-constructor.php'], []);
183+
184+
$this->analyse([__DIR__ . '/data/method-signature-variance-static.php'], [
185+
[
186+
'Template type X is declared as covariant, but occurs in contravariant position in parameter a of method MethodSignatureVariance\StaticMethod\B::a().',
187+
43,
188+
],
189+
[
190+
'Template type X is declared as covariant, but occurs in contravariant position in parameter c of method MethodSignatureVariance\StaticMethod\B::a().',
191+
43,
192+
],
193+
[
194+
'Template type X is declared as covariant, but occurs in contravariant position in return type of method MethodSignatureVariance\StaticMethod\B::c().',
195+
49,
196+
],
197+
[
198+
'Template type X is declared as contravariant, but occurs in covariant position in parameter b of method MethodSignatureVariance\StaticMethod\C::a().',
199+
62,
200+
],
201+
[
202+
'Template type X is declared as contravariant, but occurs in covariant position in return type of method MethodSignatureVariance\StaticMethod\C::b().',
203+
65,
204+
],
205+
[
206+
'Template type X is declared as contravariant, but occurs in covariant position in return type of method MethodSignatureVariance\StaticMethod\C::d().',
207+
71,
208+
],
209+
]);
183210
}
184211

185212
public function testBug8880(): void

‎tests/PHPStan/Rules/Generics/UsedTraitsRuleTest.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ protected function getRule(): Rule
1919
new GenericAncestorsCheck(
2020
$this->createReflectionProvider(),
2121
new GenericObjectTypeCheck(),
22-
new VarianceCheck(true),
22+
new VarianceCheck(true, true),
2323
true,
2424
[],
2525
),
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace MethodSignatureVariance\StaticMethod;
4+
5+
/** @template-contravariant T */
6+
interface In {
7+
}
8+
9+
/** @template-covariant T */
10+
interface Out {
11+
}
12+
13+
/** @template T */
14+
interface Invariant {
15+
}
16+
17+
/** @template X */
18+
class A {
19+
/**
20+
* @param X $a
21+
* @param In<X> $b
22+
* @param Out<X> $c
23+
*/
24+
static function a($a, $b, $c) {}
25+
26+
/** @return X */
27+
static function b() {}
28+
29+
/** @return In<X> */
30+
static function c() {}
31+
32+
/** @return Out<X> */
33+
static function d() {}
34+
}
35+
36+
/** @template-covariant X */
37+
class B {
38+
/**
39+
* @param X $a
40+
* @param In<X> $b
41+
* @param Out<X> $c
42+
*/
43+
static function a($a, $b, $c) {}
44+
45+
/** @return X */
46+
static function b() {}
47+
48+
/** @return In<X> */
49+
static function c() {}
50+
51+
/** @return Out<X> */
52+
static function d() {}
53+
}
54+
55+
/** @template-contravariant X */
56+
class C {
57+
/**
58+
* @param X $a
59+
* @param In<X> $b
60+
* @param Out<X> $c
61+
*/
62+
static function a($a, $b, $c) {}
63+
64+
/** @return X */
65+
static function b() {}
66+
67+
/** @return In<X> */
68+
static function c() {}
69+
70+
/** @return Out<X> */
71+
static function d() {}
72+
}

0 commit comments

Comments
 (0)