File tree 3 files changed +35
-1
lines changed
Internal/Analyzer/Statements/Expression/Call
3 files changed +35
-1
lines changed Original file line number Diff line number Diff line change @@ -353,11 +353,13 @@ class Context
353
353
354
354
/**
355
355
* @var bool
356
+ * Set by @psalm-immutable
356
357
*/
357
358
public $ mutation_free = false ;
358
359
359
360
/**
360
361
* @var bool
362
+ * Set by @psalm-external-mutation-free
361
363
*/
362
364
public $ external_mutation_free = false ;
363
365
Original file line number Diff line number Diff line change @@ -642,7 +642,7 @@ private static function getAnalyzeNamedExpression(
642
642
}
643
643
644
644
if ($ var_type_part instanceof TClosure || $ var_type_part instanceof TCallable) {
645
- if (!$ var_type_part ->is_pure && $ context ->pure ) {
645
+ if (!$ var_type_part ->is_pure && ( $ context ->pure || $ context -> mutation_free ) ) {
646
646
IssueBuffer::maybeAdd (
647
647
new ImpureFunctionCall (
648
648
'Cannot call an impure function from a mutation-free context ' ,
Original file line number Diff line number Diff line change @@ -876,6 +876,38 @@ function testImpure(): void
876
876
' ,
877
877
'error_message ' => 'ImpureMethodCall ' ,
878
878
],
879
+ 'impureCallableInImmutableContext ' => [
880
+ '<?php
881
+
882
+ /**
883
+ * @psalm-immutable
884
+ */
885
+ class Either
886
+ {
887
+ /**
888
+ * @psalm-param callable $_
889
+ */
890
+ public function fold($_): void
891
+ {
892
+ $_();
893
+ }
894
+ }
895
+
896
+ class Whatever
897
+ {
898
+ public function __construct()
899
+ {
900
+ $either = new Either();
901
+ $either->fold(
902
+ function (): void {}
903
+ );
904
+ }
905
+ }
906
+
907
+ new Whatever();
908
+ ' ,
909
+ 'error_message ' => 'ImpureFunctionCall ' ,
910
+ ],
879
911
];
880
912
}
881
913
}
You can’t perform that action at this time.
0 commit comments