Skip to content

[overload][intersection-types] undetected LSP violation in multiple inheritance #15790

Description

@randolf-scholz

Bug Report

Essentially, the bug occurs when trying to define a subclass of C≤A&B, and implementing a shared method via @overload:

classA:
deffoo(self, x: Hashable) ->Hashable: ...
classB:
deffoo(self, x: Sized) ->Sized: ...
classC(A, B):
@overloaddeffoo(self, x: Hashable) ->Hashable: ...
@overloaddeffoo(self, x: Sized) ->Sized: ...

C is not a proper subclass of A & B since C.foo(Hashable & Sized) yields Hashable, violating LSP for B. mypy does not detect this issue. To resolve this, an extra overload of the form def foo(x: Hashable & Sized) -> ... is needed.

To Reproduce

A concrete demo with non-trivial types.
fromtypingimportoverloadfromcollections.abcimportHashable, SizedclassA:
deffoo(self, x: Hashable) ->int: returnhash(x)
classB:
deffoo(self, x: Sized) ->str: returnf"x has {len(x)} elements"classC(A, B):
@overloaddeffoo(self, x: Hashable) ->int: ...
@overloaddeffoo(self, x: Sized) ->str: ... deffoo(self, x): # type: ignore[no-untyped-def]ifisinstance(x, Hashable):
returnA.foo(self, x)
ifisinstance(x, Sized):
returnB.foo(self, x)
# mypy does not complain about LSPa_lsp: A=C()
b_lsp: B=C()
c: C=C()
# tuples are hashable and sized.x: tuple[int, int, int] = (1,2,3)
# but the return types are incompatible!reveal_type(a_lsp.foo(x)) # intreveal_type(b_lsp.foo(x)) # strreveal_type(c.foo(x)) # int, is not a subtype of str

This file parses even using --strict without raising any warnings/errors. (mypy-playground)
However, the inconsistency becomes obvious as c.foo(<tuple>) reveals as int, which is incompatible with b.foo(<tuple>).

Expected Behavior

@overloaddeffoo(self, x: Hashable) ->int: ...
@overloaddeffoo(self, x: Sized) ->str: ... 

Are not type-safe overloads to satisfy LSP for both superclasses. Mypy should notice this and issue a warning. Likely, to solve this issue in a satisfactory manner, intersection-types are needed (python/typing#213).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions