diff --git a/src/Psalm/Checker/Statements/Block/IfChecker.php b/src/Psalm/Checker/Statements/Block/IfChecker.php index 587ae2f28..6c0e92d8c 100644 --- a/src/Psalm/Checker/Statements/Block/IfChecker.php +++ b/src/Psalm/Checker/Statements/Block/IfChecker.php @@ -62,6 +62,8 @@ class IfChecker $context->inside_conditional = true; + $pre_condition_vars_in_scope = $context->vars_in_scope; + $referenced_var_ids = $context->referenced_var_ids; $context->referenced_var_ids = []; @@ -144,6 +146,20 @@ class IfChecker // get all the var ids that were referened in the conditional, but not assigned in it $cond_referenced_var_ids = array_diff_key($cond_referenced_var_ids, $cond_assigned_var_ids); + // remove all newly-asserted var ids too + $cond_referenced_var_ids = array_filter( + $cond_referenced_var_ids, + /** + * @param string $var_id + * + * @return bool + */ + function ($var_id) use ($pre_condition_vars_in_scope) { + return isset($pre_condition_vars_in_scope[$var_id]); + }, + ARRAY_FILTER_USE_KEY + ); + $if_context->inside_conditional = false; $mixed_var_ids = []; diff --git a/src/Psalm/Checker/Statements/Expression/BinaryOpChecker.php b/src/Psalm/Checker/Statements/Expression/BinaryOpChecker.php index f87a352eb..a4100c58d 100644 --- a/src/Psalm/Checker/Statements/Expression/BinaryOpChecker.php +++ b/src/Psalm/Checker/Statements/Expression/BinaryOpChecker.php @@ -55,6 +55,7 @@ class BinaryOpChecker $pre_referenced_var_ids = $context->referenced_var_ids; $context->referenced_var_ids = []; + $original_vars_in_scope = $context->vars_in_scope; $pre_assigned_var_ids = $context->assigned_var_ids; @@ -69,6 +70,20 @@ class BinaryOpChecker $new_referenced_var_ids = array_diff_key($new_referenced_var_ids, $new_assigned_var_ids); + // remove all newly-asserted var ids too + $new_referenced_var_ids = array_filter( + $new_referenced_var_ids, + /** + * @param string $var_id + * + * @return bool + */ + function ($var_id) use ($original_vars_in_scope) { + return isset($original_vars_in_scope[$var_id]); + }, + ARRAY_FILTER_USE_KEY + ); + $simplified_clauses = AlgebraChecker::simplifyCNF(array_merge($context->clauses, $if_clauses)); $left_type_assertions = AlgebraChecker::getTruthsFromFormula($simplified_clauses); diff --git a/src/Psalm/Type.php b/src/Psalm/Type.php index 45050f599..fbc39d3fe 100644 --- a/src/Psalm/Type.php +++ b/src/Psalm/Type.php @@ -3,7 +3,6 @@ namespace Psalm; use Psalm\Exception\TypeParseTreeException; use Psalm\Type\Atomic; -use Psalm\Type\Atomic\Generic; use Psalm\Type\Atomic\ObjectLike; use Psalm\Type\Atomic\TArray; use Psalm\Type\Atomic\TBool; diff --git a/src/Psalm/Type/Atomic/Fn.php b/src/Psalm/Type/Atomic/Fn.php index 0877a7bff..cf10c1da6 100644 --- a/src/Psalm/Type/Atomic/Fn.php +++ b/src/Psalm/Type/Atomic/Fn.php @@ -4,6 +4,9 @@ namespace Psalm\Type\Atomic; use Psalm\FunctionLikeParameter; use Psalm\Type\Union; +/** + * Represents a closure where we know the return type and params + */ class Fn extends TNamedObject { /** diff --git a/src/Psalm/Type/Atomic/Generic.php b/src/Psalm/Type/Atomic/Generic.php deleted file mode 100644 index 5fcd7d5cf..000000000 --- a/src/Psalm/Type/Atomic/Generic.php +++ /dev/null @@ -1,6 +0,0 @@ -types as $type) { - if ($type instanceof Atomic\Generic) { + if ($type instanceof Atomic\TGenericObject || $type instanceof Atomic\TArray) { return true; } } diff --git a/tests/RedundantConditionTest.php b/tests/RedundantConditionTest.php index 6b38e7e26..7ee8d81c8 100644 --- a/tests/RedundantConditionTest.php +++ b/tests/RedundantConditionTest.php @@ -303,6 +303,18 @@ class RedundantConditionTest extends TestCase 'assertions' => [], 'error_levels' => ['RedundantConditionGivenDocblockType'], ], + 'nullToMixedWithNullCheckNoContinue' => [ + ' 3) {}', + 'assignments' => [], + 'error_levels' => [], + ], ]; }