diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php index bfbbcc9fa..12c19526e 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php @@ -299,7 +299,8 @@ class ExistingAtomicStaticCallAnalyzer true, false, \is_string($static_type) - && $static_type !== $context->self + && ($static_type !== $context->self + || $class_storage->final) ); $return_type_location = $codebase->methods->getMethodReturnTypeLocation( diff --git a/src/Psalm/Internal/Type/TypeExpander.php b/src/Psalm/Internal/Type/TypeExpander.php index 325c91a86..c5cc96ac0 100644 --- a/src/Psalm/Internal/Type/TypeExpander.php +++ b/src/Psalm/Internal/Type/TypeExpander.php @@ -165,6 +165,8 @@ class TypeExpander $return_type->extra_types[$extra_static_type->getKey()] = clone $extra_static_type; } } + } elseif ($return_type->was_static && is_string($static_class_type) && $final) { + $return_type->value = $static_class_type; } elseif ($self_class && $return_type_lc === 'self') { $return_type->value = $self_class; } elseif ($parent_class && $return_type_lc === 'parent') { diff --git a/tests/MethodSignatureTest.php b/tests/MethodSignatureTest.php index 1e857e558..e87f384f6 100644 --- a/tests/MethodSignatureTest.php +++ b/tests/MethodSignatureTest.php @@ -869,6 +869,40 @@ class MethodSignatureTest extends TestCase [], '7.4' ], + 'extendStaticReturnTypeInFinal' => [ + '