Skip to content

Commit c05ba98

Browse files
committed
Fix nullable closure parameter type
1 parent 7a66cb6 commit c05ba98

File tree

5 files changed

+77
-1
lines changed

5 files changed

+77
-1
lines changed

src/Analyser/MutatingScope.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,7 @@ private function resolveType(Expr $node): Type
15881588
$parameters[] = new NativeParameterReflection(
15891589
$param->var->name,
15901590
$firstOptionalParameterIndex !== null && $i >= $firstOptionalParameterIndex,
1591-
$this->getFunctionType($param->type, $param->type === null, false),
1591+
$this->getFunctionType($param->type, $this->isParameterValueNullable($param), false),
15921592
$param->byRef
15931593
? PassedByReference::createCreatesNewVariable()
15941594
: PassedByReference::createNo(),

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,10 @@ public function dataFileAsserts(): iterable
767767
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5668.php');
768768
yield from $this->gatherAssertTypes(__DIR__ . '/data/generics-empty-array.php');
769769
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/bug-5757.php');
770+
771+
if (PHP_VERSION_ID >= 70400) {
772+
yield from $this->gatherAssertTypes(__DIR__ . '/data/nullable-closure-parameter.php');
773+
}
770774
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6584.php');
771775
}
772776

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php // lint >= 7.4
2+
3+
namespace NullableClosureParameter;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Foo
8+
{
9+
10+
public function doFoo()
11+
{
12+
$a = function (string $test = null) {
13+
assertType('string|null', $test);
14+
return $test;
15+
};
16+
assertType('string|null', $a());
17+
18+
$b = fn (string $test = null) => $test;
19+
assertType('string|null', $b());
20+
21+
fn (string $test = null): string => assertType('string|null', $test);
22+
}
23+
24+
}

tests/PHPStan/Rules/Functions/CallCallablesRuleTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,25 @@ public function testFirstClassCallables(): void
241241
]);
242242
}
243243

244+
public function testBug6701(): void
245+
{
246+
if (PHP_VERSION_ID < 70400 && !self::$useStaticReflectionProvider) {
247+
$this->markTestSkipped('Test requires PHP 7.4.');
248+
}
249+
$this->analyse([__DIR__ . '/data/bug-6701.php'], [
250+
[
251+
'Parameter #1 $test of closure expects string|null, int given.',
252+
14,
253+
],
254+
[
255+
'Parameter #1 $test of closure expects string|null, int given.',
256+
18,
257+
],
258+
[
259+
'Parameter #1 $test of closure expects string|null, int given.',
260+
24,
261+
],
262+
]);
263+
}
264+
244265
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Bug6701;
4+
5+
class Foo
6+
{
7+
8+
public function doFoo(int $i)
9+
{
10+
$a = function ( string $test = null ): string {
11+
return $test ?? '';
12+
};
13+
$a(null);
14+
$a($i);
15+
16+
$b = fn ( string $test = null ): string => $test ?? '';
17+
$b(null);
18+
$b($i);
19+
20+
$c = function ( ?string $test = null ): string {
21+
return $test ?? '';
22+
};
23+
$c(null);
24+
$c($i);
25+
}
26+
27+
}

0 commit comments

Comments
 (0)