$formula_1 * @param array $formula_2 * @param array $new_assigned_var_ids * * @return void */ public static function checkForParadox( array $formula_1, array $formula_2, StatementsAnalyzer $statements_analyzer, PhpParser\Node $stmt, array $new_assigned_var_ids ) { try { $negated_formula2 = Algebra::negateFormula($formula_2); } catch (\Psalm\Exception\ComplicatedExpressionException $e) { return; } $formula_1_hashes = []; foreach ($formula_1 as $formula_1_clause) { $formula_1_hashes[$formula_1_clause->hash] = true; } $formula_2_hashes = []; foreach ($formula_2 as $formula_2_clause) { $hash = $formula_2_clause->hash; if (!$formula_2_clause->generated && !$formula_2_clause->wedge && $formula_2_clause->reconcilable && (isset($formula_1_hashes[$hash]) || isset($formula_2_hashes[$hash])) && !array_intersect_key($new_assigned_var_ids, $formula_2_clause->possibilities) ) { if (IssueBuffer::accepts( new RedundantCondition( $formula_2_clause . ' has already been asserted', new CodeLocation($statements_analyzer, $stmt), null ), $statements_analyzer->getSuppressedIssues() )) { // fall through } } foreach ($formula_2_clause->possibilities as $key => $values) { if (!$formula_2_clause->generated && count($values) > 1 && !isset($new_assigned_var_ids[$key]) && count(array_unique($values)) < count($values) ) { if (IssueBuffer::accepts( new ParadoxicalCondition( 'Found a redundant condition when evaluating assertion (' . $formula_2_clause . ')', new CodeLocation($statements_analyzer, $stmt) ), $statements_analyzer->getSuppressedIssues() )) { // fall through } } } $formula_2_hashes[$hash] = true; } // remove impossible types foreach ($negated_formula2 as $clause_2) { if (count($negated_formula2) === 1) { foreach ($clause_2->possibilities as $key => $values) { if (count($values) > 1 && !isset($new_assigned_var_ids[$key]) && count(array_unique($values)) < count($values) ) { if (IssueBuffer::accepts( new RedundantCondition( 'Found a redundant condition when evaluating ' . $key, new CodeLocation($statements_analyzer, $stmt), null ), $statements_analyzer->getSuppressedIssues() )) { // fall through } } } } if (!$clause_2->reconcilable || $clause_2->wedge) { continue; } foreach ($formula_1 as $clause_1) { if ($clause_2 === $clause_1 || !$clause_1->reconcilable || $clause_1->wedge) { continue; } $clause_2_contains_1_possibilities = true; foreach ($clause_1->possibilities as $key => $keyed_possibilities) { if (!isset($clause_2->possibilities[$key])) { $clause_2_contains_1_possibilities = false; break; } if ($clause_2->possibilities[$key] != $keyed_possibilities) { $clause_2_contains_1_possibilities = false; break; } } if ($clause_2_contains_1_possibilities) { $clause_2_string = (string) $clause_2; $clause_1_string = (string) $clause_1; if ($clause_2_string === $clause_1_string) { $paradox_message = 'Encountered a duplicate check for (' . $clause_2_string . ')'; } else { $paradox_message = 'Encountered a paradox when evaluating the conditionals (' . $clause_2_string . ') and (' . $clause_1_string . ')'; } if (IssueBuffer::accepts( new ParadoxicalCondition( $paradox_message, new CodeLocation($statements_analyzer, $stmt) ), $statements_analyzer->getSuppressedIssues() )) { // fall through } return; } } } } }