Skip to content

Commit 149a1e7

Browse files
rvanvelzenondrejmirtes
authored andcommitted
Specify types on match() condition correctly
1 parent e55a83f commit 149a1e7

File tree

5 files changed

+77
-4
lines changed

5 files changed

+77
-4
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,11 +1991,16 @@ public function resolveIdentical(Expr\BinaryOp\Identical $expr, Scope $scope, Ty
19911991
$exprNode = $expressions[0];
19921992
$constantType = $expressions[1];
19931993

1994-
$specifiedType = $this->specifyTypesForConstantBinaryExpression($exprNode, $constantType, $context, $scope, $rootExpr);
1994+
$unwrappedExprNode = $exprNode;
1995+
if ($exprNode instanceof AlwaysRememberedExpr) {
1996+
$unwrappedExprNode = $exprNode->getExpr();
1997+
}
1998+
1999+
$specifiedType = $this->specifyTypesForConstantBinaryExpression($unwrappedExprNode, $constantType, $context, $scope, $rootExpr);
19952000
if ($specifiedType !== null) {
1996-
if ($exprNode instanceof AlwaysRememberedExpr) {
1997-
$specifiedType->unionWith(
1998-
$this->create($exprNode->getExpr(), $constantType, $context, false, $scope, $rootExpr),
2001+
if ($exprNode !== $unwrappedExprNode) {
2002+
$specifiedType = $specifiedType->unionWith(
2003+
$this->create($exprNode, $constantType, $context, false, $scope, $rootExpr),
19992004
);
20002005
}
20012006
return $specifiedType;

tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,4 +1669,13 @@ public function testBug10297(): void
16691669
$this->analyse([__DIR__ . '/data/bug-10297.php'], []);
16701670
}
16711671

1672+
public function testBug10974(): void
1673+
{
1674+
if (PHP_VERSION_ID < 80000) {
1675+
$this->markTestSkipped('Test requires PHP 8.0.');
1676+
}
1677+
1678+
$this->analyse([__DIR__ . '/data/bug-10974.php'], []);
1679+
}
1680+
16721681
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php declare(strict_types = 1); // lint >= 8.0
2+
3+
namespace Bug10974;
4+
5+
function non(): void {}
6+
function single(string $str): void {}
7+
/** @param non-empty-array<string> $strs */
8+
function multiple(array $strs): void {}
9+
10+
/** @param array<string> $arr */
11+
function test(array $arr): void
12+
{
13+
match (count($arr))
14+
{
15+
0 => non(),
16+
1 => single(reset($arr)),
17+
default => multiple($arr)
18+
};
19+
20+
if (empty($arr)) {
21+
non();
22+
} elseif (count($arr) === 1) {
23+
single(reset($arr));
24+
} else {
25+
multiple($arr);
26+
}
27+
}

tests/PHPStan/Rules/Properties/AccessPropertiesRuleTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,4 +937,16 @@ public function testBug8629(): void
937937
$this->analyse([__DIR__ . '/data/bug-8629.php'], []);
938938
}
939939

940+
public function testBug9694(): void
941+
{
942+
if (PHP_VERSION_ID < 80000) {
943+
$this->markTestSkipped('Test requires PHP 8.0.');
944+
}
945+
946+
$this->checkThisOnly = false;
947+
$this->checkUnionTypes = true;
948+
$this->checkDynamicProperties = true;
949+
$this->analyse([__DIR__ . '/data/bug-9694.php'], []);
950+
}
951+
940952
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php declare(strict_types = 1); // lint >= 8.0
2+
3+
class TotpEnrollment
4+
{
5+
public bool $confirmed;
6+
}
7+
8+
class User
9+
{
10+
public ?TotpEnrollment $totpEnrollment;
11+
}
12+
13+
function () {
14+
$user = new User();
15+
16+
return match ($user->totpEnrollment === null) {
17+
true => false,
18+
false => $user->totpEnrollment->confirmed,
19+
};
20+
};

0 commit comments

Comments
 (0)