assertNotContains appears to be messing something up.

Open
#262 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Stale
Tech stack
php
Domain
testing

Research direction

Start with the shortened OmegaTag and testBasic examples in the issue, focusing on the interaction between assertNotContains() and the later assertCount() call. Compare the analysis with and without assertNotContains(); done when the collection is no longer inferred as NEVER and the impossibleType warning is resolved.

Written by the indexing model from the issue text.

Description

I've got a weird issue that I can't seem to figure out. I think it is a bug in PHPStan, but I'm not certain.
I appreciate if you can point me in a way on how to debug this or help you figure out what is wrong.

Some context first:

  • popped up after upgrading PHPStan yesterday, it was not there before. I update very often, so it was a recent change.
  • Happens on both PHP8.4 and PHP8.5alpha
  • It involves the PHPUnit method "assetNotContains", so I don't think I can create a playground example.
  • I tried creating a small repo with an example, but I can't reproduce the error there. I'm not sure why. I used the same phpstan.neon file (just paths changed) and the contents of the classes appear identical to me (except namespaces).

Given this (a bit shortened) test class:

class OmegaTag
{
    /**
     * @var Collection<array-key, OmegaProduct>
     */
    private Collection $products;

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

    /**
     * @return Collection<array-key, OmegaProduct>
     */
    public function getProducts(): Collection
    {
        return $this->products;
    }
}

This (shortened) test:

    public function testBasic(): void
    {
        $product = new OmegaProduct();
        $tag = new OmegaTag();

        self::assertNotContains($product, $tag->getProducts());
        self::assertCount(0, $tag->getProducts());
    }

This gives me this error:

Call to static method PHPUnit\Framework\Assert::assertCount() with 0 and *NEVER* will always evaluate to false.                                   
🪪  staticMethod.impossibleType

I'm not sure how PHPStan got to the type *NEVER*.

Observations:

  • When I remove the line with the method assertNotContains, the error goes away.
  • When I refactor the 2 $tag->getProducts() calls to a single variable and use that in the test, the error is still there.

It seems that assertNotContains narrows the type to never, while I think it should not do that.

Is there any direction you can point me in to find out what is wrong here?
Or is there any more info I can give if you think this is a bug?

Dominant language
PHP
Stars
544
Forks
58
Avg merge
2d 1h
Merged PRs (30d)
5

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from phpstan/phpstan-phpunit

All issues in phpstan/phpstan-phpunit

Similar issues

More PHP issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.