Skip to content
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

callable protocols cannot infer the type of their own self #15188

Closed
glyph opened this issue May 5, 2023 · 0 comments · Fixed by #15913
Closed

callable protocols cannot infer the type of their own self #15188

glyph opened this issue May 5, 2023 · 0 comments · Fixed by #15913
Labels
bug mypy got something wrong

Comments

@glyph
Copy link

glyph commented May 5, 2023

Bug Report

Methods on protocols with a __call__ method cannot infer the type of self
as callable in other methods.

To Reproduce

https://mypy-play.net/?mypy=latest&python=3.11&flags=strict&gist=7234281168a0762dd9a81b1f10d8a96a

from typing import Callable, ParamSpec, Protocol, TypeVar

Params = ParamSpec("Params")
Result = TypeVar("Result", covariant=True)

class FancyMethod(Protocol):

    def __call__(self, arg1: int, arg2: str) -> list[float]:
        """
        Calling me results in a very specific signature.
        """

    def returnMe(self: Callable[Params, Result]) -> Callable[Params, Result]:
        ...

def externalGet(self: Callable[Params, Result]) -> Callable[Params, Result]:
    return self

Expected Behavior

I would expect that this would be inferred in returnMe the same way that it would be in externalGet.

Actual Behavior

main.py:13: error: The erased type of self "def (*Params.args, **Params.kwargs) -> Result`-2" is not a supertype of its class "__main__.FancyMethod"  [misc]
@glyph glyph added the bug mypy got something wrong label May 5, 2023
hauntsaninja pushed a commit that referenced this issue Sep 14, 2023
Fixes #15734
Fixes #15188
Fixes #14321
Fixes #13107 (plain Callable was
already working, this fixes the protocol example)
Fixes #16058

It looks like treating trivial suffixes (especially for erased
callables) as "whatever works" is a right thing, because it reflects the
whole idea of why we normally check subtyping with respect to an e.g.
erased type. As you can see this fixes a bunch of issues. Note it was
necessary to make couple more tweaks to make everything work smoothly:
* Adjust self-type erasure level in `checker.py` to match other places.
* Explicitly allow `Callable` as a `self`/`cls` annotation (actually I
am not sure we need to keep this check at all, since we now have good
inference for self-types, and we check they are safe either at
definition site or at call site).
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

Successfully merging a pull request may close this issue.

1 participant