1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 12:55:26 +01:00

Don't refine empty/falsy assertions on templates inside loops

This commit is contained in:
orklah 2021-10-23 11:17:47 +02:00
parent 7bb37af1e5
commit fb5a652e18
3 changed files with 37 additions and 14 deletions

View File

@ -143,7 +143,8 @@ class SimpleAssertionReconciler extends \Psalm\Type\Reconciler
$code_location, $code_location,
$suppressed_issues, $suppressed_issues,
$failed_reconciliation, $failed_reconciliation,
false false,
$inside_loop
); );
} }
@ -2218,7 +2219,8 @@ class SimpleAssertionReconciler extends \Psalm\Type\Reconciler
?CodeLocation $code_location, ?CodeLocation $code_location,
array $suppressed_issues, array $suppressed_issues,
int &$failed_reconciliation, int &$failed_reconciliation,
bool $recursive_check bool $recursive_check,
bool $inside_loop
) : Union { ) : Union {
$old_var_type_string = $existing_var_type->getId(); $old_var_type_string = $existing_var_type->getId();
$existing_var_atomic_types = $existing_var_type->getAtomicTypes(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes();
@ -2363,20 +2365,22 @@ class SimpleAssertionReconciler extends \Psalm\Type\Reconciler
if (!$existing_var_atomic_type->as->isMixed()) { if (!$existing_var_atomic_type->as->isMixed()) {
$template_did_fail = 0; $template_did_fail = 0;
$existing_var_atomic_type = clone $existing_var_atomic_type; $tmp_existing_var_atomic_type = clone $existing_var_atomic_type;
$existing_var_atomic_type->as = self::reconcileFalsyOrEmpty( $reconciled_type = self::reconcileFalsyOrEmpty(
$assertion, $assertion,
$existing_var_atomic_type->as, $tmp_existing_var_atomic_type->as,
$key, $key,
$negated, $negated,
$code_location, $code_location,
$suppressed_issues, $suppressed_issues,
$template_did_fail, $template_did_fail,
$recursive_check $recursive_check,
$inside_loop
); );
if (!$template_did_fail) { if (!$template_did_fail && !$inside_loop) {
$existing_var_atomic_type->as = $reconciled_type;
$existing_var_type->addType($existing_var_atomic_type); $existing_var_type->addType($existing_var_atomic_type);
} }
} }

View File

@ -180,7 +180,8 @@ class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation, $failed_reconciliation,
$is_equality, $is_equality,
$is_strict_equality, $is_strict_equality,
false false,
$inside_loop
); );
} }
@ -570,7 +571,8 @@ class SimpleNegatedAssertionReconciler extends Reconciler
int &$failed_reconciliation, int &$failed_reconciliation,
bool $is_equality, bool $is_equality,
bool $is_strict_equality, bool $is_strict_equality,
bool $recursive_check bool $recursive_check,
bool $inside_loop
) : Type\Union { ) : Type\Union {
$old_var_type_string = $existing_var_type->getId(); $old_var_type_string = $existing_var_type->getId();
$existing_var_atomic_types = $existing_var_type->getAtomicTypes(); $existing_var_atomic_types = $existing_var_type->getAtomicTypes();
@ -728,11 +730,11 @@ class SimpleNegatedAssertionReconciler extends Reconciler
if (!$is_equality && !$existing_var_atomic_type->as->isMixed()) { if (!$is_equality && !$existing_var_atomic_type->as->isMixed()) {
$template_did_fail = 0; $template_did_fail = 0;
$existing_var_atomic_type = clone $existing_var_atomic_type; $tmp_existing_var_atomic_type = clone $existing_var_atomic_type;
$existing_var_atomic_type->as = self::reconcileFalsyOrEmpty( $reconciled_type = self::reconcileFalsyOrEmpty(
$assertion, $assertion,
$existing_var_atomic_type->as, $tmp_existing_var_atomic_type->as,
$key, $key,
$negated, $negated,
$code_location, $code_location,
@ -740,10 +742,12 @@ class SimpleNegatedAssertionReconciler extends Reconciler
$template_did_fail, $template_did_fail,
$is_equality, $is_equality,
$is_strict_equality, $is_strict_equality,
true true,
$inside_loop
); );
if (!$template_did_fail) { if (!$template_did_fail && !$inside_loop) {
$existing_var_atomic_type->as = $reconciled_type;
$existing_var_type->addType($existing_var_atomic_type); $existing_var_type->addType($existing_var_atomic_type);
} }
} }

View File

@ -811,6 +811,21 @@ class ConditionalReturnTypeTest extends TestCase
return iterator_to_array($iterable, false); return iterator_to_array($iterable, false);
}' }'
], ],
'dontChokeOnFalsyAssertionsWithTemplatesInLoop' => [
'<?php
/**
* @psalm-return ($list_output is true ? list : array)
*/
function scope(bool $list_output = true): array
{
for ($i = 0; $i < 5; $i++) {
$list_output ? [] : [];
}
return [];
}
'
],
]; ];
} }
} }