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!