microsoft / pyright

Static Type Checker for Python
Other
13.39k stars 1.46k forks source link

Inconsistency between mypy and Pyright for overloaded method with union of callable types #9042

Closed hrpatil closed 1 month ago

hrpatil commented 1 month ago

There appears to be a discrepancy between mypy and Pyright in how they handle overloaded methods with a union of callable types. The following code passes mypy checks without any errors, but Pyright reports "Overloaded implementation is not consistent with signature of overload" errors.

from typing import Any, Callable, Concatenate, TypeAlias, TypeVar, overload

Template: TypeAlias = dict[str, Any]
F1: TypeAlias = Callable[
    Concatenate[Template, str, None, str, ...], Template | list[Template] | None
]
F2: TypeAlias = Callable[
    Concatenate[list[Template], str, None, list[str], ...], list[Template] | None
]
F3: TypeAlias = Callable[
    Concatenate[Template, str, str, str, ...], Template | list[Template] | None
]
F4: TypeAlias = Callable[
    Concatenate[list[Template], str, str, list[str], ...], list[Template] | None
]
SlideCreationFunc: TypeAlias = F1 | F2 | F3 | F4
F = TypeVar("F", bound=SlideCreationFunc)

class Presentation:
    def __init__(self) -> None:
        self.slides: list[
            tuple[str, str, str | None, str | list[str], SlideCreationFunc]
        ] = []

    @overload
    def slide(
        self, section: str, slide_group: None, slide: str
    ) -> Callable[[F1], F1]: ...

    @overload
    def slide(
        self, section: str, slide_group: None, slide: list[str]
    ) -> Callable[[F2], F2]: ...

    @overload
    def slide(
        self, section: str, slide_group: str, slide: str
    ) -> Callable[[F3], F3]: ...

    @overload
    def slide(
        self, section: str, slide_group: str, slide: list[str]
    ) -> Callable[[F4], F4]: ...

    def slide(
        self, 
        section: str, 
        slide_group: str | None, 
        slide: str | list[str]
    ) -> Callable[[F], F]:
        def decorator(f: F) -> F:
            self.slides.append((f.__name__, section, slide_group, slide, f))
            return f
        return decorator

Code sample in pyright playground

Code sample in mypy play-net

pylance version : 2024.9.1 (9 September 2024) Release - No error pyright version: 1.1.381 - 4 errors

erictraut commented 1 month ago

I'm not able to repro the problem with recent versions of pyright. The reason you're seeing errors in the pyright playground is that you have it set to pyright 1.1.353, which is quite old. If you switch to a more recent version of pyright, you should see the errors go away.

hrpatil commented 1 month ago

I've tested on the latest version of Pyright and can confirm there is no issue. The problem was indeed with an outdated version in my virtual environment. Updating Pyright resolved the errors. Thank you for your help in identifying this, and I appreciate your quick response to my report.