Skip to content

Commit

Permalink
Consider a ClosureType() as maybe impure by default when no impurePoi…
Browse files Browse the repository at this point in the history
…nts array provided
  • Loading branch information
jf-m authored Jun 4, 2024
1 parent 7af14fb commit 04b8403
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/PhpDoc/TypeNodeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ private function resolveIdentifierTypeNode(IdentifierTypeNode $typeNode, NameSco
return new CallableType(null, null, true, null, null, [], TrinaryLogic::createYes());

case 'pure-closure':
return new ClosureType();
return ClosureType::createPure();

case 'resource':
$type = $this->tryResolvePseudoTypeClassType($typeNode, $nameScope);
Expand Down
13 changes: 11 additions & 2 deletions src/Type/ClosureType.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,15 @@ class ClosureType implements TypeWithClassName, CallableParametersAcceptor

private TemplateTypeVarianceMap $callSiteVarianceMap;

/** @var SimpleImpurePoint[] */
private array $impurePoints;

/**
* @api
* @param array<int, ParameterReflection>|null $parameters
* @param array<non-empty-string, TemplateTag> $templateTags
* @param SimpleThrowPoint[] $throwPoints
* @param SimpleImpurePoint[] $impurePoints
* @param ?SimpleImpurePoint[] $impurePoints
* @param InvalidateExprNode[] $invalidateExpressions
* @param string[] $usedVariables
*/
Expand All @@ -93,7 +96,7 @@ public function __construct(
?TemplateTypeVarianceMap $callSiteVarianceMap = null,
private array $templateTags = [],
private array $throwPoints = [],
private array $impurePoints = [],
?array $impurePoints = null,
private array $invalidateExpressions = [],
private array $usedVariables = [],
)
Expand All @@ -105,6 +108,7 @@ public function __construct(
$this->templateTypeMap = $templateTypeMap ?? TemplateTypeMap::createEmpty();
$this->resolvedTemplateTypeMap = $resolvedTemplateTypeMap ?? TemplateTypeMap::createEmpty();
$this->callSiteVarianceMap = $callSiteVarianceMap ?? TemplateTypeVarianceMap::createEmpty();
$this->impurePoints = $impurePoints ?? [new SimpleImpurePoint('functionCall', 'call to an unknown Closure', false)];
}

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

public static function createPure(): self
{
return new self(null, null, true, null, null, null, [], [], []);
}

public function isPure(): TrinaryLogic
{
$impurePoints = $this->getImpurePoints();
Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Type/ClosureTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public function dataIsSuperTypeOf(): array
new ClosureType([], new MixedType(), false),
TrinaryLogic::createYes(),
],
[
new ClosureType([], new MixedType(), false, null, null, null, [], [], []),
new ClosureType([], new MixedType(), false),
TrinaryLogic::createMaybe(),
],
[
new ClosureType([], new UnionType([new IntegerType(), new StringType()]), false),
new ClosureType([], new IntegerType(), false),
Expand Down
12 changes: 6 additions & 6 deletions tests/PHPStan/Type/TypeCombinatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2535,7 +2535,7 @@ public function dataUnion(): iterable
yield [
[
new CallableType(null, null, true, null, null, [], TrinaryLogic::createYes()),
new ClosureType(),
ClosureType::createPure(),
],
CallableType::class,
'pure-callable(): mixed',
Expand All @@ -2553,7 +2553,7 @@ public function dataUnion(): iterable
new ClosureType([], new MixedType(), true, null, null, null, [], [], [
new SimpleImpurePoint('functionCall', 'foo', true),
]),
new ClosureType(),
ClosureType::createPure(),
],
UnionType::class,
'(Closure(): mixed)|(pure-Closure)',
Expand All @@ -2563,7 +2563,7 @@ public function dataUnion(): iterable
new ClosureType([], new MixedType(), true, null, null, null, [], [], [
new SimpleImpurePoint('functionCall', 'foo', false),
]),
new ClosureType(),
ClosureType::createPure(),
],
ClosureType::class,
'Closure(): mixed',
Expand Down Expand Up @@ -4219,7 +4219,7 @@ public function dataIntersect(): iterable
yield [
[
new CallableType(null, null, true, null, null, [], TrinaryLogic::createYes()),
new ClosureType(),
ClosureType::createPure(),
],
ClosureType::class,
'pure-Closure',
Expand All @@ -4237,7 +4237,7 @@ public function dataIntersect(): iterable
new ClosureType([], new MixedType(), true, null, null, null, [], [], [
new SimpleImpurePoint('functionCall', 'foo', true),
]),
new ClosureType(),
ClosureType::createPure(),
],
NeverType::class,
'*NEVER*=implicit',
Expand All @@ -4247,7 +4247,7 @@ public function dataIntersect(): iterable
new ClosureType([], new MixedType(), true, null, null, null, [], [], [
new SimpleImpurePoint('functionCall', 'foo', false),
]),
new ClosureType(),
ClosureType::createPure(),
],
ClosureType::class,
'pure-Closure',
Expand Down

0 comments on commit 04b8403

Please sign in to comment.