Skip to content

Commit 58f1d72

Browse files
Support int range in bitwise operations
1 parent 54a5bd6 commit 58f1d72

File tree

3 files changed

+88
-6
lines changed

3 files changed

+88
-6
lines changed

src/Reflection/InitializerExprTypeResolver.php

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -611,8 +611,17 @@ public function getBitwiseAndType(Expr $left, Expr $right, callable $getTypeCall
611611
return $this->getNeverType($leftType, $rightType);
612612
}
613613

614-
$leftTypes = $leftType->getConstantScalarTypes();
615-
$rightTypes = $rightType->getConstantScalarTypes();
614+
if ($leftType instanceof IntegerRangeType) {
615+
$leftTypes = $leftType->getFiniteTypes();
616+
} else {
617+
$leftTypes = $leftType->getConstantScalarTypes();
618+
}
619+
if ($rightType instanceof IntegerRangeType) {
620+
$rightTypes = $rightType->getFiniteTypes();
621+
} else {
622+
$rightTypes = $rightType->getConstantScalarTypes();
623+
}
624+
616625
$leftTypesCount = count($leftTypes);
617626
$rightTypesCount = count($rightTypes);
618627
if ($leftTypesCount > 0 && $rightTypesCount > 0) {
@@ -680,8 +689,17 @@ public function getBitwiseOrType(Expr $left, Expr $right, callable $getTypeCallb
680689
return $this->getNeverType($leftType, $rightType);
681690
}
682691

683-
$leftTypes = $leftType->getConstantScalarTypes();
684-
$rightTypes = $rightType->getConstantScalarTypes();
692+
if ($leftType instanceof IntegerRangeType) {
693+
$leftTypes = $leftType->getFiniteTypes();
694+
} else {
695+
$leftTypes = $leftType->getConstantScalarTypes();
696+
}
697+
if ($rightType instanceof IntegerRangeType) {
698+
$rightTypes = $rightType->getFiniteTypes();
699+
} else {
700+
$rightTypes = $rightType->getConstantScalarTypes();
701+
}
702+
685703
$leftTypesCount = count($leftTypes);
686704
$rightTypesCount = count($rightTypes);
687705
if ($leftTypesCount > 0 && $rightTypesCount > 0) {
@@ -739,8 +757,17 @@ public function getBitwiseXorType(Expr $left, Expr $right, callable $getTypeCall
739757
return $this->getNeverType($leftType, $rightType);
740758
}
741759

742-
$leftTypes = $leftType->getConstantScalarTypes();
743-
$rightTypes = $rightType->getConstantScalarTypes();
760+
if ($leftType instanceof IntegerRangeType) {
761+
$leftTypes = $leftType->getFiniteTypes();
762+
} else {
763+
$leftTypes = $leftType->getConstantScalarTypes();
764+
}
765+
if ($rightType instanceof IntegerRangeType) {
766+
$rightTypes = $rightType->getFiniteTypes();
767+
} else {
768+
$rightTypes = $rightType->getConstantScalarTypes();
769+
}
770+
744771
$leftTypesCount = count($leftTypes);
745772
$rightTypesCount = count($rightTypes);
746773
if ($leftTypesCount > 0 && $rightTypesCount > 0) {

tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,18 @@ public function testBug13035(): void
956956
$this->analyse([__DIR__ . '/data/bug-13035.php'], []);
957957
}
958958

959+
public function testBug7912(): void
960+
{
961+
$this->checkExplicitMixed = true;
962+
$this->checkImplicitMixed = true;
963+
$this->analyse([__DIR__ . '/data/bug-7912.php'], [
964+
[
965+
'Property Bug7912\A::$has (int<0, 1>) does not accept 999.',
966+
35,
967+
],
968+
]);
969+
}
970+
959971
public function testBug13654(): void
960972
{
961973
$this->checkExplicitMixed = true;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Bug7912;
4+
5+
class A
6+
{
7+
/** @var int<0,1> */
8+
public int $has = 0;
9+
10+
/** @var int<0,1> */
11+
public int $not = 0;
12+
}
13+
14+
class B
15+
{
16+
/** @var int<0,1> */
17+
public int $has = 1;
18+
}
19+
20+
$a = new A();
21+
$b = new B();
22+
23+
// The following versions throw an error, even though | between 0,1 will always be 0,1
24+
$a->has |= $b->has;
25+
$a->has = $a->has | $b->has;
26+
27+
// The following versions don't:
28+
$a->has = 0 | 1;
29+
$a->has |= 1;
30+
31+
$int = 1;
32+
$a->has |= $int;
33+
34+
// This properly errors:
35+
$a->has |= 999;
36+
37+
// And these all work:
38+
/** @var int<0,1> */
39+
$c = 0;
40+
/** @var int<0,1> */
41+
$e = 1;
42+
$c |= $e;
43+
$c |= $a->has;

0 commit comments

Comments
 (0)