|
86 | 86 | use PHPStan\Node\ExecutionEndNode; |
87 | 87 | use PHPStan\Node\Expr\AlwaysRememberedExpr; |
88 | 88 | use PHPStan\Node\Expr\ExistingArrayDimFetch; |
| 89 | +use PHPStan\Node\Expr\ForeachValueByRefExpr; |
89 | 90 | use PHPStan\Node\Expr\GetIterableKeyTypeExpr; |
90 | 91 | use PHPStan\Node\Expr\GetIterableValueTypeExpr; |
91 | 92 | use PHPStan\Node\Expr\GetOffsetValueTypeExpr; |
@@ -1207,6 +1208,14 @@ private function processStmtNode( |
1207 | 1208 | $originalScope = $scope; |
1208 | 1209 | $bodyScope = $scope; |
1209 | 1210 |
|
| 1211 | + if ($stmt->keyVar instanceof Variable) { |
| 1212 | + $nodeCallback(new VariableAssignNode($stmt->keyVar, new GetIterableKeyTypeExpr($stmt->expr)), $originalScope); |
| 1213 | + } |
| 1214 | + |
| 1215 | + if ($stmt->valueVar instanceof Variable) { |
| 1216 | + $nodeCallback(new VariableAssignNode($stmt->valueVar, new GetIterableValueTypeExpr($stmt->expr)), $originalScope); |
| 1217 | + } |
| 1218 | + |
1210 | 1219 | if ($context->isTopLevel()) { |
1211 | 1220 | $originalScope = $this->polluteScopeWithAlwaysIterableForeach ? $scope->filterByTruthyValue($arrayComparisonExpr) : $scope; |
1212 | 1221 | $bodyScope = $this->enterForeach($originalScope, $originalScope, $stmt, $nodeCallback); |
@@ -1269,6 +1278,9 @@ private function processStmtNode( |
1269 | 1278 | if (!(new ObjectType(Traversable::class))->isSuperTypeOf($scope->getType($stmt->expr))->no()) { |
1270 | 1279 | $throwPoints[] = ThrowPoint::createImplicit($scope, $stmt->expr); |
1271 | 1280 | } |
| 1281 | + if ($stmt->byRef) { |
| 1282 | + $finalScope = $finalScope->assignExpression(new ForeachValueByRefExpr($stmt->valueVar), new MixedType(), new MixedType()); |
| 1283 | + } |
1272 | 1284 |
|
1273 | 1285 | return new StatementResult( |
1274 | 1286 | $finalScope, |
@@ -1926,6 +1938,7 @@ public function leaveNode(Node $node): ?ExistingArrayDimFetch |
1926 | 1938 | $scope = $scope->invalidateExpression($var); |
1927 | 1939 | } |
1928 | 1940 |
|
| 1941 | + $scope = $scope->invalidateExpression(new ForeachValueByRefExpr($var)); |
1929 | 1942 | } |
1930 | 1943 | } elseif ($stmt instanceof Node\Stmt\Use_) { |
1931 | 1944 | $hasYield = false; |
|
0 commit comments