Repository: python/mypy (Python)

Issue:
Overloading staticmethods
Overloaded staticmethod isn't considered correctly by the type checker.
foobar.py
```
from typing import overload

class Snafu(object):
    @overload
    @staticmethod
    def snafu(value: None) -> None: ...

    @overload
    @staticmethod
    def snafu(value: bytes) -> bytes: ...

    @overload
    @staticmethod
    def snafu(value: str) -> bytes: ...

    @staticmethod
    def snafu(value):
        return bytes(value, encoding='UTF-16')

print(Snafu().snafu('123'))
```
While running `mypy foobar.py` expected output: `Success: no issues found in 1 source file`,
but got `foobar.py:21: error: No overload variant of "snafu" of "Snafu" matches argument type "str"
`.
I guessed [#5224](https://github.com/python/mypy/pull/5224) had to fix this, but i've got the behavior above.

Am i doing something wrong?

mypy v0.740, Python v3.7.4


Hints:
It looks like it only works right now if you call it directly via the class: `Snafu.snauf('123')`.
@Michael0x2a Any chance you are excited to take another look at this thrilling interaction?
I have also ran into this problem. Any chance it gets addressed?
bug stil exists in

mypy 0.812
python 3.8.x
My current workaround is to write an overloaded function (outside of the class body) instead of an overloaded staticmethod.
This bug still appears to exist in mypy 0.931, python 3.10x :( 
This is also a problem for typeshed: python/typeshed#7543.
Problem still present for mypy 0.961, python 3.10.2 

```
class Toto:

    @overload
    @staticmethod
    def toto(arg: int, arg2: str) -> None: ...

    @overload
    @staticmethod
    def toto(arg: int) -> None: ...

    @overload
    @staticmethod
    def toto() -> None: ...

    @staticmethod
    def toto(arg: int = 0, arg2: str='') -> None:
        pass


Toto.toto(3)
t = Toto()
t.toto(3)
```

```
Oucome of mypy:
tests\qapplication.py:35: error: Attribute function "toto" with type "Callable[[], None]" does not accept self argument  [misc]
tests\qapplication.py:35: error: No overload variant of "toto" of "Toto" matches argument type "int"  [call-overload]
tests\qapplication.py:35: note: Possible overload variants:
tests\qapplication.py:35: note:     def toto(arg, arg2: str) -> None
tests\qapplication.py:35: note:     def toto(arg) -> None
tests\qapplication.py:35: note:     def toto() -> None
Found 3 errors in 1 file (checked 1 source file)

```

Line 35 is the `t.toto(3)` 
Had this issue too (0.961 3.10.5), only crops up on instances of the class, not the class itself

Patch:
diff --git a/mypy/checkmember.py b/mypy/checkmember.py
--- a/mypy/checkmember.py
+++ b/mypy/checkmember.py
@@ -302,7 +302,7 @@ def analyze_instance_member_access(
             mx.msg.cant_assign_to_method(mx.context)
         signature = function_type(method, mx.named_type("builtins.function"))
         signature = freshen_function_type_vars(signature)
-        if name == "__new__":
+        if name == "__new__" or method.is_static:
             # __new__ is special and behaves like a static method -- don't strip
             # the first argument.
             pass
@@ -315,6 +315,8 @@ def analyze_instance_member_access(
                     signature, dispatched_type, method.is_class, mx.context, name, mx.msg
                 )
             signature = bind_self(signature, mx.self_type, is_classmethod=method.is_class)
+        # TODO: should we skip these steps for static methods as well?
+        # Since generic static methods should not be allowed.
         typ = map_instance_to_supertype(typ, method.info)
         member_type = expand_type_by_instance(signature, typ)
         freeze_type_vars(member_type)


Test patch:
diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test
--- a/test-data/unit/check-overloading.test
+++ b/test-data/unit/check-overloading.test
@@ -6527,3 +6527,20 @@ class Test:
     def foo(self, arg: Sequence[A]) -> None: ...
     def foo(self, arg: Union[Sequence[E], Sequence[A]]) -> None:
         ...
+
+[case testOverloadedStaticMethodOnInstance]
+from typing import overload
+
+class Snafu(object):
+    @overload
+    @staticmethod
+    def snafu(value: bytes) -> bytes: ...
+    @overload
+    @staticmethod
+    def snafu(value: str) -> str: ...
+    @staticmethod
+    def snafu(value):
+        ...
+reveal_type(Snafu().snafu('123'))  # N: Revealed type is "builtins.str"
+reveal_type(Snafu.snafu('123'))  # N: Revealed type is "builtins.str"
+[builtins fixtures/staticmethod.pyi]