Skip to content

Commit e9b783a

Browse files
committed
Fix return type of arrow function
1 parent a1c7572 commit e9b783a

File tree

4 files changed

+57
-7
lines changed

4 files changed

+57
-7
lines changed

src/Analyser/MutatingScope.php

+31-7
Original file line numberDiff line numberDiff line change
@@ -1308,7 +1308,7 @@ private function resolveType(Expr $node): Type
13081308
}
13091309

13101310
if ($node instanceof Expr\ArrowFunction) {
1311-
$returnType = $this->getType($node->expr);
1311+
$returnType = $this->enterArrowFunctionWithoutReflection($node)->getType($node->expr);
13121312
if ($node->returnType !== null) {
13131313
$returnType = TypehintHelper::decideType($this->getFunctionType($node->returnType, false, false), $returnType);
13141314
}
@@ -2789,6 +2789,35 @@ public function enterAnonymousFunction(
27892789
}
27902790

27912791
public function enterArrowFunction(Expr\ArrowFunction $arrowFunction): self
2792+
{
2793+
$anonymousFunctionReflection = $this->getType($arrowFunction);
2794+
if (!$anonymousFunctionReflection instanceof ClosureType) {
2795+
throw new \PHPStan\ShouldNotHappenException();
2796+
}
2797+
2798+
$scope = $this->enterArrowFunctionWithoutReflection($arrowFunction);
2799+
2800+
return $this->scopeFactory->create(
2801+
$scope->context,
2802+
$scope->isDeclareStrictTypes(),
2803+
$scope->constantTypes,
2804+
$scope->getFunction(),
2805+
$scope->getNamespace(),
2806+
$scope->variableTypes,
2807+
$scope->moreSpecificTypes,
2808+
$scope->conditionalExpressions,
2809+
$scope->inClosureBindScopeClass,
2810+
$anonymousFunctionReflection,
2811+
true,
2812+
[],
2813+
[],
2814+
[],
2815+
$scope->afterExtractCall,
2816+
$scope->parentScope
2817+
);
2818+
}
2819+
2820+
private function enterArrowFunctionWithoutReflection(Expr\ArrowFunction $arrowFunction): self
27922821
{
27932822
$variableTypes = $this->variableTypes;
27942823
$mixed = new MixedType();
@@ -2813,11 +2842,6 @@ public function enterArrowFunction(Expr\ArrowFunction $arrowFunction): self
28132842
unset($variableTypes['this']);
28142843
}
28152844

2816-
$anonymousFunctionReflection = $this->getType($arrowFunction);
2817-
if (!$anonymousFunctionReflection instanceof ClosureType) {
2818-
throw new \PHPStan\ShouldNotHappenException();
2819-
}
2820-
28212845
$conditionalExpressions = [];
28222846
foreach ($this->conditionalExpressions as $conditionalExprString => $holders) {
28232847
$newHolders = [];
@@ -2883,7 +2907,7 @@ public function enterArrowFunction(Expr\ArrowFunction $arrowFunction): self
28832907
$this->moreSpecificTypes,
28842908
$conditionalExpressions,
28852909
$this->inClosureBindScopeClass,
2886-
$anonymousFunctionReflection,
2910+
null,
28872911
true,
28882912
[],
28892913
[],

tests/PHPStan/Analyser/NodeScopeResolverTest.php

+10
Original file line numberDiff line numberDiff line change
@@ -10594,6 +10594,15 @@ public function dataBug4188(): array
1059410594
return $this->gatherAssertTypes(__DIR__ . '/data/bug-4188.php');
1059510595
}
1059610596

10597+
public function dataBug4339(): array
10598+
{
10599+
if (PHP_VERSION_ID < 70400) {
10600+
return [];
10601+
}
10602+
10603+
return $this->gatherAssertTypes(__DIR__ . '/data/bug-4339.php');
10604+
}
10605+
1059710606
/**
1059810607
* @param string $file
1059910608
* @return array<string, mixed[]>
@@ -10797,6 +10806,7 @@ private function gatherAssertTypes(string $file): array
1079710806
* @dataProvider dataBug2980
1079810807
* @dataProvider dataBug3986
1079910808
* @dataProvider dataBug4188
10809+
* @dataProvider dataBug4339
1080010810
* @param string $assertType
1080110811
* @param string $file
1080210812
* @param mixed ...$args
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php // lint >= 7.4
2+
3+
namespace Bug4339;
4+
5+
use function PHPStan\Analyser\assertType;
6+
7+
function (?string $v) {
8+
assertType('string', $v ?? '-');
9+
fn (?string $value): string => assertType('string', $value ?? '-');
10+
fn (?string $value): void => assertType('string|null', $value);
11+
12+
$f = fn (?string $value): string => $value ?? '-';
13+
14+
assertType('string', $f($v));
15+
};

tests/PHPStan/Rules/Functions/data/arrow-functions-return-type.php

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public function doFoo(): void
2727
public function doBar(): void
2828
{
2929
fn () => $this->doFoo();
30+
fn (?string $value): string => $value ?? '-';
3031
}
3132

3233
}

0 commit comments

Comments
 (0)