phpstan / phpstan-doctrine

Doctrine extensions for PHPStan
MIT License
588 stars 96 forks source link

Doctrine Query::execute() without a hydration mode returns mixed (1.4.4) instead of int (1.4.3) #594

Closed zacharylund closed 2 months ago

zacharylund commented 2 months ago

Calls to Query::execute() for update and delete statements without a hydration mode now return mixed. Specifying any hydration mode causes it to return int. Given that these are void statement types, it makes sense that the execute method should always return int.

$updateQuery = $this
    ->em
    ->createQueryBuilder()
    ->from(Entity::class, 'w')
    ->update()
    ->set('w.value', '1')
    ->where('w.value = -1')
    ->getQuery()
;

$deleteQuery = $this
    ->em
    ->createQueryBuilder()
    ->from(Entity::class, 'w')
    ->delete()
    ->where('w.value = -1')
    ->getQuery()
;

// phpstan-doctrine 1.4.3 dumped type: int
// phpstan-doctrine 1.4.4 dumped type: mixed
\PHPStan\dumpType($updateQuery->execute());
\PHPStan\dumpType($deleteQuery->execute());

// phpstan-doctrine 1.4.3 dumped type: int
// phpstan-doctrine 1.4.4 dumped type: int<0, max>
\PHPStan\dumpType($updateQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_OBJECT));
\PHPStan\dumpType($updateQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY));
\PHPStan\dumpType($updateQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_SCALAR));
\PHPStan\dumpType($updateQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_SINGLE_SCALAR));
\PHPStan\dumpType($updateQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_SIMPLEOBJECT));
\PHPStan\dumpType($updateQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_SCALAR_COLUMN));
\PHPStan\dumpType($deleteQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_OBJECT));
\PHPStan\dumpType($deleteQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY));
\PHPStan\dumpType($deleteQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_SCALAR));
\PHPStan\dumpType($deleteQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_SINGLE_SCALAR));
\PHPStan\dumpType($deleteQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_SIMPLEOBJECT));
\PHPStan\dumpType($deleteQuery->execute(null, \Doctrine\ORM\AbstractQuery::HYDRATE_SCALAR_COLUMN));
ondrejmirtes commented 2 months ago

/cc @VincentLanglet

VincentLanglet commented 2 months ago

I'm not sure but I think it's coming from @janedbal PR https://github.com/phpstan/phpstan-doctrine/pull/590/files

Before the PR return $this->getMethodReturnTypeForHydrationMode was called with the logic

$isVoidType = (new VoidType())->isSuperTypeOf($queryResultType);

        if ($isVoidType->yes()) {
            // A void query result type indicates an UPDATE or DELETE query.
            // In this case all methods return the number of affected rows.
            return new IntegerType();
        }

        if ($isVoidType->maybe()) {
            // We can't be sure what the query type is, so we return the
            // declared return type of the method.
            return null;
        }

        if (!$hydrationMode instanceof ConstantIntegerType) {
            return null;
        }

// Do things

But after the PR, the check

if (!$hydrationMode instanceof ConstantIntegerType) {
            return null;
        }

was moved before calling $this->hydrationModeReturnTypeResolver->getMethodReturnTypeForHydrationMode(

janedbal commented 2 months ago

Maybe I failed rebase conflicts. I separated the logic before your revert...

VincentLanglet commented 2 months ago

Can you try https://github.com/phpstan/phpstan-doctrine/pull/597 @zacharylund ?

I'm taking one week of vacations, so I'm unusure finding time for test soon. I'll see

zacharylund commented 2 months ago

That fixes my errors out outputs Dumped type: int<0, max> across the board. Thanks for tracking that down!

ondrejmirtes commented 2 months ago

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

github-actions[bot] commented 1 month ago

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.