Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion mypy/expandtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,9 +453,15 @@ def visit_union_type(self, t: UnionType) -> Type:
# After substituting for type variables in t.items, some resulting types
# might be subtypes of others, however calling make_simplified_union()
# can cause recursion, so we just remove strict duplicates.
return UnionType.make_union(
simplified = UnionType.make_union(
remove_trivial(flatten_nested_unions(expanded)), t.line, t.column
)
# This call to get_proper_type() is unfortunate but is required to preserve
# the invariant that ProperType will stay ProperType after applying expand_type(),
# otherwise a single item union of a type alias will break it. Note this should not
# cause infinite recursion since pathological aliases like A = Union[A, B] are
# banned at the semantic analysis level.
return get_proper_type(simplified)

def visit_partial_type(self, t: PartialType) -> Type:
return t
Expand Down
15 changes: 15 additions & 0 deletions test-data/unit/check-type-aliases.test
Original file line number Diff line number Diff line change
Expand Up @@ -1028,3 +1028,18 @@ RHSAlias3: type = tuple[int, ...]
WrongTypeElement = str | tuple[float, 1] # E: Invalid type: try using Literal[1] instead?
WrongEllipsis = str | tuple[float, float, ...] # E: Unexpected "..."
[builtins fixtures/tuple.pyi]

[case testNoCompiledCrashOnSingleItemUnion]
# flags: --no-strict-optional
from typing import Callable, Union, Generic, TypeVar

Alias = Callable[[], int]

T = TypeVar("T")
class C(Generic[T]):
attr: Union[Alias, None] = None

@classmethod
def test(cls) -> None:
cls.attr
[builtins fixtures/classmethod.pyi]