From 04f3e29f94c81b3d861b9edddac483cab08b48f5 Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Thu, 18 Mar 2021 11:06:54 -0400 Subject: [PATCH] =?UTF-8?q?Expand=20documentation=20method=20return=20type?= =?UTF-8?q?=20to=20ensure=20we=E2=80=99re=20giving=20a=20fair=20shot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Psalm/Internal/Codebase/Methods.php | 18 +++++++- tests/Template/ClassTemplateExtendsTest.php | 50 +++++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/Psalm/Internal/Codebase/Methods.php b/src/Psalm/Internal/Codebase/Methods.php index 8b1683e55..d76095af2 100644 --- a/src/Psalm/Internal/Codebase/Methods.php +++ b/src/Psalm/Internal/Codebase/Methods.php @@ -764,15 +764,29 @@ class Methods return clone $candidate_type; } + $overridden_class_storage = + $this->classlike_storage_provider->get($overridden_method_id->fq_class_name); + + $overridden_storage_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion( + $source_analyzer->getCodebase(), + clone $overridden_storage->return_type, + $overridden_method_id->fq_class_name, + $appearing_fq_class_name, + $overridden_class_storage->parent_class, + true, + false, + $storage->final + ); + $old_contained_by_new = UnionTypeComparator::isContainedBy( $source_analyzer->getCodebase(), $candidate_type, - $overridden_storage->return_type + $overridden_storage_return_type ); $new_contained_by_old = UnionTypeComparator::isContainedBy( $source_analyzer->getCodebase(), - $overridden_storage->return_type, + $overridden_storage_return_type, $candidate_type ); diff --git a/tests/Template/ClassTemplateExtendsTest.php b/tests/Template/ClassTemplateExtendsTest.php index 677fe1788..265e910ab 100644 --- a/tests/Template/ClassTemplateExtendsTest.php +++ b/tests/Template/ClassTemplateExtendsTest.php @@ -4350,6 +4350,56 @@ class ClassTemplateExtendsTest extends TestCase $foo = new ObjectStorage();' ], + 'liskovTerminatedByFinalClass' => [ + ' $type + */ + public function __construct(string $type) + { + $this->type = $type; + } + } + + abstract class Enum { + /** + * @return EnumSet + */ + public static function all() : EnumSet + { + return new EnumSet(static::class); + } + } + + /** + * @extends EnumSet + */ + final class CustomEnumSet extends EnumSet { + + public function __construct() + { + parent::__construct(CustomEnum::class); + } + }', + [], + [], + '7.4' + ], ]; }