Skip to content

Regression with Narrowing (Test Cases) #20600

@George-Ogden

Description

@George-Ogden

I had been working on narrowing in #20277.
After #20275 was fixed in #20492, I merged and ran some test cases.

Here are some test cases that I wrote from that one that the new version fails on:

[case testMultipleTypeEqualsCheck]
from typing import Any

x: Any
y: Any
if type(x) == type(y) == int:
    reveal_type(y) # N: Revealed type is "builtins.int"
    reveal_type(x) # N: Revealed type is "builtins.int"

z: Any
if int == type(z) == int:
    reveal_type(z) # N: Revealed type is "builtins.int"

[case testTypeEqualsCheckUsingImplicitTypes]
from typing import Any

x: str
y: Any
z: object
if type(y) is type(x):
    reveal_type(x) # N: Revealed type is "builtins.str"
    reveal_type(y) # N: Revealed type is "builtins.str"

if type(x) is type(z):
    reveal_type(x) # N: Revealed type is "builtins.str"
    reveal_type(z) # N: Revealed type is "builtins.str"

[case testTypeEqualsCheckUsingDifferentSpecializedTypes]
from collections import defaultdict

x: defaultdict
y: dict
z: object
if type(x) is type(y) is type(z):
    reveal_type(x) # N: Revealed type is "collections.defaultdict[Any, Any]"
    reveal_type(y) # N: Revealed type is "collections.defaultdict[Any, Any]"
    reveal_type(z) # N: Revealed type is "collections.defaultdict[Any, Any]"

[case testUnionTypeEquality]
from typing import Any, reveal_type
# flags: --warn-unreachable

x: Any = ()
if type(x) == (int, str):
    reveal_type(x) # E: Statement is unreachable

class X: x = 1
class Y: y = 1
class Z(X, Y): ...

z = Z()
x: X = z
y: Y = z
if type(x) is type(y):
    reveal_type(x)  # N: Revealed type is "__main__.<subclass of "__main__.X" and "__main__.Y">"
    reveal_type(y)  # N: Revealed type is "__main__.<subclass of "__main__.Y" and "__main__.X">"
    x.y + y.x

if isinstance(x, type(y)) and isinstance(y, type(x)):
    reveal_type(x)  # N: Revealed type is "__main__.<subclass of "__main__.X" and "__main__.Y">"
    reveal_type(y)  # N: Revealed type is "__main__.<subclass of "__main__.X" and "__main__.Y">"
    x.y + y.x

[case testTypeEqualsCheckUsingIsNonOverlapping]
# flags: --warn-unreachable
from typing import Union

y: str
if type(y) is int:  # E: Subclass of "str" and "int" cannot exist: would have incompatible method signatures
    y  # E: Statement is unreachable
else:
    reveal_type(y) # N: Revealed type is "builtins.str"

[case testTypeEqualsMultipleTypesShouldntNarrow]
# make sure we don't do any narrowing if there are multiple types being compared
# flags: --warn-unreachable

from typing import Union

x: Union[int, str]
if type(x) == int == str:
    reveal_type(x)  # E: Statement is unreachable
else:
    reveal_type(x)  # N: Revealed type is "builtins.int | builtins.str"

Please let me know if I can contribute to #20598 (or any other parts of this feature).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions