Skip to content

Commit 87b3684

Browse files
Rework
1 parent e0a4341 commit 87b3684

File tree

4 files changed

+60
-50
lines changed

4 files changed

+60
-50
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -576,43 +576,48 @@ public function specifyTypesInCondition(
576576
throw new ShouldNotHappenException();
577577
}
578578

579-
if ($expr instanceof BooleanAnd && $scope->getType($expr->left)->isTrue()->yes()) {
579+
if ($context->falsey() && $scope->getType($expr->left)->isTrue()->yes()) {
580580
$leftTypes = null;
581581
} else {
582582
$leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context, $rootExpr);
583583
}
584584

585585
$rightScope = $scope->filterByTruthyValue($expr->left);
586-
if ($expr instanceof BooleanAnd && $rightScope->getType($expr->right)->isTrue()->yes()) {
586+
if ($context->falsey() && $scope->getType($expr->right)->isTrue()->yes()) {
587587
$rightTypes = null;
588588
} else {
589589
$rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context, $rootExpr);
590590
}
591591

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);
592+
if ($leftTypes === null && $rightTypes === null) {
593+
$types = new SpecifiedTypes([], [], false, [], $expr);
594+
} elseif ($leftTypes === null) {
595+
$types = $context->true() ? $rightTypes : $rightTypes->normalize($rightScope);
596+
} elseif ($rightTypes === null) {
597+
$types = $context->true() ? $leftTypes : $leftTypes->normalize($scope);
598+
} else {
599+
$types = $context->true()
600+
? $leftTypes->unionWith($rightTypes)
601+
: $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope));
600602
}
601603

602-
$types = $context->true()
603-
? $leftTypes->unionWith($rightTypes)
604-
: $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope));
605604
if ($context->false()) {
606-
return new SpecifiedTypes(
607-
$types->getSureTypes(),
608-
$types->getSureNotTypes(),
609-
false,
610-
array_merge(
605+
if ($leftTypes === null || $rightTypes === null) {
606+
$conditionalTypes = [];
607+
} else {
608+
$conditionalTypes = array_merge(
611609
$this->processBooleanNotSureConditionalTypes($scope, $leftTypes, $rightTypes),
612610
$this->processBooleanNotSureConditionalTypes($scope, $rightTypes, $leftTypes),
613611
$this->processBooleanSureConditionalTypes($scope, $leftTypes, $rightTypes),
614612
$this->processBooleanSureConditionalTypes($scope, $rightTypes, $leftTypes),
615-
),
613+
);
614+
}
615+
616+
return new SpecifiedTypes(
617+
$types->getSureTypes(),
618+
$types->getSureNotTypes(),
619+
false,
620+
$conditionalTypes,
616621
$rootExpr,
617622
);
618623
}
@@ -623,26 +628,26 @@ public function specifyTypesInCondition(
623628
throw new ShouldNotHappenException();
624629
}
625630

626-
if ($expr instanceof BooleanOr && $scope->getType($expr->left)->isFalse()->yes()) {
631+
if ($context->truthy() && $scope->getType($expr->left)->isFalse()->yes()) {
627632
$leftTypes = null;
628633
} else {
629634
$leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context, $rootExpr);
630635
}
631636

632637
$rightScope = $scope->filterByFalseyValue($expr->left);
633-
if ($expr instanceof BooleanOr && $rightScope->getType($expr->right)->isFalse()->yes()) {
638+
if ($context->truthy() && $scope->getType($expr->right)->isFalse()->yes()) {
634639
$rightTypes = null;
635640
} else {
636641
$rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context, $rootExpr);
637642
}
638643

639-
if (null === $leftTypes && null === $rightTypes) {
644+
if ($leftTypes === null && $rightTypes === null) {
640645
return new SpecifiedTypes([], [], false, [], $expr);
641646
}
642-
if (null === $leftTypes) {
647+
if ($leftTypes === null) {
643648
return $context->true() ? $rightTypes->normalize($rightScope) : $rightTypes;
644649
}
645-
if (null === $rightTypes) {
650+
if ($rightTypes === null) {
646651
return $context->true() ? $leftTypes->normalize($scope) : $leftTypes;
647652
}
648653

tests/PHPStan/Analyser/TypeSpecifierTest.php

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ protected function setUp(): void
7070
$this->scope = $this->scope->assignVariable('barOrFalse', new UnionType([new ObjectType('Bar'), new ConstantBooleanType(false)]), new UnionType([new ObjectType('Bar'), new ConstantBooleanType(false)]));
7171
$this->scope = $this->scope->assignVariable('stringOrFalse', new UnionType([new StringType(), new ConstantBooleanType(false)]), new UnionType([new StringType(), new ConstantBooleanType(false)]));
7272
$this->scope = $this->scope->assignVariable('array', new ArrayType(new MixedType(), new MixedType()), new ArrayType(new MixedType(), new MixedType()));
73+
$this->scope = $this->scope->assignVariable('arrayOrNull', new UnionType([new ArrayType(new MixedType(), new MixedType()), new NullType()]), new UnionType([new ArrayType(new MixedType(), new MixedType()), new NullType()]));
7374
$this->scope = $this->scope->assignVariable('foo', new MixedType(), new MixedType());
75+
$this->scope = $this->scope->assignVariable('mixed', new MixedType(), new MixedType());
7476
$this->scope = $this->scope->assignVariable('classString', new ClassStringType(), new ClassStringType());
7577
$this->scope = $this->scope->assignVariable('genericClassString', new GenericClassStringType(new ObjectType('Bar')), new GenericClassStringType(new ObjectType('Bar')));
7678
$this->scope = $this->scope->assignVariable('object', new ObjectWithoutClassType(), new ObjectWithoutClassType());
@@ -349,9 +351,17 @@ public function dataCondition(): iterable
349351
$this->createFunctionCall('is_int', 'foo'),
350352
$this->createFunctionCall('is_string', 'bar'),
351353
),
352-
[],
354+
['$foo' => 'int'],
353355
['$foo' => '~int', '$bar' => '~string'],
354356
],
357+
[
358+
new Expr\BinaryOp\BooleanOr(
359+
$this->createFunctionCall('is_int', 'foo'),
360+
$this->createFunctionCall('is_string', 'mixed'),
361+
),
362+
[],
363+
['$foo' => '~int', '$mixed' => '~string'],
364+
],
355365
[
356366
new Expr\BinaryOp\BooleanAnd(
357367
new Expr\BinaryOp\BooleanOr(
@@ -648,19 +658,37 @@ public function dataCondition(): iterable
648658
[
649659
new Expr\Empty_(new Variable('array')),
650660
[
651-
'$array' => 'array{}|null',
661+
'$array' => 'array{}',
652662
],
653663
[
654664
'$array' => '~0|0.0|\'\'|\'0\'|array{}|false|null',
655665
],
656666
],
667+
[
668+
new Expr\Empty_(new Variable('arrayOrNull')),
669+
[
670+
'$arrayOrNull' => 'array{}|null',
671+
],
672+
[
673+
'$arrayOrNull' => '~0|0.0|\'\'|\'0\'|array{}|false|null',
674+
],
675+
],
657676
[
658677
new BooleanNot(new Expr\Empty_(new Variable('array'))),
659678
[
660679
'$array' => '~0|0.0|\'\'|\'0\'|array{}|false|null',
661680
],
662681
[
663-
'$array' => 'array{}|null',
682+
'$array' => 'array{}',
683+
],
684+
],
685+
[
686+
new BooleanNot(new Expr\Empty_(new Variable('arrayOrNull'))),
687+
[
688+
'$arrayOrNull' => '~0|0.0|\'\'|\'0\'|array{}|false|null',
689+
],
690+
[
691+
'$arrayOrNull' => 'array{}|null',
664692
],
665693
],
666694
[

tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,6 @@ public function testInstanceof(): void
119119
232,
120120
$tipText,
121121
],
122-
[
123-
'Instanceof between *NEVER* and ImpossibleInstanceOf\Foo will always evaluate to false.',
124-
234,
125-
],
126122
[
127123
'Instanceof between ImpossibleInstanceOf\Bar&ImpossibleInstanceOf\Foo and ImpossibleInstanceOf\Foo will always evaluate to true.',
128124
238,
@@ -232,10 +228,6 @@ public function testInstanceofWithoutAlwaysTrue(): void
232228
'Instanceof between *NEVER* and ImpossibleInstanceOf\Lorem will always evaluate to false.',
233229
228,
234230
],
235-
[
236-
'Instanceof between *NEVER* and ImpossibleInstanceOf\Foo will always evaluate to false.',
237-
234,
238-
],
239231
[
240232
'Instanceof between *NEVER* and ImpossibleInstanceOf\Bar will always evaluate to false.',
241233
240,

tests/PHPStan/Rules/Comparison/BooleanAndConstantConditionRuleTest.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,6 @@ public function testRule(): void
9797
64,
9898
//$tipText,
9999
],
100-
[
101-
'Result of && is always false.',
102-
66,
103-
//$tipText,
104-
],
105100
[
106101
'Result of && is always false.',
107102
125,
@@ -190,11 +185,6 @@ public function testRuleLogicalAnd(): void
190185
64,
191186
//$tipText,
192187
],
193-
[
194-
'Result of && is always false.',
195-
66,
196-
//$tipText,
197-
],
198188
[
199189
'Result of && is always false.',
200190
125,
@@ -274,11 +264,6 @@ public function testRuleLogicalAndBleedingEdge(): void
274264
64,
275265
//$tipText,
276266
],
277-
[
278-
'Result of and is always false.',
279-
66,
280-
//$tipText,
281-
],
282267
[
283268
'Result of and is always false.',
284269
125,

0 commit comments

Comments
 (0)