diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 136e2023ba..a43ba35dda 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -3603,6 +3603,15 @@ private function createConditionalExpressions( } foreach ($variableTypeGuards as $guardExprString => $guardHolder) { + if ( + array_key_exists($exprString, $theirExpressionTypes) + && $theirExpressionTypes[$exprString]->getCertainty()->yes() + && array_key_exists($guardExprString, $theirExpressionTypes) + && $theirExpressionTypes[$guardExprString]->getCertainty()->yes() + && !$guardHolder->getType()->isSuperTypeOf($theirExpressionTypes[$guardExprString]->getType())->no() + ) { + continue; + } $conditionalExpression = new ConditionalExpressionHolder([$guardExprString => $guardHolder], $holder); $conditionalExpressions[$exprString][$conditionalExpression->getKey()] = $conditionalExpression; } diff --git a/tests/PHPStan/Analyser/nsrt/bug-10085.php b/tests/PHPStan/Analyser/nsrt/bug-10085.php new file mode 100644 index 0000000000..aa8dcc3b8a --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-10085.php @@ -0,0 +1,28 @@ + $foo + * @param list $bar + */ + public function sayHello(array $foo, array $bar): void + { + $a = $foo; + if ($a === []) { + $a = $bar; + } + + if ($a === []) { + return; + } + + assertType('array', $foo); + } +} diff --git a/tests/PHPStan/Analyser/nsrt/bug-11328.php b/tests/PHPStan/Analyser/nsrt/bug-11328.php new file mode 100644 index 0000000000..bf315fc73c --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-11328.php @@ -0,0 +1,27 @@ += 8.1 + +declare(strict_types = 1); + +namespace Bug11328; + +use function PHPStan\Testing\assertType; + +enum Status: string { + case Live = 's1'; + case Expired = 's2'; +} + +/** @param Status[] $statuses */ +function check(array $statuses): void { + $fromDeadline = null; + $toDeadline = null; + if (in_array(Status::Live, $statuses, true)) { + $fromDeadline = (new \DateTimeImmutable())->setTime(23, 59, 59); + } + if (in_array(Status::Expired, $statuses, true)) { + assertType('DateTimeImmutable|null', $fromDeadline); + if ($fromDeadline === null) { + $toDeadline = (new \DateTimeImmutable())->setTime(0, 0, 0); + } + } +} diff --git a/tests/PHPStan/Analyser/nsrt/bug-14211.php b/tests/PHPStan/Analyser/nsrt/bug-14211.php new file mode 100644 index 0000000000..b3ef9d987c --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-14211.php @@ -0,0 +1,27 @@ += 8.0 + +declare(strict_types = 1); + +namespace Bug14211; + +use function PHPStan\Testing\assertType; + +/** @param array $data */ +function DoSomithing(array $data): bool { + + if (!isset($data['x'])) + return false; + + $m = isset($data['y']); + + if ($m) { + assertType('true', $m); // ok: true + } + assertType('bool', $m); // ok: bool + + if ($m) { + assertType('true', $m); // <-- should not be: NEVER + } + + return true; +} diff --git a/tests/PHPStan/Analyser/nsrt/bug-14411-regression.php b/tests/PHPStan/Analyser/nsrt/bug-14411-regression.php new file mode 100644 index 0000000000..31fb5421b0 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-14411-regression.php @@ -0,0 +1,36 @@ += 8.0 + +declare(strict_types = 1); + +namespace Bug14411Regression; + +use function PHPStan\Testing\assertType; +use function PHPStan\Testing\assertVariableCertainty; +use PHPStan\TrinaryLogic; + +interface OrderInterface {} + +class Event +{ + /** @return mixed */ + public function getSubject() + { + return new \stdClass(); + } +} + +function getOrder(Event|OrderInterface $event): OrderInterface +{ + if ($event instanceof Event) { + $order = $event->getSubject(); + assert($order instanceof OrderInterface); + } + + if ($event instanceof OrderInterface) { + $order = $event; + } + + assertVariableCertainty(TrinaryLogic::createYes(), $order); + + return $order; +} diff --git a/tests/PHPStan/Analyser/nsrt/bug-14411.php b/tests/PHPStan/Analyser/nsrt/bug-14411.php new file mode 100644 index 0000000000..753532ed59 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-14411.php @@ -0,0 +1,34 @@ += 8.0 + +declare(strict_types = 1); + +namespace Bug14411; + +use function PHPStan\Testing\assertType; + +/** @phpstan-impure */ +function get_mixed(): mixed { + return random_int(0, 1) ? 'foo' : null; +} + +/** @phpstan-impure */ +function get_optional_int(): ?int { + return random_int(0, 1) ? 42 : null; +} + +function (): void { + $a = get_mixed(); + + if ($a !== null) { + $b = $a; + } + else { + $b = get_optional_int(); + } + if ($b !== null) { + assertType('mixed', $a); + if ($a === null) { + echo 'this is absolutely possible'; + } + } +};