pyre-check icon indicating copy to clipboard operation
pyre-check copied to clipboard

Type narrowing with isinstance doesn't work when the first argument is a walrus-operator assignment

Open tmke8 opened this issue 2 years ago • 1 comments

Bug description As pyre is quite strict with the type narrowing of non-final attributes (which I don't mind), I want to use the walrus operator to make the type narrowing more convenient, but it doesn't seem to play nice with isinstance().

Reproduction steps

from dataclasses import dataclass

@dataclass
class A:
    x: str | int

    def f(self) -> int:
        if isinstance(y := self.x, int):
            reveal_type(y)  # Revealed type for `y` is `typing.Union[int, str]`.
            reveal_type(self.x)  # Revealed type for `self.x` is `typing.Union[int, str]`.
            return y + 2  # Error: `+` is not supported for operand types `typing.Union[int, str]` and `int`.
        return 0

Expected behavior The type of y should be int because I just narrowed it.

Actual behavior The type of y is not narrowed.

Additional context It works fine in mypy and pyright.

Furthermore, the following works fine in pyre:

from dataclasses import dataclass

@dataclass
class B:
    x: str | int

    def f(self) -> int:
        y = self.x
        if isinstance(y, int):
            reveal_type(y)  # Revealed type for `y` is `int`.
            reveal_type(self.x)  # Revealed type for `self.x` is `typing.Union[int, str]`.
            return y + 2
        return 0

pyre version

Binary version: d4aef6ea269d577faf9a2a503032fda33f725936
Client version: 0.9.17

tmke8 avatar Dec 04 '22 18:12 tmke8

I see there was already a TODO for this

https://github.com/facebook/pyre-check/blob/2da1844a4ae1861bf5b765a80feaf463a62d8831/source/analysis/test/integration/isinstanceTest.ml#L400-L407

tmke8 avatar Dec 15 '22 12:12 tmke8

I think @stroxler recently fixed this, it should be available with the next open source release

yangdanny97 avatar Jul 25 '24 04:07 yangdanny97