Skip to content

Change GenericObjectType generics via TypeSpecifyingExtension #6620

@staabm

Description

@staabm

Feature request

In my use case, I have partly successfull already implemented in staabm/phpstan-dba#258, I have the following scenario.

A PDOStatement class is specifed via a return type extension of PdoStatement->query() like

        $query = 'SELECT email, adaid FROM ada';
        $stmt = $pdo->query($query, PDO::FETCH_NUM);
        assertType('PDOStatement<array{string, int<0, 4294967295>}>', $stmt);

to implement support for PDO native PDOStatement->setFetchType() I am using a MethodTypeSpecifyingExtension to support

        $query = 'SELECT email, adaid FROM ada';
        $stmt = $pdo->query($query, PDO::FETCH_NUM);
        assertType('PDOStatement<array{string, int<0, 4294967295>}>', $stmt);

        $stmt->setFetchMode(PDO::FETCH_ASSOC);
        assertType('PDOStatement<array{email: string, adaid: int<0, 4294967295>}>', $stmt);

.. so the idea is to turn a PDOStatement<array{string, int<0, 4294967295>}> into a PDOStatement<array{email: string, adaid: int<0, 4294967295>}> - and suprisingly this worked - from a phpunit point of view regarding assertType.

it has a negative side-effect though, that the ImpossibleCheckTypeHelper realizes a incompatibility between the generic-type before/after the specifying extension does what it is supposed to do.

https://github.com/phpstan/phpstan-src/blob/c5a9c2c50b9b639715ca85541fcfd7f877f5df06/src/Rules/Comparison/ImpossibleCheckTypeHelper.php#L195-L200

in the above scenario $isSuperType->no() is true and therefore we run into the return false case.
this return false triggers the following case

https://github.com/phpstan/phpstan-src/blob/c5a9c2c50b9b639715ca85541fcfd7f877f5df06/src/Rules/Comparison/ImpossibleCheckTypeMethodCallRule.php#L57-L66

which makes phpstan error like

Call to method PDOStatement<array<int|string, int<0, 4294967295>|string>,array<int|string,
         int<0, 4294967295>|string>>::setFetchMode() with 3 will always evaluate to false.

I create this issue as a "feature request" as I can see, that the behaviour as is makes sense.
Still I hope in scenarios where a MethodTypeSpecifyingExtension uses $overwrite=true like I do with
return $this->typeSpecifier->create($methodCall->var, $reducedType, TypeSpecifierContext::createTrue(), true);
the ImpossibleCheckTypeHelper could be made a bit tolerant regarding the types involved.

as it seems, in the end phpstan and the type-system work as expected with my MethodTypeSpecifyingExtension but the "verification" after type changes is not happy with me changing the generic type involved.

I wanted to discuss my scenario before submitting failing test cases, to see whether we agree, that this is something usefull to support.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions