python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.27k stars 2.79k forks source link

using a decorator on an overloaded function where the decorator uses `Concatenate` causes false positive "Overloaded function implementation does not accept all possible arguments" error #17459

Open DetachHead opened 3 months ago

DetachHead commented 3 months ago
from typing import Callable, Concatenate, TypeVar, overload, ParamSpec

T = TypeVar("T")
P = ParamSpec("P")
R = TypeVar("R")

def foo(fn: Callable[Concatenate[T, P], R]) -> Callable[Concatenate[T, P], R]:
    return fn

class Foo:
    @overload
    def bar(self, a: str) -> str: ...
    @overload
    def bar(self, a: int) -> int: ...

    # error: Overloaded function implementation does not accept all possible arguments of signature 1
    # error: Overloaded function implementation does not accept all possible arguments of signature 2
    @foo
    def bar(self, a: object) -> object: ...

playground

ilevkivskyi commented 3 months ago

This is because foo() destroys the argument name for the first argument. Internally, I see the inferred type for implementation is

def (__main__.Foo, a: builtins.object) -> builtins.object

so it cannot accept call like Foo.bar(self=Foo(), a=1). This seems way too pedantic however.

DetachHead commented 2 months ago

imo self should be implicitly positional only. i can't think of a case where you'd want to specify it as a keyword argument

erictraut commented 2 months ago

imo self should be implicitly positional only

There was a discussion about this in the typing forum. The general consensus was aligned with this viewpoint, and this is what I've implemented in pyright, but this hasn't yet been formally incorporated into the typing spec. You're welcome to add your input to the discussion thread.