Skip to content

Commit

Permalink
Fix return type of arrow function
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jan 8, 2021
1 parent a1c7572 commit e9b783a
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 7 deletions.
38 changes: 31 additions & 7 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -1308,7 +1308,7 @@ private function resolveType(Expr $node): Type
}

if ($node instanceof Expr\ArrowFunction) {
$returnType = $this->getType($node->expr);
$returnType = $this->enterArrowFunctionWithoutReflection($node)->getType($node->expr);
if ($node->returnType !== null) {
$returnType = TypehintHelper::decideType($this->getFunctionType($node->returnType, false, false), $returnType);
}
Expand Down Expand Up @@ -2789,6 +2789,35 @@ public function enterAnonymousFunction(
}

public function enterArrowFunction(Expr\ArrowFunction $arrowFunction): self
{
$anonymousFunctionReflection = $this->getType($arrowFunction);
if (!$anonymousFunctionReflection instanceof ClosureType) {
throw new \PHPStan\ShouldNotHappenException();
}

$scope = $this->enterArrowFunctionWithoutReflection($arrowFunction);

return $this->scopeFactory->create(
$scope->context,
$scope->isDeclareStrictTypes(),
$scope->constantTypes,
$scope->getFunction(),
$scope->getNamespace(),
$scope->variableTypes,
$scope->moreSpecificTypes,
$scope->conditionalExpressions,
$scope->inClosureBindScopeClass,
$anonymousFunctionReflection,
true,
[],
[],
[],
$scope->afterExtractCall,
$scope->parentScope
);
}

private function enterArrowFunctionWithoutReflection(Expr\ArrowFunction $arrowFunction): self
{
$variableTypes = $this->variableTypes;
$mixed = new MixedType();
Expand All @@ -2813,11 +2842,6 @@ public function enterArrowFunction(Expr\ArrowFunction $arrowFunction): self
unset($variableTypes['this']);
}

$anonymousFunctionReflection = $this->getType($arrowFunction);
if (!$anonymousFunctionReflection instanceof ClosureType) {
throw new \PHPStan\ShouldNotHappenException();
}

$conditionalExpressions = [];
foreach ($this->conditionalExpressions as $conditionalExprString => $holders) {
$newHolders = [];
Expand Down Expand Up @@ -2883,7 +2907,7 @@ public function enterArrowFunction(Expr\ArrowFunction $arrowFunction): self
$this->moreSpecificTypes,
$conditionalExpressions,
$this->inClosureBindScopeClass,
$anonymousFunctionReflection,
null,
true,
[],
[],
Expand Down
10 changes: 10 additions & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10594,6 +10594,15 @@ public function dataBug4188(): array
return $this->gatherAssertTypes(__DIR__ . '/data/bug-4188.php');
}

public function dataBug4339(): array
{
if (PHP_VERSION_ID < 70400) {
return [];
}

return $this->gatherAssertTypes(__DIR__ . '/data/bug-4339.php');
}

/**
* @param string $file
* @return array<string, mixed[]>
Expand Down Expand Up @@ -10797,6 +10806,7 @@ private function gatherAssertTypes(string $file): array
* @dataProvider dataBug2980
* @dataProvider dataBug3986
* @dataProvider dataBug4188
* @dataProvider dataBug4339
* @param string $assertType
* @param string $file
* @param mixed ...$args
Expand Down
15 changes: 15 additions & 0 deletions tests/PHPStan/Analyser/data/bug-4339.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php // lint >= 7.4

namespace Bug4339;

use function PHPStan\Analyser\assertType;

function (?string $v) {
assertType('string', $v ?? '-');
fn (?string $value): string => assertType('string', $value ?? '-');
fn (?string $value): void => assertType('string|null', $value);

$f = fn (?string $value): string => $value ?? '-';

assertType('string', $f($v));
};
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function doFoo(): void
public function doBar(): void
{
fn () => $this->doFoo();
fn (?string $value): string => $value ?? '-';
}

}

0 comments on commit e9b783a

Please sign in to comment.