python / python/mypy

Mypy not inferring return type of dict.get()

Open
#20,631 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Bug Report

Mypy fails to infer the return type of dict.get(), even though the dictionary is fully type-hinted, triggering a no-any-return error when Mypy is run in --strict mode.

To Reproduce

https://mypy-play.net/?mypy=latest&python=3.14&flags=strict&gist=61ec65a894e2259d4b3a0e65ef31c33c

from typing import ClassVar, Final, Self, Any


class Interface:

    # Every subclass has a _name attribute (set by __init_subclass__)
    _name: ClassVar[Final[str]]

    # Registry of subclasses
    _iftypes: ClassVar[Final[dict[str, type[Self]]]] = {}

    def __init_subclass__(cls, **kwargs: Any) -> None:
        super().__init_subclass__(**kwargs)
        name = cls.__name__.lower()
        cls._name = name
        cls._iftypes[name] = cls

    def __init__(self, ifname: str) -> None:
        self._ifname = ifname

    @classmethod
    def from_registry(cls, name: str, kind: str) -> Self:
        #ifcls: type[Self] | None = cls._iftypes.get(kind)
        ifcls = cls._iftypes.get(kind)
        if ifcls is None:
            raise ValueError()
        return ifcls(name)


class Bond(Interface):
    pass


class Bridge(Interface):
    pass


class VLAN(Interface):
    pass


for kind, ifcls in Interface._iftypes.items():
    print(f'{kind}: {ifcls.__name__}')

Expected Behavior

Mypy should infer that the object returned by dict.get() and assigned to ifcls on line 25 is type[Self] | None, which is narrowed to just type[Self] by the check on line 26. Thus, calling its constructor must return a instance of Self.

Actual Behavior

$ mypy --strict bug.py
main.py:28: error: Returning Any from function declared to return "Self"  [no-any-return]
Found 1 error in 1 file (checked 1 source file)

Your Environment

Fedora 43 (x86_64)
python3-3.14.2-1.fc43.x86_64
python3-mypy-1.18.2-1.fc43.noarch

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 linked mypy-play reproduction and the shown example with --strict to confirm the no-any-return error. Trace how the fully typed dict.get() result is inferred and narrowed around ifcls, then add coverage for the expected type[Self] | None behavior and verify the example no longer reports the error.

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.