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:
parent
b904b1d173
commit
3803bbfce0
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -1276,6 +1276,7 @@ class UnusedVariableTest extends TestCase
|
||||
$a = 4;
|
||||
throw new Exception("bad");
|
||||
} finally {
|
||||
/** @psalm-suppress PossiblyUndefinedVariable */
|
||||
echo $a;
|
||||
}
|
||||
}'
|
||||
|
Loading…
Reference in New Issue
Block a user