From 5579fd469b89c97063bb3c7062b5e9b776a3d72a Mon Sep 17 00:00:00 2001 From: robchett Date: Wed, 7 Feb 2024 20:37:00 +0000 Subject: [PATCH 1/2] Prevent mixed|null when function param is mixed with a null default value --- .../Reflector/FunctionLikeNodeScanner.php | 4 +++- tests/ArgTest.php | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php index f04a90072d0..f0a8f34cc63 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeNodeScanner.php @@ -825,7 +825,9 @@ private function getTranslatedFunctionParam( $this->codebase->analysis_php_version_id, ); - if ($is_nullable) { + if ($param_type->isMixed()) { + $is_nullable = false; + } elseif ($is_nullable) { $param_type = $param_type->getBuilder()->addType(new TNull)->freeze(); } else { $is_nullable = $param_type->isNullable(); diff --git a/tests/ArgTest.php b/tests/ArgTest.php index 5fefdbef086..36efb359362 100644 --- a/tests/ArgTest.php +++ b/tests/ArgTest.php @@ -355,6 +355,20 @@ function foo($a, ...$b) {} var_caller("foo");', ], + 'mixedNullable' => [ + 'code' => 'default;', + 'assertions' => [ + '$_v===' => 'mixed', + ], + 'ignored_issues' => [], + 'php_version' => '8.0', + ], ]; } From 6b405937ab20d6250af693f456c90c5bb6de4486 Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Sat, 10 Feb 2024 01:28:19 +0100 Subject: [PATCH 2/2] Forbid constructors from returning any values Fixes vimeo/psalm#9713 --- psalm-baseline.xml | 3 ++- .../Internal/Analyzer/Statements/ReturnAnalyzer.php | 12 ++++++++++++ tests/ReturnTypeTest.php | 11 +++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 58202505f72..8d205b058f7 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + @@ -1057,6 +1057,7 @@ + calling_function_id]]> diff --git a/src/Psalm/Internal/Analyzer/Statements/ReturnAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/ReturnAnalyzer.php index 4f0867f169d..49160c4bf8e 100644 --- a/src/Psalm/Internal/Analyzer/Statements/ReturnAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/ReturnAnalyzer.php @@ -257,6 +257,18 @@ public static function analyze( $statements_analyzer, null, ); + + [, $method_name] = explode('::', $cased_method_id); + if ($method_name === '__construct') { + IssueBuffer::maybeAdd( + new InvalidReturnStatement( + 'No return values are expected for ' . $cased_method_id, + new CodeLocation($source, $stmt->expr), + ), + $statements_analyzer->getSuppressedIssues(), + ); + return; + } } else { $declared_return_type = $storage->return_type; } diff --git a/tests/ReturnTypeTest.php b/tests/ReturnTypeTest.php index dff8fbc41be..64e79d442c3 100644 --- a/tests/ReturnTypeTest.php +++ b/tests/ReturnTypeTest.php @@ -1863,6 +1863,17 @@ function foo(bool $x): never 'ignored_issues' => [], 'php_version' => '8.1', ], + 'constructorsShouldReturnVoid' => [ + 'code' => <<<'PHP' + 'InvalidReturnStatement', + ], ]; } }