Skip to content

Commit 45824e4

Browse files
Remove purity check from native type
1 parent b57bcad commit 45824e4

File tree

4 files changed

+59
-13
lines changed

4 files changed

+59
-13
lines changed

src/Rules/PhpDoc/VarTagTypeRuleHelper.php

+25-11
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,7 +27,11 @@
2427
final class VarTagTypeRuleHelper
2528
{
2629

27-
public function __construct(private bool $checkTypeAgainstPhpDocType, private bool $strictWideningCheck)
30+
public function __construct(
31+
private TypeNodeResolver $typeNodeResolver,
32+
private bool $checkTypeAgainstPhpDocType,
33+
private bool $strictWideningCheck,
34+
)
2835
{
2936
}
3037

@@ -134,15 +141,15 @@ private function shouldVarTagTypeBeReported(Node\Expr $expr, Type $type, Type $v
134141
$type = new ArrayType(new MixedType(), new MixedType());
135142
}
136143

137-
return $type->isSuperTypeOf($varTagType)->no();
144+
return $this->isSuperTypeOfVarType($type, $varTagType)->no();
138145
}
139146

140147
if ($expr instanceof Expr\ConstFetch) {
141-
return $type->isSuperTypeOf($varTagType)->no();
148+
return $this->isSuperTypeOfVarType($type, $varTagType)->no();
142149
}
143150

144151
if ($expr instanceof Node\Scalar) {
145-
return $type->isSuperTypeOf($varTagType)->no();
152+
return $this->isSuperTypeOfVarType($type, $varTagType)->no();
146153
}
147154

148155
if ($expr instanceof Expr\New_) {
@@ -157,36 +164,43 @@ private function shouldVarTagTypeBeReported(Node\Expr $expr, Type $type, Type $v
157164
private function checkType(Type $type, Type $varTagType, int $depth = 0): bool
158165
{
159166
if ($this->strictWideningCheck) {
160-
return !$type->isSuperTypeOf($varTagType)->yes();
167+
return !$this->isSuperTypeOfVarType($type, $varTagType)->yes();
161168
}
162169

163170
if ($type->isConstantArray()->yes()) {
164171
if ($type->isIterableAtLeastOnce()->no()) {
165172
$type = new ArrayType(new MixedType(), new MixedType());
166-
return $type->isSuperTypeOf($varTagType)->no();
173+
return $this->isSuperTypeOfVarType($type, $varTagType)->no();
167174
}
168175
}
169176

170177
if ($type->isIterable()->yes() && $varTagType->isIterable()->yes()) {
171-
if ($type->isSuperTypeOf($varTagType)->no()) {
178+
if ($this->isSuperTypeOfVarType($type, $varTagType)->no()) {
172179
return true;
173180
}
174181

175182
$innerType = $type->getIterableValueType();
176183
$innerVarTagType = $varTagType->getIterableValueType();
177184

178185
if ($type->equals($innerType) || $varTagType->equals($innerVarTagType)) {
179-
return !$innerType->isSuperTypeOf($innerVarTagType)->yes();
186+
return !$this->isSuperTypeOfVarType($innerType, $innerVarTagType)->yes();
180187
}
181188

182189
return $this->checkType($innerType, $innerVarTagType, $depth + 1);
183190
}
184191

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

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

192206
}

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)