Fix phpstan/phpstan#10290: Function should return Err<array> but returns Err<array>#5337
Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Open
Fix phpstan/phpstan#10290: Function should return Err<array> but returns Err<array>#5337phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
Conversation
…ate positions in accepts() context - Modified GenericObjectType::isSuperTypeOfInternal() to accept subtypes for invariant template parameters when in the accepts context (used for error reporting) - When the declared template variance is invariant and the type argument is a strict subtype, accepts() now returns Yes instead of No - isSuperTypeOf() behavior remains unchanged (strict invariant equality) - New regression test in tests/PHPStan/Rules/Functions/data/bug-10290.php - Also fixes phpstan/phpstan#4590 (OkResponse<array{ok: string}> accepted for OkResponse<array<string, string>>) - Updated existing tests to reflect the more lenient accepts behavior
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
When a generic class has an invariant template parameter (
@template T), PHPStan was rejecting subtypes in theaccepts()context. For example,Err<array<mixed>>would not acceptErr<non-empty-array<mixed, mixed>>even thoughnon-empty-arrayis a subtype ofarray. This caused false positive errors like:This fix makes the
accepts()method (used for error reporting in return types, parameter passing, etc.) treat invariant generic template parameters as covariant — accepting subtypes. TheisSuperTypeOf()method (used for type inference) retains strict invariant behavior.Changes
src/Type/Generic/GenericObjectType.php: InisSuperTypeOfInternal(), when inacceptsContextand the template is declared invariant, check if the expected type is a supertype of the actual type. If yes, accept it.tests/PHPStan/Rules/Functions/data/bug-10290.php— Result/Ok/Err pattern with invariant genericstests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php— addedtestBug10290tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php—testBug4590now expects no errorstests/PHPStan/Rules/Methods/CallMethodsRuleTest.php— removed false positive errors intestGenericVariance,testBug5372,testGenericObjectLowerBoundtests/PHPStan/Type/Generic/GenericObjectTypeTest.php— addeddataAcceptsTypeProjections()to separate accepts vs isSuperTypeOf expectations for type projectionstests/PHPStan/Type/StaticTypeTest.php— updatedGenericStaticTypeaccepts testRoot cause
GenericObjectType::isSuperTypeOfInternal()delegates invariant template checking toTemplateTypeVariance::isValidVariance(), which usesType::equals()— requiring exact type match. In theaccepts()context (parameter$acceptsContext = true), this was too strict. The fix adds a condition: when in accepts context and the template is declared invariant, if the expected type argument is a supertype of the actual type argument ($a->isSuperTypeOf($b)->yes()), accept it instead of requiring equality.Test
Added
tests/PHPStan/Rules/Functions/data/bug-10290.phpreproducing the issue withResult/Ok/Errgeneric classes. The test verifies that:Err<non-empty-array<mixed, mixed>>is accepted for return typeErr<array<mixed>>Ok<non-falsy-string>is accepted for return typeOk<non-empty-string>Ok<bool>is still rejected for return typeOk<true>(supertype, not subtype)Fixes phpstan/phpstan#10290