Skip to content

False-positive no-untyped-def with @overload #13834

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
bersbersbers opened this issue Oct 7, 2022 · 3 comments
Closed

False-positive no-untyped-def with @overload #13834

bersbersbers opened this issue Oct 7, 2022 · 3 comments
Labels
bug mypy got something wrong

Comments

@bersbersbers
Copy link

bersbersbers commented Oct 7, 2022

Bug Report

I get a false-positive no-untyped-def on the non-@overload-decorated definition.

To Reproduce

Example from PEP 484:

In regular modules, a series of @overload-decorated definitions must be followed by exactly one non-@overload-decorated definition (for the same function/method).

"""False-positive no-untyped-def."""
from typing import overload

@overload
def utf8(value: None) -> None:
    ...

@overload
def utf8(value: bytes) -> bytes:
    ...

def utf8(value):
    print(value)

Expected Behavior

No error.

Actual Behavior

bug.py:15: error: Function is missing a type annotation
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 0.982
  • Mypy command-line flags: --disallow-untyped-defs (!)
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.10.7
@bersbersbers bersbersbers added the bug mypy got something wrong label Oct 7, 2022
@JelleZijlstra
Copy link
Member

mypy is correct here. We need annotations on the overload implementation so that we can type check its body.

@bersbersbers
Copy link
Author

We need annotations on the overload implementation so that we can type check its body.

Hm - I wonder why mypy does not simply check the body once for each overload.

Anyway, assuming we can ignore PEP 484, I wonder how to implement this correctly. I mean, the point of the overloads is to separate disjoint sets of argument types, so it seems somewhat pointless to combine them again into a single type annotation that covers all overloads. Here's an example that does not work, but maybe I am approaching it the wrong way:

from typing import Callable, overload

@overload
def pass_value_to_func(func: Callable[[float], None], value: float) -> None: ...
@overload
def pass_value_to_func(func: Callable[[int], None], value: int) -> None: ...

def pass_value_to_func(func: Callable[[float], None] | Callable[[int], None], value: float | int) -> None:
    func(value)

def print_float(value: float) -> None:
    print(value)

def print_int(value: int) -> None:
    print(value)

pass_value_to_func(print_float, 1.0)
pass_value_to_func(print_int, 1)

bug.py:9: error: Argument 1 has incompatible type "Union[float, int]"; expected "int"
Found 1 error in 1 file (checked 1 source file)

@hauntsaninja
Copy link
Collaborator

Duplicate of #3360

@hauntsaninja hauntsaninja marked this as a duplicate of #3360 Oct 7, 2022
@hauntsaninja hauntsaninja closed this as not planned Won't fix, can't repro, duplicate, stale Oct 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

3 participants