Skip to content
Permalink
Browse files

Refine lists with object-like array types

Fixes #2357
  • Loading branch information
muglug committed Nov 26, 2019
1 parent 532e2d6 commit 842b2a53df68d75713569f5aac39f85f89ee4c13
Showing with 68 additions and 0 deletions.
  1. +42 −0 src/Psalm/Internal/Type/AssertionReconciler.php
  2. +26 −0 tests/AssertAnnotationTest.php
@@ -2125,6 +2125,8 @@ private static function filterTypeWithAnother(
) : Type\Union {
$matching_atomic_types = [];
$has_cloned_type = false;
foreach ($new_type->getTypes() as $new_type_part) {
$has_local_match = false;
@@ -2167,6 +2169,42 @@ private static function filterTypeWithAnother(
$matching_atomic_types[] = $existing_type_part;
}
if ($new_type_part instanceof Type\Atomic\ObjectLike
&& $existing_type_part instanceof Type\Atomic\TList
) {
$new_type_key = $new_type_part->getGenericKeyType();
$new_type_value = $new_type_part->getGenericValueType();
if (!$new_type_key->hasString()) {
$has_param_match = false;
$new_type_value = self::filterTypeWithAnother(
$codebase,
$existing_type_part->type_param,
$new_type_value,
$template_type_map,
$has_param_match,
$any_scalar_type_match_found
);
$hybrid_type_part = new Type\Atomic\ObjectLike($new_type_part->properties);
$hybrid_type_part->previous_key_type = Type::getInt();
$hybrid_type_part->previous_value_type = $new_type_value;
$hybrid_type_part->is_list = true;
if (!$has_cloned_type) {
$new_type = clone $new_type;
}
$has_local_match = true;
$new_type->removeType($key);
$new_type->addType($hybrid_type_part);
continue;
}
}
if (($new_type_part instanceof Type\Atomic\TGenericObject
|| $new_type_part instanceof Type\Atomic\TArray
|| $new_type_part instanceof Type\Atomic\TIterable)
@@ -2232,6 +2270,10 @@ function ($extra_type) use ($codebase) {
}
)
) {
if (!$has_cloned_type) {
$new_type = clone $new_type;
}
$new_type->removeType($key);
$new_type->addType($existing_type_part);
$new_type->from_docblock = $existing_type_part->from_docblock;
@@ -666,6 +666,32 @@ function f($_p): bool {
if (rand(0, 1) && f($q)) {}
if (!f($q)) {}'
],
'assertDifferentTypeOfArray' => [
'<?php
/**
* @psalm-assert array{0: string, 1: string} $value
* @param mixed $value
*/
function isStringTuple($value): void {
if (!is_array($value)
|| !isset($value[0])
|| !isset($value[1])
|| !is_string($value[0])
|| !is_string($value[1])
) {
throw new \Exception("bad");
}
}
$s = "";
$parts = explode(":", $s, 2);
isStringTuple($parts);
echo $parts[0];
echo $parts[1];'
],
];
}

0 comments on commit 842b2a5

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