Skip to content

Commit 2177d57

Browse files
committed
Review fixes
1 parent d3e3088 commit 2177d57

File tree

10 files changed

+126
-45
lines changed

10 files changed

+126
-45
lines changed

src/Reflection/InitializerExprTypeResolver.php

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,18 +1324,6 @@ public function resolveIdenticalType(Type $leftType, Type $rightType): BooleanTy
13241324

13251325
public function resolveEqualType(Type $leftType, Type $rightType): BooleanType
13261326
{
1327-
$integerType = new IntegerType();
1328-
$floatType = new FloatType();
1329-
1330-
if (
1331-
(count($leftType->getEnumCases()) === 1 && count($rightType->getEnumCases()) === 1)
1332-
|| ($leftType->isString()->yes() && $rightType->isString()->yes())
1333-
|| ($integerType->isSuperTypeOf($leftType)->yes() && $integerType->isSuperTypeOf($rightType)->yes())
1334-
|| ($floatType->isSuperTypeOf($leftType)->yes() && $floatType->isSuperTypeOf($rightType)->yes())
1335-
) {
1336-
return $this->resolveIdenticalType($leftType, $rightType);
1337-
}
1338-
13391327
if ($leftType instanceof ConstantArrayType && $rightType instanceof ConstantArrayType) {
13401328
return $this->resolveConstantArrayTypeComparison($leftType, $rightType, fn ($leftValueType, $rightValueType): BooleanType => $this->resolveEqualType($leftValueType, $rightValueType));
13411329
}

src/Type/Accessory/AccessoryNonEmptyStringType.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,11 @@ public function isScalar(): TrinaryLogic
275275

276276
public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
277277
{
278-
$looseFalse = new NullType();
278+
$looseFalse = new UnionType([
279+
new NullType(),
280+
new ConstantStringType(''),
281+
new ConstantBooleanType(false),
282+
]);
279283

280284
if ($looseFalse->isSuperTypeOf($type)->yes()) {
281285
return new ConstantBooleanType(false);

src/Type/Accessory/NonEmptyArrayType.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,14 @@ public function isScalar(): TrinaryLogic
355355

356356
public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
357357
{
358+
if ($type->isTrue()->yes()) {
359+
return new ConstantBooleanType(true);
360+
}
361+
362+
if ($type->isFalse()->yes()) {
363+
return new ConstantBooleanType(false);
364+
}
365+
358366
if ($type->isArray()->yes() && $type->isIterableAtLeastOnce()->no()) {
359367
return new ConstantBooleanType(false);
360368
}

src/Type/ArrayType.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -358,15 +358,8 @@ public function isScalar(): TrinaryLogic
358358

359359
public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
360360
{
361-
$looseTrue = new ConstantBooleanType(true);
362-
363-
if ($looseTrue->isSuperTypeOf($type)->yes()) {
364-
return new ConstantBooleanType(true);
365-
}
366-
367361
$looseFalse = new UnionType([
368362
new ObjectWithoutClassType(),
369-
new ConstantBooleanType(false),
370363
new StringType(),
371364
new NullType(),
372365
new IntegerType(),

src/Type/BooleanType.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,6 @@ public function isScalar(): TrinaryLogic
121121

122122
public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
123123
{
124-
if ($type->isObject()->yes()) {
125-
return new ConstantBooleanType(true);
126-
}
127-
128124
return new BooleanType();
129125
}
130126

src/Type/CallableType.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,7 @@ public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
448448
]);
449449

450450
if ($looseFalse->isSuperTypeOf($type)->yes()
451-
|| $type->isConstantArray()->yes() && $type->isIterableAtLeastOnce()->no()
452-
|| $type->isNumericString()->yes()
451+
|| ($type->isArray()->yes() && $type->isIterableAtLeastOnce()->no())
453452
) {
454453
return new ConstantBooleanType(false);
455454
}

src/Type/ObjectType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,7 @@ public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
10291029
return new ConstantBooleanType(false);
10301030
}
10311031

1032-
if ($type->isConstantArray()->yes() && $type->isIterableAtLeastOnce()->no()) {
1032+
if ($type->isArray()->yes() && $type->isIterableAtLeastOnce()->no()) {
10331033
return new ConstantBooleanType(false);
10341034
}
10351035

src/Type/Traits/ConstantScalarTypeTrait.php

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
use PHPStan\Type\ConstantScalarType;
1313
use PHPStan\Type\LooseComparisonHelper;
1414
use PHPStan\Type\Type;
15+
use PHPStan\Type\TypeCombinator;
16+
use PHPStan\Type\TypeUtils;
17+
use function count;
1518

1619
trait ConstantScalarTypeTrait
1720
{
@@ -61,14 +64,37 @@ public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
6164
return LooseComparisonHelper::compareConstantScalars($this, $type, $phpVersion);
6265
}
6366

67+
$constantScalars = TypeUtils::getConstantScalars($type);
68+
if (count($constantScalars) > 0) {
69+
$results = [];
70+
foreach ($constantScalars as $scalarType) {
71+
$results[] = $this->looseCompare($scalarType, $phpVersion);
72+
}
73+
74+
return TypeCombinator::union(...$results);
75+
}
76+
6477
if ($type->isObject()->yes()) {
6578
return $type->looseCompare($this, $phpVersion);
6679
}
6780

68-
if ($type->isConstantArray()->yes() && $type->isIterableAtLeastOnce()->no()) {
81+
if ($type->isArray()->yes() && $type->isIterableAtLeastOnce()->no()) {
6982
// @phpstan-ignore-next-line
7083
return new ConstantBooleanType($this->getValue() == []); // phpcs:ignore
7184
}
85+
if ($type->isArray()->yes() && $type->isIterableAtLeastOnce()->yes()) {
86+
// @phpstan-ignore-next-line
87+
return new ConstantBooleanType($this->getValue() != []); // phpcs:ignore
88+
}
89+
90+
if ($type->isString()->yes() && $type->isNonEmptyString()->no()) {
91+
// @phpstan-ignore-next-line
92+
return new ConstantBooleanType($this->getValue() == ''); // phpcs:ignore
93+
}
94+
if ($type->isNonEmptyString()->yes()) {
95+
// @phpstan-ignore-next-line
96+
return new ConstantBooleanType($this->getValue() != ''); // phpcs:ignore
97+
}
7298

7399
return parent::looseCompare($type, $phpVersion);
74100
}

src/Type/Traits/ObjectTypeTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
219219
return new ConstantBooleanType(false);
220220
}
221221

222-
if ($type->isConstantArray()->yes() && $type->isIterableAtLeastOnce()->no()) {
222+
if ($type->isArray()->yes() && $type->isIterableAtLeastOnce()->no()) {
223223
return new ConstantBooleanType(false);
224224
}
225225

tests/PHPStan/Analyser/data/loose-comparisons.php

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
class HelloWorld
1111
{
1212
/**
13+
* @param non-empty-string $nonEmptyString
14+
* @param non-empty-array $nonEmptyArray
1315
* @param true $true
1416
* @param false $false
1517
* @param 1 $one
@@ -22,8 +24,14 @@ class HelloWorld
2224
* @param array{} $emptyArr
2325
* @param 'php' $phpStr
2426
* @param '' $emptyStr
27+
* @param 'a'|'123'|'123.23' $unionMaybeNumeric
28+
* @param 1|2|3 $unionNumbers
29+
* @param 'a'|'b'|'c' $unionStrings
30+
* @param 'a'|'123'|123|array $unionMaybeArray
2531
*/
2632
public function sayTrue(
33+
$nonEmptyString,
34+
$nonEmptyArray,
2735
$true,
2836
$false,
2937
$one,
@@ -35,9 +43,21 @@ public function sayTrue(
3543
$null,
3644
$emptyArr,
3745
$phpStr,
38-
$emptyStr
46+
$emptyStr,
47+
array $arr,
48+
int $int,
49+
float $float,
50+
bool $bool,
51+
string $string,
52+
object $obj,
53+
$unionMaybeNumeric,
54+
$unionNumbers,
55+
$unionStrings,
56+
$unionMaybeArray
3957
): void
4058
{
59+
assertType('true', $true == $nonEmptyString);
60+
assertType('true', $true == $nonEmptyArray);
4161
assertType('true', $true == $true);
4262
assertType('false', $true == $false);
4363
assertType('true', $true == $one);
@@ -50,9 +70,22 @@ public function sayTrue(
5070
assertType('false', $true == $emptyArr);
5171
assertType('true', $true == $phpStr);
5272
assertType('false', $true == $emptyStr);
73+
assertType('bool', $true == $arr);
74+
assertType('bool', $true == $int);
75+
assertType('bool', $true == $float);
76+
assertType('bool', $true == $bool);
77+
assertType('bool', $true == $string);
78+
assertType('true', $true == $obj);
79+
assertType('true', $true == new \stdClass());
80+
assertType('true', $true == $unionMaybeNumeric);
81+
assertType('true', $true == $unionNumbers);
82+
assertType('true', $true == $unionStrings);
83+
assertType('bool', $true == $unionMaybeArray);
5384
}
5485

5586
/**
87+
* @param non-empty-string $nonEmptyString
88+
* @param non-empty-array $nonEmptyArray
5689
* @param true $true
5790
* @param false $false
5891
* @param 1 $one
@@ -65,8 +98,16 @@ public function sayTrue(
6598
* @param array{} $emptyArr
6699
* @param 'php' $phpStr
67100
* @param '' $emptyStr
101+
* @param array $arr
102+
* @param 'a'|'123'|'123.23' $unionMaybeNumeric
103+
* @param 1|2|3 $unionNumbers
104+
* @param 'a'|'b'|'c' $unionStrings
105+
* @param 'a'|'123'|123|array $unionMaybeArray
68106
*/
69107
public function sayFalse(
108+
$nonEmptyString,
109+
$nonEmptyArray,
110+
$callable,
70111
$true,
71112
$false,
72113
$one,
@@ -78,9 +119,21 @@ public function sayFalse(
78119
$null,
79120
$emptyArr,
80121
$phpStr,
81-
$emptyStr
122+
$emptyStr,
123+
array $arr,
124+
int $int,
125+
float $float,
126+
bool $bool,
127+
string $string,
128+
object $obj,
129+
$unionMaybeNumeric,
130+
$unionNumbers,
131+
$unionStrings,
132+
$unionMaybeArray
82133
): void
83134
{
135+
assertType('false', $false == $nonEmptyString);
136+
assertType('false', $false == $nonEmptyArray);
84137
assertType('false', $false == $true);
85138
assertType('true', $false == $false);
86139
assertType('false', $false == $one);
@@ -93,6 +146,17 @@ public function sayFalse(
93146
assertType('true', $false == $emptyArr);
94147
assertType('false', $false == $phpStr);
95148
assertType('true', $false == $emptyStr);
149+
assertType('bool', $false == $arr);
150+
assertType('bool', $false == $int);
151+
assertType('bool', $false == $float);
152+
assertType('bool', $false == $bool);
153+
assertType('bool', $false == $string);
154+
assertType('false', $false == $obj);
155+
assertType('false', $false == new \stdClass());
156+
assertType('false', $false == $unionMaybeNumeric);
157+
assertType('false', $false == $unionNumbers);
158+
assertType('false', $false == $unionStrings);
159+
assertType('bool', $false == $unionMaybeArray);
96160
}
97161

98162
/**
@@ -798,8 +862,8 @@ public function looseBool(
798862
assertType('bool', $bool == $float);
799863
assertType('true', $bool == $bool);
800864
assertType('bool', $bool == $string);
801-
assertType('true', $bool == $obj);
802-
assertType('true', $bool == new \stdClass());
865+
assertType('bool', $bool == $obj);
866+
assertType('bool', $bool == new \stdClass());
803867
}
804868

805869
/**
@@ -1054,8 +1118,8 @@ public function looseArray(
10541118
$unionStrings,
10551119
$unionMaybeArray
10561120
) {
1057-
assertType('true', $arr == $true);
1058-
assertType('false', $arr == $false);
1121+
assertType('bool', $arr == $true);
1122+
assertType('bool', $arr == $false);
10591123
assertType('false', $arr == $one);
10601124
assertType('false', $arr == $zero);
10611125
assertType('false', $arr == 10);
@@ -1129,15 +1193,16 @@ public function looseCallable(
11291193
$unionStrings,
11301194
$unionMaybeArray
11311195
) {
1196+
assertType('bool', $callable == 'myFunction');
11321197
assertType('true', $callable == $true);
11331198
assertType('false', $callable == $false);
11341199
assertType('true', $callable == $one);
11351200
assertType('false', $callable == $zero);
11361201
assertType('false', $callable == 10);
11371202
assertType('false', $callable == $minusOne);
1138-
assertType('false', $callable == $oneStr);
1139-
assertType('false', $callable == $zeroStr);
1140-
assertType('false', $callable == $minusOneStr);
1203+
assertType('bool', $callable == $oneStr); // could be false, because invalid function name
1204+
assertType('bool', $callable == $zeroStr); // could be false, because invalid function name
1205+
assertType('bool', $callable == $minusOneStr); // could be false, because invalid function name
11411206
assertType('false', $callable == $null);
11421207
assertType('false', $callable == $emptyArr);
11431208
assertType('bool', $callable == $phpStr);
@@ -1225,7 +1290,7 @@ public function looseUnion(
12251290
assertType('bool', $unionMaybeNumeric == $string);
12261291
assertType('false', $unionMaybeNumeric == $obj);
12271292
assertType('false', $unionMaybeNumeric == new \stdClass());
1228-
assertType('bool', $unionMaybeNumeric == $unionNumbers);
1293+
assertType('false', $unionMaybeNumeric == $unionNumbers);
12291294
assertType('bool', $unionMaybeNumeric == $unionStrings);
12301295
assertType('bool', $unionMaybeNumeric == $unionMaybeArray);
12311296

@@ -1250,7 +1315,7 @@ public function looseUnion(
12501315
assertType('bool', $unionNumbers == $string);
12511316
assertType('bool', $unionNumbers == $obj);
12521317
assertType('bool', $unionNumbers == new \stdClass());
1253-
assertType('bool', $unionNumbers == $unionMaybeNumeric);
1318+
assertType('false', $unionNumbers == $unionMaybeNumeric);
12541319
assertType('false', $unionNumbers == $unionStrings);
12551320
assertType('bool', $unionNumbers == $unionMaybeArray);
12561321

@@ -1276,11 +1341,11 @@ public function looseUnion(
12761341
assertType('false', $unionStrings == $obj);
12771342
assertType('false', $unionStrings == new \stdClass());
12781343
assertType('bool', $unionStrings == $unionMaybeNumeric);
1279-
assertType('bool', $unionStrings == $unionNumbers);
1344+
assertType('false', $unionStrings == $unionNumbers);
12801345
assertType('bool', $unionStrings == $unionMaybeArray);
12811346

1282-
assertType('true', $unionMaybeArray == $true);
1283-
assertType('false', $unionMaybeArray == $false);
1347+
assertType('bool', $unionMaybeArray == $true);
1348+
assertType('bool', $unionMaybeArray == $false);
12841349
assertType('false', $unionMaybeArray == $one);
12851350
assertType('false', $unionMaybeArray == $zero);
12861351
assertType('false', $unionMaybeArray == 10);
@@ -1302,7 +1367,7 @@ public function looseUnion(
13021367
assertType('false', $unionMaybeArray == $obj);
13031368
assertType('false', $unionMaybeArray == new \stdClass());
13041369
assertType('bool', $unionMaybeArray == $unionMaybeNumeric);
1305-
assertType('bool', $unionMaybeArray == $unionNumbers);
1370+
assertType('false', $unionMaybeArray == $unionNumbers);
13061371
assertType('bool', $unionMaybeArray == $unionStrings);
13071372
}
13081373

@@ -1357,7 +1422,7 @@ public function looseIntersection(
13571422
$unionMaybeArray
13581423
) {
13591424
assertType('bool', $nonEmptyString == $true);
1360-
assertType('bool', $nonEmptyString == $false);
1425+
assertType('false', $nonEmptyString == $false);
13611426
assertType('bool', $nonEmptyString == $one);
13621427
assertType('bool', $nonEmptyString == $zero);
13631428
assertType('bool', $nonEmptyString == 10);
@@ -1411,3 +1476,5 @@ public function looseIntersection(
14111476
assertType('bool', $nonEmptyArray == $unionMaybeArray);
14121477
}
14131478
}
1479+
1480+
function myFunction() {}

0 commit comments

Comments
 (0)