Skip to content

Commit d986d87

Browse files
committed
Fix incompatible overrides of overloaded methods in concrete subclasses
Fixes #14002
1 parent 428b172 commit d986d87

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

mypy/checker.py

+12
Original file line numberDiff line numberDiff line change
@@ -1868,6 +1868,18 @@ def check_method_override_for_base_with_name(
18681868
original_class_or_static = False # a variable can't be class or static
18691869

18701870
if isinstance(original_type, FunctionLike):
1871+
active_self_type = self.scope.active_self_type()
1872+
if isinstance(original_type, Overloaded) and active_self_type:
1873+
# If we have an overload, filter to overloads that match the self type.
1874+
# This avoids false positives for concrete subclasses of generic classes,
1875+
# see testSelfTypeOverrideCompatibility for an example.
1876+
# It's possible we might want to do this as part of bind_and_map_method
1877+
filtered_items = [
1878+
item for item in original_type.items
1879+
if not item.arg_types or is_subtype(active_self_type, item.arg_types[0])
1880+
]
1881+
if filtered_items:
1882+
original_type = Overloaded(filtered_items)
18711883
original_type = self.bind_and_map_method(base_attr, original_type, defn.info, base)
18721884
if original_node and is_property(original_node):
18731885
original_type = get_property_type(original_type)

test-data/unit/check-selftype.test

+51
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,57 @@ reveal_type(cast(A, C()).copy()) # N: Revealed type is "__main__.A"
128128

129129
[builtins fixtures/bool.pyi]
130130

131+
[case testSelfTypeOverrideCompatibility]
132+
from typing import overload, TypeVar, Generic
133+
134+
T = TypeVar("T", str, int)
135+
136+
class A(Generic[T]):
137+
@overload
138+
def f(self: A[int]) -> int: ...
139+
@overload
140+
def f(self: A[str]) -> str: ...
141+
def f(self): ...
142+
143+
class B(A[T]):
144+
@overload
145+
def f(self: A[int]) -> int: ...
146+
@overload
147+
def f(self: A[str]) -> str: ...
148+
def f(self): ...
149+
150+
class C(A[int]):
151+
def f(self) -> int: ...
152+
153+
class D(A[str]):
154+
def f(self) -> int: ... # E: Signature of "f" incompatible with supertype "A" \
155+
# N: Superclass: \
156+
# N: @overload \
157+
# N: def f(self) -> str \
158+
# N: Subclass: \
159+
# N: def f(self) -> int
160+
161+
class E(A[T]):
162+
def f(self) -> int: ... # E: Signature of "f" incompatible with supertype "A" \
163+
# N: Superclass: \
164+
# N: @overload \
165+
# N: def f(self) -> int \
166+
# N: @overload \
167+
# N: def f(self) -> str \
168+
# N: Subclass: \
169+
# N: def f(self) -> int
170+
171+
172+
class F(A[bytes]): # E: Value of type variable "T" of "A" cannot be "bytes"
173+
def f(self) -> bytes: ... # E: Signature of "f" incompatible with supertype "A" \
174+
# N: Superclass: \
175+
# N: @overload \
176+
# N: def f(self) -> int \
177+
# N: @overload \
178+
# N: def f(self) -> str \
179+
# N: Subclass: \
180+
# N: def f(self) -> bytes
181+
131182
[case testSelfTypeSuper]
132183
from typing import TypeVar, cast
133184

0 commit comments

Comments
 (0)