Skip to content

Commit 2681e50

Browse files
phpstan-botstaabm
andauthored
Fix execution branch confusion
Co-authored-by: Markus Staab <markus.staab@redaxo.de>
1 parent 1dd0e56 commit 2681e50

File tree

3 files changed

+168
-4
lines changed

3 files changed

+168
-4
lines changed

src/Analyser/MutatingScope.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4141,17 +4141,21 @@ private function createConditionalExpressions(
41414141
continue;
41424142
}
41434143

4144-
$conditionalExpression = new ConditionalExpressionHolder($variableTypeGuards, $holder);
4145-
$conditionalExpressions[$exprString][$conditionalExpression->getKey()] = $conditionalExpression;
4144+
foreach ($variableTypeGuards as $guardExprString => $guardHolder) {
4145+
$conditionalExpression = new ConditionalExpressionHolder([$guardExprString => $guardHolder], $holder);
4146+
$conditionalExpressions[$exprString][$conditionalExpression->getKey()] = $conditionalExpression;
4147+
}
41464148
}
41474149

41484150
foreach ($mergedExpressionTypes as $exprString => $mergedExprTypeHolder) {
41494151
if (array_key_exists($exprString, $ourExpressionTypes)) {
41504152
continue;
41514153
}
41524154

4153-
$conditionalExpression = new ConditionalExpressionHolder($typeGuards, new ExpressionTypeHolder($mergedExprTypeHolder->getExpr(), new ErrorType(), TrinaryLogic::createNo()));
4154-
$conditionalExpressions[$exprString][$conditionalExpression->getKey()] = $conditionalExpression;
4155+
foreach ($typeGuards as $guardExprString => $guardHolder) {
4156+
$conditionalExpression = new ConditionalExpressionHolder([$guardExprString => $guardHolder], new ExpressionTypeHolder($mergedExprTypeHolder->getExpr(), new ErrorType(), TrinaryLogic::createNo()));
4157+
$conditionalExpressions[$exprString][$conditionalExpression->getKey()] = $conditionalExpression;
4158+
}
41554159
}
41564160

41574161
return $conditionalExpressions;
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug5051;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class HelloWorld
8+
{
9+
public function test(?object $data): void
10+
{
11+
if ($data === null) {
12+
$foo = 'bar';
13+
$update = false;
14+
} else {
15+
$foo = 'baz';
16+
$update = true;
17+
}
18+
19+
assertType('object|null', $data);
20+
assertType("'bar'|'baz'", $foo);
21+
22+
if ($update) {
23+
assertType('object', $data);
24+
assertType("'baz'", $foo);
25+
} else {
26+
assertType('null', $data);
27+
assertType("'bar'", $foo);
28+
}
29+
assertType('object|null', $data);
30+
assertType("'bar'|'baz'", $foo);
31+
}
32+
33+
/**
34+
* @param 1|2|3|10 $data
35+
*/
36+
public function testWithBooleans($data): void
37+
{
38+
$foo = 1;
39+
if ($data === 1 || $data === 2) {
40+
$update = false;
41+
$foo = false;
42+
} elseif ($data === 3) {
43+
$update = false;
44+
$foo = true;
45+
} else {
46+
$update = true;
47+
$foo = true;
48+
}
49+
50+
if ($update) {
51+
assertType('10', $data);
52+
assertType('bool', $foo);
53+
} else {
54+
assertType('1|2|3', $data);
55+
assertType('bool', $foo);
56+
}
57+
58+
if ($foo) {
59+
assertType('1|2|3|10', $data);
60+
assertType('bool', $update);
61+
} else {
62+
assertType('1|2|3|10', $data);
63+
assertType('bool', $update);
64+
}
65+
66+
if ($data === 1) {
67+
assertType('bool', $update);
68+
assertType('bool', $foo);
69+
} else {
70+
assertType('bool', $update);
71+
assertType('bool', $foo);
72+
}
73+
74+
if ($data === 2) {
75+
assertType('bool', $update);
76+
assertType('bool', $foo);
77+
} else {
78+
assertType('bool', $update);
79+
assertType('bool', $foo);
80+
}
81+
82+
if ($data === 3) {
83+
assertType('bool', $update);
84+
assertType('bool', $foo);
85+
} else {
86+
assertType('bool', $update);
87+
assertType('bool', $foo);
88+
}
89+
90+
if ($data === 1 || $data === 2) {
91+
assertType('bool', $update);
92+
assertType('bool', $foo);
93+
} else {
94+
assertType('bool', $update);
95+
assertType('bool', $foo);
96+
}
97+
98+
}
99+
100+
public function testWithDifferentVariableNames(?object $data): void
101+
{
102+
if ($data === null) {
103+
$update = false;
104+
$foo = 'bar';
105+
} else {
106+
$update = true;
107+
$fuu = 'baz';
108+
}
109+
110+
if ($update) {
111+
assertType('object', $data);
112+
}
113+
}
114+
115+
public function testWithoutExtraAssignment(?object $data): void
116+
{
117+
if ($data === null) {
118+
$update = false;
119+
} else {
120+
$update = true;
121+
}
122+
123+
if ($update) {
124+
assertType('object', $data);
125+
}
126+
}
127+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php // lint >= 8.0
2+
3+
namespace Bug5058;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class test{
8+
9+
private string $properString;
10+
11+
public function doSomething(mixed $string): void
12+
{
13+
14+
$errors = [];
15+
if(is_string($string) === false){
16+
$errors['string'] = 'fail';
17+
}
18+
19+
assertType('mixed', $string);
20+
if(empty($errors) === false){
21+
throw new Exception('Epic fail');
22+
}
23+
24+
assertType('string', $string);
25+
$this->properString = $string;
26+
}
27+
28+
public function getProperString(): string
29+
{
30+
return $this->properString;
31+
}
32+
33+
}

0 commit comments

Comments
 (0)