Unions of homogeneous collections unnecessarily broadened when used to construct a new collection
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Bug Report
mypy infers an incorrectly broad type in some cases where collections are constructed from a collection whose type is a union. In particular, if the input to a collection constructor is a union of collections with homogeneous element types, the type that mypy infers ignores the fact that the inputs are homogeneous. The type mypy infers is not wrong (in that the actual type will be covered by it), but it is unnecessarily broad (it matches types which are obviously not possible -- i.e., a collection with heterogeneous element types).
To Reproduce
https://mypy-play.net/?mypy=latest&python=3.12&gist=04f25887cd105eefebfdcbdbd3c03665
https://gist.github.com/mypy-play/04f25887cd105eefebfdcbdbd3c03665
from typing import Generator
from typing_extensions import reveal_type
list_union: list[int] | list[None]
set_union: set[int] | set[None]
tuple_union: tuple[int, ...] | tuple[None, ...]
generator_union: Generator[int, None, None] | Generator[None, None, None]
# Expected: "Union[builtins.list[builtins.int], builtins.list[None]]"
# Actual: "builtins.list[Union[builtins.int, None]]"
reveal_type(list(list_union))
reveal_type(list(set_union))
reveal_type(list(tuple_union))
reveal_type([x for x in generator_union])
# Expected: "Union[builtins.set[builtins.int], builtins.set[None]]"
# Actual: "builtins.set[Union[builtins.int, None]]"
reveal_type(set(list_union))
reveal_type(set(set_union))
reveal_type(set(tuple_union))
reveal_type({x for x in generator_union})
# Expected: "Union[builtins.tuple[builtins.int, ...], builtins.tuple[None, ...]]"
# Actual: "builtins.tuple[Union[builtins.int, None], ...]"
reveal_type(tuple(list_union))
reveal_type(tuple(set_union))
reveal_type(tuple(tuple_union))
reveal_type(tuple(x for x in generator_union))
Expected Behavior
Because mypy knows that the argument to the collection constructor is a collection whose elements are all of the same type, I assumed it would thus realize that it would result in a collection whose elements are all of the same type.
Actual Behavior
mypy incorrectly reports that the resulting collection may have heterogeneous element types.
Your Environment
- Mypy version used: 1.15.0
- Mypy command-line flags: None
- Mypy configuration options from
mypy.ini(and other config files): None - Python version used: 3.12
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the Python reproducer from the issue or the linked mypy-play gist and compare the reveal_type results with the expected unions. Trace mypy's handling of collection constructors and comprehensions for unions of homogeneous collections. Done means the examples infer the corresponding union of homogeneous list, set, and tuple types without introducing heterogeneous element types.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100