Skip to content

Commit 87a71c3

Browse files
committed
Always merge scopes from seemingly dead conditions
1 parent 222545e commit 87a71c3

4 files changed

Lines changed: 18 additions & 8 deletions

File tree

src/Analyser/MutatingScope.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,11 @@ private function resolveType(Expr $node): Type
499499
}
500500

501501
if ($node instanceof \PhpParser\Node\Expr\BooleanNot) {
502-
$exprBooleanType = $this->getType($node->expr)->toBoolean();
502+
if ($this->treatPhpDocTypesAsCertain) {
503+
$exprBooleanType = $this->getType($node->expr)->toBoolean();
504+
} else {
505+
$exprBooleanType = $this->getNativeType($node->expr)->toBoolean();
506+
}
503507
if ($exprBooleanType instanceof ConstantBooleanType) {
504508
return new ConstantBooleanType(!$exprBooleanType->getValue());
505509
}
@@ -591,8 +595,14 @@ private function resolveType(Expr $node): Type
591595
}
592596

593597
if ($node instanceof \PhpParser\Node\Expr\BinaryOp\LogicalXor) {
594-
$leftBooleanType = $this->getType($node->left)->toBoolean();
595-
$rightBooleanType = $this->getType($node->right)->toBoolean();
598+
if ($this->treatPhpDocTypesAsCertain) {
599+
$leftBooleanType = $this->getType($node->left)->toBoolean();
600+
$rightBooleanType = $this->getType($node->right)->toBoolean();
601+
} else {
602+
$leftBooleanType = $this->getNativeType($node->left)->toBoolean();
603+
$rightBooleanType = $this->getNativeType($node->right)->toBoolean();
604+
}
605+
596606
if (
597607
$leftBooleanType instanceof ConstantBooleanType
598608
&& $rightBooleanType instanceof ConstantBooleanType

src/Analyser/NodeScopeResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ private function processStmtNode(
521521
new StatementExitPoint($stmt, $scope),
522522
]);
523523
} elseif ($stmt instanceof If_) {
524-
$conditionType = $scope->getType($stmt->cond)->toBoolean();
524+
$conditionType = $scope->doNotTreatPhpDocTypesAsCertain()->getType($stmt->cond)->toBoolean();
525525
$ifAlwaysTrue = $conditionType instanceof ConstantBooleanType && $conditionType->getValue();
526526
$condResult = $this->processExprNode($stmt->cond, $scope, $nodeCallback, ExpressionContext::createDeep());
527527
$exitPoints = [];
@@ -545,7 +545,7 @@ private function processStmtNode(
545545
$condScope = $scope;
546546
foreach ($stmt->elseifs as $elseif) {
547547
$nodeCallback($elseif, $scope);
548-
$elseIfConditionType = $condScope->getType($elseif->cond)->toBoolean();
548+
$elseIfConditionType = $condScope->doNotTreatPhpDocTypesAsCertain()->getType($elseif->cond)->toBoolean();
549549
$condResult = $this->processExprNode($elseif->cond, $condScope, $nodeCallback, ExpressionContext::createDeep());
550550
$condScope = $condResult->getScope();
551551
$branchScopeStatementResult = $this->processStmtNodes($elseif, $elseif->stmts, $condResult->getTruthyScope(), $nodeCallback);

tests/PHPStan/Analyser/data/native-types.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,7 @@ public function doIfElse(\DateTimeInterface $date): void
163163
}
164164

165165
assertType(\DateTimeImmutable::class, $date);
166-
167-
// in reality it works but here the analyser is ran with treatPhpDocTypesAsCertain=true
168-
// assertNativeType(\DateTimeInterface::class, $date);
166+
assertNativeType(\DateTimeInterface::class, $date);
169167

170168
if ($date instanceof \DateTime) {
171169

tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,10 +290,12 @@ public function testReportTypesFromPhpDocs(): void
290290
[
291291
'Instanceof between DateTimeImmutable and DateTimeImmutable will always evaluate to true.',
292292
33,
293+
'Because the type is coming from a PHPDoc, you can turn off this check by setting <fg=cyan>treatPhpDocTypesAsCertain: false</> in your <fg=cyan>%configurationFile%</>.',
293294
],
294295
[
295296
'Instanceof between DateTimeImmutable and DateTime will always evaluate to false.',
296297
36,
298+
'Because the type is coming from a PHPDoc, you can turn off this check by setting <fg=cyan>treatPhpDocTypesAsCertain: false</> in your <fg=cyan>%configurationFile%</>.',
297299
],
298300
]);
299301
}

0 commit comments

Comments
 (0)