diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 37299b5d85..cf7c6f9fdf 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -1155,10 +1155,43 @@ public function create( return new SpecifiedTypes([], [], false, [], $rootExpr); } - while ($expr instanceof Expr\Assign) { - $expr = $expr->var; + $specifiedExprs = []; + + if ($expr instanceof Expr\Assign) { + $specifiedExprs[] = $expr->var; + + while ($expr->expr instanceof Expr\Assign) { + $specifiedExprs[] = $expr->expr->var; + $expr = $expr->expr; + } + } else { + $specifiedExprs[] = $expr; } + $types = null; + + foreach ($specifiedExprs as $specifiedExpr) { + $newTypes = $this->createForExpr($specifiedExpr, $type, $context, $overwrite, $scope, $rootExpr); + + if ($types === null) { + $types = $newTypes; + } else { + $types = $types->unionWith($newTypes); + } + } + + return $types; + } + + private function createForExpr( + Expr $expr, + Type $type, + TypeSpecifierContext $context, + bool $overwrite = false, + ?Scope $scope = null, + ?Expr $rootExpr = null, + ): SpecifiedTypes + { if ($scope !== null) { if ($context->true()) { $resultType = TypeCombinator::intersect($scope->getType($expr), $type); diff --git a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php index ed36af3e2f..76c7abaed6 100644 --- a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php @@ -416,4 +416,10 @@ public function testBug7229(): void ]); } + public function testBug7142(): void + { + $this->checkExplicitMixed = true; + $this->analyse([__DIR__ . '/data/bug-7142.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Arrays/data/bug-7142.php b/tests/PHPStan/Rules/Arrays/data/bug-7142.php new file mode 100644 index 0000000000..ca1078ee28 --- /dev/null +++ b/tests/PHPStan/Rules/Arrays/data/bug-7142.php @@ -0,0 +1,26 @@ + 1]; + } + return null; +} + +/** +* @return void +*/ +function foo(){ + if (!is_null($a = $b = $c = maybeNull())){ + echo $a['id']; + echo $b['id']; // 20 "Offset 'id' does not exist on array{id: int}|null." + echo $c['id']; // 21 "Offset 'id' does not exist on array{id: int}|null." + } +} +