Skip to content
Permalink
Browse files

Fix #1825 - improve behaviour of callable reconciliation

  • Loading branch information...
muglug committed Jun 20, 2019
1 parent db38270 commit ac06ea659efa0ee05b8d9889e394d2e6b9b0db38
@@ -865,6 +865,12 @@ public static function isAtomicContainedBy(
return true;
}
if ($input_type_part instanceof Type\Atomic\TCallableObject &&
$container_type_part instanceof TObject
) {
return true;
}
if ($container_type_part instanceof TNumeric &&
($input_type_part->isNumericType() || $input_type_part instanceof TString)
) {
@@ -911,6 +911,7 @@ function (Type\Union $t) {
foreach ($existing_var_atomic_types as $type) {
if ($type instanceof TBool) {
$bool_types[] = $type;
$type->from_docblock = false;
} elseif ($type instanceof TScalar) {
$bool_types[] = new TBool;
$did_remove_type = true;
@@ -942,6 +943,54 @@ function (Type\Union $t) {
return Type::getMixed();
}
if ($new_var_type === 'string' && !$existing_var_type->hasMixed()) {
$string_types = [];
$did_remove_type = false;
foreach ($existing_var_atomic_types as $type) {
if ($type instanceof TString) {
$string_types[] = $type;
if (get_class($type) === TString::class) {
$type->from_docblock = false;
}
} elseif ($type instanceof TCallable) {
$string_types[] = new Type\Atomic\TCallableString;
$did_remove_type = true;
} elseif ($type instanceof TNumeric) {
$string_types[] = new TNumericString;
$did_remove_type = true;
} elseif ($type instanceof TScalar || $type instanceof TArrayKey) {
$string_types[] = new TString;
$did_remove_type = true;
} else {
$did_remove_type = true;
}
}
if ((!$did_remove_type || !$string_types) && !$is_equality) {
if ($key && $code_location) {
self::triggerIssueForImpossible(
$existing_var_type,
$old_var_type_string,
$key,
$new_var_type,
!$did_remove_type,
$code_location,
$suppressed_issues
);
}
}
if ($string_types) {
return new Type\Union($string_types);
}
$failed_reconciliation = 2;
return Type::getMixed();
}
$is_maybe_callable_array = false;
if ($new_var_type === 'array' && isset($existing_var_atomic_types['callable'])) {
@@ -950,14 +999,14 @@ function (Type\Union $t) {
if (!isset($existing_var_atomic_types['array'])) {
$existing_var_type->addType(
new TCallableObjectLikeArray([
Type::getMixed(),
new Type\Union([new TObject, new TString]),
Type::getString()
])
);
} else {
$array_combination = \Psalm\Internal\Type\TypeCombination::combineTypes([
new TCallableObjectLikeArray([
Type::getMixed(),
new Type\Union([new TObject, new TString]),
Type::getString()
]),
$existing_var_atomic_types['array']
@@ -874,8 +874,8 @@ function foo(callable $c) : void {
* @psalm-suppress MixedArgument
*/
function foo($c) : void {
if (is_array($c)) {
echo $c[2];
if (is_array($c) && is_string($c[1])) {
echo $c[1];
}
}',
],
@@ -272,7 +272,20 @@ function foo($arr): void {
'assertions' => [],
'error_levels' => ['MixedAssignment', 'MixedArrayAccess'],
],
'hardPhpTypeAssertionsOnDocblockType' => [
'hardPhpTypeAssertionsOnDocblockBoolType' => [
'<?php
/** @param bool|null $bar */
function foo($bar): void {
if (!is_null($bar) && !is_bool($bar)) {
throw new \Exception("bad");
}
if ($bar !== null) {}
}',
'assertions' => [],
'error_levels' => ['DocblockTypeContradiction'],
],
'hardPhpTypeAssertionsOnDocblockStringType' => [
'<?php
/** @param string|null $bar */
function foo($bar): void {
@@ -1363,6 +1363,20 @@ public function foo(self $value): void {
}
}',
],
'reconcileCallable' => [
'<?php
function reflectCallable(callable $callable): ReflectionFunctionAbstract {
if (\is_array($callable)) {
return new \ReflectionMethod($callable[0], $callable[1]);
} elseif ($callable instanceof \Closure || \is_string($callable)) {
return new \ReflectionFunction($callable);
} elseif (\is_object($callable)) {
return new \ReflectionMethod($callable, "__invoke");
} else {
throw new \InvalidArgumentException("Bad");
}
}'
],
];
}

0 comments on commit ac06ea6

Please sign in to comment.
You can’t perform that action at this time.