1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

Fix issue re-asserting non-empty-mixed

This commit is contained in:
Brown 2018-12-10 18:33:26 -05:00
parent fb19e510a7
commit d9945a0ced
4 changed files with 138 additions and 75 deletions

View File

@ -906,6 +906,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
if ($var_id if ($var_id
&& $class_type && $class_type
&& $has_valid_method_call_type && $has_valid_method_call_type
&& !$class_type->hasMixed()
&& !$invalid_method_call_types && !$invalid_method_call_types
&& $existent_method_ids && $existent_method_ids
&& ($class_type->from_docblock || $class_type->isNullable()) && ($class_type->from_docblock || $class_type->isNullable())

View File

@ -1208,6 +1208,41 @@ class Reconciler
|| $existing_var_type->possibly_undefined || $existing_var_type->possibly_undefined
|| $existing_var_type->possibly_undefined_from_try; || $existing_var_type->possibly_undefined_from_try;
if ($is_strict_equality && $new_var_type === 'empty') {
$existing_var_type->removeType('null');
$existing_var_type->removeType('false');
if ($existing_var_type->hasType('array')
&& $existing_var_type->getTypes()['array']->getId() === 'array<empty, empty>'
) {
$existing_var_type->removeType('array');
}
if ($existing_var_type->hasMixed()) {
$existing_var_type->removeType('mixed');
if (!$existing_var_atomic_types['mixed'] instanceof Type\Atomic\TEmptyMixed) {
$existing_var_type->addType(new Type\Atomic\TNonEmptyMixed);
}
}
self::removeFalsyNegatedLiteralTypes(
$existing_var_type,
$did_remove_type
);
$existing_var_type->possibly_undefined = false;
$existing_var_type->possibly_undefined_from_try = false;
if ($existing_var_type->getTypes()) {
return $existing_var_type;
}
$failed_reconciliation = true;
return Type::getMixed();
}
if ($existing_var_type->hasMixed()) { if ($existing_var_type->hasMixed()) {
if ($existing_var_type->isMixed() if ($existing_var_type->isMixed()
&& $existing_var_atomic_types['mixed'] instanceof Type\Atomic\TEmptyMixed && $existing_var_atomic_types['mixed'] instanceof Type\Atomic\TEmptyMixed
@ -1257,28 +1292,6 @@ class Reconciler
} }
} }
if ($is_strict_equality && $new_var_type === 'empty') {
$existing_var_type->removeType('null');
$existing_var_type->removeType('false');
if ($existing_var_type->hasType('array')
&& $existing_var_type->getTypes()['array']->getId() === 'array<empty, empty>'
) {
$existing_var_type->removeType('array');
}
$existing_var_type->possibly_undefined = false;
$existing_var_type->possibly_undefined_from_try = false;
if ($existing_var_type->getTypes()) {
return $existing_var_type;
}
$failed_reconciliation = true;
return Type::getMixed();
}
if ($existing_var_type->hasType('null')) { if ($existing_var_type->hasType('null')) {
$did_remove_type = true; $did_remove_type = true;
$existing_var_type->removeType('null'); $existing_var_type->removeType('null');
@ -1295,59 +1308,10 @@ class Reconciler
$existing_var_type->addType(new TTrue); $existing_var_type->addType(new TTrue);
} }
if ($existing_var_type->hasString()) { self::removeFalsyNegatedLiteralTypes(
$existing_string_types = $existing_var_type->getLiteralStrings(); $existing_var_type,
$did_remove_type
if ($existing_string_types) { );
foreach ($existing_string_types as $string_key => $literal_type) {
if (!$literal_type->value) {
$existing_var_type->removeType($string_key);
$did_remove_type = true;
}
}
} else {
$did_remove_type = true;
}
}
if ($existing_var_type->hasInt()) {
$existing_int_types = $existing_var_type->getLiteralInts();
if ($existing_int_types) {
foreach ($existing_int_types as $int_key => $literal_type) {
if (!$literal_type->value) {
$existing_var_type->removeType($int_key);
$did_remove_type = true;
}
}
} else {
$did_remove_type = true;
}
}
if ($existing_var_type->hasType('array')) {
$array_atomic_type = $existing_var_type->getTypes()['array'];
if ($array_atomic_type instanceof Type\Atomic\TArray
&& !$array_atomic_type instanceof Type\Atomic\TNonEmptyArray
) {
$did_remove_type = true;
if ($array_atomic_type->getId() === 'array<empty, empty>') {
$existing_var_type->removeType('array');
} else {
$existing_var_type->addType(
new Type\Atomic\TNonEmptyArray(
$array_atomic_type->type_params
)
);
}
} elseif ($array_atomic_type instanceof Type\Atomic\ObjectLike
&& !$array_atomic_type->sealed
) {
$did_remove_type = true;
}
}
$existing_var_type->possibly_undefined = false; $existing_var_type->possibly_undefined = false;
$existing_var_type->possibly_undefined_from_try = false; $existing_var_type->possibly_undefined_from_try = false;
@ -1500,6 +1464,68 @@ class Reconciler
return $existing_var_type; return $existing_var_type;
} }
/**
* @return void
*/
private static function removeFalsyNegatedLiteralTypes(
Type\Union $existing_var_type,
bool &$did_remove_type
) {
if ($existing_var_type->hasString()) {
$existing_string_types = $existing_var_type->getLiteralStrings();
if ($existing_string_types) {
foreach ($existing_string_types as $string_key => $literal_type) {
if (!$literal_type->value) {
$existing_var_type->removeType($string_key);
$did_remove_type = true;
}
}
} else {
$did_remove_type = true;
}
}
if ($existing_var_type->hasInt()) {
$existing_int_types = $existing_var_type->getLiteralInts();
if ($existing_int_types) {
foreach ($existing_int_types as $int_key => $literal_type) {
if (!$literal_type->value) {
$existing_var_type->removeType($int_key);
$did_remove_type = true;
}
}
} else {
$did_remove_type = true;
}
}
if ($existing_var_type->hasType('array')) {
$array_atomic_type = $existing_var_type->getTypes()['array'];
if ($array_atomic_type instanceof Type\Atomic\TArray
&& !$array_atomic_type instanceof Type\Atomic\TNonEmptyArray
) {
$did_remove_type = true;
if ($array_atomic_type->getId() === 'array<empty, empty>') {
$existing_var_type->removeType('array');
} else {
$existing_var_type->addType(
new Type\Atomic\TNonEmptyArray(
$array_atomic_type->type_params
)
);
}
} elseif ($array_atomic_type instanceof Type\Atomic\ObjectLike
&& !$array_atomic_type->sealed
) {
$did_remove_type = true;
}
}
}
/** /**
* @param string $new_var_type * @param string $new_var_type
* @param int $bracket_pos * @param int $bracket_pos

View File

@ -168,6 +168,23 @@ class ArrayAccessTest extends TestCase
'assertions' => [], 'assertions' => [],
'error_levels' => ['PossiblyUndefinedArrayOffset'], 'error_levels' => ['PossiblyUndefinedArrayOffset'],
], ],
'noRedundantConditionOnMixedArrayAccess' => [
'<?php
/** @var array<int, int> */
$b = [];
/** @var array<int, int> */
$c = [];
/** @var array<int, mixed> */
$d = [];
if (!empty($d[0]) && !isset($c[$d[0]])) {
if (isset($b[$d[0]])) {}
}',
[],
'error_levels' => ['MixedArrayOffset'],
],
]; ];
} }

View File

@ -202,6 +202,25 @@ class MethodCallTest extends TestCase
$db = new PDO("sqlite:sqlitedb"); $db = new PDO("sqlite:sqlitedb");
$db->sqliteCreateFunction("md5rev", "md5_and_reverse", 1);', $db->sqliteCreateFunction("md5rev", "md5_and_reverse", 1);',
], ],
'dontConvertedMaybeMixedAfterCall' => [
'<?php
class B {
public function foo() : void {}
}
/**
* @param array<B> $b
*/
function foo(array $a, array $b) : void {
$c = array_merge($b, $a);
foreach ($c as $d) {
$d->foo();
if ($d instanceof B) {}
}
}',
[],
'error_levels' => ['MixedAssignment', 'MixedMethodCall'],
],
]; ];
} }