Skip to content

"An implementation for an overloaded function is not allowed in a stub file" for overloaded type hint #19128

Open
@kylebarron

Description

@kylebarron

Bug Report

I'm documenting a compiled extension module written in Rust. I write docstrings in my .pyi file so that IDEs and API documentation can automatically pick up those docstrings.

Docstrings are allowed in functions but this errors when a function is overloaded.

To Reproduce

# tmp.pyi

from typing import overload

def fn1() -> None:
    """Call this function."""

@overload
def fn2(a: str) -> str: ...
@overload
def fn2(a: int) -> int: ...
def fn2(a: int | str) -> int | str:
    """Call this function."""
uv run mypy tmp.pyi

gives:

tmp.pyi:10: error: An implementation for an overloaded function is not allowed in a stub file  [misc]

Note that this does not error on line 3 for the non-overloaded function.

Expected Behavior

Expected mypy to not error when a docstring is included on a function that has overloads.

Actual Behavior

tmp.pyi:10: error: An implementation for an overloaded function is not allowed in a stub file  [misc]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used:

    > uv run mypy --version
    mypy 1.15.0 (compiled: yes)
    
  • Mypy command-line flags: None, just uv run mypy tmp.pyi

  • Mypy configuration options from mypy.ini (and other config files): None

  • Python version used:

    > uv run python --version
    Python 3.9.21
    

Activity

kylebarron

kylebarron commented on May 21, 2025

@kylebarron
Author

It turns out I actually get this error even without a docstring:

# tmp.pyi

from typing import overload

def fn1() -> None:
    """Call this function."""

@overload
def fn2(a: str) -> str: ...
@overload
def fn2(a: int) -> int: ...
def fn2(a: int | str) -> int | str: ...

this still gives an error of

An implementation for an overloaded function is not allowed in a stub file

changed the title [-]"An implementation for an overloaded function is not allowed in a stub file" for overloaded type hint with docstring (but no implementation)[/-] [+]"An implementation for an overloaded function is not allowed in a stub file" for overloaded type hint[/+] on May 21, 2025
JelleZijlstra

JelleZijlstra commented on May 21, 2025

@JelleZijlstra
Member

That error is correct and your code does exactly what the error tells you not to.

A docstring might be a good use case for doing this though, so maybe we should relax the check.

kylebarron

kylebarron commented on May 21, 2025

@kylebarron
Author

I'm sorry, I don't understand what the difference is between fn1 and fn2 here

def fn1() -> None:
    """Call this function."""

@overload
def fn2(a: str) -> str: ...
@overload
def fn2(a: int) -> int: ...
def fn2(a: int | str) -> int | str:
    """Call this function."""

Why would mypy allow one but not the other?

In the mypy stubs documentation it also says

It is also acceptable for the function body to contain a docstring

JelleZijlstra

JelleZijlstra commented on May 21, 2025

@JelleZijlstra
Member

The error is "An implementation for an overloaded function is not allowed in a stub file". The second one is an overloaded function, the first one isn't.

kylebarron

kylebarron commented on May 22, 2025

@kylebarron
Author

Sorry, the part I'm confused about is not "overloaded function" it's "implementation".

Neither of the two definitions are associated with any code body, so I wouldn't have expected either of them to be considered to have "an implementation".

And especially because the first doesn't error, to a user the definition of "having an implementation" seems inconsistent.

sterliakov

sterliakov commented on May 22, 2025

@sterliakov
Collaborator

Overloaded function implementation refers to the whole def not marked with @overload. Stubs are different, the typical usage (enforced by mypy here) for overload in stubs looks like this:

@overload
def fn2(a: str) -> str: ...
@overload
def fn2(a: int) -> int: ...

There's no point in adding the final signature to stub code, it is ignored when checking foreign calls and only affects checking the body of the implementation.

aatle

aatle commented on May 26, 2025

@aatle
Contributor

I'm having a similar issue for documenting a C extension module.

The error is expected; overloaded functions typically don't need an implementation definition inside stub files.
But then, where does the docstring go?
If it's placed inside an implementation definition in the stub file, then mypy errors.

Should it be placed inside only the last overload then?
One linter complains about this, pydocstyle, used in ruff, https://docs.astral.sh/ruff/rules/overload-with-docstring/, though no reasoning is given why it's bad and many tools support per-overload docstrings.
But then, these tools might assume that there is no docstring for the previous overloads. I tested 2 LSPs: for Pylance, an overload with no dosctring will inherit it from the first overload that does, but Jedi makes no attempt to share docstrings and so the first few overloads would have no docstrings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @JelleZijlstra@kylebarron@sterliakov@aatle

        Issue actions

          "An implementation for an overloaded function is not allowed in a stub file" for overloaded type hint · Issue #19128 · python/mypy