Skip to content

Commit 04b8403

Browse files
authored
Consider a ClosureType() as maybe impure by default when no impurePoints array provided
1 parent 7af14fb commit 04b8403

File tree

4 files changed

+23
-9
lines changed

4 files changed

+23
-9
lines changed

src/PhpDoc/TypeNodeResolver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ private function resolveIdentifierTypeNode(IdentifierTypeNode $typeNode, NameSco
360360
return new CallableType(null, null, true, null, null, [], TrinaryLogic::createYes());
361361

362362
case 'pure-closure':
363-
return new ClosureType();
363+
return ClosureType::createPure();
364364

365365
case 'resource':
366366
$type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope);

src/Type/ClosureType.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,15 @@ class ClosureType implements TypeWithClassName, CallableParametersAcceptor
7575

7676
private TemplateTypeVarianceMap $callSiteVarianceMap;
7777

78+
/** @var SimpleImpurePoint[] */
79+
private array $impurePoints;
80+
7881
/**
7982
* @api
8083
* @param array<int, ParameterReflection>|null $parameters
8184
* @param array<non-empty-string, TemplateTag> $templateTags
8285
* @param SimpleThrowPoint[] $throwPoints
83-
* @param SimpleImpurePoint[] $impurePoints
86+
* @param ?SimpleImpurePoint[] $impurePoints
8487
* @param InvalidateExprNode[] $invalidateExpressions
8588
* @param string[] $usedVariables
8689
*/
@@ -93,7 +96,7 @@ public function __construct(
9396
?TemplateTypeVarianceMap $callSiteVarianceMap = null,
9497
private array $templateTags = [],
9598
private array $throwPoints = [],
96-
private array $impurePoints = [],
99+
?array $impurePoints = null,
97100
private array $invalidateExpressions = [],
98101
private array $usedVariables = [],
99102
)
@@ -105,6 +108,7 @@ public function __construct(
105108
$this->templateTypeMap = $templateTypeMap ?? TemplateTypeMap::createEmpty();
106109
$this->resolvedTemplateTypeMap = $resolvedTemplateTypeMap ?? TemplateTypeMap::createEmpty();
107110
$this->callSiteVarianceMap = $callSiteVarianceMap ?? TemplateTypeVarianceMap::createEmpty();
111+
$this->impurePoints = $impurePoints ?? [new SimpleImpurePoint('functionCall', 'call to an unknown Closure', false)];
108112
}
109113

110114
/**
@@ -115,6 +119,11 @@ public function getTemplateTags(): array
115119
return $this->templateTags;
116120
}
117121

122+
public static function createPure(): self
123+
{
124+
return new self(null, null, true, null, null, null, [], [], []);
125+
}
126+
118127
public function isPure(): TrinaryLogic
119128
{
120129
$impurePoints = $this->getImpurePoints();

tests/PHPStan/Type/ClosureTypeTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ public function dataIsSuperTypeOf(): array
2323
new ClosureType([], new MixedType(), false),
2424
TrinaryLogic::createYes(),
2525
],
26+
[
27+
new ClosureType([], new MixedType(), false, null, null, null, [], [], []),
28+
new ClosureType([], new MixedType(), false),
29+
TrinaryLogic::createMaybe(),
30+
],
2631
[
2732
new ClosureType([], new UnionType([new IntegerType(), new StringType()]), false),
2833
new ClosureType([], new IntegerType(), false),

tests/PHPStan/Type/TypeCombinatorTest.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2535,7 +2535,7 @@ public function dataUnion(): iterable
25352535
yield [
25362536
[
25372537
new CallableType(null, null, true, null, null, [], TrinaryLogic::createYes()),
2538-
new ClosureType(),
2538+
ClosureType::createPure(),
25392539
],
25402540
CallableType::class,
25412541
'pure-callable(): mixed',
@@ -2553,7 +2553,7 @@ public function dataUnion(): iterable
25532553
new ClosureType([], new MixedType(), true, null, null, null, [], [], [
25542554
new SimpleImpurePoint('functionCall', 'foo', true),
25552555
]),
2556-
new ClosureType(),
2556+
ClosureType::createPure(),
25572557
],
25582558
UnionType::class,
25592559
'(Closure(): mixed)|(pure-Closure)',
@@ -2563,7 +2563,7 @@ public function dataUnion(): iterable
25632563
new ClosureType([], new MixedType(), true, null, null, null, [], [], [
25642564
new SimpleImpurePoint('functionCall', 'foo', false),
25652565
]),
2566-
new ClosureType(),
2566+
ClosureType::createPure(),
25672567
],
25682568
ClosureType::class,
25692569
'Closure(): mixed',
@@ -4219,7 +4219,7 @@ public function dataIntersect(): iterable
42194219
yield [
42204220
[
42214221
new CallableType(null, null, true, null, null, [], TrinaryLogic::createYes()),
4222-
new ClosureType(),
4222+
ClosureType::createPure(),
42234223
],
42244224
ClosureType::class,
42254225
'pure-Closure',
@@ -4237,7 +4237,7 @@ public function dataIntersect(): iterable
42374237
new ClosureType([], new MixedType(), true, null, null, null, [], [], [
42384238
new SimpleImpurePoint('functionCall', 'foo', true),
42394239
]),
4240-
new ClosureType(),
4240+
ClosureType::createPure(),
42414241
],
42424242
NeverType::class,
42434243
'*NEVER*=implicit',
@@ -4247,7 +4247,7 @@ public function dataIntersect(): iterable
42474247
new ClosureType([], new MixedType(), true, null, null, null, [], [], [
42484248
new SimpleImpurePoint('functionCall', 'foo', false),
42494249
]),
4250-
new ClosureType(),
4250+
ClosureType::createPure(),
42514251
],
42524252
ClosureType::class,
42534253
'pure-Closure',

0 commit comments

Comments
 (0)