Repository navigation
Require every receiver union member to have the property when resolving native type of PropertyFetch and StaticPropertyFetch - #6813
Open
phpstan-bot wants to merge 1 commit into
Conversation
…ng native type of `PropertyFetch` and `StaticPropertyFetch` - PropertyFetchHandler: the native-type path used MutatingScope::getInstancePropertyReflection(), which keeps only the union members that have the property, so `?Foo` / `Foo|Bar` receivers got the property's native type. Now it returns ErrorType unless the whole receiver type (with null removed only on a nullsafe chain) has the property, as 2.2 did via PropertyReflectionFinder. - StaticPropertyFetchHandler: same for `$expr::$prop` - a nullable class expression outside a nullsafe chain, or a union with members lacking the static property, gives ErrorType. - Ported both changes to the turbo-ext C++ mirrors (PropertyFetchHandler.cpp, StaticPropertyFetchHandler.cpp); analysis output is identical with the extension on and off. - Probed method calls, static method calls, class constants, array dim fetch, nullsafe and dynamic-name property fetches against 2.2.17: they already match, so no changes there.
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.
Summary
Since 2.3.0, the native type of a property fetch on a nullable receiver (
?Dekking $data; $data->amount) was the property's native type (float) rather than*ERROR*as in 2.2.17. WithtreatPhpDocTypesAsCertain: falsethis made$data->amount === nullreport as always false, even though the fetch givesnullat runtime when$datais null. The same regression affected union receivers where only some members declare the property, and static property fetches on an expression ($data::$prop).Changes
src/Analyser/ExprHandler/PropertyFetchHandler.php: on the native-type path, returnErrorTypeunlesshasInstanceProperty()isyesfor the whole receiver type. Before that check, null is removed only when the receiver is part of a nullsafe chain, which short-circuits anyway.src/Analyser/ExprHandler/StaticPropertyFetchHandler.php: on the native-type path, returnErrorTypewhen the class expression is nullable outside a nullsafe chain, or when the fetched-on type does not have the static property for all members.turbo-ext/src/PropertyFetchHandler.cpp,turbo-ext/src/StaticPropertyFetchHandler.cpp: same changes in the native mirrors.ArrayDimFetchon nullable arrays,?->property fetches, dynamic-name property fetches ($d->{'amount'},$d::${'s'}; these go through the same fixed code path).Root cause
Commit 34bc963 ("Fetch handlers read operand results") switched the native-type path from
PropertyReflectionFindertoMutatingScope::getInstancePropertyReflection()/getStaticPropertyReflection(). That finder requiredhasInstanceProperty()/hasStaticProperty()to beyeson the whole receiver type. The newMutatingScopemethods filter a union down to the members that have the property, soDekking|nullresolved toDekking::$amount. That filtering is fine for the PHPDoc type, where rules report the bad fetch separately. It is wrong for the native type, which must describe what can actually happen at runtime.Test
tests/PHPStan/Analyser/nsrt/bug-15424.php:assertNativeType()/assertType()checks for:tests/PHPStan/Rules/Comparison/data/bug-15424.php+StrictComparisonOfDifferentTypesRuleTest::testBug15424(treatPhpDocTypesAsCertain: false): the issue's reproducer; only the non-nullable receiver comparison is reported.Both tests fail without the fix.
Fixes phpstan/phpstan#15424