Skip to content

Commit

Permalink
fix #2125 - Don’t assume function args are necessarily authoratative
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed Sep 11, 2019
1 parent a8e58b0 commit 944531b
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 6 deletions.
20 changes: 14 additions & 6 deletions src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php
Expand Up @@ -1244,7 +1244,8 @@ protected static function checkFunctionLikeArgumentsMatch(
$existing_generic_params, $existing_generic_params,
$generic_params, $generic_params,
$template_types, $template_types,
$function_storage ? $function_storage->pure : false $function_storage ? $function_storage->pure : false,
$in_call_map
) === false) { ) === false) {
return false; return false;
} }
Expand Down Expand Up @@ -1382,9 +1383,10 @@ private static function checkFunctionLikeArgumentMatches(
PhpParser\Node\Arg $arg, PhpParser\Node\Arg $arg,
Context $context, Context $context,
array $existing_generic_params, array $existing_generic_params,
array &$generic_params = null, ?array &$generic_params,
array $template_types = null, ?array $template_types,
bool $function_is_pure bool $function_is_pure,
bool $in_call_map
) { ) {
$codebase = $statements_analyzer->getCodebase(); $codebase = $statements_analyzer->getCodebase();


Expand Down Expand Up @@ -1449,7 +1451,8 @@ private static function checkFunctionLikeArgumentMatches(
$existing_generic_params, $existing_generic_params,
$generic_params, $generic_params,
$template_types, $template_types,
$function_is_pure $function_is_pure,
$in_call_map
) === false) { ) === false) {
return false; return false;
} }
Expand Down Expand Up @@ -1612,7 +1615,8 @@ private static function checkFunctionLikeTypeMatches(
?array $existing_generic_params, ?array $existing_generic_params,
?array &$generic_params, ?array &$generic_params,
?array $template_types, ?array $template_types,
bool $function_is_pure bool $function_is_pure,
bool $in_call_map
) { ) {
if (!$function_param->type) { if (!$function_param->type) {
if (!$codebase->infer_types_from_usage) { if (!$codebase->infer_types_from_usage) {
Expand Down Expand Up @@ -1771,6 +1775,7 @@ private static function checkFunctionLikeTypeMatches(
$function_param, $function_param,
$arg->unpack, $arg->unpack,
$function_is_pure, $function_is_pure,
$in_call_map,
$function_location $function_location
) === false) { ) === false) {
return false; return false;
Expand Down Expand Up @@ -2277,6 +2282,7 @@ public static function checkFunctionArgumentType(
FunctionLikeParameter $function_param, FunctionLikeParameter $function_param,
bool $unpack, bool $unpack,
bool $function_is_pure, bool $function_is_pure,
bool $in_call_map,
CodeLocation $function_location CodeLocation $function_location
) { ) {
$codebase = $statements_analyzer->getCodebase(); $codebase = $statements_analyzer->getCodebase();
Expand Down Expand Up @@ -2353,6 +2359,7 @@ public static function checkFunctionArgumentType(
if (!$function_param->by_ref if (!$function_param->by_ref
&& !($function_param->is_variadic xor $unpack) && !($function_param->is_variadic xor $unpack)
&& $cased_method_id !== 'echo' && $cased_method_id !== 'echo'
&& (!$in_call_map || $context->strict_types)
) { ) {
self::coerceValueAfterGatekeeperArgument( self::coerceValueAfterGatekeeperArgument(
$statements_analyzer, $statements_analyzer,
Expand Down Expand Up @@ -2769,6 +2776,7 @@ public static function checkFunctionArgumentType(
&& !$function_param->by_ref && !$function_param->by_ref
&& !($function_param->is_variadic xor $unpack) && !($function_param->is_variadic xor $unpack)
&& $cased_method_id !== 'echo' && $cased_method_id !== 'echo'
&& (!$in_call_map || $context->strict_types)
) { ) {
self::coerceValueAfterGatekeeperArgument( self::coerceValueAfterGatekeeperArgument(
$statements_analyzer, $statements_analyzer,
Expand Down
2 changes: 2 additions & 0 deletions src/Psalm/Internal/Analyzer/StatementsAnalyzer.php
Expand Up @@ -568,6 +568,7 @@ function ($line) {
$context, $context,
$echo_param, $echo_param,
false, false,
false,
true, true,
new CodeLocation($this->source, $stmt) new CodeLocation($this->source, $stmt)
) === false) { ) === false) {
Expand Down Expand Up @@ -620,6 +621,7 @@ function ($line) {
) { ) {
$function_id = strtolower($stmt->name->name); $function_id = strtolower($stmt->name->name);
$function_context = new Context($context->self); $function_context = new Context($context->self);
$function_context->strict_types = $context->strict_types;
$config = Config::getInstance(); $config = Config::getInstance();
$function_context->collect_references = $codebase->collect_references; $function_context->collect_references = $codebase->collect_references;
$function_context->collect_exceptions = $config->check_for_throws_docblock; $function_context->collect_exceptions = $config->check_for_throws_docblock;
Expand Down
31 changes: 31 additions & 0 deletions tests/FunctionCallTest.php
Expand Up @@ -1858,6 +1858,20 @@ function foo(int $a, string $b, bool $c) : array {
$a = print_r([], 1); $a = print_r([], 1);
echo $a;', echo $a;',
], ],
'dontCoerceCallMapArgs' => [
'<?php
function getStr() : ?string {
return rand(0,1) ? "test" : null;
}
function test() : void {
$g = getStr();
/** @psalm-suppress PossiblyNullArgument */
$x = strtoupper($g);
$c = "prefix " . (strtoupper($g ?? "") === "x" ? "xa" : "ya");
echo "$x, $c\n";
}'
],
]; ];
} }


Expand Down Expand Up @@ -2429,6 +2443,23 @@ function foo($data): void {
}', }',
'error_message' => 'UndefinedVariable', 'error_message' => 'UndefinedVariable',
], ],
'coerceCallMapArgsInStrictMode' => [
'<?php
declare(strict_types=1);
function getStr() : ?string {
return rand(0,1) ? "test" : null;
}
function test() : void {
$g = getStr();
/** @psalm-suppress PossiblyNullArgument */
$x = strtoupper($g);
$c = "prefix " . (strtoupper($g ?? "") === "x" ? "xa" : "ya");
echo "$x, $c\n";
}',
'error_message' => 'TypeDoesNotContainType',
],
]; ];
} }
} }

0 comments on commit 944531b

Please sign in to comment.