1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Fix issue with array unification after scanning

This commit is contained in:
Matthew Brown 2017-11-16 01:11:46 -05:00
parent 36a760657d
commit 7d33db0d19
3 changed files with 62 additions and 7 deletions

View File

@ -172,6 +172,8 @@ class SwitchChecker
if ($possibly_redefined_vars === null) {
$possibly_redefined_vars = $case_redefined_vars;
} else {
$possibly_redefined_vars = [];
foreach ($case_redefined_vars as $var_id => $type) {
if (!isset($possibly_redefined_vars[$var_id])) {
$possibly_redefined_vars[$var_id] = $type;

View File

@ -1113,7 +1113,15 @@ class FetchChecker
}
}
} elseif ($type instanceof Type\Atomic\TArray && $value_index !== null) {
$stmt->inferredType = $type->type_params[$value_index];
if (!isset($stmt->inferredType)) {
$stmt->inferredType = $type->type_params[$value_index];
} else {
$stmt->inferredType = Type::combineUnionTypes(
$stmt->inferredType,
$type->type_params[$value_index]
);
}
if ($stmt->inferredType->isEmpty()) {
if (IssueBuffer::accepts(
new EmptyArrayAccess(
@ -1133,10 +1141,26 @@ class FetchChecker
if ($string_key_value || $int_key_value !== null) {
if ($string_key_value && isset($type->properties[$string_key_value])) {
$has_valid_offset = true;
$stmt->inferredType = clone $type->properties[$string_key_value];
if (!isset($stmt->inferredType)) {
$stmt->inferredType = clone $type->properties[$string_key_value];
} else {
$stmt->inferredType = Type::combineUnionTypes(
$stmt->inferredType,
$type->properties[$string_key_value]
);
}
} elseif ($int_key_value !== null && isset($type->properties[(string)$int_key_value])) {
$has_valid_offset = true;
$stmt->inferredType = clone $type->properties[(string)$int_key_value];
if (!isset($stmt->inferredType)) {
$stmt->inferredType = clone $type->properties[(string)$int_key_value];
} else {
$stmt->inferredType = Type::combineUnionTypes(
$stmt->inferredType,
$type->properties[(string)$int_key_value]
);
}
} else {
$invalid_offset_types[] = '"' . ($string_key_value ?: $int_key_value) . '"';
}
@ -1145,8 +1169,16 @@ class FetchChecker
$used_key_type,
Type::getString()
)) {
if (!isset($stmt->inferredType)) {
$stmt->inferredType = $type->getGenericTypeParam();
} else {
$stmt->inferredType = Type::combineUnionTypes(
$stmt->inferredType,
$type->getGenericTypeParam()
);
}
$has_valid_offset = true;
$stmt->inferredType = $type->getGenericTypeParam();
} else {
$invalid_offset_types[] = 'string';
}
@ -1165,7 +1197,15 @@ class FetchChecker
$has_valid_offset = true;
}
$stmt->inferredType = Type::getString();
if (!isset($stmt->inferredType)) {
$stmt->inferredType = Type::getString();
} else {
$stmt->inferredType = Type::combineUnionTypes(
$stmt->inferredType,
Type::getString()
);
}
continue;
}
@ -1240,7 +1280,7 @@ class FetchChecker
if ($has_valid_offset) {
if (IssueBuffer::accepts(
new PossiblyInvalidArrayOffset(
'Cannot access value on array variable ' . $var_id . ' using ' . $used_key_type
'Cannot access value on variable ' . $var_id . ' using ' . $used_key_type
. ' offset, expecting ' . $invalid_offset_type,
new CodeLocation($statements_checker->getSource(), $stmt)
),
@ -1251,7 +1291,7 @@ class FetchChecker
} else {
if (IssueBuffer::accepts(
new InvalidArrayOffset(
'Cannot access value on array variable ' . $var_id . ' using ' . $used_key_type
'Cannot access value on variable ' . $var_id . ' using ' . $used_key_type
. ' offset, expecting ' . $invalid_offset_type,
new CodeLocation($statements_checker->getSource(), $stmt)
),

View File

@ -119,6 +119,19 @@ class ArrayAccessTest extends TestCase
$y = $x["a"];',
'error_message' => 'PossiblyInvalidArrayOffset',
],
'possiblyInvalidArrayAccessWithNestedArray' => [
'<?php
/**
* @return array<int,array<string,float>>|string
* @return string
*/
function return_array() {
return rand() % 5 > 3 ? [["key" => 3.5]] : "key:3.5";
}
$result = return_array();
$v = $result[0]["key"];',
'error_message' => 'PossiblyInvalidArrayOffset',
],
'possiblyInvalidArrayAccess' => [
'<?php
$a = rand(0, 10) > 5 ? 5 : ["hello"];