Skip to content

Commit 6e91d05

Browse files
Try
1 parent 37608db commit 6e91d05

File tree

3 files changed

+33
-12
lines changed

3 files changed

+33
-12
lines changed

src/Reflection/InitializerExprTypeResolver.php

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,9 +1008,16 @@ public function getBitwiseAndTypeFromTypes(Type $leftType, Type $rightType): Typ
10081008
$rightType = $this->optimizeScalarType($rightType);
10091009
}
10101010

1011+
if ($leftType instanceof MixedType && $rightType instanceof MixedType) {
1012+
return new BenevolentUnionType([new IntegerType(), new StringType()]);
1013+
}
1014+
10111015
$leftIsString = $leftType->isString();
10121016
$rightIsString = $rightType->isString();
1013-
if ($leftIsString->yes() && $rightIsString->yes()) {
1017+
if (
1018+
($leftIsString->yes() || $leftType instanceof MixedType)
1019+
&& ($rightIsString->yes() || $rightType instanceof MixedType)
1020+
) {
10141021
return new StringType();
10151022
}
10161023
if ($leftIsString->maybe() && $rightIsString->maybe()) {
@@ -1087,9 +1094,16 @@ public function getBitwiseOrTypeFromTypes(Type $leftType, Type $rightType): Type
10871094
$rightType = $this->optimizeScalarType($rightType);
10881095
}
10891096

1097+
if ($leftType instanceof MixedType && $rightType instanceof MixedType) {
1098+
return new BenevolentUnionType([new IntegerType(), new StringType()]);
1099+
}
1100+
10901101
$leftIsString = $leftType->isString();
10911102
$rightIsString = $rightType->isString();
1092-
if ($leftIsString->yes() && $rightIsString->yes()) {
1103+
if (
1104+
($leftIsString->yes() || $leftType instanceof MixedType)
1105+
&& ($rightIsString->yes() || $rightType instanceof MixedType)
1106+
) {
10931107
return new StringType();
10941108
}
10951109
if ($leftIsString->maybe() && $rightIsString->maybe()) {
@@ -1156,9 +1170,16 @@ public function getBitwiseXorTypeFromTypes(Type $leftType, Type $rightType): Typ
11561170
$rightType = $this->optimizeScalarType($rightType);
11571171
}
11581172

1173+
if ($leftType instanceof MixedType && $rightType instanceof MixedType) {
1174+
return new BenevolentUnionType([new IntegerType(), new StringType()]);
1175+
}
1176+
11591177
$leftIsString = $leftType->isString();
11601178
$rightIsString = $rightType->isString();
1161-
if ($leftIsString->yes() && $rightIsString->yes()) {
1179+
if (
1180+
($leftIsString->yes() || $leftType instanceof MixedType)
1181+
&& ($rightIsString->yes() || $rightType instanceof MixedType)
1182+
) {
11621183
return new StringType();
11631184
}
11641185
if ($leftIsString->maybe() && $rightIsString->maybe()) {

tests/PHPStan/Analyser/Generator/data/gnsr.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public function doBitwiseNot($a, int $b): void
110110
public function doBitwiseAnd($a, $b, int $c, int $d): void
111111
{
112112
assertType('int', $a & $b);
113-
assertNativeType('*ERROR*', $a & $b);
113+
assertNativeType('(int|string)', $a & $b);
114114
assertType('1', 1 & 1);
115115
assertNativeType('1', 1 & 1);
116116
assertType('int', $c & $d);
@@ -125,7 +125,7 @@ public function doBitwiseAnd($a, $b, int $c, int $d): void
125125
public function doBitwiseOr($a, $b, int $c, int $d): void
126126
{
127127
assertType('int', $a | $b);
128-
assertNativeType('*ERROR*', $a | $b);
128+
assertNativeType('(int|string)', $a | $b);
129129
assertType('1', 1 | 1);
130130
assertNativeType('1', 1 | 1);
131131
assertType('int', $c | $d);
@@ -140,7 +140,7 @@ public function doBitwiseOr($a, $b, int $c, int $d): void
140140
public function doBitwiseXor($a, $b, int $c, int $d): void
141141
{
142142
assertType('int', $a ^ $b);
143-
assertNativeType('*ERROR*', $a ^ $b);
143+
assertNativeType('(int|string)', $a ^ $b);
144144
assertType('0', 1 ^ 1);
145145
assertNativeType('0', 1 ^ 1);
146146
assertType('int', $c ^ $d);

tests/PHPStan/Analyser/nsrt/bitwise.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,30 @@ function test(int $int, string $string, $stringOrInt, $mixed) : void
1616
assertType('int', $int & $mixed);
1717
assertType('string', $string & $string);
1818
assertType('*ERROR*', $string & $stringOrInt);
19-
assertType('*ERROR*', $string & $mixed);
19+
assertType('string', $string & $mixed);
2020
assertType('*ERROR*', $stringOrInt & $stringOrInt);
2121
assertType('*ERROR*', $stringOrInt & $mixed);
22-
assertType('*ERROR*', $mixed & $mixed);
22+
assertType('(int|string)', $mixed & $mixed);
2323

2424
assertType('int', $int | $int);
2525
assertType('*ERROR*', $int | $string);
2626
assertType('*ERROR*', $int | $stringOrInt);
2727
assertType('int', $int | $mixed);
2828
assertType('string', $string | $string);
2929
assertType('*ERROR*', $string | $stringOrInt);
30-
assertType('*ERROR*', $string | $mixed);
30+
assertType('string', $string | $mixed);
3131
assertType('*ERROR*', $stringOrInt | $stringOrInt);
3232
assertType('*ERROR*', $stringOrInt | $mixed);
33-
assertType('*ERROR*', $mixed | $mixed);
33+
assertType('(int|string)', $mixed | $mixed);
3434

3535
assertType('int', $int ^ $int);
3636
assertType('*ERROR*', $int ^ $string);
3737
assertType('*ERROR*', $int ^ $stringOrInt);
3838
assertType('int', $int ^ $mixed);
3939
assertType('string', $string ^ $string);
4040
assertType('*ERROR*', $string ^ $stringOrInt);
41-
assertType('*ERROR*', $string ^ $mixed);
41+
assertType('string', $string ^ $mixed);
4242
assertType('*ERROR*', $stringOrInt ^ $stringOrInt);
4343
assertType('*ERROR*', $stringOrInt ^ $mixed);
44-
assertType('*ERROR*', $mixed ^ $mixed);
44+
assertType('(int|string)', $mixed ^ $mixed);
4545
}

0 commit comments

Comments
 (0)