diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 0a6cf38249..1a31978205 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -2568,7 +2568,7 @@ private function resolveNormalizedIdentical(Expr\BinaryOp\Identical $expr, Scope $argType = $scope->getType($unwrappedLeftExpr->getArgs()[0]->value); $isZero = (new ConstantIntegerType(0))->isSuperTypeOf($rightType); if ($isZero->yes()) { - $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, $scope)->setRootExpr($expr); + $funcTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); if ($context->truthy() && !$argType->isArray()->yes()) { $newArgType = new UnionType([ @@ -2586,11 +2586,15 @@ private function resolveNormalizedIdentical(Expr\BinaryOp\Identical $expr, Scope $specifiedTypes = $this->specifyTypesForCountFuncCall($unwrappedLeftExpr, $argType, $rightType, $context, $scope, $expr); if ($specifiedTypes !== null) { + if ($leftExpr !== $unwrappedLeftExpr) { + $funcTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); + return $specifiedTypes->unionWith($funcTypes); + } return $specifiedTypes; } if ($context->truthy() && $argType->isArray()->yes()) { - $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, $scope)->setRootExpr($expr); + $funcTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); if (IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($rightType)->yes()) { return $funcTypes->unionWith( $this->create($unwrappedLeftExpr->getArgs()[0]->value, new NonEmptyArrayType(), $context, $scope)->setRootExpr($expr), @@ -2616,7 +2620,7 @@ private function resolveNormalizedIdentical(Expr\BinaryOp\Identical $expr, Scope $isZero = (new ConstantIntegerType(0))->isSuperTypeOf($rightType); if ($isZero->yes()) { - $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, $scope)->setRootExpr($expr); + $funcTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); return $funcTypes->unionWith( $this->create($unwrappedLeftExpr->getArgs()[0]->value, new ConstantStringType(''), $context, $scope)->setRootExpr($expr), ); @@ -2625,7 +2629,7 @@ private function resolveNormalizedIdentical(Expr\BinaryOp\Identical $expr, Scope if ($context->truthy() && IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($rightType)->yes()) { $argType = $scope->getType($unwrappedLeftExpr->getArgs()[0]->value); if ($argType->isString()->yes()) { - $funcTypes = $this->create($unwrappedLeftExpr, $rightType, $context, $scope)->setRootExpr($expr); + $funcTypes = $this->create($leftExpr, $rightType, $context, $scope)->setRootExpr($expr); $accessory = new AccessoryNonEmptyStringType(); if (IntegerRangeType::fromInterval(2, null)->isSuperTypeOf($rightType)->yes()) { diff --git a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php index 370f40e652..09330a874b 100644 --- a/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php @@ -453,6 +453,12 @@ public function testBug13029(): void $this->analyse([__DIR__ . '/data/bug-13029.php'], []); } + #[RequiresPhp('>= 8.0')] + public function testBug12790(): void + { + $this->analyse([__DIR__ . '/data/bug-12790.php'], []); + } + #[RequiresPhp('>= 8.0')] public function testBug11310(): void { diff --git a/tests/PHPStan/Rules/Comparison/data/bug-12790.php b/tests/PHPStan/Rules/Comparison/data/bug-12790.php new file mode 100644 index 0000000000..b1332145ad --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/data/bug-12790.php @@ -0,0 +1,24 @@ += 8.0 + +declare(strict_types = 1); + +namespace Bug12790; + +$r = []; +$r[] = 'a'; +if (rand(0, 1)) { + $r[] = 'b'; +} + +echo match (count($r)) { + 1 => 'one', + 2 => 'two', +}; + +/** @param 'a'|'ab' $s */ +function matchStrlen(string $s): string { + return match (strlen($s)) { + 1 => 'one', + 2 => 'two', + }; +}