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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect ImplementedReturnTypeMismatch #3760

Closed
azjezz opened this issue Jul 6, 2020 · 9 comments
Closed

Incorrect ImplementedReturnTypeMismatch #3760

azjezz opened this issue Jul 6, 2020 · 9 comments

Comments

@azjezz
Copy link
Contributor

azjezz commented Jul 6, 2020

I have encountered this issue 3 times before, and every time it finds it's way back into psalm 馃

snippet: https://psalm.dev/r/b4af700040

related issues:

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/b4af700040
<?php

/**
 * @template Tk of array-key
 * @template Tv
 */
interface Collection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return Collection<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): Collection;
}

/**
 * @template Tk of array-key
 * @template Tv
 * @extends Collection<Tk, Tv>
 */
interface MutableCollection extends Collection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return MutableCollection<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): MutableCollection;
}

/**
 * @template Tk of array-key
 * @template Tv
 * @extends Collection<Tk, Tv>
 */
interface Map extends Collection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return Map<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): Map;
}

/**
 * @template Tk of array-key
 * @template Tv
 * @extends Map<Tk, Tv>
 * @extends MutableCollection<Tk, Tv>
 */
interface MutableMap extends Map, MutableCollection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return MutableMap<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): MutableMap;
}
Psalm output (using commit ada2fe0):

ERROR: ImplementedReturnTypeMismatch - 25:13 - The inherited return type 'Collection<Tk:MutableCollection as array-key, array{0: Tv:MutableCollection as mixed, 1: Tu:fn-collection::zip as mixed}>' for Collection::zip is different to the implemented return type for MutableCollection::zip 'MutableCollection<Tk:MutableCollection as array-key, array{0: Tv:MutableCollection as mixed, 1: Tu:fn-mutablecollection::zip as mixed}>'

ERROR: ImplementedReturnTypeMismatch - 39:13 - The inherited return type 'Collection<Tk:Map as array-key, array{0: Tv:Map as mixed, 1: Tu:fn-collection::zip as mixed}>' for Collection::zip is different to the implemented return type for Map::zip 'Map<Tk:Map as array-key, array{0: Tv:Map as mixed, 1: Tu:fn-map::zip as mixed}>'

ERROR: ImplementedReturnTypeMismatch - 54:13 - The inherited return type 'Map<Tk:MutableMap as array-key, array{0: Tv:MutableMap as mixed, 1: Tu:fn-map::zip as mixed}>' for Map::zip is different to the implemented return type for MutableMap::zip 'MutableMap<Tk:MutableMap as array-key, array{0: Tv:MutableMap as mixed, 1: Tu:fn-mutablemap::zip as mixed}>'

@azjezz
Copy link
Contributor Author

azjezz commented Jul 6, 2020

currently https://github.com/azjezz/psl has only this issue left before it hits 100% code coverage 馃槃

@muglug
Copy link
Collaborator

muglug commented Jul 6, 2020

You just need to define the template Tv as covariant: https://psalm.dev/r/38ae009d63

@muglug muglug closed this as completed Jul 6, 2020
@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/38ae009d63
<?php

/**
 * @template Tk of array-key
 * @template-covariant Tv
 */
interface Collection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return Collection<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): Collection;
}

/**
 * @template Tk of array-key
 * @template-covariant Tv
 * @extends Collection<Tk, Tv>
 */
interface MutableCollection extends Collection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return MutableCollection<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): MutableCollection;
}

/**
 * @template Tk of array-key
 * @template-covariant Tv
 * @extends Collection<Tk, Tv>
 */
interface Map extends Collection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return Map<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): Map;
}

/**
 * @template Tk of array-key
 * @template Tv
 * @extends Map<Tk, Tv>
 * @extends MutableCollection<Tk, Tv>
 */
interface MutableMap extends Map, MutableCollection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return MutableMap<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): MutableMap;
}
Psalm output (using commit 1b498e6):

No issues!

@azjezz
Copy link
Contributor Author

azjezz commented Jul 7, 2020

I think i don't understand what covariant means in psalm exactly, using covariant triggers around 100 other type errors ( see https://psalm.dev/r/53aa1bd176 for an example ).

Tv in this context doesn't have to be covariant, the following triggers no errors under hack-lang :

interface A<Tk, Tv> {
  public function zip<Tu>(Container<Tu> $container): A<Tk, (Tv, Tu)>;
}

interface B<Tk, Tv> extends A<Tk, Tv> {
  public function zip<Tu>(Container<Tu> $container): B<Tk, (Tv, Tu)>;

  public function filter((function(Tv): bool) $func): B<Tk, Tv>;
}

interface C<Tk, Tv> extends A<Tk, Tv> {
  public function zip<Tu>(Container<Tu> $container): C<Tk, (Tv, Tu)>;
}

interface D<Tk, Tv> extends B<Tk, Tv>, C<Tk, Tv> {
  public function zip<Tu>(Container<Tu> $container): D<Tk, (Tv, Tu)>;

  public function filter((function(Tv): bool) $func): D<Tk, Tv>;
}

Note: marking Tv covariant in hack-lang won't trigger any type errors for the given example.

@psalm-github-bot
Copy link

psalm-github-bot bot commented Jul 7, 2020

I found these snippets:

https://psalm.dev/r/53aa1bd176
<?php

/**
 * @template Tk of array-key
 * @template-covariant Tv
 */
interface Collection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return Collection<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): Collection;
}

/**
 * @template Tk of array-key
 * @template-covariant Tv
 * @extends Collection<Tk, Tv>
 */
interface MutableCollection extends Collection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return MutableCollection<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): MutableCollection;
}

/**
 * @template Tk of array-key
 * @template-covariant Tv
 * @extends Collection<Tk, Tv>
 */
interface Map extends Collection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return Map<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): Map;
    
 /**
  * @param (callable(Tv): bool) $func
  *
  * @return Map<Tk, Tv>
  */
 public function filter(callable $func): Map;
}

/**
 * @template Tk of array-key
 * @template Tv
 * @extends Map<Tk, Tv>
 * @extends MutableCollection<Tk, Tv>
 */
interface MutableMap extends Map, MutableCollection {
 /**
  * @template Tu
  * @param iterable<Tu> $iterable
  * @return MutableMap<Tk, array{0: Tv, 1: Tu}>
  */
 public function zip(iterable $iterable): MutableMap;

 /**
  * @param (callable(Tv): bool) $func
  *
  * @return MutableMap<Tk, Tv>
  */
 public function filter(callable $func): MutableMap;
}
Psalm output (using commit 279cad3):

ERROR: InvalidTemplateParam - 44:12 - Template param Tv of Map is marked covariant and cannot be used here

@muglug
Copy link
Collaborator

muglug commented Jul 7, 2020

Yeah definitely buggy behaviour actually

@muglug muglug reopened this Jul 7, 2020
@muglug muglug closed this as completed in 8ecee6d Jul 7, 2020
@muglug
Copy link
Collaborator

muglug commented Jul 7, 2020

@azjezz happy for you to add this to bin/test-with-real-projects.sh to prevent future regressions!

@azjezz
Copy link
Contributor Author

azjezz commented Jul 7, 2020

I'll make sure to send a PR once 100% type coverage is achieved in PSL. Thank you for the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants