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

Fix docblock mixed escape hatch

revert https://github.com/vimeo/psalm/pull/7663 including previous from_docblock Mixed assignments, as the tests required 2 suppressions and created an escape hatch via mixed on higher psalm error levels, where mixed isn't reported, thus hiding potentially fatal bugs.
It's still possible to run the validation of docblock docs though: a @var declaration that contains both possible types, to ensure later code won't escape any checks (and no @psalm-suppress needed at all)

This is also a required preparation to fix some isset issues of https://github.com/vimeo/psalm/issues/9759
This commit is contained in:
kkmuffme 2023-11-18 11:03:17 +01:00
parent d94f7bd553
commit 0d7c5a2d8e
5 changed files with 44 additions and 102 deletions

View File

@ -304,9 +304,7 @@ final class NegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
return $existing_var_type;

View File

@ -40,7 +40,6 @@ use Psalm\Type\Atomic\TCallableObject;
use Psalm\Type\Atomic\TCallableString;
use Psalm\Type\Atomic\TClassConstant;
use Psalm\Type\Atomic\TClassString;
use Psalm\Type\Atomic\TEmptyMixed;
use Psalm\Type\Atomic\TFalse;
use Psalm\Type\Atomic\TFloat;
use Psalm\Type\Atomic\TGenericObject;
@ -976,9 +975,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? new Union([new TEmptyMixed()])
: Type::getNever();
return Type::getNever();
}
/**
@ -1071,9 +1068,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? new Union([new TEmptyMixed()])
: Type::getNever();
return Type::getNever();
}
/**
@ -1165,9 +1160,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? new Union([new TEmptyMixed()])
: Type::getNever();
return Type::getNever();
}
/**
@ -1244,9 +1237,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1329,9 +1320,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1414,9 +1403,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1489,9 +1476,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1582,9 +1567,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1702,9 +1685,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1760,9 +1741,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1832,9 +1811,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1895,9 +1872,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1939,9 +1914,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
return $intersection;
@ -2260,9 +2233,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -2375,9 +2346,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -2485,9 +2454,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -2725,9 +2692,7 @@ final class SimpleAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**

View File

@ -141,9 +141,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
}
}
return $existing_var_type->from_docblock
? Type::getNull()
: Type::getNever();
return Type::getNever();
}
return Type::getNull();
@ -507,9 +505,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -703,9 +699,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -785,9 +779,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -867,9 +859,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -924,9 +914,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = 2;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
if ($redundant) {
@ -1139,9 +1127,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1240,9 +1226,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1336,9 +1320,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1438,9 +1420,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1535,9 +1515,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1641,9 +1619,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1746,9 +1722,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**
@ -1818,9 +1792,7 @@ final class SimpleNegatedAssertionReconciler extends Reconciler
$failed_reconciliation = Reconciler::RECONCILIATION_EMPTY;
return $existing_var_type->from_docblock
? Type::getMixed()
: Type::getNever();
return Type::getNever();
}
/**

View File

@ -80,7 +80,7 @@ class ConditionalTest extends TestCase
}
}',
'assertions' => [],
'ignored_issues' => ['DocblockTypeContradiction'],
'ignored_issues' => ['DocblockTypeContradiction', 'TypeDoesNotContainType'],
],
'notInstanceof' => [
'code' => '<?php

View File

@ -2142,12 +2142,19 @@ class UnusedVariableTest extends TestCase
* @param bool $b
*/
function validate($b, string $source) : void {
/**
* @psalm-suppress DocblockTypeContradiction
* @psalm-suppress MixedAssignment
*/
/** @var bool|string $b */
if (!is_bool($b)) {
$source = $b;
$b = false;
}
/**
* test to ensure $b is only type bool and not bool|string anymore
* after we set $b = false; inside the condition above
* @psalm-suppress TypeDoesNotContainType
*/
if (!is_bool($b)) {
echo "this should not happen";
}
print_r($source);