Skip to content

Commit

Permalink
forbid calling impure callable in immutable context
Browse files Browse the repository at this point in the history
  • Loading branch information
orklah committed Jan 1, 2022
1 parent f9b3600 commit 8049438
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/Psalm/Context.php
Expand Up @@ -353,11 +353,13 @@ class Context

/**
* @var bool
* Set by @psalm-immutable
*/
public $mutation_free = false;

/**
* @var bool
* Set by @psalm-external-mutation-free
*/
public $external_mutation_free = false;

Expand Down
Expand Up @@ -642,7 +642,7 @@ private static function getAnalyzeNamedExpression(
}

if ($var_type_part instanceof TClosure || $var_type_part instanceof TCallable) {
if (!$var_type_part->is_pure && $context->pure) {
if (!$var_type_part->is_pure && ($context->pure || $context->mutation_free)) {
IssueBuffer::maybeAdd(
new ImpureFunctionCall(
'Cannot call an impure function from a mutation-free context',
Expand Down
32 changes: 32 additions & 0 deletions tests/PureAnnotationTest.php
Expand Up @@ -876,6 +876,38 @@ function testImpure(): void
',
'error_message' => 'ImpureMethodCall',
],
'impureCallableInImmutableContext' => [
'<?php
/**
* @psalm-immutable
*/
class Either
{
/**
* @psalm-param callable $_
*/
public function fold($_): void
{
$_();
}
}
class Whatever
{
public function __construct()
{
$either = new Either();
$either->fold(
function (): void {}
);
}
}
new Whatever();
',
'error_message' => 'ImpureFunctionCall',
],
];
}
}

0 comments on commit 8049438

Please sign in to comment.