python / python/mypy

Misleading error message with `dict.get` like method. (polymorphic function with conflicting context)

Open
#20,576 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Consider this example that emulates dict.get: (https://mypy-play.net/?mypy=latest&python=3.12)

from typing import Any, reveal_type

class Map[K, V]:
    def set(self, key: K, value: V) -> None: ...
    def get[T](self, key: Any, default: T, /) -> V | T: ...

d_any: Map[str, Any] = Map()

reveal_type(d_any.get("key", None))  # Any | None  ✅️

result: str = reveal_type(d_any.get("key", None))  # Any | str ❌️
# error: Argument 2 to "get" of "Map" has incompatible type "None"; expected "str" 

mypys error message is misleading. None is a perfectly reasonable argument for the default value of d_any.get. The problem is that the return type Any | None is not assignable to str. It would make more sense if either:

  1. mypy reports that Any | None cannot be assigned to str.
    (e.g. by a two step approach: first try to solve with context and if that fails, use the return type that is inferred from the arguments alone)[^1]
  2. mypy reports that it cannot find a solution for the type variable T.
    (e.g. single step that considers both constraints from arguments and context)

[^1]: In certain special cases like tuple/list/set/dict-comprehensions, the current behavior that inverts the priority seems fine

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 reproducing the example in the linked mypy playground and compare the diagnostic with the two proposed outcomes. Trace mypy's generic type inference and contextual typing behavior for the polymorphic get call. Done means the diagnostic no longer incorrectly blames None and a regression test covers this example.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.