Skip to content

Compatibility of return type with subclass upon overload #19952

@cmp0xff

Description

@cmp0xff

Hi, we have the following minimal code snippet that reproduces our concern from pandas-dev/pandas-stubs#1385. In words, when the return types from different overloads are parametrised by a type variable, type checkers can work. When return types are subclasses, however, mypy does not seem to work.

from typing import Any, Generic, Never, TypeVar, overload, reveal_type

T = TypeVar("T")

class Arg(Generic[T]): ...

class Gen(Generic[T]): ...

# part 1: return type is Generic

class D0:
    @overload
    def m(self, p: Arg[Never]) -> Gen: ...

    @overload
    def m(self, p: Arg[int]) -> Gen[int]: ...

reveal_type(D0().m(Arg[Any]()))  # pyright gives Gen[Unknown], mypy gives Gen[Any], good
reveal_type(D0().m(Arg[int]()))  # Gen[int], good
reveal_type(D0().m(Arg[float]()))  # error, good

# part 2: return types are subclasses

class Base: ...

class Sub(Base): ...

class D1:
    @overload
    def m(self, p: Arg[Never]) -> Base: ...  # we want to get Base for Arg[Any]; mypy warns overload-overlap here, whereas pyright does not warn (at least without strict)

    @overload
    def m(self, p: Arg[int]) -> Sub: ...

reveal_type(D1().m(Arg[Any]()))  # pyright gives Base, but mypy gives Any
reveal_type(D1().m(Arg[int]()))  # Sub, good
reveal_type(D1().m(Arg[float]()))  # error, good

Part 1 is understood from #19525. Could someone explain part 2? Thank you 🙂

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions