Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generics inheritance raises errors #3537

Closed
remi-san opened this issue Jun 25, 2020 · 5 comments
Closed

Generics inheritance raises errors #3537

remi-san opened this issue Jun 25, 2020 · 5 comments
Labels
Milestone

Comments

@remi-san
Copy link

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?

@remi-san remi-san changed the title Generics heritage raises errors Generics inheritance raises errors Jun 26, 2020
@ondrejmirtes ondrejmirtes added this to the Generics milestone Jun 28, 2020
@hultberg
Copy link

hultberg commented Oct 16, 2020

I think I may have the same issue with @extends. I have an example in https://phpstan.org/r/952f7013-2b00-4cb4-9e26-353a9924f3b3 where I attempt to extend AnimalCollection to accept the same as AnimalCollection does, but it seems that phpstan thinks AnimalQueue only ever contain an "Animal" and not "Dog" as the AnimalQueue was created with. I have tried several combinations with covariant without luck.

In this playground https://phpstan.org/r/8e09eb41-fa34-4714-9996-994c911d8910 I have removed T of Animal, and I get no error, but the usage of getName() inside AnimalCollection is not detected it seems.

@ondrejmirtes
Copy link
Member

@hultberg Your error isn't related to OP but rather to #2735. Repeating the constructor in the child class will work for you now: https://phpstan.org/r/8edeab32-683a-4b49-86fa-5213bd955b10

@phpstan-bot
Copy link
Contributor

@remi-san After the latest commit in dev-master, PHPStan now reports different result with your code snippet:

@@ @@
-31: Method DishDoctrineRepository::filter() should return array<Dish> but returns array<Entity>.
 31: Parameter #1 $filter of method SearchDoctrineRepository<Entity>::filterEntities() expects Filter<Entity>, DishFilter given.
Full report
Line Error
31 Parameter #1 $filter of method SearchDoctrineRepository<Entity>::filterEntities() expects Filter<Entity>, DishFilter given.

@ondrejmirtes
Copy link
Member

Fixed: phpstan/phpstan-src@4acbc6c

You can get rid of the remaining error with @template-covariant: https://phpstan.org/r/c4bc2358-d836-4dca-9222-02ebc82d34e3

@github-actions
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 29, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants