|
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