Skip to content

Commit feb2a5a

Browse files
authored
Fixed native expression type for by-ref variable after closure
1 parent 8babba3 commit feb2a5a

File tree

5 files changed

+54
-1
lines changed

5 files changed

+54
-1
lines changed

src/Analyser/MutatingScope.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4000,6 +4000,7 @@ public function processClosureScope(
40004000
array $byRefUses
40014001
): self
40024002
{
4003+
$nativeExpressionTypes = $this->nativeExpressionTypes;
40034004
$variableTypes = $this->variableTypes;
40044005
if (count($byRefUses) === 0) {
40054006
return $this;
@@ -4014,6 +4015,7 @@ public function processClosureScope(
40144015

40154016
if (!$closureScope->hasVariableType($variableName)->yes()) {
40164017
$variableTypes[$variableName] = VariableTypeHolder::createYes(new NullType());
4018+
$nativeExpressionTypes[sprintf('$%s', $variableName)] = new NullType();
40174019
continue;
40184020
}
40194021

@@ -4028,6 +4030,7 @@ public function processClosureScope(
40284030
}
40294031

40304032
$variableTypes[$variableName] = VariableTypeHolder::createYes($variableType);
4033+
$nativeExpressionTypes[sprintf('$%s', $variableName)] = $variableType;
40314034
}
40324035

40334036
return $this->scopeFactory->create(
@@ -4043,7 +4046,7 @@ public function processClosureScope(
40434046
$this->anonymousFunctionReflection,
40444047
$this->inFirstLevelStatement,
40454048
[],
4046-
$this->nativeExpressionTypes,
4049+
$nativeExpressionTypes,
40474050
$this->inFunctionCallsStack,
40484051
$this->afterExtractCall,
40494052
$this->parentScope

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5686,6 +5686,11 @@ public function dataBug4213(): array
56865686
return $this->gatherAssertTypes(__DIR__ . '/data/bug-4213.php');
56875687
}
56885688

5689+
public function dataBug4657(): array
5690+
{
5691+
return $this->gatherAssertTypes(__DIR__ . '/data/bug-4657.php');
5692+
}
5693+
56895694
/**
56905695
* @dataProvider dataArrayFunctions
56915696
* @param string $description
@@ -11306,6 +11311,7 @@ private function gatherAssertTypes(string $file): array
1130611311
* @dataProvider dataBug3558
1130711312
* @dataProvider dataBug3351
1130811313
* @dataProvider dataBug4213
11314+
* @dataProvider dataBug4657
1130911315
* @param string $assertType
1131011316
* @param string $file
1131111317
* @param mixed ...$args
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Bug4657;
4+
5+
use DateTime;
6+
use function PHPStan\Analyser\assertType;
7+
use function PHPStan\Analyser\assertNativeType;
8+
9+
function (): void {
10+
$value = null;
11+
$other = null;
12+
$callback = function () use (&$value, &$other) : void {
13+
$value = new DateTime();
14+
};
15+
$callback();
16+
17+
assertType('DateTime|null', $value);
18+
assertNativeType('DateTime|null', $value);
19+
20+
assertType('null', $other);
21+
assertNativeType('null', $other);
22+
};

tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,4 +399,11 @@ public function testBug2714(): void
399399
$this->analyse([__DIR__ . '/data/bug-2714.php'], []);
400400
}
401401

402+
public function testBug4657(): void
403+
{
404+
$this->checkAlwaysTrueCheckTypeFunctionCall = true;
405+
$this->treatPhpDocTypesAsCertain = false;
406+
$this->analyse([__DIR__ . '/data/bug-4657.php'], []);
407+
}
408+
402409
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Bug4657;
4+
5+
use DateTime;
6+
7+
function (): void {
8+
$value = null;
9+
$callback = function () use (&$value) : void {
10+
$value = new DateTime();
11+
};
12+
$callback();
13+
14+
assert(!is_null($value));
15+
};

0 commit comments

Comments
 (0)