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

Fix overeager inference

This commit is contained in:
Matt Brown 2020-11-03 16:44:24 -05:00 committed by Daniil Gentili
parent d4846b14e6
commit 8b44459c7c
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
7 changed files with 49 additions and 6 deletions

View File

@ -248,6 +248,10 @@ class Algebra
}
foreach ($clause->possibilities as $var => $possible_types) {
if ($var[0] === '*') {
continue;
}
// if there's only one possible type, return it
if (count($clause->possibilities) === 1 && count($possible_types) === 1) {
$possible_type = array_pop($possible_types);
@ -551,6 +555,13 @@ class Algebra
*/
public static function negateFormula(array $clauses): array
{
$clauses = array_filter(
$clauses,
function ($clause) {
return $clause->reconcilable;
}
);
if (!$clauses) {
$cond_id = \mt_rand(0, 100000000);
return [new Clause([], $cond_id, $cond_id, true)];

View File

@ -350,6 +350,10 @@ class FormulaGenerator
return $clauses;
}
return [new Clause([], $conditional_object_id, $creating_object_id, true)];
/** @psalm-suppress MixedOperand */
$conditional_ref = '*' . $conditional->getAttribute('startFilePos')
. ':' . $conditional->getAttribute('endFilePos');
return [new Clause([$conditional_ref => ['!falsy']], $conditional_object_id, $creating_object_id)];
}
}

View File

@ -27,7 +27,7 @@ class AlgebraAnalyzer
*
* @param list<Clause> $formula_1
* @param list<Clause> $formula_2
* @param array<string, mixed> $new_assigned_var_ids
* @param array<string, int> $new_assigned_var_ids
*/
public static function checkForParadox(
array $formula_1,

View File

@ -307,6 +307,8 @@ class IfAnalyzer
$if_scope->if_cond_changed_var_ids = $changed_var_ids;
}
$if_context->reconciled_expression_clauses = [];
$old_if_context = clone $if_context;
$context->vars_possibly_in_scope = array_merge(
$if_context->vars_possibly_in_scope,

View File

@ -120,10 +120,7 @@ class MethodCallPurityAnalyzer
&& !$method_storage->mutation_free
&& !$method_pure_compatible
) {
if (!$method_storage->mutation_free) {
$statements_analyzer->getSource()->inferred_has_mutation = true;
}
$statements_analyzer->getSource()->inferred_has_mutation = true;
$statements_analyzer->getSource()->inferred_impure = true;
}

View File

@ -55,6 +55,19 @@ class AlgebraTest extends TestCase
$this->assertSame(['$b' => ['falsy']], $negated_formula[2]->possibilities);
}
public function testNegateFormulaWithUnreconcilableTerm(): void
{
$formula = [
new Clause(['$a' => ['int']], 1, 1),
new Clause(['$b' => ['int']], 1, 2, false, false),
];
$negated_formula = Algebra::negateFormula($formula);
$this->assertCount(1, $negated_formula);
$this->assertSame(['$a' => ['!int']], $negated_formula[0]->possibilities);
}
public function testCombinatorialExpansion(): void
{
$dnf = '<?php ($b0 === true && $b4 === true && $b8 === true)

View File

@ -2958,6 +2958,22 @@ class ConditionalTest extends \Psalm\Tests\TestCase
return $pos;
}'
],
'usedAssertedVarButNotWithStrongerTypeGuarantee' => [
'<?php
function broken(bool $b, ?User $u) : void {
if ($b || (rand(0, 1) && (!$u || takesUser($u)))) {
return;
}
if ($u) {}
}
class User {}
function takesUser(User $a) : bool {
return true;
}'
],
];
}