diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 969d0be6b4..afe1373704 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -5055,7 +5055,7 @@ private function processAssignVar( $valueToWrite = $scope->getType($assignedExpr); $nativeValueToWrite = $scope->getNativeType($assignedExpr); $originalValueToWrite = $valueToWrite; - $originalNativeValueToWrite = $valueToWrite; + $originalNativeValueToWrite = $nativeValueToWrite; // 3. eval assigned expr $result = $processExprCallback($scope); @@ -5076,67 +5076,9 @@ private function processAssignVar( } $offsetValueType = $varType; $offsetNativeValueType = $varNativeType; - $offsetValueTypeStack = [$offsetValueType]; - $offsetValueNativeTypeStack = [$offsetNativeValueType]; - foreach (array_slice($offsetTypes, 0, -1) as $offsetType) { - if ($offsetType === null) { - $offsetValueType = new ConstantArrayType([], []); - - } else { - $offsetValueType = $offsetValueType->getOffsetValueType($offsetType); - if ($offsetValueType instanceof ErrorType) { - $offsetValueType = new ConstantArrayType([], []); - } - } - $offsetValueTypeStack[] = $offsetValueType; - } - foreach (array_slice($offsetNativeTypes, 0, -1) as $offsetNativeType) { - if ($offsetNativeType === null) { - $offsetNativeValueType = new ConstantArrayType([], []); - - } else { - $offsetNativeValueType = $offsetNativeValueType->getOffsetValueType($offsetNativeType); - if ($offsetNativeValueType instanceof ErrorType) { - $offsetNativeValueType = new ConstantArrayType([], []); - } - } - - $offsetValueNativeTypeStack[] = $offsetNativeValueType; - } - - foreach (array_reverse($offsetTypes) as $i => $offsetType) { - /** @var Type $offsetValueType */ - $offsetValueType = array_pop($offsetValueTypeStack); - if (!$offsetValueType instanceof MixedType) { - $types = [ - new ArrayType(new MixedType(), new MixedType()), - new ObjectType(ArrayAccess::class), - new NullType(), - ]; - if ($offsetType !== null && $offsetType->isInteger()->yes()) { - $types[] = new StringType(); - } - $offsetValueType = TypeCombinator::intersect($offsetValueType, TypeCombinator::union(...$types)); - } - $valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0); - } - foreach (array_reverse($offsetNativeTypes) as $i => $offsetNativeType) { - /** @var Type $offsetNativeValueType */ - $offsetNativeValueType = array_pop($offsetValueNativeTypeStack); - if (!$offsetNativeValueType instanceof MixedType) { - $types = [ - new ArrayType(new MixedType(), new MixedType()), - new ObjectType(ArrayAccess::class), - new NullType(), - ]; - if ($offsetNativeType !== null && $offsetNativeType->isInteger()->yes()) { - $types[] = new StringType(); - } - $offsetNativeValueType = TypeCombinator::intersect($offsetNativeValueType, TypeCombinator::union(...$types)); - } - $nativeValueToWrite = $offsetNativeValueType->setOffsetValueType($offsetNativeType, $nativeValueToWrite, $i === 0); - } + $valueToWrite = $this->produceArrayDimFetchAssignValueToWrite($offsetTypes, $offsetValueType, $valueToWrite); + $nativeValueToWrite = $this->produceArrayDimFetchAssignValueToWrite($offsetNativeTypes, $offsetNativeValueType, $nativeValueToWrite); if ($varType->isArray()->yes() || !(new ObjectType(ArrayAccess::class))->isSuperTypeOf($varType)->yes()) { if ($var instanceof Variable && is_string($var->name)) { @@ -5409,6 +5351,46 @@ static function (): void { return new ExpressionResult($scope, $hasYield, $throwPoints, $impurePoints); } + /** + * @param list $offsetTypes + */ + private function produceArrayDimFetchAssignValueToWrite(array $offsetTypes, Type $offsetValueType, Type $valueToWrite): Type + { + $offsetValueTypeStack = [$offsetValueType]; + foreach (array_slice($offsetTypes, 0, -1) as $offsetType) { + if ($offsetType === null) { + $offsetValueType = new ConstantArrayType([], []); + + } else { + $offsetValueType = $offsetValueType->getOffsetValueType($offsetType); + if ($offsetValueType instanceof ErrorType) { + $offsetValueType = new ConstantArrayType([], []); + } + } + + $offsetValueTypeStack[] = $offsetValueType; + } + + foreach (array_reverse($offsetTypes) as $i => $offsetType) { + /** @var Type $offsetValueType */ + $offsetValueType = array_pop($offsetValueTypeStack); + if (!$offsetValueType instanceof MixedType) { + $types = [ + new ArrayType(new MixedType(), new MixedType()), + new ObjectType(ArrayAccess::class), + new NullType(), + ]; + if ($offsetType !== null && $offsetType->isInteger()->yes()) { + $types[] = new StringType(); + } + $offsetValueType = TypeCombinator::intersect($offsetValueType, TypeCombinator::union(...$types)); + } + $valueToWrite = $offsetValueType->setOffsetValueType($offsetType, $valueToWrite, $i === 0); + } + + return $valueToWrite; + } + private function unwrapAssign(Expr $expr): Expr { if ($expr instanceof Assign) {