diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php index 8085cd042..8e43ee0f3 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php @@ -15,6 +15,7 @@ use Psalm\Internal\Analyzer\TraitAnalyzer; use Psalm\Internal\Codebase\TaintFlowGraph; use Psalm\Internal\Codebase\VariableUseGraph; use Psalm\Internal\DataFlow\DataFlowNode; +use Psalm\Internal\Type\Comparator\AtomicTypeComparator; use Psalm\Internal\Type\Comparator\TypeComparisonResult; use Psalm\Internal\Type\Comparator\UnionTypeComparator; use Psalm\Internal\Type\TemplateInferredTypeReplacer; @@ -1514,7 +1515,11 @@ class ArrayFetchAnalyzer if ($type->is_list && (!is_numeric($key_value->value) || $key_value->value < 0)) { $expected_offset_types[] = $type->getGenericKeyType(); $has_valid_offset = false; - } elseif (isset($properties[$key_value->value]) || $replacement_type) { + } elseif ((isset($properties[$key_value->value]) && !( + $key_value->value === 0 && AtomicTypeComparator::isLegacyTListLike($type) + )) + || $replacement_type + ) { $has_valid_offset = true; if ($replacement_type) { diff --git a/src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php b/src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php index 9cb7702b2..62a28ec99 100644 --- a/src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php +++ b/src/Psalm/Internal/Type/Comparator/AtomicTypeComparator.php @@ -729,7 +729,7 @@ class AtomicTypeComparator return $input_type_part->getKey() === $container_type_part->getKey(); } - private static function isLegacyTListLike(Atomic $array): bool + public static function isLegacyTListLike(Atomic $array): bool { return $array instanceof TKeyedArray && $array->is_list @@ -739,7 +739,7 @@ class AtomicTypeComparator && $array->properties[0]->equals($array->fallback_params[1], true, true, false) ; } - private static function isLegacyTNonEmptyListLike(Atomic $array): bool + public static function isLegacyTNonEmptyListLike(Atomic $array): bool { return $array instanceof TKeyedArray && $array->is_list