diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php index d8479ae1a..f2d935cec 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php @@ -1244,7 +1244,8 @@ class CallAnalyzer $existing_generic_params, $generic_params, $template_types, - $function_storage ? $function_storage->pure : false + $function_storage ? $function_storage->pure : false, + $in_call_map ) === false) { return false; } @@ -1382,9 +1383,10 @@ class CallAnalyzer PhpParser\Node\Arg $arg, Context $context, array $existing_generic_params, - array &$generic_params = null, - array $template_types = null, - bool $function_is_pure + ?array &$generic_params, + ?array $template_types, + bool $function_is_pure, + bool $in_call_map ) { $codebase = $statements_analyzer->getCodebase(); @@ -1449,7 +1451,8 @@ class CallAnalyzer $existing_generic_params, $generic_params, $template_types, - $function_is_pure + $function_is_pure, + $in_call_map ) === false) { return false; } @@ -1612,7 +1615,8 @@ class CallAnalyzer ?array $existing_generic_params, ?array &$generic_params, ?array $template_types, - bool $function_is_pure + bool $function_is_pure, + bool $in_call_map ) { if (!$function_param->type) { if (!$codebase->infer_types_from_usage) { @@ -1771,6 +1775,7 @@ class CallAnalyzer $function_param, $arg->unpack, $function_is_pure, + $in_call_map, $function_location ) === false) { return false; @@ -2277,6 +2282,7 @@ class CallAnalyzer FunctionLikeParameter $function_param, bool $unpack, bool $function_is_pure, + bool $in_call_map, CodeLocation $function_location ) { $codebase = $statements_analyzer->getCodebase(); @@ -2353,6 +2359,7 @@ class CallAnalyzer if (!$function_param->by_ref && !($function_param->is_variadic xor $unpack) && $cased_method_id !== 'echo' + && (!$in_call_map || $context->strict_types) ) { self::coerceValueAfterGatekeeperArgument( $statements_analyzer, @@ -2769,6 +2776,7 @@ class CallAnalyzer && !$function_param->by_ref && !($function_param->is_variadic xor $unpack) && $cased_method_id !== 'echo' + && (!$in_call_map || $context->strict_types) ) { self::coerceValueAfterGatekeeperArgument( $statements_analyzer, diff --git a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php index fbffbef2d..268d702bb 100644 --- a/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php @@ -568,6 +568,7 @@ class StatementsAnalyzer extends SourceAnalyzer implements StatementsSource $context, $echo_param, false, + false, true, new CodeLocation($this->source, $stmt) ) === false) { @@ -620,6 +621,7 @@ class StatementsAnalyzer extends SourceAnalyzer implements StatementsSource ) { $function_id = strtolower($stmt->name->name); $function_context = new Context($context->self); + $function_context->strict_types = $context->strict_types; $config = Config::getInstance(); $function_context->collect_references = $codebase->collect_references; $function_context->collect_exceptions = $config->check_for_throws_docblock; diff --git a/tests/FunctionCallTest.php b/tests/FunctionCallTest.php index 61e10aa55..8e2aa59be 100644 --- a/tests/FunctionCallTest.php +++ b/tests/FunctionCallTest.php @@ -1858,6 +1858,20 @@ class FunctionCallTest extends TestCase $a = print_r([], 1); echo $a;', ], + 'dontCoerceCallMapArgs' => [ + ' 'UndefinedVariable', ], + 'coerceCallMapArgsInStrictMode' => [ + ' 'TypeDoesNotContainType', + ], ]; } }