phpstan icon indicating copy to clipboard operation
phpstan copied to clipboard

Unresolvable type error in PHPUnit\assertSame when the same enum is passed for second time

Open janedbal opened this issue 3 years ago • 11 comments

Bug report

I'm getting following error in a phpunit test that looks like this. Using bleeding edge on 1.7.1, assuming this is a bug of https://github.com/phpstan/phpstan-src/pull/1319. Using phpstan/phpstan-phpunit version 1.1.1

Code snippet that reproduces the problem

self::assertSame(SomeEnum::SomeCase, $order->getEnum()); // no error here

$this->someMethod($order);

self::assertSame(SomeEnum::SomeCase, $order->getEnum()); // Parameter #1 $expected of static method PHPUnit\Framework\Assert::assertSame() contains unresolvable type.

Expected output

No error

janedbal avatar May 26 '22 12:05 janedbal

This bug report is missing a link to reproduction at phpstan.org/try.

It will most likely be closed after manual review.

mergeable[bot] avatar May 26 '22 12:05 mergeable[bot]

I can't reproduce this. Could you share a small reproducing repository?

rvanvelzen avatar May 27 '22 07:05 rvanvelzen

Here it is: https://github.com/janedbal/phpstan-bug-7324

janedbal avatar May 27 '22 08:05 janedbal

Thanks. I don't know if the repo is representative of the original code, but it contains an impossible assertion which is where the error originates. It becomes a lot clearer if you dump the types:

self::assertSame(SomeEnum::SomeOtherCase, $holder->getEnum());
dumpType($holder->getEnum()); // SomeEnum::SomeOtherCase
self::assertSame(SomeEnum::SomeCase, $holder->getEnum());
dumpType($holder->getEnum()); // *NEVER*
self::assertSame(SomeEnum::SomeCase, $holder->getEnum());
dumpType($holder->getEnum()); // *NEVER*

I'd expect the impossible type checker to kick for the 2nd call already though. You're now getting a somewhat awkward error for the 3rd call because of how this works internally.

rvanvelzen avatar May 27 '22 12:05 rvanvelzen

It was too simplified, there are some facade calls in between, so it is not impossible. It is just the non-disablable remembering value feature again :(

janedbal avatar May 27 '22 12:05 janedbal

i'm getting this too:

$subSection = new QuoteSubSection();
$subSection->setName('foo');

$section = new QuoteSection();
$section->addSection($subSection);

$quote = new Quote();
$quote->addSection($section);

self::assertSame($subSection, $quote->getSubSectionNamed('foo'));
self::assertSame($subSection, $quote->getSubSectionNamed('FOO'));
self::assertSame($subSection, $quote->getSubSectionNamed('Foo'));

the 2nd and 3rd assertSame calls trigger Parameter #1 $expected of static method PHPUnit\Framework\Assert::assertSame() contains unresolvable type.

bendavies avatar Jun 06 '22 08:06 bendavies

Please provide a small reproducing repo.

rvanvelzen avatar Jun 06 '22 14:06 rvanvelzen

Hey @rvanvelzen, I just encountered this issue as well, and managed to reproduce it in an as-small-as-possible-yet-fully-functional repository! :tada:

https://github.com/gnutix/phpstan-assertsame-unresolvable-type-bug/pull/2/files

gnutix avatar Jul 30 '22 10:07 gnutix

Hi @gnutix, your zip() and zipAll() methods don't annotate that the resulting array can contain nulls, which is why PHPStan considers your $expected to be impossible after the first assertSame(). The dumped types reflect that situation.

rvanvelzen avatar Aug 01 '22 08:08 rvanvelzen

This issue should be solvable by

rememberPossiblyImpureFunctionValues: false

since 1.8.0. But that might be problematic to do in existing projects.

janedbal avatar Aug 01 '22 09:08 janedbal

@rvanvelzen oh my, good catch... :scream:

Adding null to the return type removes the inspection indeed. :+1:

gnutix avatar Aug 05 '22 12:08 gnutix

@ondrejmirtes Any reference to a fix?

janedbal avatar Jun 19 '23 10:06 janedbal

@janedbal There isn't anything new to link. I forgot to close this issue after implementing rememberPossiblyImpureFunctionValues.

For this example:

self::assertSame(SomeEnum::SomeCase, $order->getEnum()); // no error here

$this->someMethod($order);

self::assertSame(SomeEnum::SomeCase, $order->getEnum());

Either rememberPossiblyImpureFunctionValues needs to be set to false, or someMethod needs to be marked with @phpstan-impure, or someMethod needs to return void.

ondrejmirtes avatar Jun 19 '23 10:06 ondrejmirtes

That fixes the issue, but it is pretty unclear from the error message. Hopefully people find this thread then...

janedbal avatar Jun 19 '23 11:06 janedbal

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

github-actions[bot] avatar Jul 21 '23 00:07 github-actions[bot]