Skip to content

Commit

Permalink
More precise ?? type inference
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Dec 21, 2023
1 parent 3c78441 commit d801919
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 7 deletions.
5 changes: 3 additions & 2 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -1576,7 +1576,8 @@ private function resolveType(string $exprString, Expr $node): Type
}

if ($node instanceof Expr\BinaryOp\Coalesce) {
$leftType = $this->getType($node->left);
$issetLeftExpr = new Expr\Isset_([$node->left]);
$leftType = $this->filterByTruthyValue($issetLeftExpr)->getType($node->left);

$result = $this->issetCheck($node->left, static function (Type $type): ?bool {
$isNull = $type->isNull();
Expand All @@ -1591,7 +1592,7 @@ private function resolveType(string $exprString, Expr $node): Type
return TypeCombinator::removeNull($leftType);
}

$rightType = $this->filterByFalseyValue(new Expr\Isset_([$node->left]))->getType($node->right);
$rightType = $this->filterByFalseyValue($issetLeftExpr)->getType($node->right);

if ($result === null) {
return TypeCombinator::union(
Expand Down
1 change: 1 addition & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ public function dataFileAsserts(): iterable
}

yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3875.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10327.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2611.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3548.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10131.php');
Expand Down
16 changes: 16 additions & 0 deletions tests/PHPStan/Analyser/data/bug-10327.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Bug10327;

use function PHPStan\Testing\assertType;

/**
* @param object{optionalKey?: int} $object
* @param array{optionalKey?: int} $array
*/
function test(object $object, array $array): void
{
$valueObject = $object->optionalKey ?? null;

assertType('int|null', $valueObject);
}
8 changes: 4 additions & 4 deletions tests/PHPStan/Analyser/data/bug-4117.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ public function getIterator(): ArrayIterator
public function broken(int $key)
{
$item = $this->items[$key] ?? null;
assertType('T (class Bug4117Types\GenericList, argument)|null', $item);
assertType('T of mixed~null (class Bug4117Types\GenericList, argument)|null', $item);
if ($item) {
assertType("T of mixed~0|0.0|''|'0'|array{}|false|null (class Bug4117Types\GenericList, argument)", $item);
} else {
assertType("(array{}&T (class Bug4117Types\GenericList, argument))|(0.0&T (class Bug4117Types\GenericList, argument))|(0&T (class Bug4117Types\GenericList, argument))|(''&T (class Bug4117Types\GenericList, argument))|('0'&T (class Bug4117Types\GenericList, argument))|(T (class Bug4117Types\GenericList, argument)&false)|null", $item);
assertType("(array{}&T of mixed~null (class Bug4117Types\GenericList, argument))|(0.0&T of mixed~null (class Bug4117Types\GenericList, argument))|(0&T of mixed~null (class Bug4117Types\GenericList, argument))|(''&T of mixed~null (class Bug4117Types\GenericList, argument))|('0'&T of mixed~null (class Bug4117Types\GenericList, argument))|(T of mixed~null (class Bug4117Types\GenericList, argument)&false)|null", $item);
}

assertType('T (class Bug4117Types\GenericList, argument)|null', $item);
assertType('T of mixed~null (class Bug4117Types\GenericList, argument)|null', $item);

return $item;
}
Expand All @@ -48,7 +48,7 @@ public function broken(int $key)
public function works(int $key)
{
$item = $this->items[$key] ?? null;
assertType('T (class Bug4117Types\GenericList, argument)|null', $item);
assertType('T of mixed~null (class Bug4117Types\GenericList, argument)|null', $item);

return $item;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
assertType('bool', isset($sometimesDefinedVariable));
assertType('bool', isset($neverDefinedVariable));

assertType('mixed', $foo ?? false);
assertType('mixed~null', $foo ?? false);

$bar = 'abc';
assertType('\'abc\'', $bar ?? false);

0 comments on commit d801919

Please sign in to comment.