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 wrongtopic-type-narrowingConditional type narrowing / binder

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions