python / python/mypy

`Iterable[Any]` incorrectly matches `Iterable[Never]` overload, inferring `Never` instead of the element type

Open
#21,317 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug topic-enum
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the any_never_bug.py reproducer with mypy --config-file /dev/null and confirm the revealed type. Trace overload resolution for Iterable[Any] against the Iterable[Never] and Iterable[_T] signatures, then verify that the result is Box[Color] without regressing the shown overload behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers, devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.