diff --git a/src/Type/Generic/TemplateTypeVariance.php b/src/Type/Generic/TemplateTypeVariance.php index 35536317dd6..6bc8d433241 100644 --- a/src/Type/Generic/TemplateTypeVariance.php +++ b/src/Type/Generic/TemplateTypeVariance.php @@ -176,6 +176,13 @@ public function isValidVariance(TemplateType $templateType, Type $a, Type $b): I } if ($this->invariant()) { + if ($a instanceof TemplateType && $b instanceof TemplateType + && $a->getScope()->equals($b->getScope()) + && $a->getName() === $b->getName() + ) { + return IsSuperTypeOfResult::createYes(); + } + $result = $a->equals($b); $reasons = []; if (!$result) { diff --git a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php index da3ba5d6d56..59cc2e52258 100644 --- a/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php @@ -451,4 +451,11 @@ public function testBug13565(): void ]); } + public function testBug13190(): void + { + $this->checkNullables = true; + $this->checkExplicitMixed = false; + $this->analyse([__DIR__ . '/data/bug-13190.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Functions/data/bug-13190.php b/tests/PHPStan/Rules/Functions/data/bug-13190.php new file mode 100644 index 00000000000..0565117ebb6 --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-13190.php @@ -0,0 +1,55 @@ += 8.0 +declare(strict_types = 1); + +namespace Bug13190; + +/** + * @template T + */ +interface Box +{ + /** + * @return T + */ + public function toInner(): mixed; +} + +/** + * @template T + * + * @implements Box + */ +final class BoxImpl implements Box +{ + /** + * @param T $value + */ + public function __construct( + private mixed $value, + ) {} + + /** + * @return T + */ + #[\Override] + public function toInner(): mixed + { + return $this->value; + } +} + +/** + * @template T + * + * @param T|Box $to_box + * + * @return Box + */ +function inbox($to_box): Box +{ + if ($to_box instanceof Box) { + return $to_box; + } else { + return new BoxImpl($to_box); + } +}