diff --git a/src/Psalm/Internal/Codebase/Populator.php b/src/Psalm/Internal/Codebase/Populator.php index a19c11e80..84a040fcb 100644 --- a/src/Psalm/Internal/Codebase/Populator.php +++ b/src/Psalm/Internal/Codebase/Populator.php @@ -311,14 +311,9 @@ class Populator $declaring_method_storage = $declaring_class_storage->methods[$declaring_method_name]; if (($declaring_method_storage->has_docblock_param_types - || $declaring_method_storage->return_type - !== $declaring_method_storage->signature_return_type) + || $declaring_method_storage->has_docblock_return_type) && !$method_storage->has_docblock_param_types - && $method_storage->return_type === $method_storage->signature_return_type - && (!$declaring_method_storage->signature_return_type - || ($method_storage->signature_return_type - && $method_storage->signature_return_type->getId() - === $declaring_method_storage->signature_return_type->getId())) + && !$method_storage->has_docblock_return_type && $method_storage->inherited_return_type !== null ) { if (!isset($storage->documenting_method_ids[$method_name]) diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php index 651112097..50a3fe69a 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php @@ -868,6 +868,10 @@ class FunctionLikeDocblockScanner $storage->return_type->setFromDocblock(); + if ($storage instanceof MethodStorage) { + $storage->has_docblock_return_type = true; + } + if ($storage->signature_return_type) { $all_typehint_types_match = true; $signature_return_atomic_types = $storage->signature_return_type->getAtomicTypes(); @@ -882,6 +886,10 @@ class FunctionLikeDocblockScanner if ($all_typehint_types_match) { $storage->return_type->from_docblock = false; + + if ($storage instanceof MethodStorage) { + $storage->has_docblock_return_type = true; + } } if ($storage->signature_return_type->isNullable() diff --git a/src/Psalm/Storage/MethodStorage.php b/src/Psalm/Storage/MethodStorage.php index 801d2a4e4..50dbcf57d 100644 --- a/src/Psalm/Storage/MethodStorage.php +++ b/src/Psalm/Storage/MethodStorage.php @@ -60,6 +60,11 @@ class MethodStorage extends FunctionLikeStorage */ public $has_docblock_param_types = false; + /** + * @var bool + */ + public $has_docblock_return_type = false; + /** * @var bool */ diff --git a/tests/MethodSignatureTest.php b/tests/MethodSignatureTest.php index b8649b292..1e857e558 100644 --- a/tests/MethodSignatureTest.php +++ b/tests/MethodSignatureTest.php @@ -847,6 +847,28 @@ class MethodSignatureTest extends TestCase public function foo(): void {} }' ], + 'inheritParamTypeWhenSignatureReturnTypeChanged' => [ + ' [ + ' */ + class CovariantUserBuilder implements BuilderInterface { + public function create($data): RuntimeException { + return new RuntimeException($data); + } + }', + [], + [], + '7.4' + ], ]; } @@ -5301,26 +5319,6 @@ class ClassTemplateExtendsTest extends TestCase }', 'error_message' => 'ArgumentTypeCoercion' ], - 'inheritSubstitutedParamFromInterface' => [ - ' */ - class CovariantUserBuilder implements BuilderInterface { - public function create($data): RuntimeException { - /** @psalm-suppress MixedArgument */ - return new RuntimeException($data); - } - }', - 'error_message' => 'MissingParamType', - [], - false, - '7.4' - ], ]; } }