FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix: deduplicate union items after type alias resolution (#22194) by DawnofGenX · Pull Request #22200 · python/mypy · GitHub

Repository navigation

Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .py  (1) .test  (1) All 2 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
29 changes: 23 additions & 6 deletions mypy/messages.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
flatten_nested_unions,
get_proper_type,
get_proper_types,
remove_dups,
)
from mypy.typetraverser import TypeTraverserVisitor
from mypy.util import plural_s, unmangle
Expand Down Expand Up @@ -2788,7 +2789,7 @@ def format_literal_value(typ: LiteralType) -> str:
elif isinstance(typ, LiteralType):
return f"Literal[{format_literal_value(typ)}]"
elif isinstance(typ, UnionType):
typ = get_proper_type(ignore_last_known_values(typ))
typ = get_proper_type(ignore_last_known_values(strip_alias_duplicates(typ)))
if not isinstance(typ, UnionType):
return format(typ)
literal_items, union_items = separate_union_literals(typ)
Expand Down Expand Up @@ -3524,12 +3525,28 @@ def ignore_last_known_values(t: UnionType) -> Type:
union_items: list[Type] = []
seen_instances = set()
for item in t.items:
if isinstance(item, ProperType) and isinstance(item, Instance):
erased = item.copy_modified(last_known_value=None)
proper = get_proper_type(item)
if isinstance(proper, Instance):
erased = proper.copy_modified(last_known_value=None)
if erased in seen_instances:
continue
seen_instances.add(erased)
union_items.append(erased)
else:
union_items.append(item)
union_items.append(item)
return UnionType.make_union(union_items, t.line, t.column)


def strip_alias_duplicates(t: UnionType) -> UnionType:
"""Drop union items that duplicate another item once aliases are expanded.

A union like ``TextInput | ImageInput``, where ``TextInput`` is ``str`` and
``ImageInput`` is ``str | None``, currently renders as ``str | str | None``
because the duplicate only shows up after the aliases are resolved (GH
22194). Expanding the aliases and re-deduplicating here keeps the message
readable without changing the type recorded in the symbol table, so it is
safe for recursive aliases, which stay collapsed by the formatter.
"""
expanded = flatten_nested_unions(t.items, handle_recursive=False)
unique = remove_dups([get_proper_type(item) for item in expanded])
if len(unique) == len(expanded):
return t
return UnionType(unique, t.line, t.column)
12 changes: 12 additions & 0 deletions test-data/unit/check-union-or-syntax.test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,18 @@ b: X # E: Variable "__main__.X" is not valid as a type \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
[builtins fixtures/type.pyi]

[case testUnionOrSyntaxWithTypeAliasDeduplication]
from typing_extensions import TypeAlias

TextInput: TypeAlias = str
ImageInput: TypeAlias = str | None

SingleInput: TypeAlias = TextInput | ImageInput
def f(si: SingleInput) -> None:
pass
f(1) # E: Argument 1 to "f" has incompatible type "int"; expected "str | None"
[builtins fixtures/type.pyi]

[case testUnionOrSyntaxInComment]
x = 1 # type: int | str

Expand Down
Loading

Back | FazBrowse Home | New Git URL