diff --git a/src/Psalm/Type/Reconciler.php b/src/Psalm/Type/Reconciler.php index fe14a59a524..958831f9b27 100644 --- a/src/Psalm/Type/Reconciler.php +++ b/src/Psalm/Type/Reconciler.php @@ -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) { @@ -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'; @@ -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())) { @@ -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); @@ -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) { @@ -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; diff --git a/tests/AssertTest.php b/tests/AssertTest.php index eeefc0208e8..58e9efe526a 100644 --- a/tests/AssertTest.php +++ b/tests/AssertTest.php @@ -338,6 +338,26 @@ public function bar(array $args) : void { } }' ], + 'assertNotEmptyOnArray' => [ + ' [ + '