diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index bb361d5615..4751e203a9 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -6297,7 +6297,7 @@ private function processAssignVar( if ($varType->isArray()->yes() || !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->yes()) { if ($var instanceof Variable && is_string($var->name)) { - $this->callNodeCallback($nodeCallback, new VariableAssignNode($var, $assignedPropertyExpr), $scopeBeforeAssignEval, $storage); + $this->callNodeCallback($nodeCallback, new VariableAssignNode($var, new TypeExpr($valueToWrite)), $scopeBeforeAssignEval, $storage); $scope = $scope->assignVariable($var->name, $valueToWrite, $nativeValueToWrite, TrinaryLogic::createYes()); } else { if ($var instanceof PropertyFetch || $var instanceof StaticPropertyFetch) { diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index da0f571127..d0983dbb84 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -253,6 +253,8 @@ private static function findTestFiles(): iterable yield __DIR__ . '/../Rules/Arrays/data/narrow-superglobal.php'; yield __DIR__ . '/../Rules/Methods/data/bug-12927.php'; yield __DIR__ . '/../Rules/Properties/data/bug-14012.php'; + yield __DIR__ . '/../Rules/Variables/data/bug-14124.php'; + yield __DIR__ . '/../Rules/Variables/data/bug-14124b.php'; } /** diff --git a/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php b/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php index bdd78d2dfd..6da45dd248 100644 --- a/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php +++ b/tests/PHPStan/Rules/Variables/ParameterOutAssignedTypeRuleTest.php @@ -81,4 +81,14 @@ public function testBug12754(): void $this->analyse([__DIR__ . '/data/bug-12754.php'], []); } + public function testBug14124(): void + { + $this->analyse([__DIR__ . '/data/bug-14124.php'], []); + } + + public function testBug14124b(): void + { + $this->analyse([__DIR__ . '/data/bug-14124b.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Variables/data/bug-14124.php b/tests/PHPStan/Rules/Variables/data/bug-14124.php new file mode 100644 index 0000000000..be3ad1a8de --- /dev/null +++ b/tests/PHPStan/Rules/Variables/data/bug-14124.php @@ -0,0 +1,33 @@ +> $convert + * @param-out array> $convert + */ +function example3a(array &$convert): void +{ + foreach ($convert as &$inner) { + foreach ($inner as &$val) { + $val = strtoupper($val); + } + } + assertType('array>', $convert); +} + +/** + * @param array> $convert + * @param-out array> $convert + */ +function example3b(array &$convert): void +{ + foreach ($convert as $outerKey => $inner) { + foreach ($inner as $key => $val) { + $convert[$outerKey][$key] = strtoupper($val); + } + } + assertType('array>', $convert); +} diff --git a/tests/PHPStan/Rules/Variables/data/bug-14124b.php b/tests/PHPStan/Rules/Variables/data/bug-14124b.php new file mode 100644 index 0000000000..0ad84eb7a3 --- /dev/null +++ b/tests/PHPStan/Rules/Variables/data/bug-14124b.php @@ -0,0 +1,37 @@ +>> $convert + * @param-out array>> $convert + */ +function example3a(array &$convert): void +{ + foreach ($convert as &$inner) { + foreach ($inner as &$val) { + foreach ($val as &$val2) { + $val2 = strtoupper($val2); + } + } + } + assertType('array>>', $convert); +} + +/** + * @param array>> $convert + * @param-out array>> $convert + */ +function example3b(array &$convert): void +{ + foreach ($convert as $outerKey => $inner) { + foreach ($inner as $key => $val) { + foreach ($val as $key2 => $val2) { + $convert[$outerKey][$key][$key2] = strtoupper($val); + } + } + } + assertType('array>>', $convert); +}