Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 48e3ee2

Browse files
Fix specifying types for left side of null coalesce
1 parent f654282 commit 48e3ee2

File tree

7 files changed

+137
-0
lines changed

7 files changed

+137
-0
lines changed

‎src/Analyser/TypeSpecifier.php‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,15 @@ private function createForExpr(
12791279
$expr = NullsafeOperatorHelper::getNullsafeShortcircuitedExpr($expr);
12801280
}
12811281

1282+
if (
1283+
$scope !== null
1284+
&& $context->true()
1285+
&& $expr instanceof Expr\BinaryOp\Coalesce
1286+
&& $type->isSuperTypeOf($scope->getType($expr->right))->no()
1287+
) {
1288+
$expr = $expr->left;
1289+
}
1290+
12821291
if (
12831292
$expr instanceof FuncCall
12841293
&& $expr->name instanceof Name

‎tests/PHPStan/Analyser/NodeScopeResolverTest.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,12 @@ public function dataFileAsserts(): iterable
10191019

10201020
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7921.php');
10211021
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7928.php');
1022+
1023+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7949.php');
1024+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7639.php');
1025+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5304.php');
1026+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7244.php');
1027+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7501.php');
10221028
}
10231029

10241030
/**
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Bug5304;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @param array{foo?: string} $in
9+
*/
10+
function takesArg(array $in): void
11+
{
12+
if(is_string($in['foo'] ?? null)) {
13+
assertType('array{foo: string}', $in);
14+
}
15+
16+
if(isset($in['foo'])) {
17+
assertType('array{foo: string}', $in);
18+
}
19+
20+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug7244;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class HelloWorld
8+
{
9+
/**
10+
* @param array<string, mixed> $arguments
11+
*/
12+
public function getFormat(array $arguments): string {
13+
$value = \is_string($arguments['format'] ?? null) ? $arguments['format'] : 'Y-m-d';
14+
assertType('string', $value);
15+
return $value;
16+
}
17+
18+
/**
19+
* @param array<string, mixed> $arguments
20+
*/
21+
public function getFormatWithoutFallback(array $arguments): string {
22+
$value = \is_string($arguments['format']) ? $arguments['format'] : 'Y-m-d';
23+
assertType('string', $value);
24+
return $value;
25+
}
26+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug7501;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @param array{key?: mixed} $a
9+
*/
10+
function f(array $a): void
11+
{
12+
if (isset($a['key']) && is_int($a['key'])) {
13+
assertType('array{key: int}', $a);
14+
}
15+
16+
if (is_int($a['key'] ?? null)) {
17+
assertType('array{key: int}', $a);
18+
}
19+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug7639;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
abstract class TestCase
8+
{
9+
/**
10+
* @return static|null
11+
*/
12+
public static function getTestFromBacktrace()
13+
{
14+
foreach (debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS | \DEBUG_BACKTRACE_PROVIDE_OBJECT) as $frame) {
15+
if (($frame['object'] ?? null) instanceof static) {
16+
assertType('static(Bug7639\\TestCase)', $frame['object']);
17+
return $frame['object'];
18+
}
19+
}
20+
21+
return null;
22+
}
23+
24+
/**
25+
* @return static|null
26+
*/
27+
public static function getTestFromBacktraceWithoutNullCoalesce()
28+
{
29+
foreach (debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS | \DEBUG_BACKTRACE_PROVIDE_OBJECT) as $frame) {
30+
if (isset($frame['object']) && $frame['object'] instanceof static) {
31+
assertType('static(Bug7639\\TestCase)', $frame['object']);
32+
return $frame['object'];
33+
}
34+
}
35+
36+
return null;
37+
}
38+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug7949;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class HelloWorld
8+
{
9+
public function bar(?string $price): void
10+
{
11+
$price = strlen($price ?? '') > 0 ? $price : '0';
12+
assertType('non-empty-string', $price);
13+
14+
$this->foo($price);
15+
}
16+
17+
public function foo(string $test): void {
18+
}
19+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /