Skip to content

Commit

Permalink
Merge pull request #9700 from klimick/method-contextual-closure-arg-i…
Browse files Browse the repository at this point in the history
…nference

Contextual closure arg inference for class methods
  • Loading branch information
orklah committed Apr 24, 2023
2 parents 30fcaae + cf0ca8b commit 41796e3
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ public static function analyze(
if ($inferred_template_result) {
$template_result->lower_bounds += $inferred_template_result->lower_bounds;
}
if ($method_storage && $method_storage->template_types) {
$template_result->template_types += $method_storage->template_types;
}

if ($codebase->store_node_types
&& !$stmt->isFirstClassCallable()
Expand Down
28 changes: 25 additions & 3 deletions src/Psalm/Internal/Type/TemplateStandinTypeReplacer.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,17 @@ private static function handleAtomicStandin(
);
}

if ($atomic_type instanceof TTemplateParam
&& isset($template_result->lower_bounds[$atomic_type->param_name][$atomic_type->defining_class])
) {
$most_specific_type = self::getMostSpecificTypeFromBounds(
$template_result->lower_bounds[$atomic_type->param_name][$atomic_type->defining_class],
$codebase,
);

return array_values($most_specific_type->getAtomicTypes());
}

if ($atomic_type instanceof TTemplateParamClass
&& isset($template_result->template_types[$atomic_type->param_name][$atomic_type->defining_class])
) {
Expand Down Expand Up @@ -259,11 +270,14 @@ private static function handleAtomicStandin(

$include_first = true;

if (isset($template_result->template_types[$atomic_type->array_param_name][$atomic_type->defining_class])
if (isset($template_result->lower_bounds[$atomic_type->array_param_name][$atomic_type->defining_class])
&& !empty($template_result->lower_bounds[$atomic_type->offset_param_name])
) {
$array_template_type
= $template_result->template_types[$atomic_type->array_param_name][$atomic_type->defining_class];
= self::getMostSpecificTypeFromBounds(
$template_result->lower_bounds[$atomic_type->array_param_name][$atomic_type->defining_class],
$codebase,
);
$offset_template_type
= self::getMostSpecificTypeFromBounds(
array_values($template_result->lower_bounds[$atomic_type->offset_param_name])[0],
Expand Down Expand Up @@ -317,10 +331,18 @@ private static function handleAtomicStandin(
$atomic_types = [];

$include_first = true;
$template_type = null;

if (isset($template_result->template_types[$atomic_type->param_name][$atomic_type->defining_class])) {
if (isset($template_result->lower_bounds[$atomic_type->param_name][$atomic_type->defining_class])) {
$template_type = self::getMostSpecificTypeFromBounds(
$template_result->lower_bounds[$atomic_type->param_name][$atomic_type->defining_class],
$codebase,
);
} elseif (isset($template_result->template_types[$atomic_type->param_name][$atomic_type->defining_class])) {
$template_type = $template_result->template_types[$atomic_type->param_name][$atomic_type->defining_class];
}

if ($template_type) {
foreach ($template_type->getAtomicTypes() as $template_atomic) {
if ($template_atomic instanceof TList) {
$template_atomic = $template_atomic->getKeyedArray();
Expand Down
23 changes: 23 additions & 0 deletions tests/CallableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,29 @@ function asTupled(ArrayList $list): ArrayList
'$b' => 'ArrayList<list{int}>',
],
],
'inferArgByPreviousMethodArg' => [
'code' => '<?php
final class ArrayList
{
/**
* @template A
* @template B
* @template C
* @param list<A> $list
* @param callable(A): B $first
* @param callable(B): C $second
* @return list<C>
*/
public function map(array $list, callable $first, callable $second): array
{
throw new RuntimeException("never");
}
}
$result = (new ArrayList())->map([1, 2, 3], fn($i) => ["num" => $i], fn($i) => ["object" => $i]);',
'assertions' => [
'$result' => 'list<array{object: array{num: int}}>',
],
],
'inferArgByPreviousFunctionArg' => [
'code' => '<?php
/**
Expand Down

0 comments on commit 41796e3

Please sign in to comment.