Type is lost after merge with `Union[Any, None]`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Bug Report
from typing import Any
def func(d: dict[int, Any]) -> None:
x: int | None
x = d.get(1)
reveal_type(x) # typing is lost -> Union[Any, None]
d.get get's correctly inferred as Any | None. However, merging the existing type int | None with Any | None results in Any | None. I.e. mypy looses the original type information. That is unexpected.
Comparing it to a type merge with just Any:
def f(a: Any) -> None:
x: int | None
x = a
reveal_type(x) # int | None
In this case x retains the type information, as expected.
--
Another example which doesn't rely on dict.get
def g(a: Any | None) -> None:
x: int | None
x = a
reveal_type(x) # typing is lost -> Union[Any, None]
Expected Behavior
Mypy should retain the original type information even after merging it with Any | None.
Your Environment
- Mypy version used: 0.971
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 with the three reproducer functions in the issue and run them through mypy with reveal_type to confirm the current behavior. Trace the type-merging and assignment logic for an existing int | None value combined with Any | None. Done means the inferred type remains int | None in all shown examples, with regression coverage for these cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100