From b215b2cc9236f27b7f1a51a6a35175fb8bcae75b Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Tue, 2 May 2017 09:40:35 +0200 Subject: [PATCH 1/3] Always flatten unions on creation --- mypy/types.py | 13 ++++++++++++- test-data/unit/check-unions.test | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/mypy/types.py b/mypy/types.py index 91f75f6c592f..c8d71b6f056b 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -987,7 +987,7 @@ class UnionType(Type): items = None # type: List[Type] def __init__(self, items: List[Type], line: int = -1, column: int = -1) -> None: - self.items = items + self.items = flatten_types(items) self.can_be_true = any(item.can_be_true for item in items) self.can_be_false = any(item.can_be_false for item in items) super().__init__(line, column) @@ -1732,6 +1732,17 @@ def get_type_vars(typ: Type) -> List[TypeVarType]: return tvars +def flatten_types(types: Iterable[Type]) -> List[Type]: + """Flatten nested unions in a type list.""" + flat_items = [] # type: List[Type] + for tp in types: + if isinstance(tp, UnionType): + flat_items.extend(flatten_types(tp.items)) + else: + flat_items.append(tp) + return flat_items + + def union_items(typ: Type) -> List[Type]: """Return the flattened items of a union type. diff --git a/test-data/unit/check-unions.test b/test-data/unit/check-unions.test index 8a89dabad82b..f7774d5e5bcb 100644 --- a/test-data/unit/check-unions.test +++ b/test-data/unit/check-unions.test @@ -453,6 +453,21 @@ reveal_type(l) \ # E: Revealed type is 'builtins.list[Union[builtins.bool, builtins.int, builtins.float, builtins.str]]' [builtins fixtures/list.pyi] +[case testNestedUnionsProcessedCorrectly] +from typing import Union + +class A: pass +class B: pass +class C: pass + +def foo(bar: Union[Union[A, B], C]) -> None: + if isinstance(bar, A): + reveal_type(bar) # E: Revealed type is '__main__.A' + else: + reveal_type(bar) # E: Revealed type is 'Union[__main__.B, __main__.C]' +[builtins fixtures/isinstance.pyi] +[out] + [case testAssignAnyToUnion] from typing import Union, Any x: Union[int, str] From c094a90d248089f441c995e75581e0faba7de115 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Tue, 2 May 2017 19:13:48 +0200 Subject: [PATCH 2/3] Fix confusing function name --- mypy/types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy/types.py b/mypy/types.py index c8d71b6f056b..683674cec0ca 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -987,7 +987,7 @@ class UnionType(Type): items = None # type: List[Type] def __init__(self, items: List[Type], line: int = -1, column: int = -1) -> None: - self.items = flatten_types(items) + self.items = flatten_nested_unions(items) self.can_be_true = any(item.can_be_true for item in items) self.can_be_false = any(item.can_be_false for item in items) super().__init__(line, column) @@ -1732,7 +1732,7 @@ def get_type_vars(typ: Type) -> List[TypeVarType]: return tvars -def flatten_types(types: Iterable[Type]) -> List[Type]: +def flatten_nested_unions(types: Iterable[Type]) -> List[Type]: """Flatten nested unions in a type list.""" flat_items = [] # type: List[Type] for tp in types: From 2ca71d60a224a07fb5a2d8a01a68a78687518765 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Tue, 2 May 2017 19:19:11 +0200 Subject: [PATCH 3/3] Fixed name change in one more place --- mypy/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/types.py b/mypy/types.py index 683674cec0ca..090abea1aad8 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1737,7 +1737,7 @@ def flatten_nested_unions(types: Iterable[Type]) -> List[Type]: flat_items = [] # type: List[Type] for tp in types: if isinstance(tp, UnionType): - flat_items.extend(flatten_types(tp.items)) + flat_items.extend(flatten_nested_unions(tp.items)) else: flat_items.append(tp) return flat_items