Skip to content

Incorrect type reported by pyreverse for unions and generics #8888

Description

Bug description

Consider the following class:

class Foo:
    def __init__(self) -> None:
        self.val: str | int = "1"

    def bar(self) -> None:
        self.val = "2"
        pass

pyreverse will infer the type of Foo.val to be "str | int, str", which is incorrect as the second assignment does not actually modify the type and "str" is a more specific type than the union "str | int".

Additionally, if the class is modified to look like this:

class Foo:
    def __init__(self) -> None:
        self.val: list[str] = []

    def bar(self) -> None:
        self.val = []
        pass

pyrverse will infer the type to be "list[str] | list", which should also be incorrect because assigning an empty list here doesn't mean that suddenly the type is list[Any].

I think fixing this issue should look at 3 different steps:

  • type hints should have precedence over inferred types: it should not be the responsibility of pyreverse to type check the code, so if type hints are provided, it should be assumed those are correct. This also allows users to get a consistent behaviour by just fixing the type hints in their code
  • if a type hint is read from the init, it should have precedence over other calls, since again, type checkers will consider other calls to be an error
  • failing the two points above, types should be aggregated and consistent: "str | int, str" should be just "str | int" and the order should be consistent across runs (in my testing, I sometimes got "str | int, str", and other times "str, str | int".

Configuration

No response

Command used

pyreverse repro.py

Pylint output

parsing repro.py


### Expected behavior

As explained in the description, the type inferred for the `val` attribute should be `str | int` in the first case and `list[str]` in the second case.

### Pylint version

```shell
pyreverse is included in pylint:
pylint 2.17.4
astroid 2.15.6
Python 3.11.4 (main, Jun  7 2023, 12:45:49) [GCC 9.4.0]

OS / Environment

No response

Additional dependencies

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions