Skip to content

Commit ee86dda

Browse files
authored
Fix issue 8467 intersect resolved conditional types
1 parent 2ca6118 commit ee86dda

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed

src/Analyser/MutatingScope.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@
119119
use function array_map;
120120
use function array_merge;
121121
use function array_pop;
122-
use function array_reverse;
123122
use function array_slice;
124123
use function count;
125124
use function explode;
@@ -3735,7 +3734,7 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self
37353734
}
37363735

37373736
foreach ($scope->conditionalExpressions as $conditionalExprString => $conditionalExpressions) {
3738-
foreach (array_reverse($conditionalExpressions) as $conditionalExpression) {
3737+
foreach ($conditionalExpressions as $conditionalExpression) {
37393738
foreach ($conditionalExpression->getConditionExpressionTypeHolders() as $holderExprString => $conditionalTypeHolder) {
37403739
if (!array_key_exists($holderExprString, $specifiedExpressions) || !$specifiedExpressions[$holderExprString]->equals($conditionalTypeHolder)) {
37413740
continue 2;
@@ -3745,10 +3744,15 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self
37453744
if ($conditionalExpression->getTypeHolder()->getCertainty()->no()) {
37463745
unset($scope->expressionTypes[$conditionalExprString]);
37473746
} else {
3748-
$scope->expressionTypes[$conditionalExprString] = $conditionalExpression->getTypeHolder();
3747+
$scope->expressionTypes[$conditionalExprString] = array_key_exists($conditionalExprString, $scope->expressionTypes)
3748+
? new ExpressionTypeHolder(
3749+
$scope->expressionTypes[$conditionalExprString]->getExpr(),
3750+
TypeCombinator::intersect($scope->expressionTypes[$conditionalExprString]->getType(), $conditionalExpression->getTypeHolder()->getType()),
3751+
TrinaryLogic::maxMin($scope->expressionTypes[$conditionalExprString]->getCertainty(), $conditionalExpression->getTypeHolder()->getCertainty()),
3752+
)
3753+
: $conditionalExpression->getTypeHolder();
37493754
$specifiedExpressions[$conditionalExprString] = $conditionalExpression->getTypeHolder();
37503755
}
3751-
continue 2;
37523756
}
37533757
}
37543758

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,7 @@ public function dataFileAsserts(): iterable
11351135
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8421.php');
11361136
yield from $this->gatherAssertTypes(__DIR__ . '/data/imagick-pixel.php');
11371137
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Arrays/data/bug-8467a.php');
1138+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8467b.php');
11381139
}
11391140

11401141
/**
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug8467b;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Test {
8+
public function foo (?string $cwd, bool $initialClone = false): void {
9+
if ($initialClone) {
10+
$origCwd = $cwd;
11+
$cwd = null;
12+
}
13+
14+
if ($initialClone && isset($origCwd)) {
15+
assertType('string', $origCwd);
16+
assertType('string|null', $cwd); // could be null
17+
}
18+
}
19+
20+
/**
21+
* @param mixed[]|null $mirrors
22+
*
23+
* @return list<non-empty-string>
24+
*
25+
* @phpstan-param list<array{url: non-empty-string, preferred: bool}>|null $mirrors
26+
*/
27+
protected function getUrls(?string $url, ?array $mirrors, ?string $ref, ?string $type, string $urlType): array
28+
{
29+
if (!$url) {
30+
return [];
31+
}
32+
33+
if ($urlType === 'dist' && false !== strpos($url, '%')) {
34+
assertType('string|null', $type);
35+
$url = 'test';
36+
}
37+
assertType('non-falsy-string', $url);
38+
39+
$urls = [$url];
40+
if ($mirrors) {
41+
foreach ($mirrors as $mirror) {
42+
if ($urlType === 'dist') {
43+
assertType('string|null', $type);
44+
} elseif ($urlType === 'source' && $type === 'git') {
45+
assertType("'git'", $type);
46+
} elseif ($urlType === 'source' && $type === 'hg') {
47+
assertType("'hg'", $type);
48+
} else {
49+
continue;
50+
}
51+
}
52+
}
53+
54+
return $urls;
55+
}
56+
}

0 commit comments

Comments
 (0)