| -- Test cases for type variables with values restriction. |
| |
| |
| [case testCallGenericFunctionWithTypeVarValueRestriction] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| def f(x: T) -> None: pass |
| f(1) |
| f('x') |
| f(object()) # E: Value of type variable "T" of "f" cannot be "object" |
| |
| [case testCallGenericFunctionWithTypeVarValueRestrictionUsingContext] |
| from typing import TypeVar, List |
| T = TypeVar('T', int, str) |
| def f(x: T) -> List[T]: pass |
| i = [1] |
| s = ['x'] |
| o = [object()] |
| if int(): |
| i = f(1) |
| s = f('') |
| o = f(1) \ |
| # E: Incompatible types in assignment (expression has type "List[int]", variable has type "List[object]") \ |
| # N: "List" is invariant -- see http://mypy.readthedocs.io/en/latest/common_issues.html#variance \ |
| # N: Consider using "Sequence" instead, which is covariant |
| [builtins fixtures/list.pyi] |
| |
| [case testCallGenericFunctionWithTypeVarValueRestrictionAndAnyArgs] |
| from typing import TypeVar, Any, cast |
| T = TypeVar('T', int, str) |
| def f(x: T) -> None: pass |
| f(cast(Any, object())) |
| [out] |
| |
| [case testCallGenericFunctionWithTypeVarValueRestrictionInDynamicFunc] |
| from typing import TypeVar, Any |
| T = TypeVar('T', int, str) |
| def f(x: T) -> None: pass |
| def g(): |
| f(object()) |
| [out] |
| |
| [case testCallGenericFunctionWithTypeVarValueRestrictionUsingSubtype] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| def f(x: T) -> None: pass |
| class S(str): pass |
| f(S()) |
| [out] |
| |
| [case testCheckGenericFunctionBodyWithTypeVarValues] |
| from typing import TypeVar |
| class A: |
| def f(self, x: int) -> A: return self |
| class B: |
| def f(self, x: int) -> B: return self |
| AB = TypeVar('AB', A, B) |
| def f(x: AB) -> AB: |
| x = x.f(1) |
| return x.f(1) |
| |
| [case testCheckGenericFunctionBodyWithTypeVarValues2] |
| from typing import TypeVar |
| class A: |
| def f(self) -> A: return A() |
| def g(self) -> B: return B() |
| class B: |
| def f(self) -> A: return A() |
| def g(self) -> B: return B() |
| AB = TypeVar('AB', A, B) |
| def f(x: AB) -> AB: |
| return x.f() # Error |
| def g(x: AB) -> AB: |
| return x.g() # Error |
| [out] |
| main:10: error: Incompatible return value type (got "A", expected "B") |
| main:12: error: Incompatible return value type (got "B", expected "A") |
| |
| [case testTypeInferenceAndTypeVarValues] |
| from typing import TypeVar |
| class A: |
| def f(self) -> A: return self |
| def g(self) -> B: return B() |
| class B: |
| def f(self) -> B: return self |
| def g(self) -> B: return B() |
| AB = TypeVar('AB', A, B) |
| def f(x: AB) -> AB: |
| y = x |
| if y: |
| return y.f() |
| else: |
| return y.g() # E: Incompatible return value type (got "B", expected "A") |
| [out] |
| |
| [case testTypeDeclaredBasedOnTypeVarWithValues] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| def f(x: T) -> T: |
| a = None # type: T |
| b = None # type: T |
| if 1: |
| a = x |
| b = x |
| a = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| b = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str") |
| return x |
| [out] |
| |
| [case testIsinstanceAndTypeVarValues] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| def f(x: T) -> T: |
| if isinstance(x, int): |
| return 2 |
| return x |
| def g(x: T) -> T: |
| if isinstance(x, str): |
| return '' |
| return x |
| def h(x: T) -> T: |
| if isinstance(x, int): |
| return '' # E: Incompatible return value type (got "str", expected "int") |
| return x |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testIsinstanceAndTypeVarValues2] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| def f(x: T) -> T: |
| if isinstance(x, int): |
| return 2 |
| else: |
| return '' |
| def g(x: T) -> T: |
| if isinstance(x, int): |
| return '' # E: Incompatible return value type (got "str", expected "int") |
| else: |
| return 2 # E: Incompatible return value type (got "int", expected "str") |
| return x |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testIsinstanceAndTypeVarValues3] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| def f(x: T) -> T: |
| if isinstance(x, int): |
| y = 1 |
| else: |
| y = '' |
| return y |
| [builtins fixtures/isinstance.pyi] |
| |
| [case testIsinstanceAndTypeVarValues4] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| def f(x: T) -> T: |
| if isinstance(x, int): |
| y = 1 |
| else: |
| y = object() |
| return y # E: Incompatible return value type (got "object", expected "str") |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testIsinstanceAndTypeVarValues5] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| def f(x: T) -> T: |
| if isinstance(x, int): |
| y = object() |
| else: |
| y = '' |
| return y # E: Incompatible return value type (got "object", expected "int") |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testIsinstanceWithUserDefinedTypeAndTypeVarValues] |
| from typing import TypeVar |
| class A: pass |
| class B: pass |
| T = TypeVar('T', A, B) |
| def f(x: T) -> None: |
| y = x |
| if isinstance(x, A): |
| # This is only checked when x is A, since A and B are not considered overlapping. |
| x = y |
| x = A() |
| else: |
| x = B() |
| x = y |
| x.foo() # E: "B" has no attribute "foo" |
| S = TypeVar('S', int, str) |
| def g(x: S) -> None: |
| y = x |
| if isinstance(x, int): |
| x = y |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testIsinstanceWithUserDefinedTypeAndTypeVarValues2] |
| from typing import TypeVar |
| class S(str): pass |
| T = TypeVar('T', S, int) |
| def f(x: T) -> None: |
| y = x |
| if isinstance(x, S): |
| # This is checked only when type of x is str. |
| x = y |
| x = S() |
| x = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "S") |
| else: |
| x = y |
| x = 1 |
| x = S() # E: Incompatible types in assignment (expression has type "S", variable has type "int") |
| [builtins fixtures/isinstance.pyi] |
| [out] |
| |
| [case testTypeVarValuesAndNestedCalls] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| def f(m: T) -> int: pass |
| def h(x: int) -> int: pass |
| def g(a: T) -> None: |
| h(f(a)) |
| [out] |
| |
| [case testGenericTypeWithTypevarValues] |
| from typing import TypeVar, Generic, Any |
| X = TypeVar('X', int, str) |
| class A(Generic[X]): pass |
| a = None # type: A[int] |
| b = None # type: A[str] |
| d = None # type: A[object] # E: Value of type variable "X" of "A" cannot be "object" |
| c = None # type: A[Any] |
| |
| [case testConstructGenericTypeWithTypevarValuesAndTypeInference] |
| from typing import TypeVar, Generic, Any, cast |
| X = TypeVar('X', int, str) |
| class A(Generic[X]): |
| def __init__(self, x: X) -> None: pass |
| A(1) |
| A('x') |
| A(cast(Any, object())) |
| A(object()) # E: Value of type variable "X" of "A" cannot be "object" |
| |
| [case testGenericTypeWithTypevarValuesAndTypevarArgument] |
| from typing import TypeVar, Generic |
| class C: pass |
| X = TypeVar('X', int, str) |
| Y = TypeVar('Y', int, C) |
| Z = TypeVar('Z') |
| class D(Generic[X]): |
| def __init__(self, x: X) -> None: pass |
| def f(x: X) -> None: |
| a = None # type: D[X] |
| def g(x: Y) -> None: |
| a = None # type: D[Y] |
| def h(x: Z) -> None: |
| a = None # type: D[Z] |
| [out] |
| main:11: error: Invalid type argument value for "D" |
| main:13: error: Type variable "Z" not valid as type argument value for "D" |
| |
| [case testGenericTypeWithTypevarValuesAndSubtypePromotion] |
| from typing import TypeVar, Generic |
| X = TypeVar('X', int, str) |
| class S(str): pass |
| class C(Generic[X]): |
| def __init__(self, x: X) -> None: pass |
| x = None # type: C[str] |
| y = C(S()) |
| if int(): |
| x = y |
| y = x |
| c_int = C(1) # type: C[int] |
| if int(): |
| y = c_int # E: Incompatible types in assignment (expression has type "C[int]", variable has type "C[str]") |
| |
| [case testGenericTypeBodyWithTypevarValues] |
| from typing import TypeVar, Generic |
| class A: |
| def f(self, x: int) -> None: pass |
| def g(self, x: int) -> None: pass |
| def h(self, x: str) -> None: pass |
| class B: |
| def f(self, x: int) -> None: pass |
| def g(self, x: str) -> None: pass |
| def h(self, x: int) -> None: pass |
| X = TypeVar('X', A, B) |
| class C(Generic[X]): |
| def f(self, x: X) -> None: |
| x.f(1) |
| x.g(1) # E: Argument 1 to "g" of "B" has incompatible type "int"; expected "str" |
| x.h(1) # E: Argument 1 to "h" of "A" has incompatible type "int"; expected "str" |
| [out] |
| |
| [case testAttributeInGenericTypeWithTypevarValues1] |
| from typing import TypeVar, Generic |
| X = TypeVar('X', int, str) |
| class C(Generic[X]): |
| x = None # type: X |
| def f(self, x: X) -> None: |
| self.x = x |
| self.x = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str") |
| [out] |
| |
| [case testAttributeInGenericTypeWithTypevarValues2] |
| from typing import TypeVar, Generic |
| X = TypeVar('X', int, str) |
| class C(Generic[X]): |
| x = None # type: X |
| cn = C() # type: C[int] |
| cn.x = 1 |
| cn.x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| cs = C() # type: C[str] |
| cs.x = '' |
| cs.x = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "str") |
| |
| [case testAttributeInGenericTypeWithTypevarValues3] |
| from typing import TypeVar, Generic |
| X = TypeVar('X', int, str) |
| class C(Generic[X]): |
| def f(self, x: X) -> None: |
| self.x = x # type: X |
| ci: C[int] |
| cs: C[str] |
| reveal_type(ci.x) # N: Revealed type is 'builtins.int*' |
| reveal_type(cs.x) # N: Revealed type is 'builtins.str*' |
| |
| [case testAttributeInGenericTypeWithTypevarValuesUsingInference1] |
| from typing import TypeVar, Generic |
| X = TypeVar('X', int, str) |
| class C(Generic[X]): |
| def f(self, x: X) -> None: |
| self.x = x # E: Need type annotation for 'x' |
| ci: C[int] |
| cs: C[str] |
| reveal_type(ci.x) # N: Revealed type is 'Any' |
| reveal_type(cs.x) # N: Revealed type is 'Any' |
| |
| [case testAttributeInGenericTypeWithTypevarValuesUsingInference2] |
| from typing import TypeVar, Generic |
| X = TypeVar('X', int, str) |
| class C(Generic[X]): |
| def f(self, x: X) -> None: |
| self.x = 1 |
| reveal_type(self.x) # N: Revealed type is 'builtins.int' |
| ci: C[int] |
| cs: C[str] |
| reveal_type(ci.x) # N: Revealed type is 'builtins.int' |
| reveal_type(cs.x) # N: Revealed type is 'builtins.int' |
| |
| [case testAttributeInGenericTypeWithTypevarValuesUsingInference3] |
| from typing import TypeVar, Generic |
| X = TypeVar('X', int, str) |
| class C(Generic[X]): |
| x: X |
| def f(self) -> None: |
| self.y = self.x # E: Need type annotation for 'y' |
| ci: C[int] |
| cs: C[str] |
| reveal_type(ci.y) # N: Revealed type is 'Any' |
| reveal_type(cs.y) # N: Revealed type is 'Any' |
| |
| [case testInferredAttributeInGenericClassBodyWithTypevarValues] |
| from typing import TypeVar, Generic |
| X = TypeVar('X', int, str) |
| class C(Generic[X]): |
| x = 1 |
| C.x = 1 |
| C.x = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| |
| [case testMultipleClassTypevarsWithValues1] |
| from typing import TypeVar, Generic |
| class A: |
| def f(self, x: int) -> None: pass |
| class B: |
| def f(self, x: str) -> None: pass |
| X = TypeVar('X', A, B) |
| Y = TypeVar('Y', int, str) |
| class C(Generic[X, Y]): |
| def f(self, x: X, y: Y) -> None: |
| x.f(y) |
| [out] |
| main:10: error: Argument 1 to "f" of "A" has incompatible type "str"; expected "int" |
| main:10: error: Argument 1 to "f" of "B" has incompatible type "int"; expected "str" |
| |
| [case testMultipleClassTypevarsWithValues2] |
| from typing import TypeVar, Generic |
| class A: pass |
| class B: pass |
| X = TypeVar('X', A, B) |
| Y = TypeVar('Y', int, str) |
| class C(Generic[X, Y]): pass |
| a = None # type: C[A, int] |
| b = None # type: C[B, str] |
| c = None # type: C[int, int] # E: Value of type variable "X" of "C" cannot be "int" |
| d = None # type: C[A, A] # E: Value of type variable "Y" of "C" cannot be "A" |
| |
| [case testCallGenericFunctionUsingMultipleTypevarsWithValues] |
| from typing import TypeVar |
| class A: pass |
| class B: pass |
| X = TypeVar('X', A, B) |
| Y = TypeVar('Y', int, str) |
| def f(x: X, y: Y) -> None: pass |
| f(A(), '') |
| f(B(), 1) |
| f(A(), A()) # E: Value of type variable "Y" of "f" cannot be "A" |
| f(1, 1) # E: Value of type variable "X" of "f" cannot be "int" |
| |
| [case testGenericFunctionWithNormalAndRestrictedTypevar] |
| from typing import TypeVar, Generic |
| X = TypeVar('X') |
| Y = TypeVar('Y', int, str) |
| class C(Generic[Y]): |
| def __init__(self, y: Y) -> None: pass |
| def f(x: X, y: Y, z: int) -> None: |
| C(y) |
| C(x) # Error |
| if int(): |
| z = x # Error |
| z = y # Error |
| y.foo # Error |
| [out] |
| main:8: error: Value of type variable "Y" of "C" cannot be "X" |
| main:10: error: Incompatible types in assignment (expression has type "X", variable has type "int") |
| main:11: error: Incompatible types in assignment (expression has type "str", variable has type "int") |
| main:12: error: "int" has no attribute "foo" |
| main:12: error: "str" has no attribute "foo" |
| |
| [case testTypeVarWithValueInferredFromObjectReturnTypeContext] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| def c1(x: object) -> None: pass |
| def c2(x: int) -> None: pass |
| def c3(x: str) -> None: pass |
| def g(x: T) -> T: pass |
| c1(g('')) |
| c2(g(1)) |
| c3(g('')) |
| c2(g('')) # E: Argument 1 to "c2" has incompatible type "str"; expected "int" |
| c3(g(1)) # E: Argument 1 to "c3" has incompatible type "int"; expected "str" |
| |
| [case testTypeVarWithValueInferredFromObjectReturnTypeContext2] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| class ss(str): pass |
| def c(x: ss) -> None: pass |
| def g(x: T) -> T: pass |
| c(g('')) |
| c(g(1)) |
| [out] |
| main:6: error: Argument 1 to "c" has incompatible type "str"; expected "ss" |
| main:7: error: Argument 1 to "c" has incompatible type "int"; expected "ss" |
| |
| [case testDefineAttributeInGenericMethodUsingTypeVarWithValues] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| class A: |
| def f(self, x: T) -> None: |
| self.x = x # E: Need type annotation for 'x' |
| self.y = [x] # E: Need type annotation for 'y' |
| self.z = 1 |
| reveal_type(A().x) # N: Revealed type is 'Any' |
| reveal_type(A().y) # N: Revealed type is 'Any' |
| reveal_type(A().z) # N: Revealed type is 'builtins.int' |
| [builtins fixtures/list.pyi] |
| |
| |
| -- Special cases |
| -- ------------- |
| |
| |
| [case testTypevarValuesSpecialCase1] |
| from typing import TypeVar, Generic |
| from abc import abstractmethod |
| T = TypeVar('T', int, str) |
| class A(Generic[T]): |
| @abstractmethod |
| def f(self) -> 'A[T]': pass |
| class B(A[str]): |
| @abstractmethod |
| def f(self) -> 'B': pass |
| class C(A[str]): |
| @abstractmethod |
| def f(self) -> int: # E: Return type "int" of "f" incompatible with return type "A[str]" in supertype "A" |
| pass |
| [out] |
| |
| [case testDefaultArgumentValueInGenericClassWithTypevarValues] |
| from typing import TypeVar, Generic |
| T = TypeVar('T', int, str) |
| class C(Generic[T]): |
| def f(self, x: int = None) -> None: pass |
| |
| [case testTypevarValuesWithOverloadedFunctionSpecialCase] |
| from foo import * |
| [file foo.pyi] |
| from typing import TypeVar, overload, Callable |
| |
| T = TypeVar('T', int, str) |
| def f(x: T) -> None: |
| y = m(g, x) |
| if int(): |
| x = y |
| y = object() # Error |
| |
| A = TypeVar('A') |
| R = TypeVar('R') |
| def m(f: Callable[[A], R], it: A) -> A: pass |
| |
| @overload |
| def g(x: int) -> int: return x |
| @overload |
| def g(x: str) -> str: return x |
| [out] |
| tmp/foo.pyi:8: error: Incompatible types in assignment (expression has type "object", variable has type "int") |
| tmp/foo.pyi:8: error: Incompatible types in assignment (expression has type "object", variable has type "str") |
| |
| [case testGenericFunctionSubtypingWithTypevarValues] |
| from typing import TypeVar |
| class A: pass |
| T = TypeVar('T', int, str) |
| U = TypeVar('U', str, A, int) |
| def f(x: T) -> T: pass |
| def g(x: U) -> U: pass |
| a = f |
| if int(): |
| a = f |
| if int(): |
| a = g |
| b = g |
| if int(): |
| b = g |
| if int(): |
| b = f # E: Incompatible types in assignment (expression has type "Callable[[T], T]", variable has type "Callable[[U], U]") |
| |
| [case testInnerFunctionWithTypevarValues] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| U = TypeVar('U', int, str) |
| def outer(x: T) -> T: |
| def inner(y: T) -> T: |
| return x |
| def inner2(y: U) -> U: |
| return y |
| inner(x) |
| inner(3) # E: Argument 1 to "inner" has incompatible type "int"; expected "str" |
| inner2(x) |
| inner2(3) |
| outer(3) |
| return x |
| [out] |
| |
| [case testInnerFunctionMutualRecursionWithTypevarValues] |
| from typing import TypeVar |
| T = TypeVar('T', int, str) |
| def outer(x: T) -> T: |
| def inner1(y: T) -> T: |
| return inner2(y) |
| def inner2(y: T) -> T: |
| return inner1('a') # E: Argument 1 to "inner1" has incompatible type "str"; expected "int" |
| return inner1(x) |
| [out] |
| |
| [case testClassMemberTypeVarInFunctionBody] |
| from typing import TypeVar, List |
| S = TypeVar('S') |
| class C: |
| T = TypeVar('T', bound=int) |
| def f(self, x: T) -> T: |
| L = List[S] |
| y: L[C.T] = [x] |
| C.T # E: Type variable "C.T" cannot be used as an expression |
| A = C.T # E: Type variable "C.T" cannot be used as an expression |
| return y[0] |
| |
| [builtins fixtures/list.pyi] |
| |
| [case testParameterLessGenericAsRestriction] |
| from typing import Sequence, Iterable, TypeVar |
| S = TypeVar('S', Sequence, Iterable) |
| def my_len(s: S) -> None: pass |
| def crash() -> None: my_len((0,)) |
| |
| [case testReferenceToDecoratedFunctionAndTypeVarValues] |
| from typing import TypeVar, Callable |
| |
| T = TypeVar('T') |
| S = TypeVar('S', int, str) |
| |
| def dec(f: Callable[..., T]) -> Callable[..., T]: ... |
| |
| @dec |
| def g(s: S) -> Callable[[S], None]: ... |
| |
| def f(x: S) -> None: |
| h = g(x) |
| h(x) |