From 20e004744f95ea958385c35301057e514a6c8174 Mon Sep 17 00:00:00 2001 From: Brown Date: Tue, 25 Aug 2020 18:04:36 -0400 Subject: [PATCH] Fix #4064 - assume most iterators are impure --- .../Statements/Block/ForeachAnalyzer.php | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php index 62544c7c7..3233bbd40 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php @@ -502,6 +502,30 @@ class ForeachAnalyzer $value_type, Type::getMixed() ); + + if (!$context->pure) { + $project_analyzer = $statements_analyzer->getProjectAnalyzer(); + + if ($codebase->alter_code + && (isset($project_analyzer->getIssuesToFix()['MissingPureAnnotation']) + || isset($project_analyzer->getIssuesToFix()['MissingImmutableAnnotation'])) + && $statements_analyzer->getSource() + instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer + ) { + $statements_analyzer->getSource()->inferred_has_mutation = true; + $statements_analyzer->getSource()->inferred_impure = true; + } + } else { + if (IssueBuffer::accepts( + new ImpureMethodCall( + 'Cannot call a possibly-mutating iterator from a pure context', + new CodeLocation($statements_analyzer, $stmt) + ), + $statements_analyzer->getSuppressedIssues() + )) { + // fall through + } + } } elseif ($iterator_atomic_type instanceof Type\Atomic\TIterable) { if ($iterator_atomic_type->extra_types) { $iterator_atomic_type_copy = clone $iterator_atomic_type; @@ -622,6 +646,30 @@ class ForeachAnalyzer } else { $raw_object_types[] = $iterator_atomic_type->value; } + + if (!$context->pure) { + $project_analyzer = $statements_analyzer->getProjectAnalyzer(); + + if ($codebase->alter_code + && (isset($project_analyzer->getIssuesToFix()['MissingPureAnnotation']) + || isset($project_analyzer->getIssuesToFix()['MissingImmutableAnnotation'])) + && $statements_analyzer->getSource() + instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer + ) { + $statements_analyzer->getSource()->inferred_has_mutation = true; + $statements_analyzer->getSource()->inferred_impure = true; + } + } else { + if (IssueBuffer::accepts( + new ImpureMethodCall( + 'Cannot call a possibly-mutating iterator from a pure context', + new CodeLocation($statements_analyzer, $stmt) + ), + $statements_analyzer->getSuppressedIssues() + )) { + // fall through + } + } } }