Skip to content

Error with interface inheritance and generics #4019

Open

Description

@lud

Hi,

I am trying to understand why phpstan reports an error on this playground:

https://phpstan.org/r/7276a596-2325-479f-8360-f14bf45586a4

Psalm chokes on the exact same point, so it must be a problem with the docblocks, but to me it looks fine.

Thank you

Activity

  1. ondrejmirtes commented on Oct 28, 2020

    @ondrejmirtes
    Member

    It's a pretty complicated code. This could work once implemented in PHPStan: https://phpstan.org/r/ffea3628-c9f4-46af-92c9-cc50455b51c4

    But personally I'd do something like this: https://phpstan.org/r/083a3acf-398e-458b-a3b8-69e00ddeb1ea

  2. lud commented on Oct 28, 2020

    @lud
    Author

    Hey thank you !

    So the answer would be to write

    /**
     * @template T of PersonInterface
     * @extends WrapperInterface<T>
     */
    

    and

    	/**
    	 * @return T
    	 */
    

    In the wrappers. You say it is not implemented, is there an issue currently ongoing that I can follow to know when it is done ?

    By the way I know it is complicated but we still need to have methods that can return only a specific type, and not a wrapper for any entity type. Oh and an object can implement two wrappers and return a different interface, hence the detailed method names.

    On the other side, the code in my example is from a serializer that does not care which wrapper type we have, it will just call the method depending on the type. But you are right, we still need a way to know which method call at some point if an object implements two wrappers. I will try to simplify the code.

  3. added this to the Generics milestone on Oct 28, 2020
  4. phpstan-bot commented on Mar 9, 2021

    @phpstan-bot
    Contributor

    @lud PHPStan now reports different result with your code snippet:

    @@ @@
    -PHP 7.4 – 8.0 (1 error)
    -==========
    -
    -33: Method Unwrapper::unwrap() should return T of EntityInterface but returns PersonInterface.
    -
    -PHP 7.1 – 7.3
    -==========
    -
    -No errors
    +33: Method Unwrapper::unwrap() should return T of EntityInterface but returns PersonInterface.
    Full report
    Line Error
    33 Method Unwrapper::unwrap() should return T of EntityInterface but returns PersonInterface.
  5. colinodell commented on Jun 3, 2021

    @colinodell

    I think I found a related (or perhaps the exact same) issue: https://phpstan.org/r/d7a5d668-29c6-464c-9925-bf6ffb9ba826

  6. ondrejmirtes commented on Jun 3, 2021

    @ondrejmirtes
    Member

    @colinodell Your error is expected, you need @template-covariant instead: https://phpstan.org/r/b143e754-c6cc-4841-bc0d-d50c8e2a1cfb

  7. ZebulanStanphill commented on Feb 27, 2022

    @ZebulanStanphill
    Contributor

    @ondrejmirtes I'm confused as to what the difference is between @template and @template-covariant. The article about generics in PHPStan doesn't even mention the latter, and the docs mention but don't explain the function of either.

  8. ondrejmirtes commented on Feb 27, 2022

    @ondrejmirtes
    Member
  9. phpstan-bot commented on Apr 4, 2023

    @phpstan-bot
    Contributor

    @ondrejmirtes After the latest push in 1.10.x, PHPStan now reports different result with your code snippet:

    @@ @@
     PHP 7.1 – 7.3 (1 error)
     ==========
     
    -28: Return type PersonInterface of method PersonWrapperInterface::unwrap() is not compatible with return type EntityInterface of method WrapperInterface::unwrap().
    +28: Return type PersonInterface of method PersonWrapperInterface::unwrap() is not compatible with return type EntityInterface of method WrapperInterface<T of PersonInterface>::unwrap().
    Full report

    PHP 7.4 – 8.0

    No errors

    PHP 7.1 – 7.3 (1 error)

    Line Error
    28 Return type PersonInterface of method PersonWrapperInterface::unwrap() is not compatible with return type EntityInterface of method WrapperInterface<T of PersonInterface>::unwrap().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions