Daniil Fajnberg
Daniil Fajnberg

Reputation: 18663

Overloaded signature supposedly incompatible with supertype, despite not strengthening preconditions

Imagine being given the following base class that you have no control over:

from typing import Optional

class A:
    def foo(self, x: Optional[bool] = None) -> None:
        pass

Now you want to write a subclass that merely distinguishes two different call signatures using typing.overload without actually constraining the parameter types:

# ... import A
from typing import Literal, Optional, overload


class B(A):
    @overload
    def foo(self, x: Literal[True]) -> None: ...

    @overload
    def foo(self, x: Optional[Literal[False]] = None) -> None: ...

    def foo(self, x: Optional[bool] = None) -> None:
        pass

I would say the two overloaded B.foo signatures combined fully cover the possible calls of A.foo. I see no violation of the Liskov Substitution Principle here since the parameter types of B.foo have not been narrowed.

Yet mypy complains about this:

error: Signature of "foo" incompatible with supertype "A"  [override]
note:      Superclass:
note:          def foo(self, x: Optional[bool] = ...) -> None
note:      Subclass:
note:          @overload
note:          def foo(self, x: Literal[True]) -> None
note:          @overload
note:          def foo(self, x: Optional[Literal[False]] = ...) -> None

Is there something I am missing here or have I stumbled onto a limitation/bug of or mypy?

I found this issue #14725, which appears to address the same problem, but since nobody reacted yet, I am not sure this is actually a bug. If more people here agree that it is, I can of course simply # type: ignore[override] it for now and keep an eye on that issue, but maybe there is a good reason this is forbidden that I just don't understand.

A few other issues I found that seem vaguely related is this one: #14002, #3750


Tested on Python 3.9-3.11 with mypy==1.1.1.

For what it's worth, the PyCharm type checker also complains about this, but interestingly it only highlights the first overload signature (the one with Literal[True]) saying that it does not match that of the supertype.

Upvotes: 2

Views: 775

Answers (0)

Related Questions