blob: 1c713fd77c38d82f3f803bf1890bacf15c2b90d0 [file] [log] [blame] [edit]
-- Enforcement of upper bounds
-- ---------------------------
[case testBoundOnGenericFunction]
from typing import TypeVar
class A: pass
class B(A): pass
class C(A): pass
class D: pass
T = TypeVar('T', bound=A)
U = TypeVar('U')
def f(x: T) -> T: pass
def g(x: U) -> U:
return f(x) # E: Value of type variable "T" of "f" cannot be "U"
f(A())
f(B())
f(D()) # E: Value of type variable "T" of "f" cannot be "D"
b = B()
if int():
b = f(b)
if int():
b = f(C()) # E: Incompatible types in assignment (expression has type "C", variable has type "B")
[case testBoundOnGenericClass]
from typing import TypeVar, Generic
class A: pass
class B(A): pass
T = TypeVar('T', bound=A)
class G(Generic[T]):
def __init__(self, x: T) -> None: pass
v: G[A]
w: G[B]
x: G[str] # E: Type argument "str" of "G" must be a subtype of "A"
y = G('a') # E: Value of type variable "T" of "G" cannot be "str"
z = G(A())
z = G(B())
[case testBoundVoid]
# flags: --no-strict-optional
from typing import TypeVar, Generic
T = TypeVar('T', bound=int)
class C(Generic[T]):
t = None # type: T
def get(self) -> T:
return self.t
c1 = None # type: C[None]
c1.get()
d = c1.get()
reveal_type(d) # N: Revealed type is "None"
[case testBoundAny]
from typing import TypeVar, Generic
T = TypeVar('T', bound=int)
class C(Generic[T]):
def __init__(self, x: T) -> None: pass
def f(x: T) -> T:
return x
def g(): pass
f(g())
C(g())
z: C
[case testBoundHigherOrderWithVoid]
# flags: --no-strict-optional
from typing import TypeVar, Callable
class A: pass
T = TypeVar('T', bound=A)
def f(g: Callable[[], T]) -> T:
return g()
def h() -> None: pass
f(h)
a = f(h)
reveal_type(a) # N: Revealed type is "None"
[case testBoundInheritance]
from typing import TypeVar, Generic
class A: pass
T = TypeVar('T')
TA = TypeVar('TA', bound=A)
class C(Generic[TA]): pass
class D0(C[TA], Generic[TA]): pass
class D1(C[T], Generic[T]): pass # E: Type argument "T" of "C" must be a subtype of "A"
class D2(C[A]): pass
class D3(C[str]): pass # E: Type argument "str" of "C" must be a subtype of "A"
-- Using information from upper bounds
-- -----------------------------------
[case testBoundGenericFunctions]
from typing import TypeVar
class A: pass
class B(A): pass
T = TypeVar('T')
TA = TypeVar('TA', bound=A)
TB = TypeVar('TB', bound=B)
def f(x: T) -> T:
return x
def g(x: TA) -> TA:
return f(x)
def h(x: TB) -> TB:
return g(x)
def g2(x: TA) -> TA:
return h(x) # Fail
def j(x: TA) -> A:
return x
def k(x: TA) -> B:
return x # Fail
[out]
main:16: error: Value of type variable "TB" of "h" cannot be "TA"
main:21: error: Incompatible return value type (got "TA", expected "B")
[case testBoundMethodUsage]
from typing import TypeVar
class A0:
def foo(self) -> None: pass
class A(A0):
def bar(self) -> None: pass
a = 1
@property
def b(self) -> int:
return self.a
class B(A):
def baz(self) -> None: pass
T = TypeVar('T', bound=A)
def f(x: T) -> T:
x.foo()
x.bar()
x.baz() # E: "T" has no attribute "baz"
x.a
x.b
return x
b = f(B())
[builtins fixtures/property.pyi]
[out]
[case testBoundClassMethod]
from typing import TypeVar
class A0:
@classmethod
def foo(cls, x: int) -> int: pass
class A(A0): pass
T = TypeVar('T', bound=A)
def f(x: T) -> int:
return x.foo(22)
[builtins fixtures/classmethod.pyi]
[case testBoundClassMethodWithNamedTupleBase]
from typing import NamedTuple, Type, TypeVar
class A(NamedTuple):
@classmethod
def foo(cls) -> None: ...
T = TypeVar('T', bound=A)
def f(x: Type[T]) -> None:
reveal_type(x.foo) # N: Revealed type is "def ()"
x.foo()
[builtins fixtures/classmethod.pyi]
[case testBoundStaticMethod]
from typing import TypeVar
class A0:
@staticmethod
def foo(x: int) -> int: pass
class A(A0): pass
T = TypeVar('T', bound=A)
def f(x: T) -> int:
return x.foo(22)
[builtins fixtures/staticmethod.pyi]
[case testBoundOnDecorator]
from typing import TypeVar, Callable, Any, cast
T = TypeVar('T', bound=Callable[..., Any])
def twice(f: T) -> T:
def result(*args, **kwargs) -> Any:
f(*args, **kwargs)
return f(*args, **kwargs)
return cast(T, result)
@twice
def foo(x: int) -> int:
return x
a = 1
b = foo(a)
if int():
b = 'a' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
twice(a) # E: Value of type variable "T" of "twice" cannot be "int"
[builtins fixtures/args.pyi]
[case testIterableBoundUnpacking]
from typing import Tuple, TypeVar
TupleT = TypeVar("TupleT", bound=Tuple[int, ...])
def f(t: TupleT) -> None:
a, *b = t
reveal_type(a) # N: Revealed type is "builtins.int"
reveal_type(b) # N: Revealed type is "builtins.list[builtins.int]"
[builtins fixtures/tuple.pyi]