Skip to content

Commit

Permalink
Fix issue creating empty array offsets
Browse files Browse the repository at this point in the history
  • Loading branch information
muglug committed Oct 9, 2019
1 parent db33efb commit e620c2c
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
21 changes: 19 additions & 2 deletions src/Psalm/Type/Reconciler.php
Expand Up @@ -168,6 +168,7 @@ public static function reconcileKeyedTypes(
$has_isset = false;
$has_inverted_isset = false;
$has_falsyish = false;
$has_empty = false;
$has_count_check = false;

foreach ($new_type_parts as $new_type_part_parts) {
Expand All @@ -186,6 +187,8 @@ public static function reconcileKeyedTypes(
|| $new_type_part_part === '=isset'
|| $new_type_part_part === 'array-key-exists';

$has_empty = $has_empty || $new_type_part_part === 'empty';

$has_falsyish = $has_falsyish
|| $new_type_part_part === 'empty'
|| $new_type_part_part === 'falsy';
Expand All @@ -204,7 +207,8 @@ public static function reconcileKeyedTypes(
$key,
$existing_types,
$code_location,
$has_isset
$has_isset,
$has_empty
);

if ($result_type && empty($result_type->getTypes())) {
Expand Down Expand Up @@ -417,7 +421,8 @@ private static function getValueForKey(
string $key,
array &$existing_keys,
?CodeLocation $code_location,
bool $has_isset
bool $has_isset,
bool $has_empty
) {
$key_parts = self::breakUpPathIntoParts($key);

Expand Down Expand Up @@ -462,12 +467,20 @@ private static function getValueForKey(

foreach ($existing_keys[$base_key]->getTypes() as $existing_key_type_part) {
if ($existing_key_type_part instanceof Type\Atomic\TArray) {
if ($has_empty) {
return null;
}

$new_base_type_candidate = clone $existing_key_type_part->type_params[1];

if ($has_isset) {
$new_base_type_candidate->possibly_undefined = true;
}
} elseif ($existing_key_type_part instanceof Type\Atomic\TList) {
if ($has_empty) {
return null;
}

$new_base_type_candidate = clone $existing_key_type_part->type_param;

if ($has_isset) {
Expand All @@ -476,6 +489,10 @@ private static function getValueForKey(
} elseif (!$existing_key_type_part instanceof Type\Atomic\ObjectLike) {
return Type::getMixed();
} elseif ($array_key[0] === '$') {
if ($has_empty) {
return null;
}

$new_base_type_candidate = $existing_key_type_part->getGenericValueType();
} else {
$array_properties = $existing_key_type_part->properties;
Expand Down
20 changes: 20 additions & 0 deletions tests/AssertTest.php
Expand Up @@ -338,6 +338,26 @@ public function bar(array $args) : void {
}
}'
],
'assertNotEmptyOnArray' => [
'<?php
function foo(bool $c, array $arr) : void {
if ($c && !empty($arr["b"])) {
return;
}
if ($c && rand(0, 1)) {}
}'
],
'assertIssetOnArray' => [
'<?php
function foo(bool $c, array $arr) : void {
if ($c && $arr && isset($arr["b"]) && $arr["b"]) {
return;
}
if ($c && rand(0, 1)) {}
}'
],
];
}
}

0 comments on commit e620c2c

Please sign in to comment.