Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 67 additions & 68 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -5767,85 +5767,84 @@ private function processArgs(

$scope = $scope->restoreOriginalScopeAfterClosureBind($originalScope);
}
foreach ($args as $i => $arg) {
if (!isset($parameters) || $parametersAcceptor === null) {
continue;
}
Comment on lines -5771 to -5773
Copy link
Contributor Author

@staabm staabm Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

effectively putting these 3 lines arround the loop instead of beeing the first statement which prevents looping thru all args


$byRefType = new MixedType();
$assignByReference = false;
$currentParameter = null;
if (isset($parameters[$i])) {
$currentParameter = $parameters[$i];
} elseif (count($parameters) > 0 && $parametersAcceptor->isVariadic()) {
$currentParameter = array_last($parameters);
}

if ($currentParameter !== null) {
$assignByReference = $currentParameter->passedByReference()->createsNewVariable();
if ($assignByReference) {
if ($currentParameter instanceof ExtendedParameterReflection && $currentParameter->getOutType() !== null) {
$byRefType = $currentParameter->getOutType();
} elseif (
$calleeReflection instanceof MethodReflection
&& !$calleeReflection->getDeclaringClass()->isBuiltin()
) {
$byRefType = $currentParameter->getType();
} elseif (
$calleeReflection instanceof FunctionReflection
&& !$calleeReflection->isBuiltin()
) {
$byRefType = $currentParameter->getType();
}
if (isset($parameters) && $parametersAcceptor !== null) {
foreach ($args as $i => $arg) {
$byRefType = new MixedType();
$assignByReference = false;
$currentParameter = null;
if (isset($parameters[$i])) {
$currentParameter = $parameters[$i];
} elseif (count($parameters) > 0 && $parametersAcceptor->isVariadic()) {
$currentParameter = array_last($parameters);
}
}

if ($assignByReference) {
if ($currentParameter === null) {
throw new ShouldNotHappenException();
if ($currentParameter !== null) {
$assignByReference = $currentParameter->passedByReference()->createsNewVariable();
if ($assignByReference) {
if ($currentParameter instanceof ExtendedParameterReflection && $currentParameter->getOutType() !== null) {
$byRefType = $currentParameter->getOutType();
} elseif (
$calleeReflection instanceof MethodReflection
&& !$calleeReflection->getDeclaringClass()->isBuiltin()
) {
$byRefType = $currentParameter->getType();
} elseif (
$calleeReflection instanceof FunctionReflection
&& !$calleeReflection->isBuiltin()
) {
$byRefType = $currentParameter->getType();
}
}
}

$argValue = $arg->value;
if (!$argValue instanceof Variable || $argValue->name !== 'this') {
$paramOutType = $this->getParameterOutExtensionsType($callLike, $calleeReflection, $currentParameter, $scope);
if ($paramOutType !== null) {
$byRefType = $paramOutType;
if ($assignByReference) {
if ($currentParameter === null) {
throw new ShouldNotHappenException();
}

$scope = $this->processVirtualAssign(
$scope,
$storage,
$stmt,
$argValue,
new TypeExpr($byRefType),
$nodeCallback,
)->getScope();
$scope = $this->lookForUnsetAllowedUndefinedExpressions($scope, $argValue);
}
} elseif ($calleeReflection !== null && $calleeReflection->hasSideEffects()->yes()) {
$argType = $scope->getType($arg->value);
if (!$argType->isObject()->no()) {
$nakedReturnType = null;
if ($nakedMethodReflection !== null) {
$nakedParametersAcceptor = ParametersAcceptorSelector::selectFromArgs(
$argValue = $arg->value;
if (!$argValue instanceof Variable || $argValue->name !== 'this') {
$paramOutType = $this->getParameterOutExtensionsType($callLike, $calleeReflection, $currentParameter, $scope);
if ($paramOutType !== null) {
$byRefType = $paramOutType;
}

$scope = $this->processVirtualAssign(
$scope,
$args,
$nakedMethodReflection->getVariants(),
$nakedMethodReflection->getNamedArgumentsVariants(),
);
$nakedReturnType = $nakedParametersAcceptor->getReturnType();
}
if (
$nakedReturnType === null
|| !(new ThisType($nakedMethodReflection->getDeclaringClass()))->isSuperTypeOf($nakedReturnType)->yes()
|| $nakedMethodReflection->isPure()->no()
) {
$storage,
$stmt,
$argValue,
new TypeExpr($byRefType),
$nodeCallback,
)->getScope();
$scope = $this->lookForUnsetAllowedUndefinedExpressions($scope, $argValue);
}
} elseif ($calleeReflection !== null && $calleeReflection->hasSideEffects()->yes()) {
$argType = $scope->getType($arg->value);
if (!$argType->isObject()->no()) {
$nakedReturnType = null;
if ($nakedMethodReflection !== null) {
$nakedParametersAcceptor = ParametersAcceptorSelector::selectFromArgs(
$scope,
$args,
$nakedMethodReflection->getVariants(),
$nakedMethodReflection->getNamedArgumentsVariants(),
);
$nakedReturnType = $nakedParametersAcceptor->getReturnType();
}
if (
$nakedReturnType === null
|| !(new ThisType($nakedMethodReflection->getDeclaringClass()))->isSuperTypeOf($nakedReturnType)->yes()
|| $nakedMethodReflection->isPure()->no()
) {
$this->callNodeCallback($nodeCallback, new InvalidateExprNode($arg->value), $scope, $storage);
$scope = $scope->invalidateExpression($arg->value, true);
}
} elseif (!(new ResourceType())->isSuperTypeOf($argType)->no()) {
$this->callNodeCallback($nodeCallback, new InvalidateExprNode($arg->value), $scope, $storage);
$scope = $scope->invalidateExpression($arg->value, true);
}
} elseif (!(new ResourceType())->isSuperTypeOf($argType)->no()) {
$this->callNodeCallback($nodeCallback, new InvalidateExprNode($arg->value), $scope, $storage);
$scope = $scope->invalidateExpression($arg->value, true);
}
}
}
Expand Down
Loading