python / python/mypy

(🐞) `overload`s that exhaust finite `Literal`s(`bool`/`Enum`) not treated as exhaustive

Open
#14,764 14 comments 30 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug topic-literal-types topic-overloads
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

@overload
def foo(a: Literal[True]) -> int: ...

@overload
def foo(a: Literal[False]) -> str: ...

def foo(a: bool) -> object: ...

a: bool
reveal_type(foo(a))  # error: No overload variant of "foo" matches argument type "bool"
@overload
def foo(a: Literal[True]) -> int: ...

@overload
def foo(a: Literal[False]) -> str: ...

@overload
def foo(a: bool) -> object: ...  # no error regarding impossible to match overload

a: bool
reveal_type(foo(a))  # object
@overload
def foo(a: Literal[True, False]) -> int | str: ...

@overload
def foo(a: bool) -> object: ...  # error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader

def foo(a: bool) -> object: ...

a: bool
reveal_type(foo(a))  # int | str

Here mypy incorrectly forces us to implement a completely redundant overload for the non Literal case when it is already exhaustively covered by both literals. It is only when the literals are in the same overload (useless in practice, but just for demonstration) that mypy correctly handles this case.

Mypy should be doing 'union math' (or what ever it's called) to apply both literal overloads at once.

This also affects all other exhaustible Literals such as Enums.

This example is pulled directly from the docs, so I think they should be updated as well to an example that doesn't contain this confusing defect.

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 overload examples in the issue and read the linked Literal types documentation. Trace mypy's overload matching and handling of finite Literal and Enum values. Done means exhaustively covered separate literal overloads no longer require a redundant non-Literal overload, with the affected documentation example updated.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.