fix: resolve static/self/parent relative to @param-closure-this bound class#6061
Open
calebdw wants to merge 1 commit into
Open
fix: resolve static/self/parent relative to @param-closure-this bound class#6061calebdw wants to merge 1 commit into
calebdw wants to merge 1 commit into
Conversation
… class When a closure or arrow function has its $this type overridden via @param-closure-this, the static/self/parent keywords in return type declarations were still resolving to the enclosing class instead of the bound class. Two fixes were needed: 1. Set inClosureBindScopeClasses when applying @param-closure-this so that resolveTypeByName and resolveName use the bound class for static/self resolution in expressions like static method calls. 2. Override the InitializerExprContext in getFunctionType when inClosureBindScopeClasses is set, so that static/self/parent in return type declarations (processed via ParserNodeTypeToPHPStanType) also resolve to the bound class instead of the enclosing class.
calebdw
force-pushed
the
calebdw/push-qwswwvrkussm
branch
from
July 18, 2026 03:41
69afe68 to
ea2dddf
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
When a closure or arrow function has its
$thistype overridden via@param-closure-this, thestatic/self/parentkeywords in return type declarations resolve to the enclosing class instead of the bound class.Reproducer
Where
Collection::macro()has@param-closure-this static $macro, PHPStan correctly resolves$thisinside the closure toCollection, but thestaticreturn type still resolves toCollectionMacros(the enclosing class) instead ofCollection.Root Cause
Two layers:
inClosureBindScopeClasseswas never set when@param-closure-thiswas applied.NodeScopeResolveronly calledassignVariable('this', ...)to change the$thistype, but did not setinClosureBindScopeClasses— which is whatresolveTypeByNamechecks when resolvingstatic/self/parentkeywords.getFunctionTypeused the enclosing class to resolvestaticin return type declarations. The closure's return typestaticwent throughInitializerExprTypeResolver::getFunctionType→ParserNodeTypeToPHPStanType::resolve, which usedInitializerExprContext::fromScope($this)— always returning the enclosing class via$scope->getClassReflection().Fix
src/Analyser/NodeScopeResolver.phpAfter
assignVariable('this', ...), chain->withClosureBindScopeClasses(...)sostatic/selfresolve to the closure-this class. Applied to both closure and arrow function paths.src/Analyser/MutatingScope.phpwithClosureBindScopeClasses()(new method): Creates a new scope withinClosureBindScopeClassesset, preserving all other state.restoreThis(): RestoreinClosureBindScopeClassesfrom the saved scope (was using$this->, now uses$restoreThisScope->).getFunctionType(): WheninClosureBindScopeClassesis set and the type isstatic/self/parent, pass a context with the bound class toInitializerExprTypeResolverso the return type resolves correctly.