| -- Test cases for the type checker related to varargs. |
| |
| |
| -- Varargs within body |
| -- ------------------- |
| |
| |
| [case testVarArgsWithinFunction] |
| from typing import Tuple |
| def f( *b: 'B') -> None: |
| ab = None # type: Tuple[B, ...] |
| ac = None # type: Tuple[C, ...] |
| b = ac # E: Incompatible types in assignment (expression has type Tuple[C, ...], variable has type Tuple[B, ...]) |
| ac = b # E: Incompatible types in assignment (expression has type Tuple[B, ...], variable has type Tuple[C, ...]) |
| b = ab |
| ab = b |
| |
| class B: pass |
| class C: pass |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| |
| [case testVarArgsAreTuple] |
| from typing import Tuple, Sequence |
| def want_tuple(types: Tuple[type, ...]): pass |
| def want_sequence(types: Sequence[type]): pass |
| def test(*t: type) -> None: |
| want_tuple(t) |
| want_sequence(t) |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| |
| -- Calling varargs function |
| -- ------------------------ |
| |
| |
| [case testCallingVarArgsFunction] |
| |
| a = None # type: A |
| b = None # type: B |
| c = None # type: C |
| |
| f(c) # E: Argument 1 to "f" has incompatible type "C"; expected "A" |
| f(a, b, c) # E: Argument 3 to "f" has incompatible type "C"; expected "A" |
| f(g()) # E: "g" does not return a value |
| f(a, g()) # E: "g" does not return a value |
| f() |
| f(a) |
| f(b) |
| f(a, b, a, b) |
| |
| def f( *a: 'A') -> None: pass |
| |
| def g() -> None: pass |
| |
| class A: pass |
| class B(A): pass |
| class C: pass |
| [builtins fixtures/list.pyi] |
| |
| [case testCallingVarArgsFunctionWithAlsoNormalArgs] |
| |
| a = None # type: A |
| b = None # type: B |
| c = None # type: C |
| |
| f(a) # E: Argument 1 to "f" has incompatible type "A"; expected "C" |
| f(c, c) # E: Argument 2 to "f" has incompatible type "C"; expected "A" |
| f(c, a, b, c) # E: Argument 4 to "f" has incompatible type "C"; expected "A" |
| f(c) |
| f(c, a) |
| f(c, b, b, a, b) |
| |
| def f(a: 'C', *b: 'A') -> None: pass |
| |
| class A: pass |
| class B(A): pass |
| class C: pass |
| [builtins fixtures/list.pyi] |
| |
| [case testCallingVarArgsFunctionWithDefaultArgs] |
| |
| a = None # type: A |
| b = None # type: B |
| c = None # type: C |
| |
| f(a) # E: Argument 1 to "f" has incompatible type "A"; expected "C" |
| f(c, c) # E: Argument 2 to "f" has incompatible type "C"; expected "A" |
| f(c, a, b, c) # E: Argument 4 to "f" has incompatible type "C"; expected "A" |
| f() |
| f(c) |
| f(c, a) |
| f(c, b, b, a, b) |
| |
| def f(a: 'C' = None, *b: 'A') -> None: |
| pass |
| |
| class A: pass |
| class B(A): pass |
| class C: pass |
| [builtins fixtures/list.pyi] |
| |
| [case testCallVarargsFunctionWithIterable] |
| from typing import Iterable |
| it1 = None # type: Iterable[int] |
| it2 = None # type: Iterable[str] |
| def f(*x: int) -> None: pass |
| f(*it1) |
| f(*it2) # E: Argument 1 to "f" has incompatible type *Iterable[str]; expected "int" |
| [builtins fixtures/for.pyi] |
| |
| [case testCallVarargsFunctionWithIterableAndPositional] |
| # flags: --fast-parser |
| from typing import Iterable |
| it1 = None # type: Iterable[int] |
| def f(*x: int) -> None: pass |
| f(*it1, 1, 2) |
| f(*it1, 1, *it1, 2) |
| f(*it1, '') # E: Argument 2 to "f" has incompatible type "str"; expected "int" |
| [builtins fixtures/for.pyi] |
| |
| [case testCallVarargsFunctionWithTupleAndPositional] |
| # flags: --fast-parser |
| def f(*x: int) -> None: pass |
| it1 = (1, 2) |
| f(*it1, 1, 2) |
| f(*it1, 1, *it1, 2) |
| f(*it1, '') # E: Argument 2 to "f" has incompatible type "str"; expected "int" |
| [builtins fixtures/for.pyi] |
| |
| |
| -- Calling varargs function + type inference |
| -- ----------------------------------------- |
| |
| |
| [case testTypeInferenceWithCalleeVarArgs] |
| from typing import TypeVar |
| T = TypeVar('T') |
| a = None # type: A |
| b = None # type: B |
| c = None # type: C |
| o = None # type: object |
| |
| a = f(o) # E: Incompatible types in assignment (expression has type "object", variable has type "A") |
| b = f(b, a) # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| b = f(a, b) # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| |
| o = f() |
| a = f(a) |
| a = f(b) |
| a = f(a, b, a) |
| o = f(a, b, o) |
| c = f(c) |
| |
| def f( *a: T) -> T: |
| pass |
| |
| class A: pass |
| class B(A): pass |
| class C: pass |
| [builtins fixtures/list.pyi] |
| |
| [case testTypeInferenceWithCalleeVarArgsAndDefaultArgs] |
| from typing import TypeVar |
| T = TypeVar('T') |
| a = None # type: A |
| o = None # type: object |
| |
| a = f(o) # E: Incompatible types in assignment (expression has type "object", variable has type "A") |
| a = f(a, o) # E: Incompatible types in assignment (expression has type "object", variable has type "A") |
| a = f(a, a, o) # E: Incompatible types in assignment (expression has type "object", variable has type "A") |
| a = f(a, a, a, o) # E: Incompatible types in assignment (expression has type "object", variable has type "A") |
| |
| a = f(a) |
| a = f(a, a) |
| a = f(a, a, a) |
| |
| def f(a: T, b: T = None, *c: T) -> T: |
| pass |
| |
| class A: pass |
| [builtins fixtures/list.pyi] |
| |
| |
| -- Calling normal function with varargs |
| -- ------------------------------------ |
| |
| |
| [case testCallingWithListVarArgs] |
| from typing import List, Any |
| aa = None # type: List[A] |
| ab = None # type: List[B] |
| a = None # type: A |
| b = None # type: B |
| |
| f(*aa) # Fail |
| f(a, *ab) # Ok |
| f(a, b) |
| (Any(f))(*aa) # IDEA: Move to check-dynamic? |
| (Any(f))(a, *ab) # IDEA: Move to check-dynamic? |
| |
| def f(a: 'A', b: 'B') -> None: |
| pass |
| |
| class A: pass |
| class B: pass |
| [builtins fixtures/list.pyi] |
| [out] |
| main:7: error: Argument 1 to "f" has incompatible type *List[A]; expected "B" |
| |
| [case testCallingWithTupleVarArgs] |
| |
| a = None # type: A |
| b = None # type: B |
| c = None # type: C |
| cc = None # type: CC |
| |
| f(*(a, b, b)) # E: Argument 1 to "f" has incompatible type *"Tuple[A, B, B]"; expected "C" |
| f(*(b, b, c)) # E: Argument 1 to "f" has incompatible type *"Tuple[B, B, C]"; expected "A" |
| f(a, *(b, b)) # E: Argument 2 to "f" has incompatible type *"Tuple[B, B]"; expected "C" |
| f(b, *(b, c)) # E: Argument 1 to "f" has incompatible type "B"; expected "A" |
| f(*(a, b)) # E: Too few arguments for "f" |
| f(*(a, b, c, c)) # E: Too many arguments for "f" |
| f(a, *(b, c, c)) # E: Too many arguments for "f" |
| f(*(a, b, c)) |
| f(a, *(b, c)) |
| f(a, b, *(c,)) |
| f(a, *(b, cc)) |
| |
| def f(a: 'A', b: 'B', c: 'C') -> None: pass |
| |
| class A: pass |
| class B: pass |
| class C: pass |
| class CC(C): pass |
| [builtins fixtures/tuple.pyi] |
| |
| [case testInvalidVarArg] |
| |
| a = None # type: A |
| |
| f(*None) |
| f(*a) # E: List or tuple expected as variable arguments |
| f(*(a,)) |
| |
| def f(a: 'A') -> None: |
| pass |
| |
| class A: pass |
| [builtins fixtures/tuple.pyi] |
| |
| |
| -- Calling varargs function with varargs |
| -- ------------------------------------- |
| |
| |
| [case testCallingVarArgsFunctionWithListVarArgs] |
| from typing import List |
| aa, ab, a, b = None, None, None, None # type: (List[A], List[B], A, B) |
| f(*aa) # Fail |
| f(a, *aa) # Fail |
| f(b, *ab) # Fail |
| f(a, a, *ab) # Fail |
| f(a, b, *aa) # Fail |
| f(b, b, *ab) # Fail |
| g(*ab) # Fail |
| f(a, *ab) |
| f(a, b, *ab) |
| f(a, b, b, *ab) |
| g(*aa) |
| |
| def f(a: 'A', *b: 'B') -> None: pass |
| def g(a: 'A', *b: 'A') -> None: pass |
| class A: pass |
| class B: pass |
| [builtins fixtures/list.pyi] |
| [out] |
| main:3: error: Argument 1 to "f" has incompatible type *List[A]; expected "B" |
| main:4: error: Argument 2 to "f" has incompatible type *List[A]; expected "B" |
| main:5: error: Argument 1 to "f" has incompatible type "B"; expected "A" |
| main:6: error: Argument 2 to "f" has incompatible type "A"; expected "B" |
| main:7: error: Argument 3 to "f" has incompatible type *List[A]; expected "B" |
| main:8: error: Argument 1 to "f" has incompatible type "B"; expected "A" |
| main:9: error: Argument 1 to "g" has incompatible type *List[B]; expected "A" |
| |
| [case testCallingVarArgsFunctionWithTupleVarArgs] |
| |
| a, b, c, cc = None, None, None, None # type: (A, B, C, CC) |
| |
| f(*(b, b, b)) # E: Argument 1 to "f" has incompatible type *"Tuple[B, B, B]"; expected "A" |
| f(*(a, a, b)) # E: Argument 1 to "f" has incompatible type *"Tuple[A, A, B]"; expected "B" |
| f(*(a, b, a)) # E: Argument 1 to "f" has incompatible type *"Tuple[A, B, A]"; expected "B" |
| f(a, *(a, b)) # E: Argument 2 to "f" has incompatible type *"Tuple[A, B]"; expected "B" |
| f(b, *(b, b)) # E: Argument 1 to "f" has incompatible type "B"; expected "A" |
| f(b, b, *(b,)) # E: Argument 1 to "f" has incompatible type "B"; expected "A" |
| f(a, a, *(b,)) # E: Argument 2 to "f" has incompatible type "A"; expected "B" |
| f(a, b, *(a,)) # E: Argument 3 to "f" has incompatible type *"Tuple[A]"; expected "B" |
| f(*()) # E: Too few arguments for "f" |
| f(*(a, b, b)) |
| f(a, *(b, b)) |
| f(a, b, *(b,)) |
| |
| def f(a: 'A', *b: 'B') -> None: |
| pass |
| |
| class A: pass |
| class B: pass |
| class C: pass |
| class CC(C): pass |
| [builtins fixtures/list.pyi] |
| |
| |
| -- Varargs special cases |
| -- --------------------- |
| |
| |
| [case testDynamicVarArg] |
| from typing import Any |
| d, a = None, None # type: (Any, A) |
| f(a, a, *d) # Fail |
| f(a, *d) # Fail |
| f(*d) # Ok |
| |
| g(*d) |
| g(a, *d) |
| g(a, a, *d) |
| |
| def f(a: 'A') -> None: pass |
| def g(a: 'A', *b: 'A') -> None: pass |
| class A: pass |
| [builtins fixtures/list.pyi] |
| [out] |
| main:3: error: Too many arguments for "f" |
| main:4: error: Too many arguments for "f" |
| |
| [case testListVarArgsAndSubtyping] |
| from typing import List |
| aa = None # type: List[A] |
| ab = None # type: List[B] |
| |
| g(*aa) # E: Argument 1 to "g" has incompatible type *List[A]; expected "B" |
| f(*aa) |
| f(*ab) |
| g(*ab) |
| |
| def f( *a: 'A') -> None: |
| pass |
| |
| def g( *a: 'B') -> None: |
| pass |
| |
| class A: pass |
| class B(A): pass |
| [builtins fixtures/list.pyi] |
| |
| [case testCallerVarArgsAndDefaultArgs] |
| |
| a, b = None, None # type: (A, B) |
| f(*()) # Fail |
| f(a, *[a]) # Fail |
| f(a, b, *[a]) # Fail |
| f(*(a, a, b)) # Fail |
| f(*(a,)) |
| f(*(a, b)) |
| f(*(a, b, b, b)) |
| f(a, *[]) |
| f(a, *[b]) |
| f(a, *[b, b]) |
| |
| def f(a: 'A', b: 'B' = None, *c: 'B') -> None: |
| pass |
| |
| class A: pass |
| class B: pass |
| [builtins fixtures/list.pyi] |
| [out] |
| main:3: error: Too few arguments for "f" |
| main:4: error: Argument 2 to "f" has incompatible type *List[A]; expected "B" |
| main:5: error: Argument 3 to "f" has incompatible type *List[A]; expected "B" |
| main:6: error: Argument 1 to "f" has incompatible type *"Tuple[A, A, B]"; expected "B" |
| |
| [case testVarArgsAfterKeywordArgInCall1] |
| def f(x: int, y: str) -> None: pass |
| f(x=1, *[2]) |
| [builtins fixtures/list.pyi] |
| [out] |
| main:2: error: "f" gets multiple values for keyword argument "x" |
| main:2: error: Argument 2 to "f" has incompatible type *List[int]; expected "str" |
| |
| [case testVarArgsAfterKeywordArgInCall2] |
| def f(x: int, y: str) -> None: pass |
| f(y='x', *[1]) |
| [builtins fixtures/list.pyi] |
| [out] |
| main:2: error: "f" gets multiple values for keyword argument "y" |
| main:2: error: Argument 2 to "f" has incompatible type *List[int]; expected "str" |
| |
| [case testVarArgsAfterKeywordArgInCall3] |
| def f(x: int, y: str) -> None: pass |
| f(y='x', *(1,)) |
| [builtins fixtures/list.pyi] |
| |
| [case testVarArgsAfterKeywordArgInCall4] |
| def f(x: int, *, y: str) -> None: pass |
| f(y='x', *[1]) |
| [builtins fixtures/list.pyi] |
| |
| [case testVarArgsAfterKeywordArgInCall5] |
| def f(x: int, *, y: str) -> None: pass |
| f(y='x', *(1,)) |
| [builtins fixtures/list.pyi] |
| |
| |
| -- Overloads + varargs |
| -- ------------------- |
| |
| |
| [case testIntersectionTypesAndVarArgs] |
| from typing import overload |
| a, b = None, None # type: (A, B) |
| |
| b = f() # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| b = f(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| b = f(a, b) # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| a = f(b) # E: Incompatible types in assignment (expression has type "B", variable has type "A") |
| a = f(b, b) # E: Incompatible types in assignment (expression has type "B", variable has type "A") |
| b = f(a, *[b]) # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| b = f(*()) # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| b = f(*(a,)) # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| b = f(*(a, b)) # E: Incompatible types in assignment (expression has type "A", variable has type "B") |
| a = f(*(b,)) # E: Incompatible types in assignment (expression has type "B", variable has type "A") |
| a = f(*(b, b)) # E: Incompatible types in assignment (expression has type "B", variable has type "A") |
| a = f(*[b]) # E: Incompatible types in assignment (expression has type "B", variable has type "A") |
| |
| a = f() |
| a = f(a) |
| a = f(a, b) |
| b = f(b) |
| b = f(b, b) |
| a = f(a, *[b]) |
| a = f(*()) |
| a = f(*(a,)) |
| a = f(*(a, b)) |
| b = f(*(b,)) |
| b = f(*(b, b)) |
| b = f(*[b]) |
| |
| class A: pass |
| class B: pass |
| |
| @overload |
| def f(a: A = None, *b: B) -> A: pass |
| |
| @overload |
| def f(a: B, *b: B) -> B: pass |
| [builtins fixtures/list.pyi] |
| |
| |
| -- Caller varargs + type inference |
| -- ------------------------------- |
| |
| |
| [case testCallerVarArgsListWithTypeInference] |
| from typing import List, TypeVar, Tuple |
| S = TypeVar('S') |
| T = TypeVar('T') |
| a, b, aa = None, None, None # type: (A, B, List[A]) |
| |
| a, b = f(*aa) # Fail |
| b, b = f(*aa) # Fail |
| a, a = f(b, *aa) # Fail |
| b, b = f(b, *aa) # Fail |
| b, b = f(b, b, *aa) # Fail |
| a, b = f(a, *a) # Fail |
| a, b = f(*a) # Fail |
| |
| a, a = f(*aa) |
| b, a = f(b, *aa) |
| b, a = f(b, a, *aa) |
| |
| def f(a: S, *b: T) -> Tuple[S, T]: |
| pass |
| |
| class A: pass |
| class B: pass |
| [builtins fixtures/list.pyi] |
| [out] |
| main:6: error: Argument 1 to "f" has incompatible type *List[A]; expected "B" |
| main:7: error: Argument 1 to "f" has incompatible type *List[A]; expected "B" |
| main:8: error: Argument 1 to "f" has incompatible type "B"; expected "A" |
| main:9: error: Argument 2 to "f" has incompatible type *List[A]; expected "B" |
| main:10: error: Argument 3 to "f" has incompatible type *List[A]; expected "B" |
| main:11: error: List or tuple expected as variable arguments |
| main:12: error: List or tuple expected as variable arguments |
| |
| [case testCallerVarArgsTupleWithTypeInference] |
| from typing import TypeVar, Tuple |
| S = TypeVar('S') |
| T = TypeVar('T') |
| a, b = None, None # type: (A, B) |
| |
| a, a = f(*(a, b)) # E: Argument 1 to "f" has incompatible type *"Tuple[A, B]"; expected "A" |
| b, b = f(a, *(b,)) # E: Argument 1 to "f" has incompatible type "A"; expected "B" |
| a, a = f(*(a, b)) # E: Argument 1 to "f" has incompatible type *"Tuple[A, B]"; expected "A" |
| b, b = f(a, *(b,)) # E: Argument 1 to "f" has incompatible type "A"; expected "B" |
| a, b = f(*(a, b, b)) # E: Too many arguments for "f" |
| |
| a, b = f(*(a, b)) |
| a, b = f(a, *(b,)) |
| |
| def f(a: S, b: T) -> Tuple[S, T]: pass |
| |
| class A: pass |
| class B: pass |
| [builtins fixtures/list.pyi] |
| |
| [case testCallerVarargsAndComplexTypeInference] |
| from typing import List, TypeVar, Generic, Tuple |
| T = TypeVar('T') |
| S = TypeVar('S') |
| a, b = None, None # type: (A, B) |
| ao = None # type: List[object] |
| aa = None # type: List[A] |
| ab = None # type: List[B] |
| |
| a, aa = G().f(*[a]) # Fail |
| aa, a = G().f(*[a]) # Fail |
| ab, aa = G().f(*[a]) # Fail |
| |
| ao, ao = G().f(*[a]) # E: Incompatible types in assignment (expression has type List[None], variable has type List[object]) |
| aa, aa = G().f(*[a]) # E: Incompatible types in assignment (expression has type List[None], variable has type List[A]) |
| |
| class G(Generic[T]): |
| def f(self, *a: S) -> Tuple[List[S], List[T]]: |
| pass |
| |
| class A: pass |
| class B: pass |
| [builtins fixtures/list.pyi] |
| [out] |
| main:9: error: Incompatible types in assignment (expression has type List[A], variable has type "A") |
| main:9: error: Incompatible types in assignment (expression has type List[None], variable has type List[A]) |
| main:10: error: Incompatible types in assignment (expression has type List[None], variable has type "A") |
| main:11: error: Incompatible types in assignment (expression has type List[None], variable has type List[A]) |
| main:11: error: Argument 1 to "f" of "G" has incompatible type *List[A]; expected "B" |
| |
| |
| -- Comment signatures |
| -- ------------------ |
| |
| |
| [case testVarArgsAndCommentSignature] |
| import typing |
| def f(*x): # type: (*int) -> None |
| pass |
| f(1) |
| f(1, 2) |
| f('') # E: Argument 1 to "f" has incompatible type "str"; expected "int" |
| f(1, '') # E: Argument 2 to "f" has incompatible type "str"; expected "int" |
| [builtins fixtures/list.pyi] |
| |
| |
| -- Subtyping |
| -- --------- |
| |
| |
| [case testVarArgsFunctionSubtyping] |
| from typing import Callable |
| x = None # type: Callable[[int], None] |
| def f(*x: int) -> None: pass |
| def g(*x: str) -> None: pass |
| x = f |
| x = g # E: Incompatible types in assignment (expression has type Callable[[StarArg(str)], None], variable has type Callable[[int], None]) |
| [builtins fixtures/list.pyi] |
| [out] |
| |
| |
| -- Decorated method where self is implied by *args |
| -- ----------------------------------------------- |
| |
| [case testVarArgsCallableSelf] |
| from typing import Callable |
| def cm(func) -> Callable[..., None]: pass |
| class C: |
| @cm |
| def foo(self) -> None: pass |
| C().foo() |
| C().foo(1) # The decorator's return type says this should be okay |