Skip to content

Commit

Permalink
Don't refine empty/falsy assertions on templates inside loops
Browse files Browse the repository at this point in the history
  • Loading branch information
orklah committed Oct 23, 2021
1 parent 7bb37af commit fb5a652
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 14 deletions.
18 changes: 11 additions & 7 deletions src/Psalm/Internal/Type/SimpleAssertionReconciler.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ public static function reconcile(
$code_location,
$suppressed_issues,
$failed_reconciliation,
false
false,
$inside_loop
);
}

Expand Down Expand Up @@ -2218,7 +2219,8 @@ private static function reconcileFalsyOrEmpty(
?CodeLocation $code_location,
array $suppressed_issues,
int &$failed_reconciliation,
bool $recursive_check
bool $recursive_check,
bool $inside_loop
) : Union {
$old_var_type_string = $existing_var_type->getId();
$existing_var_atomic_types = $existing_var_type->getAtomicTypes();
Expand Down Expand Up @@ -2363,20 +2365,22 @@ private static function reconcileFalsyOrEmpty(
if (!$existing_var_atomic_type->as->isMixed()) {
$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,
$existing_var_atomic_type->as,
$tmp_existing_var_atomic_type->as,
$key,
$negated,
$code_location,
$suppressed_issues,
$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);
}
}
Expand Down
18 changes: 11 additions & 7 deletions src/Psalm/Internal/Type/SimpleNegatedAssertionReconciler.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ public static function reconcile(
$failed_reconciliation,
$is_equality,
$is_strict_equality,
false
false,
$inside_loop
);
}

Expand Down Expand Up @@ -570,7 +571,8 @@ private static function reconcileFalsyOrEmpty(
int &$failed_reconciliation,
bool $is_equality,
bool $is_strict_equality,
bool $recursive_check
bool $recursive_check,
bool $inside_loop
) : Type\Union {
$old_var_type_string = $existing_var_type->getId();
$existing_var_atomic_types = $existing_var_type->getAtomicTypes();
Expand Down Expand Up @@ -728,22 +730,24 @@ private static function reconcileFalsyOrEmpty(
if (!$is_equality && !$existing_var_atomic_type->as->isMixed()) {
$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,
$existing_var_atomic_type->as,
$tmp_existing_var_atomic_type->as,
$key,
$negated,
$code_location,
$suppressed_issues,
$template_did_fail,
$is_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);
}
}
Expand Down
15 changes: 15 additions & 0 deletions tests/Template/ConditionalReturnTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,21 @@ function toList(?iterable $iterable): ?array {
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 [];
}
'
],
];
}
}

0 comments on commit fb5a652

Please sign in to comment.