From 1535edf3a938257e5ff3899827463f5436c9e66a Mon Sep 17 00:00:00 2001 From: Yohta Kimura Date: Wed, 7 Dec 2022 10:18:49 +0900 Subject: [PATCH 1/3] add failing tests from issue 8467 --- .../Analyser/NodeScopeResolverTest.php | 1 + tests/PHPStan/Analyser/data/bug-8467b.php | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 tests/PHPStan/Analyser/data/bug-8467b.php diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index e7b187dbce..e0a8eaa2cc 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -1135,6 +1135,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8421.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/imagick-pixel.php'); yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Arrays/data/bug-8467a.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8467b.php'); } /** diff --git a/tests/PHPStan/Analyser/data/bug-8467b.php b/tests/PHPStan/Analyser/data/bug-8467b.php new file mode 100644 index 0000000000..5f6e33e828 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-8467b.php @@ -0,0 +1,56 @@ + + * + * @phpstan-param list|null $mirrors + */ + protected function getUrls(?string $url, ?array $mirrors, ?string $ref, ?string $type, string $urlType): array + { + if (!$url) { + return []; + } + + if ($urlType === 'dist' && false !== strpos($url, '%')) { + assertType('string|null', $type); + $url = 'test'; + } + assertType('non-falsy-string', $url); + + $urls = [$url]; + if ($mirrors) { + foreach ($mirrors as $mirror) { + if ($urlType === 'dist') { + assertType('string|null', $type); + } elseif ($urlType === 'source' && $type === 'git') { + assertType("'git'", $type); + } elseif ($urlType === 'source' && $type === 'hg') { + assertType("'hg'", $type); + } else { + continue; + } + } + } + + return $urls; + } +} From b34d52808615ea1c8797d12d8739f31a2b1d2f0a Mon Sep 17 00:00:00 2001 From: Yohta Kimura Date: Wed, 7 Dec 2022 10:19:26 +0900 Subject: [PATCH 2/3] intersect resolved conditional types instead of overwriting --- src/Analyser/MutatingScope.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index f1ea0a4e7c..91bd6da533 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -119,7 +119,6 @@ use function array_map; use function array_merge; use function array_pop; -use function array_reverse; use function array_slice; use function count; use function explode; @@ -3735,7 +3734,7 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self } foreach ($scope->conditionalExpressions as $conditionalExprString => $conditionalExpressions) { - foreach (array_reverse($conditionalExpressions) as $conditionalExpression) { + foreach ($conditionalExpressions as $conditionalExpression) { foreach ($conditionalExpression->getConditionExpressionTypeHolders() as $holderExprString => $conditionalTypeHolder) { if (!array_key_exists($holderExprString, $specifiedExpressions) || !$specifiedExpressions[$holderExprString]->equals($conditionalTypeHolder)) { continue 2; @@ -3745,10 +3744,15 @@ public function filterBySpecifiedTypes(SpecifiedTypes $specifiedTypes): self if ($conditionalExpression->getTypeHolder()->getCertainty()->no()) { unset($scope->expressionTypes[$conditionalExprString]); } else { - $scope->expressionTypes[$conditionalExprString] = $conditionalExpression->getTypeHolder(); + $scope->expressionTypes[$conditionalExprString] = array_key_exists($conditionalExprString, $scope->expressionTypes) + ? new ExpressionTypeHolder( + $scope->expressionTypes[$conditionalExprString]->getExpr(), + TypeCombinator::intersect($scope->expressionTypes[$conditionalExprString]->getType(), $conditionalExpression->getTypeHolder()->getType()), + TrinaryLogic::maxMin($scope->expressionTypes[$conditionalExprString]->getCertainty(), $conditionalExpression->getTypeHolder()->getCertainty()), + ) + : $conditionalExpression->getTypeHolder(); $specifiedExpressions[$conditionalExprString] = $conditionalExpression->getTypeHolder(); } - continue 2; } } From 34b64bbfd49384c598b4fd327f2e6e8156dbec75 Mon Sep 17 00:00:00 2001 From: Yohta Kimura Date: Wed, 7 Dec 2022 10:35:39 +0900 Subject: [PATCH 3/3] leave as todo --- tests/PHPStan/Analyser/data/bug-8467b.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Analyser/data/bug-8467b.php b/tests/PHPStan/Analyser/data/bug-8467b.php index 5f6e33e828..c4971320ff 100644 --- a/tests/PHPStan/Analyser/data/bug-8467b.php +++ b/tests/PHPStan/Analyser/data/bug-8467b.php @@ -13,7 +13,7 @@ public function foo (?string $cwd, bool $initialClone = false): void { if ($initialClone && isset($origCwd)) { assertType('string', $origCwd); - assertType('null', $cwd); + assertType('string|null', $cwd); // could be null } }