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

[1.12 regression] mypy no longer recognises descriptors/get that bind self #18036

Closed
maxfischer2781 opened this issue Oct 24, 2024 · 1 comment · Fixed by #18040
Closed

[1.12 regression] mypy no longer recognises descriptors/get that bind self #18036

maxfischer2781 opened this issue Oct 24, 2024 · 1 comment · Fixed by #18040
Labels
bug mypy got something wrong

Comments

@maxfischer2781
Copy link

maxfischer2781 commented Oct 24, 2024

Bug Report

For decorators that work on methods as descriptors, I do type-hint+overload __get__ as returning the descriptor or filling in self. This previously worked up to MyPy 1.11 and PyRight was/is happy with it. However, since version 1.12 MyPy no longer matches the overload and completely loses type information; the Possible overload variant suggested is the least suitable.

I initially was notified about this for my own library providing async versions of the standard library, specifically the lru_cache. An MRE not using my library is below (in case I missed something that makes the MRE fixable but not my library, this would be good to know, too).

To Reproduce

from __future__ import annotations
from typing import Any, overload, Callable, Concatenate


class Descriptor[C: Callable[..., Any]]:
    def __init__(self, impl: C) -> None: ...

    @overload
    def __get__(
        self: Descriptor[C], instance: None, owner: type | None
    ) -> Descriptor[C]: ...

    @overload
    def __get__[S, **P, R](
        self: Descriptor[Callable[Concatenate[S, P], R]], instance: S, owner: type | None,
    ) -> Callable[P, R]: ...


class Test:
    @Descriptor
    def method(self, foo: int, bar: str) -> bytes: ...


reveal_type(Test().method)
# Pyright pyright 1.1.386    Type of "Test().method" is "(foo: int, bar: str) -> bytes"
# MyPy 1.11                  Revealed type is "def (foo: builtins.int, bar: builtins.str) -> builtins.bytes"
# MyPy 1.12                  Revealed type is "Any"

Playground link. The ordering of the overload cases does not matter.

Expected Behavior

MyPy should correctly infer the type of the bound method. MyPy should report the most suitable overload.

Actual Behavior

MyPy matches none of the overloads and thus completely loses type information. The reported most suitable overload is actually the least suitable.

Your Environment

  • Mypy version used: 1.12 and 1.13
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): defaults
  • Python version used: CPython 3.8 - 3.12
@maxfischer2781 maxfischer2781 added the bug mypy got something wrong label Oct 24, 2024
@hauntsaninja hauntsaninja changed the title [Regression] MyPy >=1.12 no longer recognises descriptors/get that bind self [1.12 regression] mypy no longer recognises descriptors/get that bind self Oct 24, 2024
@hauntsaninja
Copy link
Collaborator

Bisects to #17873 cc @JukkaL

mypy_primer -p test.py --bisect-output 'Revealed type is "Any' --debug --old 'v1.11.2'

JukkaL added a commit that referenced this issue Oct 25, 2024
ParamSpec types can match arbitrary parameter types, so treat
them as having 'object' as the upper bound.

This also fixes issues with filtering of overload items based on self type.

Fixes #18036.
@JukkaL JukkaL closed this as completed in 9323b88 Oct 25, 2024
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.

2 participants