Skip to content

Commit

Permalink
Filter right side of null coalesce assign with === null
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Oct 6, 2023
1 parent adbc35a commit f407ac6
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 1 deletion.
23 changes: 22 additions & 1 deletion src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -1932,7 +1932,28 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
$expr,
$nodeCallback,
$context,
fn (MutatingScope $scope): ExpressionResult => $this->processExprNode($expr->expr, $scope, $nodeCallback, $context->enterDeep()),
function (MutatingScope $scope) use ($expr, $nodeCallback, $context): ExpressionResult {
$originalScope = $scope;
if ($expr instanceof Expr\AssignOp\Coalesce) {
$scope = $scope->filterByFalseyValue(
new BinaryOp\NotIdentical($expr->var, new ConstFetch(new Name('null'))),
);
}

$result = $this->processExprNode($expr->expr, $scope, $nodeCallback, $context->enterDeep());
if ($expr instanceof Expr\AssignOp\Coalesce) {
return new ExpressionResult(
$result->getScope()->mergeWith(
$this->processExprNode($expr->expr, $originalScope, static function (): void {
}, $context->enterDeep())->getScope(),
),
$result->hasYield(),
$result->getThrowPoints(),
);
}

return $result;
},
$expr instanceof Expr\AssignOp\Coalesce,
);
$scope = $result->getScope();
Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Rules/Classes/InstantiationRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -456,4 +456,9 @@ public function testBug7574(): void
$this->analyse([__DIR__ . '/data/bug-7574.php'], []);
}

public function testBug9946(): void
{
$this->analyse([__DIR__ . '/data/bug-9946.php'], []);
}

}
21 changes: 21 additions & 0 deletions tests/PHPStan/Rules/Classes/data/bug-9946.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Bug9946;

class Foo
{

function test(?\DateTimeImmutable $a, ?string $b): string
{
if (!$a && !$b) {
throw new \LogicException('Either a or b MUST be set');
}
if (!$a) {
$c = new \DateTimeImmutable($b);
}
$a ??= new \DateTimeImmutable($b);

return $a->format('c');
}

}

0 comments on commit f407ac6

Please sign in to comment.