Fix phpstan/phpstan#13453: Templated return type error message is self-contradictory#5352
Fix phpstan/phpstan#13453: Templated return type error message is self-contradictory#5352phpstan-bot wants to merge 3 commits intophpstan:2.1.xfrom
Conversation
…iptions in error messages - When two different template types produce the same description at the chosen verbosity level, escalate to precise verbosity to include scope information - This fixes self-contradictory messages like "should return T of ResultA but returns T of ResultA" by showing "T of ResultA (function run(), argument) but returns T of ResultA (class I, parameter)" - New regression test in tests/PHPStan/Rules/Functions/data/bug-13453.php
VincentLanglet
left a comment
There was a problem hiding this comment.
You made two changes, but only one test ; could you test the other change too ?
…late types Cover the second code path in VerbosityLevel::getRecommendedLevelByType() where containsInvariantTemplateType is true. The test uses a generic Container<T> (invariant template) wrapping template types from different scopes that would otherwise produce identical descriptions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Done. I added a test ( |
VincentLanglet
left a comment
There was a problem hiding this comment.
the written tests need Requires PHP >= 8.0
The test data files use PHP 8.3 typed constants (public const string), so the test methods need the RequiresPhp attribute to skip on older PHP. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
There was a problem hiding this comment.
This fix seems ok (the right one ?) to me, but I'm unsure ondrej agree with the fact some error message will be updated.
On the other side, I don't see any other way to close this issue. Unless we fix other generic issues first...
WDYT @staabm ? Might be worth asking ondrej before merging this (?)
Summary
When two different template types have the same name and bound but belong to different scopes (e.g., a function template
T of ResultAand an interface templateT of ResultA), error messages like "should return T of ResultA but returns T of ResultA" were self-contradictory and confusing to users. The fix escalates the verbosity level toprecisewhen both types produce identical descriptions, adding scope information to disambiguate them.Changes
VerbosityLevel::getRecommendedLevelByType()insrc/Type/VerbosityLevel.phpto detect when accepting and accepted types have identical descriptions at the chosen level, and escalate topreciseverbosity in that casetests/PHPStan/Rules/Functions/data/bug-13453.phpand corresponding test method intests/PHPStan/Rules/Functions/ReturnTypeRuleTest.phpRoot cause
VerbosityLevel::getRecommendedLevelByType()chose verbosity based on type complexity (constant values, callables, accessory types, etc.) but never considered whether the two types being compared would produce identical string descriptions. Template types from different scopes with the same name and bound are semantically different but described identically attypeOnlyandvalueverbosity levels. Only atpreciselevel does the scope information (e.g., "function run(), argument" vs "class I, parameter") get included.Test
The regression test reproduces the exact scenario from the issue: a function with
@template T of ResultAreturning a value whose type isT of ResultAfrom an interface template. The test verifies the error message now includes scope disambiguation.Fixes phpstan/phpstan#13453