Skip to content

Overloads in super-class for sub-class specific return types #11759

Closed

Description

@twoertwein

Bug Report
It is probably not good coding style to implement sub-class specific behavior in a super-class, but it would be great to still be able to write type annotations for it.

The sub-class specific overloads in the example below make mypy and pyright correctly infer the return type. Unfortunately, mypy throws an error for the two sub-class specific overloads. Are these false-positives?

To Reproduce

from __future__ import annotations

from typing import overload


class Base:
    @overload
    def any(self: A) -> bool:   # mypy:  The erased type of self "test.A" is not a supertype of its class "test.Base"
        ...

    @overload
    def any(self: B) -> str:  # mypy:  The erased type of self "test.B" is not a supertype of its class "test.Base"
        ...

    @overload
    def any(self) -> bool | str:
        ...

    def any(self) -> bool | str:
        # implementation that handles sub-classes differently
        ...


class A(Base):
    ...


class B(Base):
    ...


# mypy&pyright: bool | str
reveal_type(Base().any())

# mypy&pyright: bool
reveal_type(A().any())

# mypy&pyright: str
reveal_type(B().any())

Expected Behavior
No erased type errors?

Actual Behavior
See inline comments.

Your Environment

  • Mypy version used: 0.910
  • Mypy command-line flags: -
  • Mypy configuration options from mypy.ini (and other config files): -
  • Python version used: 3.9.6
  • Operating system and version: 3.10.0-693.5.2.el7.x86_64

Activity

  1. AlexWaygood commented on Mar 31, 2022

    @AlexWaygood
    Member

    Is this feature really necessary? You can achieve the same thing just by doing this:

    from __future__ import annotations
    from typing import Callable
    
    
    class Base:
        def any(self) -> bool | str:
            # implementation that handles sub-classes differently
            ...
    
    
    class A(Base):
        any: Callable[[A], bool]
    
    
    class B(Base):
        any: Callable[[B], str]
    
    
    reveal_type(Base().any())  # Revealed type is "Union[builtins.bool, builtins.str]"
    reveal_type(A().any())  # Revealed type is "builtins.bool"
    reveal_type(B().any())  # Revealed type is "builtins.str"

    Mypy has no complaints, and it's even more concise.

  2. twoertwein commented on Mar 31, 2022

    @twoertwein
    Author

    Thank you @AlexWaygood, I like it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions