Hello. I found a situation in which the code analyzer gets confused about the type of an object after instanceof. In this case, $myConcreteClass will always be instanceof MyConcreteClass. But after the condition to check if ($myConcreteClass instanceof MyInterface) is true, the code analyzer no longer recognizes $myConcreteClass as MyConcreteClass in that block even though it is indeed instanceof MyConcreteClass which also implements MyInterface. Could the analyzer be improved to recognize that $myConcreteClass is both MyConcreteClass|MyInterface? Here's the snippet with the error:
<?php
interface MyInterface
{
public function mySecondMethod(string $result);
}
abstract class MyAbstractClass
{
abstract public function myMethod() : string;
}
class MyConcreteClass extends MyAbstractClass implements MyInterface
{
public function myMethod() : string
{
return 'Hello World';
}
public function mySecondMethod(string $result)
{
echo $result;
}
}
class Test
{
private MyConcreteClass $myConcreteClass;
public function testTypeHinting(MyConcreteClass $myConcreteClass)
{
if ($myConcreteClass instanceof MyInterface) {
$result = $myConcreteClass->myMethod(); // Warning: Call to unknown method: MyInterface::myMethod() PHP(PHP0418)
$myConcreteClass->mySecondMethod($result);
}
else {
$myConcreteClass->myMethod();
}
}
}
Another case where this happens is in the following modified MyAbstractClass. Since $this will always be an instanceof MyAbstractClass, should the code analyzer interpret it inside the if block as MyAbstractClass|MyInterface?
class MyAbstractClass
{
abstract public function myMethod() : string;
public function testThisImplementsInterface()
{
if ($this instanceof MyInterface)
{
$result = $myConcreteClass->myMethod(); // Warning: Call to unknown method: MyInterface::myMethod() PHP(PHP0418)
$this->mySecondMethod($result);
}
}
}
Thank you!