Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Map TypeVar-valued attributes to the checked base
  • Loading branch information
sterliakov committed Jan 4, 2025
commit e8ccf89ec17a34cf04df26e520f23d0ec68a7d53
2 changes: 2 additions & 0 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2826,8 +2826,10 @@ class C(B, A[int]): ... # this is unsafe because...
ok = is_subtype(first_sig, second_sig, ignore_pos_arg_names=True)
elif first_type and second_type:
if isinstance(first.node, Var):
first_type = map_type_from_supertype(first_type, ctx, base1)
first_type = expand_self_type(first.node, first_type, fill_typevars(ctx))
if isinstance(second.node, Var):
second_type = map_type_from_supertype(second_type, ctx, base2)
second_type = expand_self_type(second.node, second_type, fill_typevars(ctx))
ok = is_equivalent(first_type, second_type)
if not ok:
Expand Down
36 changes: 36 additions & 0 deletions test-data/unit/check-generic-subtyping.test
Original file line number Diff line number Diff line change
Expand Up @@ -1065,3 +1065,39 @@ 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 testMultipleInheritanceCompatibleTypeVar]
from typing import Generic, TypeVar

T = TypeVar("T")
U = TypeVar("U")

class A(Generic[T]):
x: T
def fn(self, t: T) -> None: ...

class A2(A[T]):
y: str
z: str

class B(Generic[T]):
x: T
def fn(self, t: T) -> None: ...

class C1(A2[str], B[str]): pass
class C2(A2[str], B[int]): pass # E: Definition of "x" in base class "A" is incompatible with definition in base class "B" \
# E: Definition of "fn" in base class "A" is incompatible with definition in base class "B"
class C3(A2[T], B[T]): pass
class C4(A2[U], B[U]): pass
class C5(A2[U], B[T]): pass # E: Definition of "x" in base class "A" is incompatible with definition in base class "B" \
# E: Definition of "fn" in base class "A" is incompatible with definition in base class "B"

class D1(A[str], B[str]): pass
class D2(A[str], B[int]): pass # E: Definition of "x" in base class "A" is incompatible with definition in base class "B" \
# E: Definition of "fn" in base class "A" is incompatible with definition in base class "B"
class D3(A[T], B[T]): pass
class D4(A[U], B[U]): pass
class D5(A[U], B[T]): pass # E: Definition of "x" in base class "A" is incompatible with definition in base class "B" \
# E: Definition of "fn" in base class "A" is incompatible with definition in base class "B"

[builtins fixtures/tuple.pyi]