Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fe166b1

Browse files
Prevent always true/false errors for unresolvable template types
1 parent 0001859 commit fe166b1

File tree

4 files changed

+65
-2
lines changed

4 files changed

+65
-2
lines changed

‎src/Analyser/TypeSpecifier.php‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
use PHPStan\Type\FloatType;
4545
use PHPStan\Type\FunctionTypeSpecifyingExtension;
4646
use PHPStan\Type\Generic\GenericClassStringType;
47+
use PHPStan\Type\Generic\TemplateType;
4748
use PHPStan\Type\Generic\TemplateTypeHelper;
4849
use PHPStan\Type\IntegerRangeType;
4950
use PHPStan\Type\IntegerType;
@@ -1215,12 +1216,30 @@ private function specifyTypesFromAsserts(TypeSpecifierContext $context, Expr\Cal
12151216

12161217
$assertExpr = $assert->getParameter()->getExpr($parameterExpr);
12171218

1219+
$templateTypeMap = $parametersAcceptor->getResolvedTemplateTypeMap();
1220+
$containsUnresolvedTemplate = false;
1221+
TypeTraverser::map(
1222+
$assert->getOriginalType(),
1223+
static function (Type $type, callable $traverse) use ($templateTypeMap, &$containsUnresolvedTemplate) {
1224+
if ($type instanceof TemplateType && $type->getScope()->getClassName() !== null) {
1225+
$resolvedType = $templateTypeMap->getType($type->getName());
1226+
if ($resolvedType === null || $type->getBound()->equals($resolvedType)) {
1227+
$containsUnresolvedTemplate = true;
1228+
return $type;
1229+
}
1230+
}
1231+
1232+
return $traverse($type);
1233+
},
1234+
);
1235+
12181236
$newTypes = $this->create(
12191237
$assertExpr,
12201238
$assert->getType(),
12211239
$assert->isNegated() ? TypeSpecifierContext::createFalse() : TypeSpecifierContext::createTrue(),
12221240
false,
12231241
$scope,
1242+
$containsUnresolvedTemplate ? $call : null,
12241243
);
12251244
$types = $types !== null ? $types->unionWith($newTypes) : $newTypes;
12261245
}

‎src/PhpDoc/Tag/AssertTag.php‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ final class AssertTag implements TypedTag
1212
public const IF_TRUE = 'true';
1313
public const IF_FALSE = 'false';
1414

15+
private ?Type $originalType = null;
16+
1517
/**
1618
* @param self::NULL|self::IF_TRUE|self::IF_FALSE $if
1719
*/
@@ -32,6 +34,11 @@ public function getType(): Type
3234
return $this->type;
3335
}
3436

37+
public function getOriginalType(): Type
38+
{
39+
return $this->originalType ??= $this->type;
40+
}
41+
3542
public function getParameter(): AssertTagParameter
3643
{
3744
return $this->parameter;
@@ -47,12 +54,16 @@ public function isNegated(): bool
4754
*/
4855
public function withType(Type $type): TypedTag
4956
{
50-
return new self($this->if, $type, $this->parameter, $this->negated);
57+
$tag = new self($this->if, $type, $this->parameter, $this->negated);
58+
$tag->originalType = $this->getOriginalType();
59+
return $tag;
5160
}
5261

5362
public function withParameter(AssertTagParameter $parameter): self
5463
{
55-
return new self($this->if, $this->type, $parameter, $this->negated);
64+
$tag = new self($this->if, $this->type, $parameter, $this->negated);
65+
$tag->originalType = $this->getOriginalType();
66+
return $tag;
5667
}
5768

5869
}

‎tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeStaticMethodCallRuleTest.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ public function testReportPhpDocs(): void
9898
]);
9999
}
100100

101+
public function testAssertUnresolvedGeneric(): void
102+
{
103+
$this->treatPhpDocTypesAsCertain = true;
104+
$this->analyse([__DIR__ . '/data/assert-unresolved-generic.php'], []);
105+
}
106+
101107
public static function getAdditionalConfigFiles(): array
102108
{
103109
return [
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace AssertUnresolvedGeneric;
4+
5+
/**
6+
* @phpstan-template T
7+
*/
8+
abstract class Enum
9+
{
10+
/**
11+
* @phpstan-assert-if-true T $value
12+
* @return bool
13+
*/
14+
public static function isValid($value)
15+
{
16+
return true;
17+
}
18+
}
19+
20+
class Impl extends Enum
21+
{
22+
}
23+
24+
function (string $value) {
25+
if (Impl::isValid($value)) {
26+
}
27+
};

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /