Describe the bug
I am using query builders that I implement as iterable collections that I extend to provide specific functionality for matching entity subtypes.
In practice, this works fine, but I am having difficulty figuring out if I am attempting to annotate this correctly or if it isn't working.
To Reproduce
/**
* @template T
*/
class A_Collection
{
/**
* @param class-string<T> $class
* @return static<T>
*/
public function __construct(
public $class,
) {
}
}
/**
* @extends A_Collection<C>
*/
class C_Collection
extends A_Collection
{
}
class A
{
static function collection()
{
return new A_Collection(static::class);
}
static function wrapCollection()
{
return static::collection();
}
}
Class B
extends A
{
}
Class C
extends A
{
static function collection()
{
return new C_Collection(static::class);
}
static function extendedWrapCollection()
{
return static::wrapCollection();
}
}
# Expecting: A_Collection<A>
$A = A::collection();
# A_Collection<A>
$Aw = A::wrapCollection();
# A_Collection<A>
# Expecting: A_Collection<B>
$B = B::collection();
# A_Collection<A>
$Bw = B::wrapCollection();
# A_Collection<A>
# Expecting: C_Collection<C>
$C = C::collection();
# C_Collection
$Cw = C::wrapCollection();
# A_Collection<A>
$Cew = C::extendedWrapCollection();
# A_Collection<A>
Expected behavior
This seems like enough type information that the calls should be inferred successfully, and during execution the expected results pan out.
When adding a signature to A::collection(), B::collection() now gives the expected result, but B::wrapCollection() does not, and C::collection becomes incorrect in a different way:
/**
* @template T
*/
class A_Collection
{
/**
* @param class-string<T> $class
* @return static<T>
*/
public function __construct(
public $class,
) {
}
}
/**
* @extends A_Collection
*/
class C_Collection
extends A_Collection
{
}
class A
{
/**
* @return A_Collection<static>
*/
static function collection()
{
return new A_Collection(static::class);
}
static function wrapCollection()
{
return static::collection();
}
}
Class B
extends A
{
}
Class C
extends A
{
static function collection()
{
return new C_Collection(static::class);
}
static function extendedWrapCollection()
{
return static::wrapCollection();
}
}
# Expecting: A_Collection<A>
$A = A::collection();
# A_Collection<A>
$Aw = A::wrapCollection();
# A_Collection<A>
# Expecting: A_Collection<B>
$B = B::collection();
# A_Collection<B>
$Bw = B::wrapCollection();
# A_Collection<A>
# Expecting: C_Collection<C>
$C = C::collection();
# A_Collection<C>
$Cw = C::wrapCollection();
# A_Collection<A>
$Cew = C::extendedWrapCollection();
# A_Collection<A>
Adding a similar annotation to C::collection() yields the expected result for that call, but similarly does not impact the wrapped calls.
Platform and version
Bazzite/Fedora 39, Flatpak
Intelephense v1.10.4
Describe the bug I am using query builders that I implement as iterable collections that I extend to provide specific functionality for matching entity subtypes.
In practice, this works fine, but I am having difficulty figuring out if I am attempting to annotate this correctly or if it isn't working.
To Reproduce
Expected behavior This seems like enough type information that the calls should be inferred successfully, and during execution the expected results pan out.
When adding a signature to A::collection(), B::collection() now gives the expected result, but B::wrapCollection() does not, and C::collection becomes incorrect in a different way:
Adding a similar annotation to C::collection() yields the expected result for that call, but similarly does not impact the wrapped calls.
Platform and version Bazzite/Fedora 39, Flatpak Intelephense v1.10.4