Avoid false inference with instanceof#3657
Conversation
0b629c6 to
649d831
Compare
| $classType = $scope->getType($expr->class); | ||
| $type = TypeTraverser::map($classType, static function (Type $type, callable $traverse): Type { | ||
| $uncertainty = false; | ||
| $type = TypeTraverser::map($classType, static function (Type $type, callable $traverse) use (&$uncertainty): Type { |
There was a problem hiding this comment.
I tried to copy the logic from MutatingScope::inferType with an uncertainty boolean:
phpstan-src/src/Analyser/MutatingScope.php
Lines 960 to 989 in adcabb3
| } | ||
|
|
||
| assertType('Throwable', $e1); | ||
| assertType('bool', $e1 instanceof $e2); // could be false |
There was a problem hiding this comment.
I'm unsure to say PHPStan that
- $e1 is not
Throwable~LogicExceptionbut stillThrowable - the specific expression
$e1 instanceof $e2is false because already computed.
But I'm not sure it's a big loss.
| assertType(self::class, $foo); | ||
| } else { | ||
| assertType('InstanceOfClassString\Foo~InstanceOfClassString\Bar', $foo); | ||
| assertType('InstanceOfClassString\Foo', $foo); |
There was a problem hiding this comment.
If I call doFar($foo, $superBar) with superBar a class extending bar,
$foo is only Foo~SuperBar but can still being Bar.
| assertType('mixed~InstanceOfNamespace\Foo', $subject); | ||
| assertType('false', $subject instanceof Foo); | ||
| assertType('false', $subject instanceof $classString); | ||
| assertType('mixed', $subject); |
There was a problem hiding this comment.
if I pass class-string<SuperFoo> for $classString the subject will only be mixed~SuperFoo but not mixed~Foo.
| } else { | ||
| assertType('object~InstanceOfNamespace\Foo', $object); | ||
| assertType('false', $object instanceof $classString); | ||
| assertType('object', $object); |
| $tipText, | ||
| ], | ||
| [ | ||
| 'Instanceof between T of Exception and Error will always evaluate to false.', |
There was a problem hiding this comment.
Code is
/**
* @template T of \Exception
* @param T $e
*/
public function test(\Throwable $t, $e): void {
if ($t instanceof $e) return;
if ($e instanceof $t) return;
}
if I call it with test(new \Exception(), new \LogicException()) the second if is true.
|
This pull request has been marked as ready for review. |
|
Thank you! |
No description provided.