Open
Description
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
Metadata
Metadata
Assignees
Labels
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
kylebarron commentedon May 21, 2025
It turns out I actually get this error even without a docstring:
this still gives an error of
[-]"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[/+]JelleZijlstra commentedon May 21, 2025
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 commentedon May 21, 2025
I'm sorry, I don't understand what the difference is between
fn1
andfn2
hereWhy would mypy allow one but not the other?
In the mypy stubs documentation it also says
JelleZijlstra commentedon May 21, 2025
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 commentedon May 22, 2025
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 commentedon May 22, 2025
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: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 commentedon May 26, 2025
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.