From a81a8c3870b119ee15accfb549caa5f9c163d8c5 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 18 Jan 2021 10:07:46 +0100 Subject: [PATCH] Fix ClosureReturnStatementsNode --- src/Analyser/NodeScopeResolver.php | 9 ++------- .../Functions/ClosureReturnTypeRuleTest.php | 12 ++++++++++++ .../Functions/data/closureReturnTypes.php | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 7258aed8b6..ce820b7236 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -2304,14 +2304,9 @@ private function processClosureNode( $gatheredReturnStatements = []; $gatheredYieldStatements = []; - $encounteredAnotherClosure = false; - $closureStmtsCallback = static function (\PhpParser\Node $node, Scope $scope) use ($nodeCallback, &$gatheredReturnStatements, &$gatheredYieldStatements, &$encounteredAnotherClosure): void { + $closureStmtsCallback = static function (\PhpParser\Node $node, Scope $scope) use ($nodeCallback, &$gatheredReturnStatements, &$gatheredYieldStatements, &$closureScope): void { $nodeCallback($node, $scope); - if ($encounteredAnotherClosure) { - return; - } - if ($node instanceof Expr\Closure || ($node instanceof New_ && $node->class instanceof Class_)) { - $encounteredAnotherClosure = true; + if ($scope->getAnonymousFunctionReflection() !== $closureScope->getAnonymousFunctionReflection()) { return; } if ($node instanceof Expr\Yield_ || $node instanceof Expr\YieldFrom) { diff --git a/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php b/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php index 352c223fd1..fb97edae37 100644 --- a/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ClosureReturnTypeRuleTest.php @@ -43,6 +43,18 @@ public function testClosureReturnTypeRule(): void 'Anonymous function should return array()|null but empty return statement found.', 88, ], + [ + 'Anonymous function should return string but returns int.', + 105, + ], + [ + 'Anonymous function should return string but returns int.', + 115, + ], + [ + 'Anonymous function should return string but returns int.', + 118, + ], ]); } diff --git a/tests/PHPStan/Rules/Functions/data/closureReturnTypes.php b/tests/PHPStan/Rules/Functions/data/closureReturnTypes.php index 15b2d9ba53..627b46d170 100644 --- a/tests/PHPStan/Rules/Functions/data/closureReturnTypes.php +++ b/tests/PHPStan/Rules/Functions/data/closureReturnTypes.php @@ -99,3 +99,21 @@ function (): int { return 'bar'; }; + +function (): string { + if (rand(0, 1)) { + return 1; + } + + $c = new class () { + public function doFoo(): int { + return 2; + } + }; + + if (rand(0, 1)) { + return 3; + } + + return 4; +};