Skip to content

Fix #13831: spurious error in specific combination of namespace blocks and function declaration with phpdoc type annotation#5077

Merged
staabm merged 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-18fxfez
Feb 27, 2026
Merged

Fix #13831: spurious error in specific combination of namespace blocks and function declaration with phpdoc type annotation#5077
staabm merged 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-18fxfez

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

Functions declared in a global namespace block (namespace { ... }) that follows a named namespace block (namespace foo { ... }) incorrectly reported missingType.iterableValue errors even when PHPDoc annotations fully specified the iterable value type (e.g., @return list<string>). The fix ensures the scope's namespace is properly reset when entering a global namespace block.

Changes

  • Modified src/Analyser/NodeScopeResolver.php: Added an else branch in the Stmt\Namespace_ handling (around line 1010) to reset the scope namespace to global when $stmt->name is null
  • Added regression test tests/PHPStan/Rules/Functions/data/bug-13831.php with a function in a global namespace block preceded by a named namespace block
  • Added test method testBug13831 in tests/PHPStan/Rules/Functions/MissingFunctionReturnTypehintRuleTest.php

Root cause

When NodeScopeResolver encountered a Stmt\Namespace_ node with $stmt->name === null (global namespace block), it did not call $scope->enterNamespace() to reset the namespace. If a named namespace block had been processed earlier, the scope retained the previous namespace. This caused getPhpDocs() to construct the wrong function name (e.g., foo\qux instead of qux), so getResolvedPhpDoc() could not find the PHPDoc annotations for the function, making it appear as if the function had no PHPDoc return type.

The fix adds $scope = $scope->enterNamespace('') for global namespace blocks. MutatingScope already normalizes empty string namespaces to null, matching the behavior in FileTypeMapper which correctly handles this case.

Test

The regression test declares a function bug13831Qux(): array with @return list<string> inside a global namespace block preceded by a named namespace block. Before the fix, PHPStan reported a false positive missingType.iterableValue error. After the fix, no errors are reported.

Fixes phpstan/phpstan#13831

- In NodeScopeResolver, when processing a `namespace { }` block (global namespace)
  after a named namespace block, the scope's namespace was not being reset to null
- This caused PHPDoc resolution to use the wrong function name (prefixed with the
  previous namespace), so PHPDoc annotations like `@return list<string>` were lost
- Added `else` branch in namespace handling to call `enterNamespace('')` for global
  namespace blocks, which MutatingScope normalizes to `null`
- New regression test in tests/PHPStan/Rules/Functions/data/bug-13831.php

Closes phpstan/phpstan#13831
@staabm staabm merged commit de68533 into phpstan:2.1.x Feb 27, 2026
636 of 647 checks passed
@VincentLanglet VincentLanglet deleted the create-pull-request/patch-18fxfez branch March 8, 2026 12:16
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