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:
parent
d94f7bd553
commit
0d7c5a2d8e
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,7 +80,7 @@ class ConditionalTest extends TestCase
|
||||
}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['DocblockTypeContradiction'],
|
||||
'ignored_issues' => ['DocblockTypeContradiction', 'TypeDoesNotContainType'],
|
||||
],
|
||||
'notInstanceof' => [
|
||||
'code' => '<?php
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user