-- 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 = None # type: G[A]
w = None # type: G[B]
x = None # type: 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]
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 = None # type: C


[case testBoundHigherOrderWithVoid]
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]
