Skip to content

Commit e0a4341

Browse files
Handle condition with always true/false
1 parent 14fd384 commit e0a4341

File tree

3 files changed

+98
-6
lines changed

3 files changed

+98
-6
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -575,10 +575,33 @@ public function specifyTypesInCondition(
575575
if (!$scope instanceof MutatingScope) {
576576
throw new ShouldNotHappenException();
577577
}
578-
$leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context, $rootExpr);
578+
579+
if ($expr instanceof BooleanAnd && $scope->getType($expr->left)->isTrue()->yes()) {
580+
$leftTypes = null;
581+
} else {
582+
$leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context, $rootExpr);
583+
}
584+
579585
$rightScope = $scope->filterByTruthyValue($expr->left);
580-
$rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context, $rootExpr);
581-
$types = $context->true() ? $leftTypes->unionWith($rightTypes) : $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope));
586+
if ($expr instanceof BooleanAnd && $rightScope->getType($expr->right)->isTrue()->yes()) {
587+
$rightTypes = null;
588+
} else {
589+
$rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context, $rootExpr);
590+
}
591+
592+
if (null === $leftTypes && null === $rightTypes) {
593+
return new SpecifiedTypes([], [], false, [], $expr);
594+
}
595+
if (null === $leftTypes) {
596+
return $context->true() ? $rightTypes : $rightTypes->normalize($rightScope);
597+
}
598+
if (null === $rightTypes) {
599+
return $context->true() ? $leftTypes : $leftTypes->normalize($scope);
600+
}
601+
602+
$types = $context->true()
603+
? $leftTypes->unionWith($rightTypes)
604+
: $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope));
582605
if ($context->false()) {
583606
return new SpecifiedTypes(
584607
$types->getSureTypes(),
@@ -599,10 +622,33 @@ public function specifyTypesInCondition(
599622
if (!$scope instanceof MutatingScope) {
600623
throw new ShouldNotHappenException();
601624
}
602-
$leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context, $rootExpr);
625+
626+
if ($expr instanceof BooleanOr && $scope->getType($expr->left)->isFalse()->yes()) {
627+
$leftTypes = null;
628+
} else {
629+
$leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context, $rootExpr);
630+
}
631+
603632
$rightScope = $scope->filterByFalseyValue($expr->left);
604-
$rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context, $rootExpr);
605-
$types = $context->true() ? $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope)) : $leftTypes->unionWith($rightTypes);
633+
if ($expr instanceof BooleanOr && $rightScope->getType($expr->right)->isFalse()->yes()) {
634+
$rightTypes = null;
635+
} else {
636+
$rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context, $rootExpr);
637+
}
638+
639+
if (null === $leftTypes && null === $rightTypes) {
640+
return new SpecifiedTypes([], [], false, [], $expr);
641+
}
642+
if (null === $leftTypes) {
643+
return $context->true() ? $rightTypes->normalize($rightScope) : $rightTypes;
644+
}
645+
if (null === $rightTypes) {
646+
return $context->true() ? $leftTypes->normalize($scope) : $leftTypes;
647+
}
648+
649+
$types = $context->true()
650+
? $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope))
651+
: $leftTypes->unionWith($rightTypes);
606652
if ($context->true()) {
607653
return new SpecifiedTypes(
608654
$types->getSureTypes(),

tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,4 +864,10 @@ public function testBug10997(): void
864864
]);
865865
}
866866

867+
public function testBug11276(): void
868+
{
869+
$this->reportPossiblyNonexistentConstantArrayOffset = true;
870+
$this->analyse([__DIR__ . '/data/bug-11276.php'], []);
871+
}
872+
867873
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug11276;
4+
5+
class HelloWorld
6+
{
7+
/**
8+
* @param array{from: string, to: string} $expected
9+
*/
10+
public function testLanguagesMatchingRegex(string $url, ?array $expected): void
11+
{
12+
preg_match('#\/(?<from>[a-z]{2})-(?<to>[a-z]{1}[a-z0-9]{1})\/#', $url, $matches);
13+
14+
foreach ($expected as $key => $value) {
15+
if ($matches instanceof ArrayAccess || \array_key_exists($key, $matches)) {
16+
$matches[$key];
17+
}
18+
}
19+
20+
foreach ($expected as $key => $value) {
21+
if (\array_key_exists($key, $matches) || $matches instanceof ArrayAccess) {
22+
$matches[$key];
23+
}
24+
}
25+
26+
foreach ($expected as $key => $value) {
27+
if (!$matches instanceof ArrayAccess && !\array_key_exists($key, $matches)) {
28+
} else {
29+
$matches[$key];
30+
}
31+
}
32+
33+
foreach ($expected as $key => $value) {
34+
if (!\array_key_exists($key, $matches) && !$matches instanceof ArrayAccess) {
35+
} else {
36+
$matches[$key];
37+
}
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)