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

Make paginator covariant #10002

Merged
merged 1 commit into from
Aug 30, 2022
Merged

Make paginator covariant #10002

merged 1 commit into from
Aug 30, 2022

Conversation

VincentLanglet
Copy link
Contributor

@VincentLanglet VincentLanglet commented Aug 22, 2022

see https://phpstan.org/blog/whats-up-with-template-covariant
see https://psalm.dev/docs/annotating_code/templated_annotations/

A method which accepts Paginator<Animal> should be able to accept Paginator<Cat>.

I received the error

Template type T is declared as covariant, but occurs in invariant position in return type of method Doctrine\ORM\Tools\Pagination\Paginator::getIterator().

It's because the template of ArrayIterator is not covariant.
But the template for Traversable is covariant.

It makes sens to use Traversable instead of ArrayIterator as return type because

  • IteratorAggregate::getIterator() use Traversable as return type
  • it doesn't make sens to allow adding elements to this Iterator

ArrayIterator implements SeekableIterator, ArrayAccess, Serializable, Countable
the issue is the ArrayAccess.

If you preferred I can use somethink like

@psalm-return Traversable<array-key, T>&Countable
@psalm-return Traversable<array-key, T>&Serializable&Countable
@psalm-return SeekableIterator<array-key, T>&Serializable&Countable
...

Any suggestion @greg0ire ?

@VincentLanglet VincentLanglet marked this pull request as ready for review August 27, 2022 12:05
@greg0ire
Copy link
Member

No suggestion yet, but can you add a piece of code under tests/Doctrine/StaticAnalysis to demonstrate the benefit and avoid regressions? It will also help understanding the PR.

@VincentLanglet
Copy link
Contributor Author

No suggestion yet, but can you add a piece of code under tests/Doctrine/StaticAnalysis to demonstrate the benefit and avoid regressions? It will also help understanding the PR.

I added as much tests as possible ^^

}

/**
* @psalm-return Paginator<T>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wouldn't be possible if Paginator wasn't covariant.

*/
function test(PaginatorFactory $catPaginatorFactory): ?Animal
{
return getFirstAnimal($catPaginatorFactory->createPaginator());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing a Paginator to getFirstAnimal wouldn't be possible if Paginator wasn't covariant

@greg0ire
Copy link
Member

Please squash your commits, and retarget to 2.14.x: this is an improvement and there is a small BC-break.

@greg0ire
Copy link
Member

If you preferred I can use something like…

actually, Traversable is fine, because it's exactly what we are supposed to return to fulfill the contract. Since we do not intend people to use getIterator() directly, but rather indirectly through foreach, it makes sense to give as little detail as possible on the type. That way, we can change the implementation and something else if we want to.

@VincentLanglet VincentLanglet changed the base branch from 2.13.x to 2.14.x August 27, 2022 14:22
@VincentLanglet
Copy link
Contributor Author

Please squash your commits, and retarget to 2.14.x: this is an improvement and there is a small BC-break.

Done

@derrabus derrabus added this to the 2.14.0 milestone Aug 30, 2022
@derrabus derrabus merged commit 8d03f8f into doctrine:2.14.x Aug 30, 2022
@VincentLanglet VincentLanglet deleted the paginator branch August 30, 2022 12:06
derrabus added a commit to derrabus/orm that referenced this pull request Aug 30, 2022
* 2.14.x:
  Bump Ubuntu version and shared workflows (doctrine#10020)
  Make paginator covariant (doctrine#10002)
  Fail gracefully if EM could not be constructed in tests (doctrine#10008)
derrabus added a commit that referenced this pull request Aug 30, 2022
* 2.14.x:
  Bump Ubuntu version and shared workflows (#10020)
  Make paginator covariant (#10002)
  Fail gracefully if EM could not be constructed in tests (#10008)
@mitelg
Copy link
Contributor

mitelg commented Jan 18, 2023

hey @VincentLanglet

sorry for coming back after this MR is merged a long time ago 😬

we want to update to the recent 2.14.1 version. our problem is that we are using $paginator->getIterator()->getArrayCopy() a lot 😅

Just to be sure: the migration path would simply be exchanging this with iterator_to_array($paginator) ? the output array is the same in my first tests, just wanted to be doubled checked 😄

thanks in advance ✌️

@VincentLanglet
Copy link
Contributor Author

$paginator->getIterator()->getArrayCopy() a lot 😅

Just to be sure: the migration path would simply be exchanging this with iterator_to_array($paginator) ?

Sure.

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

Successfully merging this pull request may close these issues.

4 participants