Skip to content

Commit 05ce763

Browse files
staabmondrejmirtes
andauthored
Fix false positive when type casting in If_ statement
Co-authored-by: Ondrej Mirtes <ondrej@mirtes.cz>
1 parent a4980e1 commit 05ce763

File tree

4 files changed

+92
-14
lines changed

4 files changed

+92
-14
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,15 +197,31 @@ public function specifyTypesInCondition(
197197
$context,
198198
$rootExpr,
199199
);
200-
} elseif (
201-
$expr instanceof Expr\Cast\String_
202-
|| $expr instanceof Expr\Cast\Double
203-
|| $expr instanceof Expr\Cast\Int_
204-
|| $expr instanceof Expr\Cast\Bool_
205-
) {
200+
} elseif ($expr instanceof Expr\Cast\Bool_) {
201+
return $this->specifyTypesInCondition(
202+
$scope,
203+
new Node\Expr\BinaryOp\Equal($expr->expr, new ConstFetch(new Name\FullyQualified('true'))),
204+
$context,
205+
$rootExpr,
206+
);
207+
} elseif ($expr instanceof Expr\Cast\String_) {
208+
return $this->specifyTypesInCondition(
209+
$scope,
210+
new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\String_('')),
211+
$context,
212+
$rootExpr,
213+
);
214+
} elseif ($expr instanceof Expr\Cast\Int_) {
215+
return $this->specifyTypesInCondition(
216+
$scope,
217+
new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\LNumber(0)),
218+
$context,
219+
$rootExpr,
220+
);
221+
} elseif ($expr instanceof Expr\Cast\Double) {
206222
return $this->specifyTypesInCondition(
207223
$scope,
208-
new Node\Expr\BinaryOp\NotEqual($expr->expr, new ConstFetch(new Name\FullyQualified('false'))),
224+
new Node\Expr\BinaryOp\NotEqual($expr->expr, new Node\Scalar\DNumber(0.0)),
209225
$context,
210226
$rootExpr,
211227
);

tests/PHPStan/Analyser/nsrt/narrow-cast.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ function doFoo(string $x, array $arr): void {
3131
/** @param int<-5, 5> $x */
3232
function castString($x, string $s, bool $b) {
3333
if ((string) $x) {
34-
assertType('int<-5, -1>|int<1, 5>', $x);
34+
assertType('int<-5, 5>', $x);
3535
} else {
36-
assertType('0', $x);
36+
assertType('int<-5, 5>', $x);
3737
}
3838

3939
if ((string) $b) {
@@ -63,8 +63,14 @@ function castInt($x, string $s, bool $b) {
6363
assertType('false', $b);
6464
}
6565

66+
if ((int) $s) {
67+
assertType('string', $s);
68+
} else {
69+
assertType('string', $s);
70+
}
71+
6672
if ((int) strpos($s, 'xy')) {
67-
assertType('non-falsy-string', $s);
73+
assertType('string', $s);
6874
} else {
6975
assertType('string', $s);
7076
}
@@ -73,9 +79,9 @@ function castInt($x, string $s, bool $b) {
7379
/** @param int<-5, 5> $x */
7480
function castFloat($x, string $s, bool $b) {
7581
if ((float) $x) {
76-
assertType('int<-5, -1>|int<1, 5>', $x);
82+
assertType('int<-5, 5>', $x);
7783
} else {
78-
assertType('0', $x);
84+
assertType('int<-5, 5>', $x);
7985
}
8086

8187
if ((float) $b) {
@@ -85,8 +91,8 @@ function castFloat($x, string $s, bool $b) {
8591
}
8692

8793
if ((float) $s) {
88-
assertType('non-falsy-string', $s);
94+
assertType('string', $s);
8995
} else {
90-
assertType("''|'0'", $s);
96+
assertType("string", $s);
9197
}
9298
}

tests/PHPStan/Rules/Comparison/ElseIfConstantConditionRuleTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PHPStan\Rules\Rule;
66
use PHPStan\Testing\RuleTestCase;
7+
use const PHP_VERSION_ID;
78

89
/**
910
* @extends RuleTestCase<ElseIfConstantConditionRule>
@@ -121,4 +122,19 @@ public function testReportPhpDoc(): void
121122
]);
122123
}
123124

125+
public function testBug11674(): void
126+
{
127+
if (PHP_VERSION_ID < 80000) {
128+
$this->markTestSkipped('Test requires PHP 8.0');
129+
}
130+
131+
$this->treatPhpDocTypesAsCertain = true;
132+
$this->analyse([__DIR__ . '/data/bug-11674.php'], [
133+
[
134+
'Elseif condition is always false.',
135+
28,
136+
],
137+
]);
138+
}
139+
124140
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php declare(strict_types = 1); // lint >= 8.0
2+
3+
namespace Bug11674;
4+
5+
class Test {
6+
7+
private ?string $param;
8+
9+
function show() : void {
10+
if ((int) $this->param) {
11+
echo 1;
12+
} elseif ($this->param) {
13+
echo 2;
14+
}
15+
}
16+
17+
function show2() : void {
18+
if ((float) $this->param) {
19+
echo 1;
20+
} elseif ($this->param) {
21+
echo 2;
22+
}
23+
}
24+
25+
function show3() : void {
26+
if ((bool) $this->param) {
27+
echo 1;
28+
} elseif ($this->param) {
29+
echo 2;
30+
}
31+
}
32+
33+
function show4() : void {
34+
if ((string) $this->param) {
35+
echo 1;
36+
} elseif ($this->param) {
37+
echo 2;
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)