diff --git a/src/Psalm/Internal/Analyzer/ClassAnalyzer.php b/src/Psalm/Internal/Analyzer/ClassAnalyzer.php index 3fcaa310d48..a584d9f0f97 100644 --- a/src/Psalm/Internal/Analyzer/ClassAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ClassAnalyzer.php @@ -1649,7 +1649,11 @@ private static function addOrUpdatePropertyType( $allow_native_type = !$docblock_only && $codebase->analysis_php_version_id >= 7_04_00 - && $codebase->allow_backwards_incompatible_changes; + && $codebase->allow_backwards_incompatible_changes + // PHP does not support callable properties, but does allow Closure properties + // hasCallableType() treats Closure as a callable, but getCallableTypes() does not + && $inferred_type->getCallableTypes() === [] + ; $manipulator->setType( $allow_native_type diff --git a/src/Psalm/Type/Atomic/TClosure.php b/src/Psalm/Type/Atomic/TClosure.php index 94ee9446d44..07d6740cbec 100644 --- a/src/Psalm/Type/Atomic/TClosure.php +++ b/src/Psalm/Type/Atomic/TClosure.php @@ -50,7 +50,8 @@ public function __construct( public function canBeFullyExpressedInPhp(int $analysis_php_version_id): bool { - return false; + // it can, if it's just 'Closure' + return $this->params === null && $this->return_type === null && $this->is_pure === null; } /** diff --git a/tests/FileManipulation/MissingPropertyTypeTest.php b/tests/FileManipulation/MissingPropertyTypeTest.php index afeb644ee88..f32d8c2562c 100644 --- a/tests/FileManipulation/MissingPropertyTypeTest.php +++ b/tests/FileManipulation/MissingPropertyTypeTest.php @@ -294,6 +294,65 @@ public function bar() { 'issues_to_fix' => ['MissingPropertyType'], 'safe_types' => true, ], + 'doNotAddCallablePropertyTypes' => [ + 'input' => <<<'PHP' + u = $u; + $this->v = $v; + } + } + PHP, + 'output' => <<<'PHP' + u = $u; + $this->v = $v; + } + } + PHP, + 'php_version' => '7.4', + 'issues_to_fix' => ['MissingPropertyType'], + 'safe_types' => true, + ], + 'addClosurePropertyType' => [ + 'input' => <<<'PHP' + u = $u; + } + } + PHP, + 'output' => <<<'PHP' + u = $u; + } + } + PHP, + 'php_version' => '7.4', + 'issues_to_fix' => ['MissingPropertyType'], + 'safe_types' => true, + ], ]; } }