Skip to content

Assign proper types for $argc and $argv in global statements#5623

Open
phpstan-bot wants to merge 3 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-14zzp1m
Open

Assign proper types for $argc and $argv in global statements#5623
phpstan-bot wants to merge 3 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-14zzp1m

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Summary

When global $argv; or global $argc; is used inside a function or method, PHPStan assigned MixedType to the variable instead of the correct CLI types (int<1, max> for $argc, non-empty-list<string> for $argv). This fix teaches NodeScopeResolver to assign the proper types for these variables in global statements.

Changes

  • Added getGlobalVariableType() private method to NodeScopeResolver (src/Analyser/NodeScopeResolver.php) that returns the correct type for $argc and $argv, falling back to MixedType for other global variables
  • Modified the global statement handling in NodeScopeResolver to use getGlobalVariableType() instead of unconditionally assigning MixedType
  • Updated tests/PHPStan/Analyser/nsrt/cli-globals.php assertions to expect the correct types and added test cases for:
    • Regular functions
    • Instance methods
    • Static methods
    • Closures
    • Reassignment after global (ensures user assignments still override)

Root cause

In NodeScopeResolver::processStmtNodes(), the global statement handler (around line 2184) unconditionally assigned new MixedType() to every variable declared via global. The special type handling for $argc/$argv in MutatingScope::getVariableType() only triggers when hasVariableType() returns maybe (i.e., in global scope where these variables aren't explicitly assigned). After global $argv;, the variable was explicitly in expressionTypes with MixedType and certainty Yes, bypassing the special handling.

The fix moves the type determination to the assignment site in NodeScopeResolver, so the correct type is stored from the start.

Analogous cases probed

  • Superglobal variables ($_SERVER, $_GET, etc.): Not affected — these don't need global declarations and are handled separately via isGlobalVariable()
  • $GLOBALS['argv']: Different code path, returns mixed for all $GLOBALS values — separate concern
  • $http_response_header: Assigned at specific function call sites, not via global — not analogous

Test

Updated tests/PHPStan/Analyser/nsrt/cli-globals.php to assert int<1, max> for $argc and non-empty-list<string> for $argv after global declarations. Added coverage for methods, static methods, closures, and reassignment.

Fixes phpstan/phpstan#12392

- NodeScopeResolver now assigns `int<1, max>` for `$argc` and
  `non-empty-list<string>` for `$argv` when processing `global`
  statements, instead of unconditionally assigning `MixedType`
- Extract `getGlobalVariableType()` helper in NodeScopeResolver
  to determine the correct type for a global variable name
- Update cli-globals.php test assertions to expect the correct types
  and add test cases for methods, static methods, closures, and
  reassignment after `global`
@phpstan-bot
Copy link
Copy Markdown
Collaborator Author

I processed this review but have nothing to report.

@staabm staabm requested a review from VincentLanglet May 9, 2026 15:23
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.

2 participants