From 62148f3217ce27e4739020301da237e8992864a6 Mon Sep 17 00:00:00 2001 From: Emil Masiakowski Date: Wed, 21 Feb 2024 20:25:58 +0100 Subject: [PATCH] Fix false issue when passing enum case to generic class Fixes #10484 --- src/Type/Generic/TemplateTypeVariance.php | 7 +++++++ .../Rules/Methods/CallMethodsRuleTest.php | 12 +++++++++++ .../PHPStan/Rules/Methods/data/bug-10484.php | 21 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 tests/PHPStan/Rules/Methods/data/bug-10484.php diff --git a/src/Type/Generic/TemplateTypeVariance.php b/src/Type/Generic/TemplateTypeVariance.php index a3ab7a04bd..e6097064bb 100644 --- a/src/Type/Generic/TemplateTypeVariance.php +++ b/src/Type/Generic/TemplateTypeVariance.php @@ -7,6 +7,7 @@ use PHPStan\TrinaryLogic; use PHPStan\Type\AcceptsResult; use PHPStan\Type\BenevolentUnionType; +use PHPStan\Type\GeneralizePrecision; use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; use PHPStan\Type\Type; @@ -157,6 +158,12 @@ public function isValidVarianceWithReason(?TemplateType $templateType, Type $a, return AcceptsResult::createYes(); } + if ($b->isEnum()->yes()) { + if ($b->generalize(GeneralizePrecision::lessSpecific())->equals($a)) { + return AcceptsResult::createYes(); + } + } + if ($this->invariant()) { $result = $a->equals($b); $reasons = []; diff --git a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php index ed69d28980..cb4e74ee33 100644 --- a/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php @@ -2529,6 +2529,18 @@ public function testBug5869(): void $this->analyse([__DIR__ . '/data/bug-5869.php'], []); } + public function testBug10484(): void + { + if (PHP_VERSION_ID < 80100) { + $this->markTestSkipped('Test requires PHP 8.1.'); + } + + $this->checkThisOnly = false; + $this->checkNullables = true; + $this->checkUnionTypes = true; + $this->analyse([__DIR__ . '/data/bug-10484.php'], []); + } + public function testGenericsEmptyArray(): void { $this->checkThisOnly = false; diff --git a/tests/PHPStan/Rules/Methods/data/bug-10484.php b/tests/PHPStan/Rules/Methods/data/bug-10484.php new file mode 100644 index 0000000000..2e9c915f51 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-10484.php @@ -0,0 +1,21 @@ + $foos + */ + public function bar(\Ds\Set $foos): void + { + } + + public function test(): void + { + $this->bar(new \Ds\Set([Foo::Bar])); + } +}