Skip to content

Use before-scope for evaluating array_splice argument types#5682

Merged
VincentLanglet merged 2 commits into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-5pm08tt
May 17, 2026
Merged

Use before-scope for evaluating array_splice argument types#5682
VincentLanglet merged 2 commits into
phpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-5pm08tt

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

@phpstan-bot phpstan-bot commented May 16, 2026

Same than #5579 for array_splice.

Fixes phpstan/phpstan#13510

Copy link
Copy Markdown
Contributor

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

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

Would it work if we keep trace of

$scopeBeforeArgs = $scope;

before the

$argsResult = $nodeScopeResolver->processArgs($stmt, $functionReflection, null, $parametersAcceptor, $normalizedExpr, $scope, $storage, $nodeCallbackForArgs, $context);

call line 268 ?

@phpstan-bot
Copy link
Copy Markdown
Collaborator Author

Done. I implemented the reviewer's suggestion: instead of per-argument $storage->findBeforeScope() lookups, we now save $scopeBeforeArgs = $scope once before processArgs and use that single scope for all argument type evaluations in both the array_push/array_unshift and array_splice handlers. This is simpler (net -5 lines) and semantically equivalent — the scope before args correctly reflects the types at evaluation time for all value arguments. All tests pass and make phpstan reports no errors.

Copy link
Copy Markdown
Contributor

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

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

Why not just

new NativeTypeExpr(
					$this->getArrayFunctionAppendingType($functionReflection, $scopeBeforeArgs, $normalizedExpr),
					$this->getArrayFunctionAppendingType($functionReflection, $scopeBeforeArgs->doNotTreatPhpDocTypesAsCertain(), $normalizedExpr),

@phpstan-bot
Copy link
Copy Markdown
Collaborator Author

Done. I implemented the reviewer's suggestion: instead of pre-computing argument types from $scopeBeforeArgs and passing them via a $precomputedArgTypes array, we now pass $scopeBeforeArgs directly as the scope to getArrayFunctionAppendingType. This is simpler (net -12 lines) because the function already uses $scope->getType() internally for both the array type and argument types — passing the before-args scope gives correct results for both. All tests pass and make phpstan reports no errors.

@VincentLanglet VincentLanglet force-pushed the create-pull-request/patch-5pm08tt branch from 031f8c4 to 63ef184 Compare May 16, 2026 20:13
@VincentLanglet VincentLanglet changed the title Use before-scope for evaluating array_push/array_unshift/array_splice argument types Use before-scope for evaluating array_splice argument types May 16, 2026
…plice` argument types

- When `array_unshift($this->arr, array_pop($this->arr))` was processed,
  `getArrayFunctionAppendingType` re-evaluated argument types using
  `$scope->getType()` on the post-args scope. By that point, the inner
  `array_pop` had already modified `$this->arr` to be possibly empty,
  causing `array_pop` to be re-evaluated as returning `T|null` instead
  of `T`.
- Pre-compute argument types from `ExpressionResultStorage::findBeforeScope()`
  which gives the scope that existed when each argument was originally
  evaluated. Pass pre-computed PHPDoc and native types separately to
  `getArrayFunctionAppendingType`.
- Apply the same fix to `array_splice` handler, which also re-evaluated
  offset, length, and replacement argument types in the post-args scope.
- Probed sort/shuffle/arsort handlers: these only read the array argument
  itself (not other args from the scope), so they are not affected.
@VincentLanglet VincentLanglet force-pushed the create-pull-request/patch-5pm08tt branch from 63ef184 to 84aeaa3 Compare May 16, 2026 20:14
@VincentLanglet VincentLanglet self-assigned this May 16, 2026
Comment thread tests/PHPStan/Rules/Properties/data/bug-13510.php Outdated
The NSRT test already covers the type inference regression. The separate
rule test is unnecessary.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@VincentLanglet VincentLanglet requested a review from staabm May 16, 2026 20:56
Copy link
Copy Markdown
Contributor

@staabm staabm left a comment

Choose a reason for hiding this comment

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

do we need the same fix for more functions in this handler?
(separate PR)

@VincentLanglet VincentLanglet merged commit 1e062f1 into phpstan:2.1.x May 17, 2026
660 of 662 checks passed
@VincentLanglet VincentLanglet deleted the create-pull-request/patch-5pm08tt branch May 17, 2026 07:54
@VincentLanglet
Copy link
Copy Markdown
Contributor

do we need the same fix for more functions in this handler? (separate PR)

When I ran the bot, it only opened the PR "Use before-scope for evaluating array_push/array_unshift/array_splice argument types" ; so I'm not sure there is more

staabm pushed a commit to staabm/phpstan-src that referenced this pull request May 17, 2026
…n#5682)

Co-authored-by: VincentLanglet <9052536+VincentLanglet@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
staabm pushed a commit that referenced this pull request May 17, 2026
Co-authored-by: VincentLanglet <9052536+VincentLanglet@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants