Skip to content

Commit 5afb299

Browse files
Remove purity check from native type
1 parent b57bcad commit 5afb299

File tree

4 files changed

+59
-14
lines changed

4 files changed

+59
-14
lines changed

src/Rules/PhpDoc/VarTagTypeRuleHelper.php

+25-12
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44

55
use PhpParser\Node;
66
use PhpParser\Node\Expr;
7+
use PHPStan\Analyser\NameScope;
78
use PHPStan\Analyser\Scope;
89
use PHPStan\Node\Expr\GetOffsetValueTypeExpr;
910
use PHPStan\PhpDoc\Tag\VarTag;
11+
use PHPStan\PhpDoc\TypeNodeResolver;
1012
use PHPStan\Rules\IdentifierRuleError;
1113
use PHPStan\Rules\RuleErrorBuilder;
14+
use PHPStan\TrinaryLogic;
1215
use PHPStan\Type\ArrayType;
1316
use PHPStan\Type\Generic\GenericObjectType;
1417
use PHPStan\Type\MixedType;
@@ -24,8 +27,11 @@
2427
final class VarTagTypeRuleHelper
2528
{
2629

27-
public function __construct(private bool $checkTypeAgainstPhpDocType, private bool $strictWideningCheck)
28-
{
30+
public function __construct(
31+
private TypeNodeResolver $typeNodeResolver,
32+
private bool $checkTypeAgainstPhpDocType,
33+
private bool $strictWideningCheck
34+
) {
2935
}
3036

3137
/**
@@ -134,15 +140,15 @@ private function shouldVarTagTypeBeReported(Node\Expr $expr, Type $type, Type $v
134140
$type = new ArrayType(new MixedType(), new MixedType());
135141
}
136142

137-
return $type->isSuperTypeOf($varTagType)->no();
143+
return $this->isSuperTypeOfVarType($type, $varTagType)->no();
138144
}
139145

140146
if ($expr instanceof Expr\ConstFetch) {
141-
return $type->isSuperTypeOf($varTagType)->no();
147+
return $this->isSuperTypeOfVarType($type, $varTagType)->no();
142148
}
143149

144150
if ($expr instanceof Node\Scalar) {
145-
return $type->isSuperTypeOf($varTagType)->no();
151+
return $this->isSuperTypeOfVarType($type, $varTagType)->no();
146152
}
147153

148154
if ($expr instanceof Expr\New_) {
@@ -157,36 +163,43 @@ private function shouldVarTagTypeBeReported(Node\Expr $expr, Type $type, Type $v
157163
private function checkType(Type $type, Type $varTagType, int $depth = 0): bool
158164
{
159165
if ($this->strictWideningCheck) {
160-
return !$type->isSuperTypeOf($varTagType)->yes();
166+
return !$this->isSuperTypeOfVarType($type, $varTagType)->yes();
161167
}
162168

163169
if ($type->isConstantArray()->yes()) {
164170
if ($type->isIterableAtLeastOnce()->no()) {
165171
$type = new ArrayType(new MixedType(), new MixedType());
166-
return $type->isSuperTypeOf($varTagType)->no();
172+
return $this->isSuperTypeOfVarType($type, $varTagType)->no();
167173
}
168174
}
169175

170176
if ($type->isIterable()->yes() && $varTagType->isIterable()->yes()) {
171-
if ($type->isSuperTypeOf($varTagType)->no()) {
177+
if ($this->isSuperTypeOfVarType($type, $varTagType)->no()) {
172178
return true;
173179
}
174180

175181
$innerType = $type->getIterableValueType();
176182
$innerVarTagType = $varTagType->getIterableValueType();
177183

178184
if ($type->equals($innerType) || $varTagType->equals($innerVarTagType)) {
179-
return !$innerType->isSuperTypeOf($innerVarTagType)->yes();
185+
return !$this->isSuperTypeOfVarType($innerType, $innerVarTagType)->yes();
180186
}
181187

182188
return $this->checkType($innerType, $innerVarTagType, $depth + 1);
183189
}
184190

185-
if ($type->isConstantValue()->yes() && $depth === 0) {
186-
return $type->isSuperTypeOf($varTagType)->no();
191+
if ($depth === 0 && $type->isConstantValue()->yes()) {
192+
return $this->isSuperTypeOfVarType($type, $varTagType)->no();
187193
}
188194

189-
return !$type->isSuperTypeOf($varTagType)->yes();
195+
return !$this->isSuperTypeOfVarType($type, $varTagType)->yes();
196+
}
197+
198+
private function isSuperTypeOfVarType(Type $type, Type $varTagType): TrinaryLogic
199+
{
200+
$type = $this->typeNodeResolver->resolve($type->toPhpDocNode(), new NameScope(null, []));
201+
202+
return $type->isSuperTypeOf($varTagType);
190203
}
191204

192205
}

tests/PHPStan/Rules/PhpDoc/VarTagChangedExpressionTypeRuleTest.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Rules\PhpDoc;
44

5+
use PHPStan\PhpDoc\TypeNodeResolver;
56
use PHPStan\Rules\Rule;
67
use PHPStan\Testing\RuleTestCase;
78

@@ -13,7 +14,11 @@ class VarTagChangedExpressionTypeRuleTest extends RuleTestCase
1314

1415
protected function getRule(): Rule
1516
{
16-
return new VarTagChangedExpressionTypeRule(new VarTagTypeRuleHelper(true, true));
17+
return new VarTagChangedExpressionTypeRule(new VarTagTypeRuleHelper(
18+
self::getContainer()->getByType(TypeNodeResolver::class),
19+
true,
20+
true,
21+
));
1722
}
1823

1924
public function testRule(): void

tests/PHPStan/Rules/PhpDoc/WrongVariableNameInVarTagRuleTest.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace PHPStan\Rules\PhpDoc;
44

5+
use PHPStan\PhpDoc\TypeNodeResolver;
56
use PHPStan\Rules\Rule;
67
use PHPStan\Testing\RuleTestCase;
78
use PHPStan\Type\FileTypeMapper;
@@ -23,7 +24,11 @@ protected function getRule(): Rule
2324
{
2425
return new WrongVariableNameInVarTagRule(
2526
self::getContainer()->getByType(FileTypeMapper::class),
26-
new VarTagTypeRuleHelper($this->checkTypeAgainstPhpDocType, $this->strictWideningCheck),
27+
new VarTagTypeRuleHelper(
28+
self::getContainer()->getByType(TypeNodeResolver::class),
29+
$this->checkTypeAgainstPhpDocType,
30+
$this->strictWideningCheck,
31+
),
2732
$this->checkTypeAgainstNativeType,
2833
);
2934
}
@@ -182,6 +187,11 @@ public function testBug4505(): void
182187
$this->analyse([__DIR__ . '/data/bug-4505.php'], []);
183188
}
184189

190+
public function testBug12458(): void
191+
{
192+
$this->analyse([__DIR__ . '/data/bug-12458.php'], []);
193+
}
194+
185195
public function testEnums(): void
186196
{
187197
if (PHP_VERSION_ID < 80100) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php declare(strict_types = 1);
2+
3+
Namespace Bug12458;
4+
5+
class HelloWorld
6+
{
7+
/**
8+
* @param list<HelloWorld> $a
9+
*/
10+
public function test(array $a): void
11+
{
12+
/** @var \Closure(): list<HelloWorld> $c */
13+
$c = function () use ($a): array {
14+
return $a;
15+
};
16+
}
17+
}

0 commit comments

Comments
 (0)