Skip to content

Generics inheritance raises errors #3537

@remi-san

Description

@remi-san

Bug report

Using v0.12.31

When declaring type implementing or extending a generic type, when this type is passed as a parameter or as a return, it is not considered a subclass of the generic type it implements or extend.

Code snippet that reproduces the problem

<?php

declare(strict_types=1);

interface Entity{}

final class Dish implements Entity
{
}

/**
 * @template T of Entity
 */
interface Filter {}

/**
 * @extends Filter<Dish>
 */
interface DishFilter extends Filter {}

/**
 * @extends SearchDoctrineRepository<Dish>
 */
final class DishDoctrineRepository extends SearchDoctrineRepository
{
    /**
     * @return array<Dish>
     */
    public function filter(DishFilter $filter): array
    {
        return parent::filterEntities($filter);
    }
}

/**
 * @template T of Entity
 */
abstract class SearchDoctrineRepository
{
    /**
     * @param Filter<T>     $filter
     *
     * @return array<T>
     */
    public function filterEntities(Filter $filter): array
    {
        return [];
    }
}

This code raises the following errors:

  • Method DishDoctrineRepository::filter() should return array<Dish> but returns array<Entity>.
  • Parameter #1 $filter of method SearchDoctrineRepository<Entity>::filterEntities() expects Filter<Entity>, DishFilter given.

It can be found here https://phpstan.org/r/5200477a-9300-454d-bca8-59511b8c51d3

Expected output

Given that DishDoctrineRepository extends SearchDoctrineRepository<Dish> I expect the return type of filterEntities() to be array<Dish> and not array<Entity> as it is detected.

And because DishFilter extends Filter<Dish>, when the method expects Filter<Dish>, it should allow to get a DishFilter.

Am I doing something wrong here?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions