diff --git a/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php b/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php index 3e28391fa35..d88bf0430aa 100644 --- a/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php +++ b/src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php @@ -324,25 +324,29 @@ public static function getCallableFromAtomic( ); if ($codebase->methods->methodExists($invoke_id)) { - $method_storage = $codebase->methods->getStorage($invoke_id); - $method_fqcln = $invoke_id->fq_class_name; - $converted_return_type = null; - if ($method_storage->return_type) { - $converted_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion( - $codebase, - $method_storage->return_type, - $method_fqcln, - $method_fqcln, - null + $declaring_method_id = $codebase->methods->getDeclaringMethodId($invoke_id); + + if ($declaring_method_id) { + $method_storage = $codebase->methods->getStorage($declaring_method_id); + $method_fqcln = $invoke_id->fq_class_name; + $converted_return_type = null; + if ($method_storage->return_type) { + $converted_return_type = \Psalm\Internal\Type\TypeExpander::expandUnion( + $codebase, + $method_storage->return_type, + $method_fqcln, + $method_fqcln, + null + ); + } + + return new TCallable( + 'callable', + $method_storage->params, + $converted_return_type, + $method_storage->pure ); } - - return new TCallable( - 'callable', - $method_storage->params, - $converted_return_type, - $method_storage->pure - ); } } diff --git a/tests/CallableTest.php b/tests/CallableTest.php index 57b710d7482..bd625d915de 100644 --- a/tests/CallableTest.php +++ b/tests/CallableTest.php @@ -848,6 +848,22 @@ function foo($arg): void {} foo(["a", "b"]);' ], + 'abstractInvokeInTrait' => [ + '