diff --git a/src/Analyser/ExprHandler/AssignHandler.php b/src/Analyser/ExprHandler/AssignHandler.php index 51995ac665..3ea0196e4a 100644 --- a/src/Analyser/ExprHandler/AssignHandler.php +++ b/src/Analyser/ExprHandler/AssignHandler.php @@ -865,6 +865,8 @@ private function processSureTypesForConditionalExpressionsAfterAssign(Scope $sco !$expr instanceof PropertyFetch && !$expr instanceof ArrayDimFetch && !$expr instanceof FuncCall + && !$expr instanceof MethodCall + && !$expr instanceof Expr\StaticCall ) { continue; } @@ -904,6 +906,8 @@ private function processSureNotTypesForConditionalExpressionsAfterAssign(Scope $ !$expr instanceof PropertyFetch && !$expr instanceof ArrayDimFetch && !$expr instanceof FuncCall + && !$expr instanceof MethodCall + && !$expr instanceof Expr\StaticCall ) { continue; } diff --git a/tests/PHPStan/Analyser/nsrt/bug-5207.php b/tests/PHPStan/Analyser/nsrt/bug-5207.php new file mode 100644 index 0000000000..87f1f8157b --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-5207.php @@ -0,0 +1,81 @@ += 8.0 + +declare(strict_types = 1); + +namespace Bug5207; + +use function PHPStan\Testing\assertType; + +abstract class HelloWorld { + abstract public function getChild(): ?HelloWorld; + + public function sayHello(): void { + $foo = null !== $this->getChild(); + if ($foo) { + assertType('Bug5207\HelloWorld', $this->getChild()); + } + } + + public function sayHelloInline(): void { + if (null !== $this->getChild()) { + assertType('Bug5207\HelloWorld', $this->getChild()); + } + } +} + +abstract class StaticWorld { + abstract public static function getChild(): ?StaticWorld; + + public static function sayHello(): void { + $foo = null !== static::getChild(); + if ($foo) { + assertType('Bug5207\StaticWorld', static::getChild()); + } + } + + public static function sayHelloInline(): void { + if (null !== static::getChild()) { + assertType('Bug5207\StaticWorld', static::getChild()); + } + } +} + +abstract class ImpureStaticWorld { + /** + * @phpstan-impure + */ + abstract public static function getChild(): ?ImpureStaticWorld; + + public static function sayHello(): void { + $foo = null !== static::getChild(); + if ($foo) { + assertType('Bug5207\ImpureStaticWorld|null', static::getChild()); + } + } + + public static function sayHelloInline(): void { + if (null !== static::getChild()) { + assertType('Bug5207\ImpureStaticWorld|null', static::getChild()); + } + } +} + +abstract class ImpureWorld { + /** + * @phpstan-impure + */ + abstract public function getChild(): ?ImpureWorld; + + public function sayHello(): void { + $foo = null !== $this->getChild(); + if ($foo) { + assertType('Bug5207\ImpureWorld|null', $this->getChild()); + } + } + + public function sayHelloInline(): void { + if (null !== $this->getChild()) { + assertType('Bug5207\ImpureWorld|null', $this->getChild()); + } + } +} diff --git a/tests/PHPStan/Analyser/nsrt/bug-9455.php b/tests/PHPStan/Analyser/nsrt/bug-9455.php new file mode 100644 index 0000000000..2a0fe4f23f --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-9455.php @@ -0,0 +1,84 @@ += 8.0 + +declare(strict_types = 1); + +namespace Bug9455; + +use function PHPStan\Testing\assertType; + +class A { + public function __construct(private int $id){} + + public function getId(): int { + return $this->id; + } +} + +class B { + public function __construct(private int $id, private ?A $a = null){} + + public function getId(): int { + return $this->id; + } + + public function getA(): ?A { + return $this->a; + } +} + +class HelloWorld +{ + public function testFails(): void + { + $a = new A(1); + $b = new B(1, $a); + + $hasA = $b->getA() !== null; + + if($hasA) { + assertType('Bug9455\A', $b->getA()); + } + } + + public function testSucceeds(): void + { + $a = new A(1); + $b = new B(1, $a); + + if($b->getA() !== null) { + assertType('Bug9455\A', $b->getA()); + } + } +} + +class C { + /** + * @phpstan-impure + */ + public function getA(): ?A { + return rand(0, 1) ? new A(1) : null; + } +} + +class ImpureTest +{ + public function testImpureMethodNotNarrowed(): void + { + $c = new C(); + + $hasA = $c->getA() !== null; + + if($hasA) { + assertType('Bug9455\A|null', $c->getA()); + } + } + + public function testImpureMethodInline(): void + { + $c = new C(); + + if($c->getA() !== null) { + assertType('Bug9455\A|null', $c->getA()); + } + } +}