blob: 11c92d07021a269eca54d7cf2b5b7f866833dcdd [file] [log] [blame]
-- Test cases for the type checker related to subtyping and inheritance with
-- generics.
-- Subtyping + inheritance
-- -----------------------
[case testSubtypingAndInheritingNonGenericTypeFromGenericType]
from typing import TypeVar, Generic
T = TypeVar('T')
ac: A[C]
ad: A[D]
b: B
if int():
b = ad # E: Incompatible types in assignment (expression has type "A[D]", variable has type "B")
ad = b # E: Incompatible types in assignment (expression has type "B", variable has type "A[D]")
if int():
b = ac # E: Incompatible types in assignment (expression has type "A[C]", variable has type "B")
if int():
b = b
ac = b
class C: pass
class A(Generic[T]): pass
class B(A[C]): pass
class D: pass
[case testSubtypingAndInheritingGenericTypeFromNonGenericType]
from typing import TypeVar, Generic
T = TypeVar('T')
a: A
bc: B[C]
bd: B[D]
if int():
bc = bd # E: Incompatible types in assignment (expression has type "B[D]", variable has type "B[C]")
bd = bc # E: Incompatible types in assignment (expression has type "B[C]", variable has type "B[D]")
if int():
bc = a # E: Incompatible types in assignment (expression has type "A", variable has type "B[C]")
bd = a # E: Incompatible types in assignment (expression has type "A", variable has type "B[D]")
if int():
a = bc
if int():
a = bd
class A: pass
class B(A, Generic[T]): pass
class C: pass
class D: pass
[case testSubtypingAndInheritingGenericTypeFromGenericType]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
ac: A[C]
ad: A[D]
bcc: B[C, C]
bdc: B[D, C]
if int():
ad = bcc # E: Incompatible types in assignment (expression has type "B[C, C]", variable has type "A[D]")
if int():
ad = bdc # E: Incompatible types in assignment (expression has type "B[D, C]", variable has type "A[D]")
bcc = ac # E: Incompatible types in assignment (expression has type "A[C]", variable has type "B[C, C]")
bdc = ac # E: Incompatible types in assignment (expression has type "A[C]", variable has type "B[D, C]")
if int():
bcc = bcc
bdc = bdc
ac = bcc
if int():
ac = bdc
class A(Generic[T]): pass
class B(A[S], Generic[T, S]): pass
class C: pass
class D: pass
[case testSubtypingAndInheritingGenericTypeFromGenericTypeAcrossHierarchy]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
X = TypeVar('X')
Y = TypeVar('Y')
ae: A[A[E]]
af: A[A[F]]
cef: C[E, F]
cff: C[F, F]
cfe: C[F, E]
if int():
ae = cef # E: Incompatible types in assignment (expression has type "C[E, F]", variable has type "A[A[E]]")
af = cfe # E: Incompatible types in assignment (expression has type "C[F, E]", variable has type "A[A[F]]")
if int():
ae = cfe
af = cef
if int():
af = cff
class A(Generic[T]): pass
class B(A[S], Generic[T, S]): pass
class C(B[A[X], A[Y]], Generic[X, Y]): pass
class E: pass
class F: pass
[case testIncludingBaseClassTwice]
from typing import TypeVar, Generic
t = TypeVar('t')
class I(Generic[t]): pass
class A(I[C], I[object]): pass # E: Duplicate base class "I"
class C: pass
-- Accessing inherited generic members
-- -----------------------------------
[case testAccessingMethodInheritedFromGenericType]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
b: B[C, D]
c: C
d: D
b.f(c) # E: Argument 1 to "f" of "A" has incompatible type "C"; expected "D"
b.f(d)
class A(Generic[T]):
def f(self, a: T) -> None:
pass
class B(A[S], Generic[T, S]): pass
class C: pass
class D: pass
[builtins fixtures/tuple.pyi]
[case testAccessingMethodInheritedFromGenericTypeInNonGenericType]
from typing import TypeVar, Generic
T = TypeVar('T')
b: B
c: C
d: D
b.f(c) # E: Argument 1 to "f" of "A" has incompatible type "C"; expected "D"
b.f(d)
class C: pass
class D: pass
class A(Generic[T]):
def f(self, a: T) -> None:
pass
class B(A[D]): pass
[builtins fixtures/tuple.pyi]
[case testAccessingMemberVarInheritedFromGenericType]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
class A(Generic[T]):
def __init__(self, a: T) -> None:
self.a = a
b: B[C, D]
c: C
d: D
b.a = c # E: Incompatible types in assignment (expression has type "C", variable has type "D")
b.a = d
class B(A[S], Generic[T, S]): pass
class C: pass
class D: pass
[builtins fixtures/tuple.pyi]
-- Overriding with generic types
-- -----------------------------
[case testOverridingMethodInSimpleTypeInheritingGenericType]
from typing import TypeVar, Generic
T = TypeVar('T')
class B(Generic[T]):
def f(self, a: T) -> None: pass
def g(self, a: T) -> None: pass
class C: pass
class D: pass
class A(B[C]):
def f(self, a: D) -> None: pass \
# E: Argument 1 of "f" is incompatible with supertype "B"; supertype defines the argument type as "C" \
# N: This violates the Liskov substitution principle \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
def g(self, a: C) -> None: pass
[out]
[case testOverridingMethodInGenericTypeInheritingSimpleType]
from typing import TypeVar, Generic
T = TypeVar('T')
class C: pass
class B:
def f(self, a: C) -> None: pass
def g(self, a: C) -> None: pass
class A(B, Generic[T]):
def f(self, a: T) -> None: pass \
# E: Argument 1 of "f" is incompatible with supertype "B"; supertype defines the argument type as "C" \
# N: This violates the Liskov substitution principle \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
def g(self, a: 'C') -> None: pass
[out]
[case testOverridingMethodInGenericTypeInheritingGenericType]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
class B(Generic[T]):
def f(self, a: T) -> None: pass
def g(self, a: T) -> None: pass
class A(B[S], Generic[T, S]):
def f(self, a: T) -> None: pass \
# E: Argument 1 of "f" is incompatible with supertype "B"; supertype defines the argument type as "S" \
# N: This violates the Liskov substitution principle \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
def g(self, a: S) -> None: pass
[out]
[case testOverridingMethodInMultilevelHierarchyOfGenericTypes]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
U = TypeVar('U')
V = TypeVar('V')
class D: pass
class C(Generic[T, U, V]):
def f(self, a: V) -> None: pass
def g(self, a: V) -> None: pass
class B(C[D, D, T], Generic[T]): pass
class A(B[S], Generic[T, S]):
def f(self, a: T) -> None: pass \
# E: Argument 1 of "f" is incompatible with supertype "C"; supertype defines the argument type as "S" \
# N: This violates the Liskov substitution principle \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
def g(self, a: S) -> None: pass
[out]
[case testOverrideGenericMethodInNonGenericClass]
from typing import TypeVar
T = TypeVar('T')
S = TypeVar('S')
class A:
def f(self, x: T, y: S) -> None: pass
class B(A):
def f(self, x: S, y: T) -> None: pass
class C(A):
# Okay, because T = object allows any type for the arguments.
def f(self, x: T, y: T) -> None: pass
[case testOverrideGenericMethodInNonGenericClassLists]
from typing import TypeVar, List
T = TypeVar('T')
S = TypeVar('S')
class A:
def f(self, x: List[T], y: List[S]) -> None: pass
class B(A):
def f(self, x: List[S], y: List[T]) -> None: pass
class C(A):
def f(self, x: List[T], y: List[T]) -> None: pass # Fail
[builtins fixtures/list.pyi]
[out]
main:11: error: Signature of "f" incompatible with supertype "A"
main:11: note: Superclass:
main:11: note: def [T, S] f(self, x: List[T], y: List[S]) -> None
main:11: note: Subclass:
main:11: note: def [T] f(self, x: List[T], y: List[T]) -> None
[case testOverrideGenericMethodInNonGenericClassGeneralize]
from typing import TypeVar
T = TypeVar('T')
T1 = TypeVar('T1', bound=str)
S = TypeVar('S')
class A:
def f(self, x: int, y: S) -> None: pass
class B(A):
def f(self, x: T, y: S) -> None: pass
class C(A):
def f(self, x: T, y: str) -> None: pass
class D(A):
def f(self, x: T1, y: S) -> None: pass # TODO: This error could be more specific.
[out]
main:12: error: Argument 2 of "f" is incompatible with supertype "A"; supertype defines the argument type as "S"
main:12: note: This violates the Liskov substitution principle
main:12: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
main:14: error: Signature of "f" incompatible with supertype "A"
main:14: note: Superclass:
main:14: note: def [S] f(self, x: int, y: S) -> None
main:14: note: Subclass:
main:14: note: def [T1 <: str, S] f(self, x: T1, y: S) -> None
-- Inheritance from generic types with implicit dynamic supertype
-- --------------------------------------------------------------
[case testInheritanceFromGenericWithImplicitDynamicAndSubtyping]
from typing import TypeVar, Generic
T = TypeVar('T')
a: A
bc: B[C]
bd: B[D]
if int():
a = bc # E: Incompatible types in assignment (expression has type "B[C]", variable has type "A")
bc = a
bd = a
class B(Generic[T]): pass
class A(B): pass
class C: pass
class D: pass
[out]
[case testInheritanceFromGenericWithImplicitDynamicAndExternalAccess]
from typing import TypeVar, Generic
T = TypeVar('T')
class B(Generic[T]):
def f(self, a: 'B[T]') -> None: pass
def __init__(self, x: 'B[T]') -> None:
self.x = x
class A(B): pass
class C: pass
a: A
c: C
bc: B[C]
a.x = c # E: Incompatible types in assignment (expression has type "C", variable has type "B[Any]")
a.f(c) # E: Argument 1 to "f" of "B" has incompatible type "C"; expected "B[Any]"
a.x = bc
a.f(bc)
[out]
[case testInheritanceFromGenericWithImplicitDynamic]
from typing import TypeVar, Generic
T = TypeVar('T')
a: A
c: C
bc: B[C]
class B(Generic[T]):
def f(self, a: 'B[T]') -> None: pass
def __init__(self, x: 'B[T]') -> None:
self.x = x
class A(B):
def g(self) -> None:
self.x = c # E: Incompatible types in assignment (expression has type "C", variable has type "B[Any]")
self.f(c) # E: Argument 1 to "f" of "B" has incompatible type "C"; expected "B[Any]"
self.x = bc
self.f(bc)
class C: pass
[out]
[case testInheritanceFromGenericWithImplicitDynamicAndOverriding]
from typing import TypeVar, Generic, Tuple
T = TypeVar('T')
class B(Generic[T]):
def f(self, a: T, b: 'Tuple[T, B[T]]') -> None:
pass
class A(B):
def f(self, a, b): pass
[builtins fixtures/tuple.pyi]
[out]
-- Inheritance from generic types and super expressions
-- ----------------------------------------------------
[case testSuperExpressionsWhenInheritingFromGenericType]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
class B(Generic[T]):
def f(self, a: T) -> None: pass
class A(B[S], Generic[T, S]):
def g(self, t: T, s: S) -> None:
super().f(t) # E: Argument 1 to "f" of "B" has incompatible type "T"; expected "S"
super().f(s)
[out]
[case testSuperExpressionsWhenInheritingFromGenericTypeAndDeepHierarchy]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
U = TypeVar('U')
V = TypeVar('V')
class C(Generic[T, U, V]):
def f(self, a: V) -> None: pass
class D: pass
class B(C[D, D, T], Generic[T]): pass
class A(B[S], Generic[T, S]):
def g(self, t: T, s: S) -> None:
super().f(t) # E: Argument 1 to "f" of "C" has incompatible type "T"; expected "S"
super().f(s)
[out]
-- Type of inherited constructor
-- -----------------------------
[case testInheritedConstructor]
from typing import TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
def __init__(self, x: T) -> None: pass
class B(A[T], Generic[T]): pass
class C(A[int]): pass
class D(A[A[T]], Generic[T]): pass
B(1)
C(1)
C('a') # E: Argument 1 to "C" has incompatible type "str"; expected "int"
D(A(1))
D(1) # E: Argument 1 to "D" has incompatible type "int"; expected "A[<nothing>]"
[case testInheritedConstructor2]
from typing import TypeVar, Generic
T = TypeVar('T')
U = TypeVar('U')
Z = TypeVar('Z')
class A(Generic[T, U]):
def __init__(self, x: T, y: U, z: Z) -> None: pass
class B(A[int, T], Generic[T]): pass
class C(B[A[T, str]], Generic[T, U]): pass
# C[T, U] <: B[A[T, str]] <: A[int, A[T, str]]
C(1, A(1, 'a', 0), 'z')
C(1, A('1', 'a', 0), 'z')
C('1', A(1, 'a', 0), 'z') # E: Argument 1 to "C" has incompatible type "str"; expected "int"
C(1, A(1, 1, 0), 'z') # E: Argument 2 to "A" has incompatible type "int"; expected "str"
-- Subtyping with a generic abstract base class
-- --------------------------------------------
[case testSubtypingWithGenericTypeSubclassingGenericAbstractClass]
from typing import TypeVar, Generic
from abc import abstractmethod
T = TypeVar('T')
S = TypeVar('S')
acd: A[C, D]
adc: A[D, C]
ic: I[C]
id: I[D]
if int():
ic = acd # E: Incompatible types in assignment (expression has type "A[C, D]", variable has type "I[C]")
id = adc # E: Incompatible types in assignment (expression has type "A[D, C]", variable has type "I[D]")
adc = ic # E: Incompatible types in assignment (expression has type "I[C]", variable has type "A[D, C]")
if int():
ic = adc
id = acd
class I(Generic[T]):
@abstractmethod
def f(self): pass
class A(I[S], Generic[T, S]): pass
class C: pass
class D: pass
[case testSubtypingWithTypeImplementingGenericABCViaInheritance]
from typing import TypeVar, Generic
S = TypeVar('S')
a: A
b: B
ic: I[C]
id: I[D]
ie: I[E]
class I(Generic[S]): pass
class B(I[C]): pass
class A(B): pass
if int():
ie = a # E: Incompatible types in assignment (expression has type "A", variable has type "I[E]")
a = ic # E: Incompatible types in assignment (expression has type "I[C]", variable has type "A")
if int():
a = id # E: Incompatible types in assignment (expression has type "I[D]", variable has type "A")
if int():
a = b # E: Incompatible types in assignment (expression has type "B", variable has type "A")
id = a # E: Incompatible types in assignment (expression has type "A", variable has type "I[D]")
ic = a
b = a
class C: pass
class D: pass
class E: pass
[builtins fixtures/tuple.pyi]
[out]
[case testSubtypingWithTypeImplementingGenericABCViaInheritance2-skip]
from typing import TypeVar, Generic
T = TypeVar('T')
class I(Generic[T]): pass
class A(I[C]): pass
class B(A, I[D]): pass # Fail
class C: pass
class D: pass
[out]
main:5: error: Class "B" has base "I" duplicated inconsistently
[case testSubtypingAndABCExtension]
from typing import TypeVar, Generic
from abc import abstractmethod, ABCMeta
t = TypeVar('t')
a: A[object]
i: I[object]
j: J[object]
(ii, jj) = (i, j)
if int():
ii = a
jj = a
if int():
jj = i
a = i # E: Incompatible types in assignment (expression has type "I[object]", variable has type "A[object]")
if int():
a = j # E: Incompatible types in assignment (expression has type "J[object]", variable has type "A[object]")
class J(Generic[t]): pass
class X(metaclass=ABCMeta): pass
class I(X, J[t], Generic[t]): pass
class A(I[t], Generic[t]): pass
[builtins fixtures/tuple.pyi]
-- Subclassing a generic ABC
-- -------------------------
[case testSubclassingGenericABC1]
from typing import TypeVar, Generic
from abc import abstractmethod
T = TypeVar('T')
class I(Generic[T]):
@abstractmethod
def f(self, a: T) -> None: pass
@abstractmethod
def g(self, a: T) -> None: pass
class A(I[C]):
def f(self, a: 'D') -> None: pass \
# E: Argument 1 of "f" is incompatible with supertype "I"; supertype defines the argument type as "C" \
# N: This violates the Liskov substitution principle \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
def g(self, a: 'C') -> None: pass
class C: pass
class D: pass
[out]
-- Extending a generic ABC with deep type hierarchy
-- ------------------------------------------------
[case testSubclassingGenericABCWithDeepHierarchy]
from typing import Any, TypeVar, Generic
from abc import abstractmethod
T = TypeVar('T')
a: A
ic: I[C]
id: I[D]
if int():
id = a # E: Incompatible types in assignment (expression has type "A", variable has type "I[D]")
ic = a
class I(Generic[T]):
@abstractmethod
def f(self, a: T, b: T) -> None: pass
@abstractmethod
def g(self, a: T, b: 'D') -> None: pass
class B(I[C]):
def f(self, a: 'C', b: 'C') -> None: pass
def g(self, a: 'C', b: Any) -> None: pass
class A(B):
def g(self, a: 'C', b: 'C') -> None: pass \
# E: Argument 2 of "g" is incompatible with supertype "I"; supertype defines the argument type as "D" \
# N: This violates the Liskov substitution principle \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
def f(self, a: 'C', b: 'C') -> None: pass
class C: pass
class D: pass
[builtins fixtures/tuple.pyi]
[case testSubclassingGenericABCWithDeepHierarchy2]
from typing import Any, TypeVar, Generic
from abc import abstractmethod
T = TypeVar('T')
class I(Generic[T]):
@abstractmethod
def f(self, a: T, b: T) -> None: pass
class B(I[C]):
def f(self, a: 'C', b: Any) -> None: pass
class A(B):
def f(self, a: 'C', b: 'D') -> None: pass \
# E: Argument 2 of "f" is incompatible with supertype "I"; supertype defines the argument type as "C" \
# N: This violates the Liskov substitution principle \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
class C: pass
class D: pass
[out]
-- Implicit Any types and subclassing generic ABC
-- ----------------------------------------------
[case testSubclassingGenericABCWithImplicitAny]
from typing import Any, TypeVar, Generic
from abc import abstractmethod
T = TypeVar('T')
a: Any
ic: I[C]
id: I[D]
ic = a
id = a
class I(Generic[T]):
@abstractmethod
def f(self, a: T) -> None: pass
class A(I):
def f(self, a): pass
class C: pass
class D: pass
[case testSubclassingGenericABCWithImplicitAnyAndDeepHierarchy]
from typing import Any, TypeVar, Generic
from abc import abstractmethod
T = TypeVar('T')
a: Any
ic: I[C]
id: I[D]
ic = a
id = a
class I(Generic[T]):
@abstractmethod
def f(self, a: T, b: T) -> None: pass
class B(I):
def f(self, a, b): pass
class A(B):
def f(self, a: 'C', b: 'D') -> None: pass
class C: pass
class D: pass
[case testImplementingGenericABCWithImplicitAnyAndDeepHierarchy2]
from typing import Any, TypeVar, Generic
from abc import abstractmethod
T = TypeVar('T')
a: Any
jc: J[C]
jd: J[D]
jc = a
jd = a
class J(Generic[T]):
@abstractmethod
def f(self, a: T, b: T) -> None: pass
class I(J):
@abstractmethod
def f(self, a, b): pass
class A(I):
def f(self, a: 'C', b: 'D') -> None: pass
class C: pass
class D: pass
-- Accessing generic ABC members
-- -----------------------------
[case testAccessingGenericABCMembers]
from typing import TypeVar, Generic
from abc import abstractmethod
T = TypeVar('T')
class I(Generic[T]):
@abstractmethod
def f(self, a: T) -> None: pass
class A: pass
class B: pass
a: A
b: B
ia: I[A]
ia.f(b) # E: Argument 1 to "f" of "I" has incompatible type "B"; expected "A"
ia.f(a)
[builtins fixtures/tuple.pyi]
[case testAccessingInheritedGenericABCMembers]
from typing import TypeVar, Generic
from abc import abstractmethod
T = TypeVar('T')
class J(Generic[T]):
@abstractmethod
def f(self, a: T) -> None: pass
class I(J[T], Generic[T]): pass
class A: pass
class B: pass
a: A
b: B
ia: I[A]
ia.f(b) # E: Argument 1 to "f" of "J" has incompatible type "B"; expected "A"
ia.f(a)
[builtins fixtures/tuple.pyi]
-- Misc
-- ----
[case testMultipleAssignmentAndGenericSubtyping]
from typing import Iterable
n: int
s: str
class Nums(Iterable[int]):
def __iter__(self): pass
def __next__(self): pass
n, n = Nums()
s, s = Nums() # E: Incompatible types in assignment (expression has type "int", variable has type "str")
[builtins fixtures/for.pyi]
[out]
-- Variance
-- --------
[case testCovariant]
from typing import TypeVar, Generic
T = TypeVar('T', covariant=True)
class G(Generic[T]): pass
class A: pass
class B(A): pass
class C(B): pass
a: G[A]
b: G[B]
c: G[C]
if int():
b = a # E: Incompatible types in assignment (expression has type "G[A]", variable has type "G[B]")
b = c
[builtins fixtures/bool.pyi]
[out]
[case testContravariant]
from typing import TypeVar, Generic
T = TypeVar('T', contravariant=True)
class G(Generic[T]): pass
class A: pass
class B(A): pass
class C(B): pass
a: G[A]
b: G[B]
c: G[C]
if int():
b = a
b = c # E: Incompatible types in assignment (expression has type "G[C]", variable has type "G[B]")
[builtins fixtures/bool.pyi]
[out]
[case testInvariant]
from typing import TypeVar, Generic
T = TypeVar('T') # invariant (default)
class G(Generic[T]): pass
class A: pass
class B(A): pass
class C(B): pass
a: G[A]
b: G[B]
c: G[C]
if int():
b = a # E: Incompatible types in assignment (expression has type "G[A]", variable has type "G[B]")
b = c # E: Incompatible types in assignment (expression has type "G[C]", variable has type "G[B]")
[builtins fixtures/bool.pyi]
[out]
[case testTypeVarSubtypeUnion]
from typing import Union, TypeVar, Generic
class U: pass
class W: pass
T = TypeVar('T', bound=Union[U, W])
class Y(Generic[T]):
def __init__(self) -> None:
pass
def f(self) -> T:
return U() # E: Incompatible return value type (got "U", expected "T")
[case testTypeVarBoundToOldUnionAttributeAccess]
from typing import Union, TypeVar
class U:
a: float
class V:
b: float
class W:
c: float
T = TypeVar("T", bound=Union[U, V, W])
def f(x: T) -> None:
x.a # E
x.b = 1.0 # E
del x.c # E
[out]
main:13: error: Item "V" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "a"
main:13: error: Item "W" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "a"
main:14: error: Item "U" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "b"
main:14: error: Item "W" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "b"
main:15: error: Item "U" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "c"
main:15: error: Item "V" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "c"
[case testTypeVarBoundToNewUnionAttributeAccess]
# flags: --python-version 3.10
from typing import TypeVar
class U:
a: int
class V:
b: int
class W:
c: int
T = TypeVar("T", bound=U | V | W)
def f(x: T) -> None:
x.a # E
x.b = 1 # E
del x.c # E
[builtins fixtures/tuple.pyi]
[out]
main:14: error: Item "V" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "a"
main:14: error: Item "W" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "a"
main:15: error: Item "U" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "b"
main:15: error: Item "W" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "b"
main:16: error: Item "U" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "c"
main:16: error: Item "V" of the upper bound "Union[U, V, W]" of type variable "T" has no attribute "c"
[case testSubtypingIterableUnpacking1]
# https://github.com/python/mypy/issues/11138
from typing import Generic, Iterator, TypeVar
T = TypeVar("T")
U = TypeVar("U")
class X1(Iterator[U], Generic[T, U]):
pass
x1: X1[str, int]
reveal_type(list(x1)) # N: Revealed type is "builtins.list[builtins.int]"
reveal_type([*x1]) # N: Revealed type is "builtins.list[builtins.int]"
class X2(Iterator[T], Generic[T, U]):
pass
x2: X2[str, int]
reveal_type(list(x2)) # N: Revealed type is "builtins.list[builtins.str]"
reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.str]"
class X3(Generic[T, U], Iterator[U]):
pass
x3: X3[str, int]
reveal_type(list(x3)) # N: Revealed type is "builtins.list[builtins.int]"
reveal_type([*x3]) # N: Revealed type is "builtins.list[builtins.int]"
class X4(Generic[T, U], Iterator[T]):
pass
x4: X4[str, int]
reveal_type(list(x4)) # N: Revealed type is "builtins.list[builtins.str]"
reveal_type([*x4]) # N: Revealed type is "builtins.list[builtins.str]"
class X5(Iterator[T]):
pass
x5: X5[str]
reveal_type(list(x5)) # N: Revealed type is "builtins.list[builtins.str]"
reveal_type([*x5]) # N: Revealed type is "builtins.list[builtins.str]"
class X6(Generic[T, U], Iterator[bool]):
pass
x6: X6[str, int]
reveal_type(list(x6)) # N: Revealed type is "builtins.list[builtins.bool]"
reveal_type([*x6]) # N: Revealed type is "builtins.list[builtins.bool]"
[builtins fixtures/list.pyi]
[case testSubtypingIterableUnpacking2]
from typing import Generic, Iterator, TypeVar, Mapping
T = TypeVar("T")
U = TypeVar("U")
class X1(Generic[T, U], Iterator[U], Mapping[U, T]):
pass
x1: X1[str, int]
reveal_type(list(x1)) # N: Revealed type is "builtins.list[builtins.int]"
reveal_type([*x1]) # N: Revealed type is "builtins.list[builtins.int]"
class X2(Generic[T, U], Iterator[U], Mapping[T, U]):
pass
x2: X2[str, int]
reveal_type(list(x2)) # N: Revealed type is "builtins.list[builtins.int]"
reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.int]"
[builtins fixtures/list.pyi]
[case testSubtypingMappingUnpacking1]
# https://github.com/python/mypy/issues/11138
from typing import Generic, TypeVar, Mapping
T = TypeVar("T")
U = TypeVar("U")
class X1(Generic[T, U], Mapping[U, T]):
pass
x1: X1[str, int]
reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int]"
reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int, builtins.str]"
class X2(Generic[T, U], Mapping[T, U]):
pass
x2: X2[str, int]
reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.str]"
reveal_type({**x2}) # N: Revealed type is "builtins.dict[builtins.str, builtins.int]"
class X3(Generic[T, U], Mapping[bool, float]):
pass
x3: X3[str, int]
reveal_type(iter(x3)) # N: Revealed type is "typing.Iterator[builtins.bool]"
reveal_type({**x3}) # N: Revealed type is "builtins.dict[builtins.bool, builtins.float]"
[builtins fixtures/dict.pyi]
[case testSubtypingMappingUnpacking2]
from typing import Generic, TypeVar, Mapping
T = TypeVar("T")
U = TypeVar("U")
class X1(Generic[T, U], Mapping[U, T]):
pass
def func_with_kwargs(**kwargs: int):
pass
x1: X1[str, int]
reveal_type(iter(x1))
reveal_type({**x1})
func_with_kwargs(**x1)
[out]
main:12: note: Revealed type is "typing.Iterator[builtins.int]"
main:13: note: Revealed type is "builtins.dict[builtins.int, builtins.str]"
main:14: error: Keywords must be strings
main:14: error: Argument 1 to "func_with_kwargs" has incompatible type "**X1[str, int]"; expected "int"
[builtins fixtures/dict.pyi]
[typing fixtures/typing-medium.pyi]
[case testSubtypingMappingUnpacking3]
from typing import Generic, TypeVar, Mapping, Iterable
T = TypeVar("T")
U = TypeVar("U")
class X1(Generic[T, U], Mapping[U, T], Iterable[U]):
pass
x1: X1[str, int]
reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int]"
reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int, builtins.str]"
# Some people would expect this to raise an error, but this currently does not:
# `Mapping` has `Iterable[U]` base class, `X2` has direct `Iterable[T]` base class.
# It would be impossible to define correct `__iter__` method for incompatible `T` and `U`.
class X2(Generic[T, U], Mapping[U, T], Iterable[T]):
pass
x2: X2[str, int]
reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.int]"
reveal_type({**x2}) # N: Revealed type is "builtins.dict[builtins.int, builtins.str]"
[builtins fixtures/dict.pyi]
[case testNotDirectIterableAndMappingSubtyping]
from typing import Generic, TypeVar, Dict, Iterable, Iterator, List
T = TypeVar("T")
U = TypeVar("U")
class X1(Generic[T, U], Dict[U, T], Iterable[U]):
def __iter__(self) -> Iterator[U]: pass
x1: X1[str, int]
reveal_type(iter(x1)) # N: Revealed type is "typing.Iterator[builtins.int]"
reveal_type({**x1}) # N: Revealed type is "builtins.dict[builtins.int, builtins.str]"
class X2(Generic[T, U], List[U]):
def __iter__(self) -> Iterator[U]: pass
x2: X2[str, int]
reveal_type(iter(x2)) # N: Revealed type is "typing.Iterator[builtins.int]"
reveal_type([*x2]) # N: Revealed type is "builtins.list[builtins.int]"
[builtins fixtures/dict.pyi]
[case testIncompatibleVariance]
from typing import TypeVar, Generic
T = TypeVar('T')
T_co = TypeVar('T_co', covariant=True)
T_contra = TypeVar('T_contra', contravariant=True)
class A(Generic[T_co]): ...
class B(A[T_contra], Generic[T_contra]): ... # E: Variance of TypeVar "T_contra" incompatible with variance in parent type
class C(Generic[T_contra]): ...
class D(C[T_co], Generic[T_co]): ... # E: Variance of TypeVar "T_co" incompatible with variance in parent type
class E(Generic[T]): ...
class F(E[T_co], Generic[T_co]): ... # E: Variance of TypeVar "T_co" incompatible with variance in parent type
class G(Generic[T]): ...
class H(G[T_contra], Generic[T_contra]): ... # E: Variance of TypeVar "T_contra" incompatible with variance in parent type