Skip to content

Commit

Permalink
Fix parent generics mapping when overriding generic attribute with pr…
Browse files Browse the repository at this point in the history
…operty (#18441)

Fixes #18189.

Following #18415, this fixes one more place where parent class generics
aren't mapped to attributes correctly.

---------

Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
  • Loading branch information
sterliakov and hauntsaninja authored Jan 11, 2025
1 parent 1affabe commit 9274a07
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
7 changes: 7 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2095,6 +2095,13 @@ def check_method_override_for_base_with_name(
if original_node and is_property(original_node):
original_type = get_property_type(original_type)

if isinstance(original_node, Var):
expanded_type = map_type_from_supertype(original_type, defn.info, base)
expanded_type = expand_self_type(
original_node, expanded_type, fill_typevars(defn.info)
)
original_type = get_proper_type(expanded_type)

if is_property(defn):
inner: FunctionLike | None
if isinstance(typ, FunctionLike):
Expand Down
120 changes: 120 additions & 0 deletions test-data/unit/check-generic-subtyping.test
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,126 @@ class F(E[T_co], Generic[T_co]): ... # E: Variance of TypeVar "T_co" incompatib
class G(Generic[T]): ...
class H(G[T_contra], Generic[T_contra]): ... # E: Variance of TypeVar "T_contra" incompatible with variance in parent type

[case testParameterizedGenericOverrideWithProperty]
from typing import TypeVar, Generic

T = TypeVar("T")

class A(Generic[T]):
def __init__(self, val: T):
self.member: T = val

class B(A[str]):
member: str

class GoodPropertyOverride(A[str]):
@property
def member(self) -> str: ...
@member.setter
def member(self, val: str): ...

class BadPropertyOverride(A[str]):
@property # E: Signature of "member" incompatible with supertype "A" \
# N: Superclass: \
# N: str \
# N: Subclass: \
# N: int
def member(self) -> int: ...
@member.setter
def member(self, val: int): ...

class BadGenericPropertyOverride(A[str], Generic[T]):
@property # E: Signature of "member" incompatible with supertype "A" \
# N: Superclass: \
# N: str \
# N: Subclass: \
# N: T
def member(self) -> T: ...
@member.setter
def member(self, val: T): ...
[builtins fixtures/property.pyi]

[case testParameterizedGenericPropertyOverrideWithProperty]
from typing import TypeVar, Generic

T = TypeVar("T")

class A(Generic[T]):
@property
def member(self) -> T: ...
@member.setter
def member(self, val: T): ...

class B(A[str]):
member: str

class GoodPropertyOverride(A[str]):
@property
def member(self) -> str: ...
@member.setter
def member(self, val: str): ...

class BadPropertyOverride(A[str]):
@property # E: Signature of "member" incompatible with supertype "A" \
# N: Superclass: \
# N: str \
# N: Subclass: \
# N: int
def member(self) -> int: ...
@member.setter
def member(self, val: int): ...

class BadGenericPropertyOverride(A[str], Generic[T]):
@property # E: Signature of "member" incompatible with supertype "A" \
# N: Superclass: \
# N: str \
# N: Subclass: \
# N: T
def member(self) -> T: ...
@member.setter
def member(self, val: T): ...
[builtins fixtures/property.pyi]

[case testParameterizedGenericOverrideSelfWithProperty]
from typing_extensions import Self

class A:
def __init__(self, val: Self):
self.member: Self = val

class GoodPropertyOverride(A):
@property
def member(self) -> "GoodPropertyOverride": ...
@member.setter
def member(self, val: "GoodPropertyOverride"): ...

class GoodPropertyOverrideSelf(A):
@property
def member(self) -> Self: ...
@member.setter
def member(self, val: Self): ...
[builtins fixtures/property.pyi]

[case testParameterizedGenericOverrideWithSelfProperty]
from typing import TypeVar, Generic
from typing_extensions import Self

T = TypeVar("T")

class A(Generic[T]):
def __init__(self, val: T):
self.member: T = val

class B(A["B"]):
member: Self

class GoodPropertyOverride(A["GoodPropertyOverride"]):
@property
def member(self) -> Self: ...
@member.setter
def member(self, val: Self): ...
[builtins fixtures/property.pyi]

[case testMultipleInheritanceCompatibleTypeVar]
from typing import Generic, TypeVar

Expand Down

0 comments on commit 9274a07

Please sign in to comment.