python / python/mypy

explode operator shouldn't be allowed for calls to arrity overloaded functions

Open
#16,054 3 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

In the test below the intention is that if test is called with one argument that it returns str, and if it is called with multiple that it returns list[str]. The assert will trip at runtime even though the example type checks. The documentation already warns that mypy can't do a perfect job of making sure that your actual implementation function respects the declarations, however, AFAICT there is no correct way to implement test, which makes me think that either this type of overloading should be forbidden or you should be forbidden from using the explode operator when calling such a function (foo, bar, *buzz would be fine but not just *buzz). mypy seems to assume that if you use the explode operator you must mean the overload that takes more than one argument, but in practice because the test implementation can't actually distinguish an explode operator using call from a regular call, the best that it can do is check how many arguments it actually received and assume that you mean the first overload if there is only 1.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from typing import overload

@overload
def test(x: str) -> str:
    assert False

@overload
def test(x: str, x2: str, *xn: str) -> list[str]:
    assert False

def test(x: str, x2: str | None = None, *xn: str) -> str | list[str]:
    allx = [x]
    if x2 is not None:
        allx.append(x2)
    allx.extend(xn)

    if len(allx) == 1:
        return allx[0]
    return allx

y = ["hi"]
z: list[str] = test(*y)
assert isinstance(z, list)

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 with the reproducer in the issue and trace how mypy resolves overloaded calls using the explode operator. Determine whether the call should be rejected or resolved differently, then add regression coverage showing that the reported example no longer type-checks incorrectly.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.