| -- 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 |