Skip to content

Commit

Permalink
Merge pull request #9794 from robchett/remove_TCallableArray_and_TCal…
Browse files Browse the repository at this point in the history
…lableList

Improved type of callable-array
  • Loading branch information
orklah authored Oct 17, 2023
2 parents 67d6468 + 0f8a320 commit 24168f6
Show file tree
Hide file tree
Showing 15 changed files with 88 additions and 82 deletions.
1 change: 1 addition & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- [BC] The only optional boolean parameter of `TKeyedArray::getGenericArrayType` was removed, and was replaced with a string parameter with a different meaning.

- [BC] The `TDependentListKey` type was removed and replaced with an optional property of the `TIntRange` type.
- [BC] `TCallableArray` and `TCallableList` removed and replaced with `TCallableKeyedArray`.

- [BC] Value of constant `Psalm\Type\TaintKindGroup::ALL_INPUT` changed to reflect new `TaintKind::INPUT_SLEEP` and `TaintKind::INPUT_XPATH` have been added. Accordingly, default values for `$taint` parameters of `Psalm\Codebase::addTaintSource()` and `Psalm\Codebase::addTaintSink()` have been changed as well.

Expand Down
2 changes: 0 additions & 2 deletions docs/running_psalm/plugins/plugins_type_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,6 @@ $a = [];
foreach (range(1,1) as $_) $a[(string)rand(0,1)] = rand(0,1); // array<string,int>
```

`TCallableArray` - denotes an array that is _also_ `callable`.

`TCallableKeyedArray` - denotes an object-like array that is _also_ `callable`.

`TClassStringMap` - Represents an array where the type of each value is a function of its string key value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
use Psalm\Type;
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TCallable;
use Psalm\Type\Atomic\TCallableArray;
use Psalm\Type\Atomic\TCallableKeyedArray;
use Psalm\Type\Atomic\TClosure;
use Psalm\Type\Atomic\TKeyedArray;
Expand Down Expand Up @@ -1528,9 +1527,7 @@ private static function checkArgCount(

foreach ($arg_value_type->getAtomicTypes() as $atomic_arg_type) {
$packed_var_definite_args_tmp = [];
if ($atomic_arg_type instanceof TCallableArray ||
$atomic_arg_type instanceof TCallableKeyedArray
) {
if ($atomic_arg_type instanceof TCallableKeyedArray) {
$packed_var_definite_args_tmp[] = 2;
} elseif ($atomic_arg_type instanceof TKeyedArray) {
if ($atomic_arg_type->fallback_params !== null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
use Psalm\Type;
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TCallable;
use Psalm\Type\Atomic\TCallableArray;
use Psalm\Type\Atomic\TCallableKeyedArray;
use Psalm\Type\Atomic\TClassString;
use Psalm\Type\Atomic\TClosure;
Expand Down Expand Up @@ -358,9 +357,7 @@ private static function getReturnTypeFromCallMapWithArgs(

if (count($atomic_types) === 1) {
if (isset($atomic_types['array'])) {
if ($atomic_types['array'] instanceof TCallableArray
|| $atomic_types['array'] instanceof TCallableKeyedArray
) {
if ($atomic_types['array'] instanceof TCallableKeyedArray) {
return Type::getInt(false, 2);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,7 @@ private static function isSupported(FunctionLikeParameter $container_param): boo
return false;
}

if ($a instanceof Type\Atomic\TCallableArray ||
$a instanceof Type\Atomic\TCallableString ||
if ($a instanceof Type\Atomic\TCallableString ||
$a instanceof Type\Atomic\TCallableKeyedArray
) {
return false;
Expand Down
10 changes: 0 additions & 10 deletions src/Psalm/Internal/Type/Comparator/CallableTypeComparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
use Psalm\Type\Atomic;
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TCallable;
use Psalm\Type\Atomic\TCallableArray;
use Psalm\Type\Atomic\TClassString;
use Psalm\Type\Atomic\TClosure;
use Psalm\Type\Atomic\TKeyedArray;
Expand Down Expand Up @@ -188,15 +187,6 @@ public static function isNotExplicitlyCallableTypeCallable(
if (!$input_type_part->type_params[1]->hasString()) {
return false;
}

if (!$input_type_part instanceof TCallableArray) {
if ($atomic_comparison_result) {
$atomic_comparison_result->type_coerced_from_mixed = true;
$atomic_comparison_result->type_coerced = true;
}

return false;
}
} elseif ($input_type_part instanceof TKeyedArray) {
$method_id = self::getCallableMethodIdFromTKeyedArray($input_type_part);

Expand Down
7 changes: 3 additions & 4 deletions src/Psalm/Internal/Type/SimpleAssertionReconciler.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
use Psalm\Type\Atomic\TArrayKey;
use Psalm\Type\Atomic\TBool;
use Psalm\Type\Atomic\TCallable;
use Psalm\Type\Atomic\TCallableArray;
use Psalm\Type\Atomic\TCallableKeyedArray;
use Psalm\Type\Atomic\TCallableObject;
use Psalm\Type\Atomic\TCallableString;
Expand Down Expand Up @@ -2305,7 +2304,7 @@ private static function reconcileArray(
} elseif ($type instanceof TCallable) {
$array_types[] = new TCallableKeyedArray([
new Union([new TClassString, new TObject]),
Type::getString(),
Type::getNonEmptyString(),
]);

$redundant = false;
Expand Down Expand Up @@ -2429,7 +2428,7 @@ private static function reconcileList(
} elseif ($type instanceof TCallable) {
$array_types[] = new TCallableKeyedArray([
new Union([new TClassString, new TObject]),
Type::getString(),
Type::getNonEmptyString(),
]);

$redundant = false;
Expand Down Expand Up @@ -2652,7 +2651,7 @@ private static function reconcileCallable(
$callable_types[] = $type;
$redundant = false;
} elseif ($type instanceof TArray) {
$type = new TCallableArray($type->type_params);
$type = new TCallableKeyedArray($type->type_params);
$callable_types[] = $type;
$redundant = false;
} elseif ($type instanceof TKeyedArray && count($type->properties) === 2) {
Expand Down
15 changes: 8 additions & 7 deletions src/Psalm/Internal/Type/SimpleNegatedAssertionReconciler.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@
use Psalm\Type\Atomic\TArrayKey;
use Psalm\Type\Atomic\TBool;
use Psalm\Type\Atomic\TCallable;
use Psalm\Type\Atomic\TCallableArray;
use Psalm\Type\Atomic\TCallableKeyedArray;
use Psalm\Type\Atomic\TCallableObject;
use Psalm\Type\Atomic\TCallableString;
use Psalm\Type\Atomic\TClassString;
use Psalm\Type\Atomic\TEmptyMixed;
use Psalm\Type\Atomic\TEmptyNumeric;
use Psalm\Type\Atomic\TEmptyScalar;
Expand Down Expand Up @@ -1187,9 +1188,9 @@ private static function reconcileObject(
$non_object_types[] = $type;
}
} elseif ($type instanceof TCallable) {
$non_object_types[] = new TCallableArray([
Type::getArrayKey(),
Type::getMixed(),
$non_object_types[] = new TCallableKeyedArray([
new Union([new TClassString, new TObject]),
Type::getNonEmptyString(),
]);
$non_object_types[] = new TCallableString();
$redundant = false;
Expand Down Expand Up @@ -1586,9 +1587,9 @@ private static function reconcileString(
$non_string_types[] = new TInt();
$redundant = false;
} elseif ($type instanceof TCallable) {
$non_string_types[] = new TCallableArray([
Type::getArrayKey(),
Type::getMixed(),
$non_string_types[] = new TCallableKeyedArray([
new Union([new TClassString, new TObject]),
Type::getNonEmptyString(),
]);
$non_string_types[] = new TCallableObject();
$redundant = false;
Expand Down
30 changes: 13 additions & 17 deletions src/Psalm/Internal/Type/TypeCombiner.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
use Psalm\Type\Atomic\TArrayKey;
use Psalm\Type\Atomic\TBool;
use Psalm\Type\Atomic\TCallable;
use Psalm\Type\Atomic\TCallableArray;
use Psalm\Type\Atomic\TCallableKeyedArray;
use Psalm\Type\Atomic\TCallableObject;
use Psalm\Type\Atomic\TCallableString;
Expand Down Expand Up @@ -400,7 +399,6 @@ private static function scrapeTypeProperties(
bool $allow_mixed_union,
int $literal_limit
): ?Union {

if ($type instanceof TMixed) {
if ($type->from_loop_isset) {
if ($combination->mixed_from_loop_isset === null) {
Expand Down Expand Up @@ -544,11 +542,17 @@ private static function scrapeTypeProperties(
}
}

if ($type instanceof TArray && $type_key === 'array') {
if ($type instanceof TCallableArray && isset($combination->value_types['callable'])) {
if ($type instanceof TCallableKeyedArray) {
if (isset($combination->value_types['callable'])) {
return null;
}

if ($combination->all_arrays_callable !== false) {
$combination->all_arrays_callable = true;
} else {
$combination->all_arrays_callable = false;
}
}
if ($type instanceof TArray && $type_key === 'array') {
foreach ($type->type_params as $i => $type_param) {
// See https://github.com/vimeo/psalm/pull/9439#issuecomment-1464563015
/** @psalm-suppress PropertyTypeCoercion */
Expand Down Expand Up @@ -587,14 +591,7 @@ private static function scrapeTypeProperties(
$combination->all_arrays_class_string_maps = false;
}

if ($type instanceof TCallableArray) {
if ($combination->all_arrays_callable !== false) {
$combination->all_arrays_callable = true;
}
} else {
$combination->all_arrays_callable = false;
}

$combination->all_arrays_callable = false;
return null;
}

Expand Down Expand Up @@ -956,8 +953,8 @@ private static function scrapeTypeProperties(
if ($type instanceof TCallable && $type_key === 'callable') {
if (($combination->value_types['string'] ?? null) instanceof TCallableString) {
unset($combination->value_types['string']);
} elseif (!empty($combination->array_type_params) && $combination->all_arrays_callable) {
$combination->array_type_params = [];
} elseif (!empty($combination->objectlike_entries) && $combination->all_arrays_callable) {
$combination->objectlike_entries = [];
} elseif (isset($combination->value_types['callable-object'])) {
unset($combination->value_types['callable-object']);
}
Expand Down Expand Up @@ -1412,7 +1409,6 @@ private static function handleKeyedArrayEntries(
$sealed || $fallback_key_type === null || $fallback_value_type === null
? null
: [$fallback_key_type, $fallback_value_type],
(bool)$combination->all_arrays_lists,
$from_docblock,
);
} else {
Expand Down Expand Up @@ -1525,7 +1521,7 @@ private static function getArrayTypeFromGenericParams(
}

if ($combination->all_arrays_callable) {
$array_type = new TCallableArray($generic_type_params);
$array_type = new TCallableKeyedArray($generic_type_params);
} elseif ($combination->array_always_filled
|| ($combination->array_sometimes_filled && $overwrite_empty_array)
|| ($combination->objectlike_entries
Expand Down
18 changes: 13 additions & 5 deletions src/Psalm/Type/Atomic.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use Psalm\Type\Atomic\TArrayKey;
use Psalm\Type\Atomic\TBool;
use Psalm\Type\Atomic\TCallable;
use Psalm\Type\Atomic\TCallableArray;
use Psalm\Type\Atomic\TCallableKeyedArray;
use Psalm\Type\Atomic\TCallableObject;
use Psalm\Type\Atomic\TCallableString;
Expand Down Expand Up @@ -258,9 +257,19 @@ private static function createInner(
]);

case 'callable-array':
return new TCallableArray([
new Union([new TArrayKey($from_docblock)]),
new Union([new TMixed(false, $from_docblock)]),
$classString = new TClassString(
'object',
null,
false,
false,
false,
true,
);
$object = new TObject(true);
$string = new TNonEmptyString(true);
return new TCallableKeyedArray([
new Union([$classString, $object]),
new Union([$string]),
]);

case 'list':
Expand Down Expand Up @@ -459,7 +468,6 @@ public function isCallableType(): bool
return $this instanceof TCallable
|| $this instanceof TCallableObject
|| $this instanceof TCallableString
|| $this instanceof TCallableArray
|| $this instanceof TCallableKeyedArray
|| $this instanceof TClosure;
}
Expand Down
16 changes: 0 additions & 16 deletions src/Psalm/Type/Atomic/TCallableArray.php

This file was deleted.

26 changes: 25 additions & 1 deletion src/Psalm/Type/Atomic/TCallableKeyedArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Psalm\Type\Atomic;

use Psalm\Type\Union;

/**
* Denotes an object-like array that is _also_ `callable`.
*
Expand All @@ -10,5 +12,27 @@
final class TCallableKeyedArray extends TKeyedArray
{
protected const NAME_ARRAY = 'callable-array';
protected const NAME_LIST = 'callable-list';
protected const NAME_LIST = 'callable-array';

/**
* Constructs a new instance of a generic type
*
* @param non-empty-array<string|int, Union> $properties
* @param array{Union, Union}|null $fallback_params
* @param array<string, bool> $class_strings
*/
public function __construct(
array $properties,
?array $class_strings = null,
?array $fallback_params = null,
bool $from_docblock = false
) {
parent::__construct(
$properties,
$class_strings,
$fallback_params,
true,
$from_docblock,
);
}
}
28 changes: 20 additions & 8 deletions tests/CallableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1827,23 +1827,35 @@ function withVariadic(int $a, int $b, int ...$rest): int
{
return 0;
}
/** @param Closure(int, int): int $f */
function int_int(Closure $f): void {}
/** @param Closure(int, int, int): int $f */
function int_int_int(Closure $f): void {}
/** @param Closure(int, int, int, int): int $f */
function int_int_int_int(Closure $f): void {}
int_int(withVariadic(...));
int_int_int(withVariadic(...));
int_int_int_int(withVariadic(...));',
'assertions' => [],
'ignored_issues' => [],
'php_version' => '8.0',
],
'callableArrayTypes' => [
'code' => '<?php
/** @var callable-array $c */
$c;
[$a, $b] = $c;
',
'assertions' => [
'$a' => 'class-string|object',
'$b' => 'string',
'$c' => 'list{class-string|object, string}',
],
],
];
}

Expand Down Expand Up @@ -2291,16 +2303,16 @@ function add(int $a, int $b, int ...$rest): int
{
return 0;
}
/** @param Closure(int, int, string, int, int): int $f */
function int_int_string_int_int(Closure $f): void {}
/** @param Closure(int, int, int, string, int): int $f */
function int_int_int_string_int(Closure $f): void {}
/** @param Closure(int, int, int, int, string): int $f */
function int_int_int_int_string(Closure $f): void {}
int_int_string_int_int(add(...));
int_int_int_string_int(add(...));
int_int_int_int_string(add(...));',
Expand Down
Loading

0 comments on commit 24168f6

Please sign in to comment.