Skip to content

Commit b15face

Browse files
committed
Merge remote-tracking branch 'origin/2.1.x' into 2.2.x
2 parents 4baf3c6 + a25e509 commit b15face

File tree

213 files changed

+1225
-1056
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

213 files changed

+1225
-1056
lines changed

phpstan-baseline.neon

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ parameters:
6666
count: 2
6767
path: src/Analyser/MutatingScope.php
6868

69+
-
70+
rawMessage: Doing instanceof PHPStan\Type\IntersectionType is error-prone and deprecated.
71+
identifier: phpstanApi.instanceofType
72+
count: 1
73+
path: src/Analyser/MutatingScope.php
74+
6975
-
7076
rawMessage: 'Parameter #2 $node of method PHPStan\BetterReflection\SourceLocator\Ast\Strategy\NodeToReflection::__invoke() expects PhpParser\Node\Expr\ArrowFunction|PhpParser\Node\Expr\Closure|PhpParser\Node\Expr\FuncCall|PhpParser\Node\Stmt\Class_|PhpParser\Node\Stmt\Const_|PhpParser\Node\Stmt\Enum_|PhpParser\Node\Stmt\Function_|PhpParser\Node\Stmt\Interface_|PhpParser\Node\Stmt\Trait_, PhpParser\Node\Stmt\ClassLike given.'
7177
identifier: argument.type

src/Analyser/MutatingScope.php

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ class MutatingScope implements Scope, NodeCallbackInvoker, CollectedDataEmitter
141141
public const KEEP_VOID_ATTRIBUTE_NAME = 'keepVoid';
142142
private const CONTAINS_SUPER_GLOBAL_ATTRIBUTE_NAME = 'containsSuperGlobal';
143143

144+
private const COMPLEX_UNION_TYPE_MEMBER_LIMIT = 8;
145+
144146
/** @var Type[] */
145147
private array $resolvedTypes = [];
146148

@@ -2745,10 +2747,12 @@ public function specifyExpressionType(Expr $expr, Type $type, Type $nativeType,
27452747
}
27462748

27472749
if ($dimType instanceof ConstantIntegerType || $dimType instanceof ConstantStringType) {
2748-
$varType = TypeCombinator::intersect(
2749-
$varType,
2750-
new HasOffsetValueType($dimType, $type),
2751-
);
2750+
if (!$this->isComplexUnionType($varType)) {
2751+
$varType = TypeCombinator::intersect(
2752+
$varType,
2753+
new HasOffsetValueType($dimType, $type),
2754+
);
2755+
}
27522756
}
27532757

27542758
$scope = $scope->specifyExpressionType(
@@ -3073,9 +3077,36 @@ private function setExpressionCertainty(Expr $expr, TrinaryLogic $certainty): se
30733077
);
30743078
}
30753079

3080+
/**
3081+
* Returns true when the type is a large union with non-trivial
3082+
* (IntersectionType) members — a sign of HasOffsetValueType
3083+
* combinatorial growth from array|object offset access patterns.
3084+
* Operating on such types is expensive and should be skipped.
3085+
*/
3086+
private function isComplexUnionType(Type $type): bool
3087+
{
3088+
if (!$type instanceof UnionType) {
3089+
return false;
3090+
}
3091+
$types = $type->getTypes();
3092+
if (count($types) <= self::COMPLEX_UNION_TYPE_MEMBER_LIMIT) {
3093+
return false;
3094+
}
3095+
foreach ($types as $member) {
3096+
if ($member instanceof IntersectionType) {
3097+
return true;
3098+
}
3099+
}
3100+
return false;
3101+
}
3102+
30763103
public function addTypeToExpression(Expr $expr, Type $type): self
30773104
{
30783105
$originalExprType = $this->getType($expr);
3106+
if ($this->isComplexUnionType($originalExprType)) {
3107+
return $this;
3108+
}
3109+
30793110
$nativeType = $this->getNativeType($expr);
30803111

30813112
if ($originalExprType->equals($nativeType)) {
@@ -3102,6 +3133,10 @@ public function removeTypeFromExpression(Expr $expr, Type $typeToRemove): self
31023133
return $this;
31033134
}
31043135

3136+
if ($this->isComplexUnionType($exprType)) {
3137+
return $this;
3138+
}
3139+
31053140
return $this->specifyExpressionType(
31063141
$expr,
31073142
TypeCombinator::remove($exprType, $typeToRemove),

0 commit comments

Comments
 (0)