1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Fix #4368 - improve handling of try with finally

This commit is contained in:
Matt Brown 2020-10-20 09:07:10 -04:00
parent b904b1d173
commit 3803bbfce0
5 changed files with 56 additions and 16 deletions

View File

@ -126,10 +126,8 @@ class TryAnalyzer
if (!isset($try_context->vars_in_scope[$var_id])) {
$try_context->vars_in_scope[$var_id] = clone $type;
if (!$stmt->catches) {
$context->vars_in_scope[$var_id]->possibly_undefined = true;
$context->vars_in_scope[$var_id]->possibly_undefined_from_try = true;
}
$context->vars_in_scope[$var_id]->possibly_undefined = true;
$context->vars_in_scope[$var_id]->possibly_undefined_from_try = true;
} else {
$try_context->vars_in_scope[$var_id] = Type::combineUnionTypes(
$try_context->vars_in_scope[$var_id],
@ -444,16 +442,6 @@ class TryAnalyzer
}
}
if ($stmt->catches) {
foreach ($definitely_newly_assigned_var_ids as $var_id => $_) {
if (isset($context->vars_in_scope[$var_id])) {
$new_type = clone $context->vars_in_scope[$var_id];
$new_type->possibly_undefined_from_try = false;
$context->vars_in_scope[$var_id] = $new_type;
}
}
}
if ($context->loop_scope
&& !$try_leaves_loop
&& !in_array(ScopeAnalyzer::ACTION_NONE, $context->loop_scope->final_actions, true)
@ -479,6 +467,13 @@ class TryAnalyzer
/** @var string $var_id */
foreach ($finally_context->assigned_var_ids as $var_id => $_) {
if (isset($context->vars_in_scope[$var_id])) {
if ($context->vars_in_scope[$var_id]->possibly_undefined
&& $context->vars_in_scope[$var_id]->possibly_undefined_from_try
) {
$context->vars_in_scope[$var_id]->possibly_undefined = false;
$context->vars_in_scope[$var_id]->possibly_undefined_from_try = false;
}
$context->vars_in_scope[$var_id] = Type::combineUnionTypes(
$context->vars_in_scope[$var_id],
$finally_context->vars_in_scope[$var_id],
@ -491,6 +486,19 @@ class TryAnalyzer
}
}
foreach ($definitely_newly_assigned_var_ids as $var_id => $_) {
if (isset($context->vars_in_scope[$var_id])) {
$new_type = clone $context->vars_in_scope[$var_id];
if ($new_type->possibly_undefined_from_try) {
$new_type->possibly_undefined = false;
$new_type->possibly_undefined_from_try = false;
}
$context->vars_in_scope[$var_id] = $new_type;
}
}
foreach ($existing_thrown_exceptions as $possibly_thrown_exception => $codelocations) {
foreach ($codelocations as $hash => $codelocation) {
$context->possibly_thrown_exceptions[$possibly_thrown_exception][$hash] = $codelocation;

View File

@ -35,7 +35,10 @@ class UnionTypeComparator
$union_comparison_result->scalar_type_match_found = true;
}
if ($input_type->possibly_undefined && !$container_type->possibly_undefined) {
if ($input_type->possibly_undefined
&& !$input_type->possibly_undefined_from_try
&& !$container_type->possibly_undefined
) {
return false;
}

View File

@ -71,6 +71,7 @@ class TypeExpander
$fleshed_out_type->ignore_nullable_issues = $return_type->ignore_nullable_issues;
$fleshed_out_type->ignore_falsable_issues = $return_type->ignore_falsable_issues;
$fleshed_out_type->possibly_undefined = $return_type->possibly_undefined;
$fleshed_out_type->possibly_undefined_from_try = $return_type->possibly_undefined_from_try;
$fleshed_out_type->by_ref = $return_type->by_ref;
$fleshed_out_type->initialized = $return_type->initialized;
$fleshed_out_type->had_template = $return_type->had_template;

View File

@ -413,7 +413,34 @@ class TryCatchTest extends TestCase
private function workThatMayOrMayNotThrow(): void {}
}'
]
],
'finallyArgIsNotUndefinedIfSet' => [
'<?php
function fooFunction (): string {
try{
$foo = "foo";
} finally {
/** @psalm-suppress PossiblyUndefinedVariable */
echo $foo;
$foo = "bar";
}
return $foo;
}'
],
'allowReturningPossiblyUndefinedFromTry' => [
'<?php
function fooFunction (): string {
try{
$foo = "foo";
} finally {
/** @psalm-suppress PossiblyUndefinedVariable */
echo $foo;
}
return $foo;
}'
],
];
}

View File

@ -1276,6 +1276,7 @@ class UnusedVariableTest extends TestCase
$a = 4;
throw new Exception("bad");
} finally {
/** @psalm-suppress PossiblyUndefinedVariable */
echo $a;
}
}'