Skip to content

PHPStan assumes deterministic result for EntityManagerInterface::isOpen() within same scope #738

@denis-korchagin95

Description

@denis-korchagin95

Bug report

Version: PHPStan - PHP Static Analysis Tool 2.1.11

I noticed a situation where PHPStan assumes that the result of EntityManagerInterface::isOpen() remains the same within a scope.

However, in real applications the state of the EntityManager can change during execution.

For example, Doctrine may close the EntityManager after an exception during flush() or database interaction.

Example:

public function run(EntityManagerInterface $em): void
{
    if ($em->isOpen() === false) {
        return;
    }

    $this->doSomething();

    if ($em->isOpen() === false) {
        $this->logger->warning('EntityManager closed');
    }
}

Output:

Strict comparison using === between true and false will always evaluate to false.  
         🪪  identical.alwaysFalse

Phpstan config:

includes:
    - vendor/phpstan/phpstan-doctrine/extension.neon
    - vendor/phpstan/phpstan-symfony/extension.neon
    - vendor/phpstan/phpstan-strict-rules/rules.neon

parameters:
    level: 8
    strictRules:
        strictArrayFilter: false
    paths:
        - ../../src
    bootstrapFiles:
        - ../../Bootstrap/bootstrap.php
    doctrine:
        objectManagerLoader: phpstan-object-manager.php
    parallel:
        processTimeout: 1000.0

Current workaround:

// @phpstan-ignore-next-line
if ($em->isOpen() === false) {

Code snippet that reproduces the problem

No response

Expected output

PHPStan should not assume that repeated calls to methods like isOpen() return the same value unless explicitly guaranteed.

Ideally there should be a way to mark such methods as non-deterministic or state-dependent.

Proposed idea:

/**
 * @phpstan-nondeterministic
 */
public function isEntityManagerClosed(): bool
{
     return $this-em->isOpen() === false;
}

To avoid ignores in the code base.

Did PHPStan help you today? Did it make you happy in any way?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions