Skip to content

Commit e54efe3

Browse files
[TypeDeclaration] Speed up BinaryOpNullableToInstanceofRector by skipping bool-shaped operands (#8607)
Co-authored-by: GitHub Action <actions@github.com>
1 parent e69554c commit e54efe3

4 files changed

Lines changed: 29 additions & 9 deletions

File tree

‎rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,7 @@ public function getNodeTypes(): array
6969
public function refactor(Node $node): ?Node
7070
{
7171
// skip if has no private property
72-
$hasAnyPrivateProperty = array_any($node->getProperties(), function (Property $property): bool {
73-
return $property->isPrivate();
74-
});
72+
$hasAnyPrivateProperty = array_any($node->getProperties(), fn(Property $property): bool => $property->isPrivate());
7573

7674
if (! $hasAnyPrivateProperty) {
7775
return null;

‎rules/TypeDeclaration/Rector/BooleanAnd/BinaryOpNullableToInstanceofRector.php‎

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
use PhpParser\Node;
88
use PhpParser\Node\Expr;
99
use PhpParser\Node\Expr\Assign;
10+
use PhpParser\Node\Expr\BinaryOp;
1011
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
1112
use PhpParser\Node\Expr\BinaryOp\BooleanOr;
1213
use PhpParser\Node\Expr\BooleanNot;
14+
use PhpParser\Node\Expr\Empty_;
1315
use PhpParser\Node\Expr\Instanceof_;
16+
use PhpParser\Node\Expr\Isset_;
1417
use PhpParser\Node\Name\FullyQualified;
1518
use PHPStan\Type\ObjectType;
1619
use Rector\Rector\AbstractRector;
@@ -89,7 +92,7 @@ public function refactor(Node $node): ?Node
8992
*/
9093
private function processNullableInstance(BooleanAnd|BooleanOr $node): null|BooleanAnd|BooleanOr
9194
{
92-
$nullableObjectType = $this->nullableTypeAnalyzer->resolveNullableObjectType($node->left);
95+
$nullableObjectType = $this->resolveNullableObjectType($node->left);
9396

9497
$hasChanged = false;
9598
if ($nullableObjectType instanceof ObjectType) {
@@ -98,7 +101,7 @@ private function processNullableInstance(BooleanAnd|BooleanOr $node): null|Boole
98101
$hasChanged = true;
99102
}
100103

101-
$nullableObjectType = $this->nullableTypeAnalyzer->resolveNullableObjectType($node->right);
104+
$nullableObjectType = $this->resolveNullableObjectType($node->right);
102105

103106
if ($nullableObjectType instanceof ObjectType) {
104107
$node->right = $this->createExprInstanceof($node->right, $nullableObjectType);
@@ -117,7 +120,7 @@ private function processNegationBooleanOr(BooleanOr $booleanOr): ?BooleanOr
117120
{
118121
$hasChanged = false;
119122
if ($booleanOr->left instanceof BooleanNot) {
120-
$nullableObjectType = $this->nullableTypeAnalyzer->resolveNullableObjectType($booleanOr->left->expr);
123+
$nullableObjectType = $this->resolveNullableObjectType($booleanOr->left->expr);
121124

122125
if ($nullableObjectType instanceof ObjectType) {
123126
$booleanOr->left->expr = $this->createExprInstanceof($booleanOr->left->expr, $nullableObjectType);
@@ -126,7 +129,7 @@ private function processNegationBooleanOr(BooleanOr $booleanOr): ?BooleanOr
126129
}
127130

128131
if ($booleanOr->right instanceof BooleanNot) {
129-
$nullableObjectType = $this->nullableTypeAnalyzer->resolveNullableObjectType($booleanOr->right->expr);
132+
$nullableObjectType = $this->resolveNullableObjectType($booleanOr->right->expr);
130133

131134
if ($nullableObjectType instanceof ObjectType) {
132135
$booleanOr->right->expr = $this->createExprInstanceof($booleanOr->right->expr, $nullableObjectType);
@@ -142,6 +145,26 @@ private function processNegationBooleanOr(BooleanOr $booleanOr): ?BooleanOr
142145
return $this->processNullableInstance($booleanOr);
143146
}
144147

148+
private function resolveNullableObjectType(Expr $expr): ?ObjectType
149+
{
150+
// cheap bail - bool/scalar-shaped operands can never be a nullable object,
151+
// skip the costly native type resolution for them (e.g. chained "$a && $b && $c")
152+
if ($this->isNeverNullableObject($expr)) {
153+
return null;
154+
}
155+
156+
return $this->nullableTypeAnalyzer->resolveNullableObjectType($expr);
157+
}
158+
159+
private function isNeverNullableObject(Expr $expr): bool
160+
{
161+
return $expr instanceof BinaryOp
162+
|| $expr instanceof BooleanNot
163+
|| $expr instanceof Instanceof_
164+
|| $expr instanceof Empty_
165+
|| $expr instanceof Isset_;
166+
}
167+
145168
private function createExprInstanceof(Expr $expr, ObjectType $objectType): Instanceof_
146169
{
147170
$fullyQualified = new FullyQualified($objectType->getClassName());

‎src/Configuration/Option.php‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ final class Option
187187
/**
188188
* @experimental Opt-in to the LPT bucket scheduler
189189
* @see \Rector\Parallel\Experimental\LptScheduleFactory
190-
* @var string
191190
*/
192191
public const string LPT = 'lpt';
193192

‎src/Parallel/Experimental/ExperimentalParallelFileProcessor.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public function process(
6767
): ProcessResult {
6868
// reversed, so that array_pop() hands out the biggest files first
6969
$jobsPerWorker = array_map(
70-
static fn (array $jobs): array => array_reverse($jobs),
70+
array_reverse(...),
7171
$bucketSchedule->getJobsPerWorker()
7272
);
7373

0 commit comments

Comments
 (0)