-
Notifications
You must be signed in to change notification settings - Fork 672
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Instanceof checks aren't properly reconciled in "else" context #9939
Comments
I found these snippets: https://psalm.dev/r/2cf106db54<?php
class X {}
function a(X $x): void {
/** @psalm-suppress RedundantCondition */
if ($x instanceof X) {
$x = 'x';
}
/** @psalm-trace $x */
}
function b(X $x): void {
/** @psalm-suppress RedundantCondition */
if (!$x instanceof X) {
$x = 'x';
}
/** @psalm-trace $x */
}
/** @param class-string<X> $xClass */
function c(X $x, $xClass): void {
if ($x instanceof $xClass) {
$x = 'x';
}
/** @psalm-trace $x */
}
/** @param class-string<X> $xClass */
function d(X $x, $xClass): void {
if (!$x instanceof $xClass) {
$x = 'x';
}
/** @psalm-trace $x */
}
|
Yeah, I remember banging my head on that multiple times :p the issue with $definite_type is that unless a class is final, it's pretty much impossible to know. (Even if there is no child known for this type, it may be a library that expect people to implement their own) There's definitely room for improvement anyway! |
At least for cases where the type after the "instanceof" is a literal (and not a variable) this is relatively simple to fix via a plugin (via AfterExpressionAnalysisEvent for Instanceof_) so that the negation at least reports a redundant condition (https://psalm.dev/r/4ca7336f15) |
I found these snippets: https://psalm.dev/r/4ca7336f15<?php
class X {}
function b(X $x): void {
if (!$x instanceof X) {
$x = 'x';
}
/** @psalm-trace $x */
}
|
Some examples with variable re-definitions: https://psalm.dev/r/2cf106db54
In
a()
,$x
should be'x'
In
b()
,$x
should beX
In
c()
, the instanceof check should not be redundantd()
works correctlyI mainly include the class-string cases because them working (in general) is the cause of the issue. This relates to #6739 and #6746
Specifically (in the negated case) this part of the code:
psalm/src/Psalm/Internal/Type/NegatedAssertionReconciler.php
Lines 198 to 204 in 56d7b37
I'm currently trying to figure out how I can differentiate
class-string<X>
fromX
or'X'
, which would be necessary to fix the issue.Maybe I could implement something similar to
TNamedObject::$definite_class
, e.g. a$definite_type
which would be true if it's definitelyX
/'X'
, but not if it'sclass-string<X>
The text was updated successfully, but these errors were encountered: