Bug Report
When a class (e.g., Box in our example below) has two __init__ overloads — one taking Iterable[Never] (binding self to Box[Never]) and one taking Iterable[_T] (binding self to Box[_T]) — passing a value whose iteration type is Any incorrectly resolves to the Iterable[Never] overload, yielding Box[Never] instead of Box[_T].
To Reproduce
Gist URL: https://gist.github.com/mypy-play/d326ca961e53d4c9d085cfda05f3e455
Playground URL: https://mypy-play.net/?gist=d326ca961e53d4c9d085cfda05f3e455
# any_never_bug.py
from enum import IntEnum
from typing import Generic, Iterable, Never, TypeVar, overload, reveal_type
_T = TypeVar("_T")
class Box(Generic[_T]):
@overload
def __init__(self: "Box[Never]", val: Iterable[Never]) -> None: ...
@overload
def __init__(self: "Box[_T]", val: Iterable[_T]) -> None: ...
def __init__(self, val: object) -> None: ...
class Color(IntEnum):
RED = 1
GREEN = 2
reveal_type(Box(Color)) # Expected: Box[Color], mypy gives: Box[Never]
% mypy --config-file /dev/null any_never_bug.py
/dev/null: No [mypy] section in config file
any_never_bug.py:21: note: Revealed type is "any_never_bug.Box[Never]"
Success: no issues found in 1 source file
Expected Behavior
Expected: Box[Color]
Actual: Box[Never]
Notes:
My best guess on root cause is that EnumMeta.__iter__ is typed in typeshed as returning Iterator[Any], so Color (the class) is seen as Iterable[Any]. I'm guessing that since Any is consistent with Never, mypy selects the Iterable[Never] overload rather than the more general Iterable[_T] one. However, Iterable[Any] should probably not be considered assignable to Iterable[Never]. I'm pretty sure Never is the bottom type and nothing except Never itself should be a subtype of it. Pyright and Pyrefly both correctly infer Box[Color] for this case.
Your Environment
- Mypy version used: mypy 1.20.2 (compiled: yes)
- Mypy command-line flags: None
- Mypy configuration options from
mypy.ini (and other config files): None
- Python version used: Python 3.11.15
Ref: astral-sh/ty#3330
Bug Report
When a class (e.g.,
Boxin our example below) has two__init__overloads — one takingIterable[Never](bindingselftoBox[Never]) and one takingIterable[_T](bindingselftoBox[_T]) — passing a value whose iteration type isAnyincorrectly resolves to theIterable[Never]overload, yieldingBox[Never]instead ofBox[_T].To Reproduce
Gist URL: https://gist.github.com/mypy-play/d326ca961e53d4c9d085cfda05f3e455
Playground URL: https://mypy-play.net/?gist=d326ca961e53d4c9d085cfda05f3e455
Expected Behavior
Expected:
Box[Color]Actual:
Box[Never]Notes:
My best guess on root cause is that
EnumMeta.__iter__is typed in typeshed as returningIterator[Any], soColor(the class) is seen asIterable[Any]. I'm guessing that sinceAnyis consistent withNever, mypy selects theIterable[Never]overload rather than the more generalIterable[_T]one. However,Iterable[Any]should probably not be considered assignable toIterable[Never]. I'm pretty sureNeveris the bottom type and nothing exceptNeveritself should be a subtype of it. Pyright and Pyrefly both correctly inferBox[Color]for this case.Your Environment
mypy.ini(and other config files): NoneRef: astral-sh/ty#3330