Fix phpstan/phpstan#14440: Intersections in class-string<A&B> not correctly detected, reported as string#5428
Conversation
- ConstantStringType::describe() at typeOnly level now returns 'class-string<ClassName>' instead of 'string' when the constant is a known class-string - This fixes misleading error messages like "returns string" when the actual type is a class-string (e.g. from SomeClass::class expressions) - Updated test expectations in 5 test files to reflect improved error messages - Added regression test for phpstan/phpstan#14440
VincentLanglet
left a comment
There was a problem hiding this comment.
Rather than modifying ConstantStringType::info, consider working on VerbosityLevel::getRecommendedLevelByType
…velByType Instead of modifying ConstantStringType::describe() at typeOnly level, use VerbosityLevel to bump to value level when the accepting type contains class-string types. The class-string<ClassName> description is now shown at value verbosity level instead of typeOnly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests now expect class-string<ClassName> instead of quoted 'ClassName' when ConstantStringType with isClassString flag is described at value verbosity level. Also update baseline and ignored error patterns. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Done. Here's a summary of the changes addressing the review: What changed:
Why this approach is better:
Test impact: Updated 12 test files and 2 config files where class-string constants now show as |
VincentLanglet
left a comment
There was a problem hiding this comment.
Do not modify AT ALL the ConstantStringType::describe implémentation.
And getRecommendedLevelByType should require a moreVerbose level only if acceptingType is a string.
If a method should return object but return a constantString there is no need for a more verbose type than string.
…s-string Address review feedback: do not modify ConstantStringType::describe() at all. Instead, only add a class-string check in VerbosityLevel::getRecommendedLevelByType that bumps verbosity to value level when the accepting type is a class-string type. This means class-string constants show as quoted values (e.g. 'stdClass') at value verbosity, not as class-string<ClassName>. The verbosity is only bumped when the accepting type contains a class-string, so when a method expects object and receives a class-string, it still shows as just 'string'. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Done. Here's a summary of the changes: What changed:
|
Summary
When a
ConstantStringTyperepresented a class-string (e.g. fromSomeClass::class), itsdescribe()method attypeOnlyverbosity level returned juststring, losing the class-string information. This caused misleading error messages like:After the fix, the error message correctly shows:
Changes
ConstantStringType::describe()insrc/Type/Constant/ConstantStringType.phpto returnclass-string<ClassName>attypeOnlylevel when theisClassStringflag is settests/PHPStan/Rules/Methods/data/bug-14440.phpandtests/PHPStan/Rules/Methods/ReturnTypeRuleTest.phptests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php(bug-8071)tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php(ClassStringWithUpperBounds)tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php(TemplateTypeInOneBranchOfConditional)tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php(bug-4413, bug-4371, is-subclass-allow-string)Root cause
ConstantStringType::describe()used a static closurestatic fn (): string => 'string'for thetypeOnlyhandler, which always returned'string'regardless of whether the constant represented a class-string. This is inconsistent withGenericClassStringTypewhich includes its generic parameter at all verbosity levels (e.g.class-string<ChildOne>). The fix uses theisClassStringflag (set during construction for::classexpressions) to returnclass-string<ClassName>instead.Test
Added
testBug14440inReturnTypeRuleTestwith test data reproducing the issue: an abstract class with@return class-string<static&I>, and two final child classes returning each other's::class. The test verifies the error messages correctly describe the return types asclass-string<ChildTwo>andclass-string<ChildOne>respectively.Fixes phpstan/phpstan#14440