mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 04:45:20 +01:00
Fix #2408 - existing offsets checked with isset should be valid
This commit is contained in:
parent
456aa1c569
commit
af28d650f3
@ -144,6 +144,7 @@ class ArrayAssignmentAnalyzer
|
|||||||
|
|
||||||
$parent_var_id = null;
|
$parent_var_id = null;
|
||||||
|
|
||||||
|
$offset_already_existed = false;
|
||||||
$full_var_id = true;
|
$full_var_id = true;
|
||||||
|
|
||||||
$child_stmt = null;
|
$child_stmt = null;
|
||||||
@ -330,6 +331,14 @@ class ArrayAssignmentAnalyzer
|
|||||||
&& !$child_stmt_var_type->hasObjectType()
|
&& !$child_stmt_var_type->hasObjectType()
|
||||||
) {
|
) {
|
||||||
$array_var_id = $root_var_id . implode('', $var_id_additions);
|
$array_var_id = $root_var_id . implode('', $var_id_additions);
|
||||||
|
$parent_var_id = $root_var_id . implode('', \array_slice($var_id_additions, 0, -1));
|
||||||
|
|
||||||
|
if (isset($context->vars_in_scope[$array_var_id])
|
||||||
|
&& !$context->vars_in_scope[$array_var_id]->possibly_undefined
|
||||||
|
) {
|
||||||
|
$offset_already_existed = true;
|
||||||
|
}
|
||||||
|
|
||||||
$context->vars_in_scope[$array_var_id] = clone $assignment_type;
|
$context->vars_in_scope[$array_var_id] = clone $assignment_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,10 +528,21 @@ class ArrayAssignmentAnalyzer
|
|||||||
$array_atomic_key_type = Type::getMixed();
|
$array_atomic_key_type = Type::getMixed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($offset_already_existed
|
||||||
|
&& $child_stmt
|
||||||
|
&& $parent_var_id
|
||||||
|
&& ($parent_type = $context->vars_in_scope[$parent_var_id] ?? null)
|
||||||
|
&& $parent_type->hasList()
|
||||||
|
) {
|
||||||
|
$array_atomic_type = new TNonEmptyList(
|
||||||
|
$current_type,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
$array_atomic_type = new TNonEmptyArray([
|
$array_atomic_type = new TNonEmptyArray([
|
||||||
$array_atomic_key_type,
|
$array_atomic_key_type,
|
||||||
$current_type,
|
$current_type,
|
||||||
]);
|
]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$array_atomic_type = new TNonEmptyList($current_type);
|
$array_atomic_type = new TNonEmptyList($current_type);
|
||||||
}
|
}
|
||||||
|
@ -618,6 +618,14 @@ class Union
|
|||||||
return isset($this->types['array']);
|
return isset($this->types['array']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasList()
|
||||||
|
{
|
||||||
|
return isset($this->types['array']) && $this->types['array'] instanceof Atomic\TList;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -1273,6 +1273,19 @@ class ArrayAssignmentTest extends TestCase
|
|||||||
'$arr3' => 'array{1: int, 2: int, 3: int, 4: int}',
|
'$arr3' => 'array{1: int, 2: int, 3: int, 4: int}',
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
'listPropertyAssignmentAfterIsset' => [
|
||||||
|
'<?php
|
||||||
|
class Collection {
|
||||||
|
/** @var list<string> */
|
||||||
|
private $list = [];
|
||||||
|
|
||||||
|
public function override(int $offset): void {
|
||||||
|
if (isset($this->list[$offset])) {
|
||||||
|
$this->list[$offset] = "a";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user