Skip to content

Commit 378f49c

Browse files
authored
Fix phpstan/phpstan#14452: Performance degradation introduced in 2.1.41 (#5441)
1 parent b12745b commit 378f49c

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

src/Analyser/MutatingScope.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,6 +3562,9 @@ private function createConditionalExpressions(
35623562

35633563
$typeGuards = [];
35643564
foreach ($newVariableTypes as $exprString => $holder) {
3565+
if ($holder->getExpr() instanceof VirtualNode) {
3566+
continue;
3567+
}
35653568
if (!array_key_exists($exprString, $mergedExpressionTypes)) {
35663569
continue;
35673570
}
@@ -3588,6 +3591,9 @@ private function createConditionalExpressions(
35883591
}
35893592

35903593
foreach ($newVariableTypes as $exprString => $holder) {
3594+
if ($holder->getExpr() instanceof VirtualNode) {
3595+
continue;
3596+
}
35913597
if (
35923598
array_key_exists($exprString, $mergedExpressionTypes)
35933599
&& $mergedExpressionTypes[$exprString]->equals($holder)

tests/bench/data/bug-14452.php

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug14452;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class MyBag
8+
{
9+
10+
public function getInt(string $key): int
11+
{
12+
return 0;
13+
}
14+
15+
public function has(string $key): bool
16+
{
17+
return false;
18+
}
19+
20+
/** @return bool|float|int|string|null */
21+
public function get(string $key)
22+
{
23+
return null;
24+
}
25+
26+
}
27+
28+
class Shared
29+
{
30+
31+
public static function calculateThings(
32+
?int $type,
33+
float $hours,
34+
float $minutes,
35+
float $seconds,
36+
?float $hourlyRate,
37+
?float $flatFee,
38+
?float $minimumCost,
39+
): float
40+
{
41+
return 0.0;
42+
}
43+
44+
}
45+
46+
/**
47+
* Performance test: many possibly-impure method calls inside conditional branches
48+
* should not cause exponential blowup in conditional expression creation.
49+
*/
50+
function test(MyBag $input): void
51+
{
52+
$prestatie = rand(0, 1) === 0;
53+
54+
$seconds = null;
55+
$minimum_seconds = null;
56+
$seconds_worked = null;
57+
$minutes = null;
58+
$minimum_minutes = null;
59+
$minutes_worked = null;
60+
$hours = null;
61+
62+
$minimum_hours = null;
63+
$hours_worked = null;
64+
$hourly_rate = null;
65+
66+
$flat_fee = round($input->getInt('flat_fee'), 2);
67+
$minimum_cost = round($input->getInt('minimum_cost'), 2);
68+
69+
if ($prestatie) {
70+
$seconds = $seconds_worked = $input->getInt('seconds_worked');
71+
$minutes = $minutes_worked = $input->getInt('minutes_worked');
72+
$hours = $hours_worked = $input->getInt('hours_worked');
73+
74+
$minimum_seconds = $input->getInt('minimum_seconds');
75+
$minimum_minutes = $input->getInt('minimum_minutes');
76+
$minimum_hours = $input->getInt('minimum_hours');
77+
78+
if ($input->has('different_billing_time')) {
79+
$different_billing_time = 1;
80+
$seconds = $input->getInt('seconds');
81+
$minutes = $input->getInt('minutes');
82+
$hours = $input->getInt('hours');
83+
}
84+
85+
$hourly_rate = round($input->getInt('hourly_rate'), 2);
86+
87+
$subtotal = Shared::calculateThings(
88+
$input->get('prestation_type'),
89+
$hours,
90+
$minutes,
91+
$seconds,
92+
$hourly_rate,
93+
$flat_fee,
94+
$minimum_cost,
95+
);
96+
}
97+
98+
$subtype = $prestatie ? $input->getInt('prestation_type') : $input->getInt('cost_type');
99+
assertType('int', $subtype);
100+
assertType('float', $flat_fee);
101+
assertType('float', $minimum_cost);
102+
}

0 commit comments

Comments
 (0)