phpstan / phpstan-doctrine

Doctrine extensions for PHPStan
MIT License
598 stars 97 forks source link

Invalid map in collection. #621

Closed laurentmuller closed 1 month ago

laurentmuller commented 1 month ago

After update PHPStan to version 1.5.4, the map function of collection does not work anymore.

Example:


use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

class Item {

    private ?Parent  $parent = null;

    public function setParent(?Parent $parent): void
    {
        $this->parent = $parent;
    }
}

class Parent {

    /**
     * @var Collection<int, Item>
     */
    private Collection $items;

    public function __construct()
    {
        $this->items = new ArrayCollection();
    }

    public function __clone()
    {
        $this->items = $this->items->map(
            fn (Item $item): Item => (clone $item)->setParent($this)
        );
    }
}

The follwing error is raised:

------ -------------------------------------------------------------------------------------------------
  Line   src\Parent.php
 ------ -------------------------------------------------------------------------------------------------
  81     Property Parent::$items (Doctrine\Common\Collections\Collection<int, Item>)
         does not accept Doctrine\Common\Collections\ReadableCollection<int, Item>.
         🪪  assign.propertyType
 ------ ------------------------------------------------------------------------------------------------- 

Maybe, the Collection and ArrayCollection stubs must be also updated.

ondrejmirtes commented 1 month ago

/cc @xificurk Is it possible you broke this with your stubs? Thanks.

laurentmuller commented 1 month ago

I does not use any custom stubs.

ondrejmirtes commented 1 month ago

You use phpstan-doctrine which includes a lot of them.

laurentmuller commented 1 month ago

Yes. But before commit #620, my code working without error.

xificurk commented 1 month ago

Hm, I might be missing some phpstan internals knowledge, but (to my surprise), it looks like the stub phpdoc from ReadableCollection::map takes precedence not only over original ReadableCollection::map phpdoc, but even original Collection::map.

mvhirsch commented 1 month ago

I'm running into the same issue, using ::filter():

    /**
     * @return Collection<int, TopicItem>
     */
    public function getItems(): Collection
    {
        $livestreamStartLimiter = new \DateTimeImmutable(self::LIVESTREAM_START_LIMITER);

        return $this->items->filter(function (TopicItem $topicItem) use ($livestreamStartLimiter): bool {
            // simplified code here
            return true;
        });
    }
 ------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Line   src/TopicBundle/Entity/Topic.php                                                                                                                                                                             
 ------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  280    Method App\TopicBundle\Entity\Topic::getItems() should return Doctrine\Common\Collections\Collection<int, App\TopicBundle\Entity\TopicItem> but returns Doctrine\Common\Collections\ReadableCollection<int,  
         App\TopicBundle\Entity\TopicItem>.                                                                                                                                                                           
         ✏️  src/TopicBundle/Entity/Topic.php                                                                                                                                                                         
 ------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

This happens while upgrading phpstan/phpstan-doctrine from 1.5.3 => 1.5.4.

laurentmuller commented 1 month ago

It'seem that we have to update the *.stub files in Collections folder to reflect the php doc.

What happens if we remove all this collection stub files ?

Jean85 commented 1 month ago

I'm running into the same issue, using ::filter():

[...]

This happens while upgrading phpstan/phpstan-doctrine from 1.5.3 => 1.5.4.

Exact same situation here.

ondrejmirtes commented 1 month ago

Fixed https://github.com/phpstan/phpstan-doctrine/pull/622

laurentmuller commented 1 month ago

I just downloaded the last version (1.5.5) and it is work as expected !

Great job !!!!

mvhirsch commented 1 month ago

Thank you, 1.5.5 works for me, too!