phptools-docs
phptools-docs copied to clipboard
Type detection fails for generic parameter from a method when implementing dependent interfaces
Hi, I found an issue with type detection when:
- parent interface uses interface-level generic parameter in method signature
- another child interface extends parent interface, replaying the generic
- class then implements both interfaces, defining the generic type on both
- result: method parameter in the class fails type detection and falls back to plain type
Here's a replication:
<?php
interface Thing {}
class Item implements Thing
{
public int $field = 10;
}
/**
* @template T of Thing
*/
interface IParent
{
/**
* @param T $para
*/
public function foo(Thing $para);
}
/**
* @template T of Thing
* @extends IParent<T>
*/
interface IChild extends IParent {}
/**
* @implements IParent<Item>
*/
class Bar implements IParent
{
public function foo(Thing $para): void
{
// all good
$para->field;
}
}
/**
* @implements IParent<Item>
* @implements IChild<Item>
*/
class Foo implements IChild, IParent
{
public function foo(Thing $para): void
{
// Undefined property: Thing::$field
// Expected: same behaviour as Bar
$para->field;
}
}
It's an excellent extension otherwise, thanks for the hard work!
Thank for the code sample! We're happy you like our extension :)
I'll try to make this working in the next update;
heya, I discovered that actually it doesn't matter as much on dependent generic interfaces, but maybe on the order of interfaces instead? This appears to replicate order dependence
<?php declare(strict_types = 1);
interface Thing {}
class Item implements Thing
{
public int $field = 10;
}
/**
* @template T of Thing
*/
interface IParent
{
/**
* @param T $para
*/
public function foo(Thing $para);
}
interface IChild {}
/**
* @implements IParent<Item>
*/
class Bar implements IParent, IChild
{
public function foo(Thing $para): void
{
// all good
$para->field;
}
}
/**
* @implements IParent<Item>
*/
class Foo implements IChild, IParent
{
public function foo(Thing $para): void
{
// Undefined property: Thing::$field
$para->field;
}
}
Thank you again.
The recent update fixes that already (the first test case https://github.com/DEVSENSE/phptools-docs/issues/667#issue-2546563927):