Skip to content

Commit 9274a07

Browse files
Fix parent generics mapping when overriding generic attribute with property (#18441)
Fixes #18189. Following #18415, this fixes one more place where parent class generics aren't mapped to attributes correctly. --------- Co-authored-by: Shantanu <[email protected]>
1 parent 1affabe commit 9274a07

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

mypy/checker.py

+7
Original file line numberDiff line numberDiff line change
@@ -2095,6 +2095,13 @@ def check_method_override_for_base_with_name(
20952095
if original_node and is_property(original_node):
20962096
original_type = get_property_type(original_type)
20972097

2098+
if isinstance(original_node, Var):
2099+
expanded_type = map_type_from_supertype(original_type, defn.info, base)
2100+
expanded_type = expand_self_type(
2101+
original_node, expanded_type, fill_typevars(defn.info)
2102+
)
2103+
original_type = get_proper_type(expanded_type)
2104+
20982105
if is_property(defn):
20992106
inner: FunctionLike | None
21002107
if isinstance(typ, FunctionLike):

test-data/unit/check-generic-subtyping.test

+120
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,126 @@ class F(E[T_co], Generic[T_co]): ... # E: Variance of TypeVar "T_co" incompatib
10661066
class G(Generic[T]): ...
10671067
class H(G[T_contra], Generic[T_contra]): ... # E: Variance of TypeVar "T_contra" incompatible with variance in parent type
10681068

1069+
[case testParameterizedGenericOverrideWithProperty]
1070+
from typing import TypeVar, Generic
1071+
1072+
T = TypeVar("T")
1073+
1074+
class A(Generic[T]):
1075+
def __init__(self, val: T):
1076+
self.member: T = val
1077+
1078+
class B(A[str]):
1079+
member: str
1080+
1081+
class GoodPropertyOverride(A[str]):
1082+
@property
1083+
def member(self) -> str: ...
1084+
@member.setter
1085+
def member(self, val: str): ...
1086+
1087+
class BadPropertyOverride(A[str]):
1088+
@property # E: Signature of "member" incompatible with supertype "A" \
1089+
# N: Superclass: \
1090+
# N: str \
1091+
# N: Subclass: \
1092+
# N: int
1093+
def member(self) -> int: ...
1094+
@member.setter
1095+
def member(self, val: int): ...
1096+
1097+
class BadGenericPropertyOverride(A[str], Generic[T]):
1098+
@property # E: Signature of "member" incompatible with supertype "A" \
1099+
# N: Superclass: \
1100+
# N: str \
1101+
# N: Subclass: \
1102+
# N: T
1103+
def member(self) -> T: ...
1104+
@member.setter
1105+
def member(self, val: T): ...
1106+
[builtins fixtures/property.pyi]
1107+
1108+
[case testParameterizedGenericPropertyOverrideWithProperty]
1109+
from typing import TypeVar, Generic
1110+
1111+
T = TypeVar("T")
1112+
1113+
class A(Generic[T]):
1114+
@property
1115+
def member(self) -> T: ...
1116+
@member.setter
1117+
def member(self, val: T): ...
1118+
1119+
class B(A[str]):
1120+
member: str
1121+
1122+
class GoodPropertyOverride(A[str]):
1123+
@property
1124+
def member(self) -> str: ...
1125+
@member.setter
1126+
def member(self, val: str): ...
1127+
1128+
class BadPropertyOverride(A[str]):
1129+
@property # E: Signature of "member" incompatible with supertype "A" \
1130+
# N: Superclass: \
1131+
# N: str \
1132+
# N: Subclass: \
1133+
# N: int
1134+
def member(self) -> int: ...
1135+
@member.setter
1136+
def member(self, val: int): ...
1137+
1138+
class BadGenericPropertyOverride(A[str], Generic[T]):
1139+
@property # E: Signature of "member" incompatible with supertype "A" \
1140+
# N: Superclass: \
1141+
# N: str \
1142+
# N: Subclass: \
1143+
# N: T
1144+
def member(self) -> T: ...
1145+
@member.setter
1146+
def member(self, val: T): ...
1147+
[builtins fixtures/property.pyi]
1148+
1149+
[case testParameterizedGenericOverrideSelfWithProperty]
1150+
from typing_extensions import Self
1151+
1152+
class A:
1153+
def __init__(self, val: Self):
1154+
self.member: Self = val
1155+
1156+
class GoodPropertyOverride(A):
1157+
@property
1158+
def member(self) -> "GoodPropertyOverride": ...
1159+
@member.setter
1160+
def member(self, val: "GoodPropertyOverride"): ...
1161+
1162+
class GoodPropertyOverrideSelf(A):
1163+
@property
1164+
def member(self) -> Self: ...
1165+
@member.setter
1166+
def member(self, val: Self): ...
1167+
[builtins fixtures/property.pyi]
1168+
1169+
[case testParameterizedGenericOverrideWithSelfProperty]
1170+
from typing import TypeVar, Generic
1171+
from typing_extensions import Self
1172+
1173+
T = TypeVar("T")
1174+
1175+
class A(Generic[T]):
1176+
def __init__(self, val: T):
1177+
self.member: T = val
1178+
1179+
class B(A["B"]):
1180+
member: Self
1181+
1182+
class GoodPropertyOverride(A["GoodPropertyOverride"]):
1183+
@property
1184+
def member(self) -> Self: ...
1185+
@member.setter
1186+
def member(self, val: Self): ...
1187+
[builtins fixtures/property.pyi]
1188+
10691189
[case testMultipleInheritanceCompatibleTypeVar]
10701190
from typing import Generic, TypeVar
10711191

0 commit comments

Comments
 (0)