Closed
Description
Bug Report
from typing import Union, NewType
Int = NewType("Int", int)
Float = NewType("Float", float)
def raw_types(arg: Union[int, float, None]) -> None:
if isinstance(arg, int):
reveal_type(arg) # Revealed type is "builtins.int"
elif isinstance(arg, float):
reveal_type(arg) # Revealed type is "builtins.float"
else:
reveal_type(arg) # Revealed type is "None"
def new_types(arg: Union[Int, Float, None]) -> None:
if isinstance(arg, int):
reveal_type(arg) # Revealed type is "__main__.Int"
elif isinstance(arg, float):
reveal_type(arg) # Revealed type is "Union[__main__.Int, __main__.Float]" (NARROWING FAILED)
else:
reveal_type(arg) # Revealed type is "None"
def new_types_not_optional(arg: Union[Int, Float]) -> None:
if isinstance(arg, int):
reveal_type(arg) # Revealed type is "__main__.Int"
elif isinstance(arg, float):
reveal_type(arg) # Revealed type is "__main__.Float"
else:
reveal_type(arg)
The bug is fairly straightforward. When narrowing a Union
of NewType
types with isinstance
, the narrowing fails if one of the possible types of the variable is None
.
To Reproduce
https://mypy-play.net/?mypy=0.931&python=3.10&gist=557b54a098f8ed366fa62ff380ec12c8
Expected Behavior
All revealed types after isinstance(arg, float)
would be builtins.float
or __main__.Float
.
Actual Behavior
The revealed type in the buggy case is still Union[__main__.Int, __main__.Float]
.