Skip to content

Commit

Permalink
Merge pull request #10935 from VincentLanglet/fix-array-callable
Browse files Browse the repository at this point in the history
  • Loading branch information
weirdan committed May 5, 2024
2 parents 0b37d26 + e97dbab commit 08ea062
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
use Psalm\Type\Union;
use UnexpectedValueException;

use function array_filter;
use function count;
use function explode;
use function implode;
Expand Down Expand Up @@ -955,12 +956,29 @@ public static function verifyType(
) {
$potential_method_ids = [];

$param_types_without_callable = array_filter(
$param_type->getAtomicTypes(),
static fn(Atomic $atomic) => !$atomic instanceof Atomic\TCallableInterface,
);
$param_type_without_callable = [] !== $param_types_without_callable
? new Union($param_types_without_callable)
: null;

foreach ($input_type->getAtomicTypes() as $input_type_part) {
if ($input_type_part instanceof TList) {
$input_type_part = $input_type_part->getKeyedArray();
}

if ($input_type_part instanceof TKeyedArray) {
// If the param accept an array, we don't report arrays as wrong callbacks.
if (null !== $param_type_without_callable && UnionTypeComparator::isContainedBy(
$codebase,
$input_type,
$param_type_without_callable,
)) {
continue;
}

$potential_method_id = CallableTypeComparator::getCallableMethodIdFromTKeyedArray(
$input_type_part,
$codebase,
Expand Down Expand Up @@ -1006,6 +1024,15 @@ public static function verifyType(
} elseif ($input_type_part instanceof TLiteralString
&& strpos($input_type_part->value, '::')
) {
// If the param also accept a string, we don't report string as wrong callbacks.
if (null !== $param_type_without_callable && UnionTypeComparator::isContainedBy(
$codebase,
$input_type,
$param_type_without_callable,
)) {
continue;
}

$parts = explode('::', $input_type_part->value);
/** @psalm-suppress PossiblyUndefinedIntArrayOffset */
$potential_method_id = new MethodIdentifier(
Expand Down
28 changes: 28 additions & 0 deletions tests/CallableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2210,6 +2210,24 @@ function foo($arg): void {}
foo(["a", "b"]);',
],
'notCallableArray' => [
'code' => '<?php
/**
* @param array{class-string, string}|callable $arg
*/
function foo($arg): void {}
foo([\DateTime::class, "format"]);',
],
'notCallableString' => [
'code' => '<?php
/**
* @param string|callable $arg
*/
function foo($arg): void {}
foo("notACallable");',
],
'callableOptionalOrAdditionalOptional' => [
'code' => '<?php
/**
Expand Down Expand Up @@ -3635,6 +3653,16 @@ public function run($callable) {
}',
'error_message' => 'ParentNotFound',
],
'wrongCallableInUnion' => [
'code' => '<?php
/**
* @param int|callable $arg
*/
function foo($arg): void {}
foo([\DateTime::class, "wrongMethod"]);',
'error_message' => 'InvalidArgument',
],
];
}
}

0 comments on commit 08ea062

Please sign in to comment.