[case testSelfTypeInstance]
from typing import TypeVar

T = TypeVar('T', bound='A', covariant=True)

class A:
    def copy(self: T) -> T: pass

class B(A):
    pass

reveal_type(A().copy)  # E: Revealed type is 'def () -> __main__.A*'
reveal_type(B().copy)  # E: Revealed type is 'def () -> __main__.B*'
reveal_type(A().copy())  # E: Revealed type is '__main__.A*'
reveal_type(B().copy())  # E: Revealed type is '__main__.B*'

[builtins fixtures/bool.pyi]

[case testSelfTypeStaticAccess]
from typing import TypeVar

T = TypeVar('T', bound='A', covariant=True)
class A:
    def copy(self: T) -> T: pass

class B(A):
    pass

# Erased instances appear on reveal_type; unrelated to self type
def f(a: A) -> None: pass
f(A.copy(A()))
f(A.copy(B()))
f(B.copy(B()))

# TODO: make it an error
# f(B.copy(A()))

def g(a: B) -> None: pass
g(A.copy(A()))  # E: Argument 1 to "g" has incompatible type "A"; expected "B"
g(A.copy(B()))
g(B.copy(B()))

[builtins fixtures/bool.pyi]

[case testSelfTypeReturn]
from typing import TypeVar, Type

R = TypeVar('R')
def _type(self: R) -> Type[R]: pass

T = TypeVar('T', bound='A', covariant=True)
class A:
    def copy(self: T) -> T:
        if B():
            return A()  # E: Incompatible return value type (got "A", expected "T")
        elif A():
            return B()  # E: Incompatible return value type (got "B", expected "T")
        reveal_type(_type(self))  # E: Revealed type is 'Type[T`-1]'
        return reveal_type(_type(self)())  # E: Revealed type is 'T`-1'

class B(A):
    pass

Q = TypeVar('Q', bound='C', covariant=True)
class C:
    def __init__(self, a: int) -> None: pass

    def copy(self: Q) -> Q:
        if self:
            return reveal_type(_type(self)(1))  # E: Revealed type is 'Q`-1'
        else:
            return _type(self)()  # E: Too few arguments for "C"


[builtins fixtures/bool.pyi]

[case testSelfTypeClass]
from typing import TypeVar, Type

T = TypeVar('T', bound='A')

class A:
    @classmethod
    def new(cls: Type[T]) -> T:
        return reveal_type(cls())  # E: Revealed type is 'T`-1'

class B(A):
    pass

Q = TypeVar('Q', bound='C', covariant=True)
class C:
    def __init__(self, a: int) -> None: pass

    @classmethod
    def new(cls: Type[Q]) -> Q:
        if cls:
            return cls(1)
        else:
            return cls()  # E: Too few arguments for "C"


reveal_type(A.new)  # E: Revealed type is 'def () -> __main__.A*'
reveal_type(B.new)  # E: Revealed type is 'def () -> __main__.B*'
reveal_type(A.new())  # E: Revealed type is '__main__.A*'
reveal_type(B.new())  # E: Revealed type is '__main__.B*'

[builtins fixtures/classmethod.pyi]

[case testSelfTypeOverride]
from typing import TypeVar, cast

T = TypeVar('T', bound='A', covariant=True)

class A:
    def copy(self: T) -> T: pass

class B(A):
    pass

Q = TypeVar('Q', bound='C', covariant=True)
class C(A):
    def copy(self: Q) -> Q: pass

reveal_type(C().copy)  # E: Revealed type is 'def () -> __main__.C*'
reveal_type(C().copy())  # E: Revealed type is '__main__.C*'
reveal_type(cast(A, C()).copy)  # E: Revealed type is 'def () -> __main__.A*'
reveal_type(cast(A, C()).copy())  # E: Revealed type is '__main__.A*'

[builtins fixtures/bool.pyi]

[case testSelfTypeSuper]
from typing import TypeVar, cast

T = TypeVar('T', bound='A', covariant=True)

class A:
    def copy(self: T) -> T: pass

Q = TypeVar('Q', bound='B', covariant=True)
class B(A):
    def copy(self: Q) -> Q:
        reveal_type(self)  # E: Revealed type is 'Q`-1'
        reveal_type(super().copy)  # E: Revealed type is 'def () -> Q`-1'
        return super().copy()

[builtins fixtures/bool.pyi]

[case testSelfTypeRecursiveBinding]
from typing import TypeVar, Callable, Type

T = TypeVar('T', bound='A', covariant=True)
class A:
    # TODO: This is potentially unsafe, as we use T in an argument type
    def copy(self: T, factory: Callable[[T], T]) -> T:
        return factory(self)

    @classmethod
    def new(cls: Type[T], factory: Callable[[T], T]) -> T:
        reveal_type(cls)   # E: Revealed type is 'Type[T`-1]'
        reveal_type(cls())   # E: Revealed type is 'T`-1'
        cls(2)  # E: Too many arguments for "A"
        return cls()

class B(A):
    pass

reveal_type(A().copy)  # E: Revealed type is 'def (factory: def (__main__.A*) -> __main__.A*) -> __main__.A*'
reveal_type(B().copy)  # E: Revealed type is 'def (factory: def (__main__.B*) -> __main__.B*) -> __main__.B*'
reveal_type(A.new)  # E: Revealed type is 'def (factory: def (__main__.A*) -> __main__.A*) -> __main__.A*'
reveal_type(B.new)  # E: Revealed type is 'def (factory: def (__main__.B*) -> __main__.B*) -> __main__.B*'

[builtins fixtures/classmethod.pyi]

[case testSelfTypeBound]
from typing import TypeVar, Callable, cast

TA = TypeVar('TA', bound='A', covariant=True)

class A:
    def copy(self: TA) -> TA:
        pass

class C(A):
    def copy(self: C) -> C:
        pass

class D(A):
   def copy(self: A) -> A:  # E: Return type of "copy" incompatible with supertype "A"
       pass

TB = TypeVar('TB', bound='B', covariant=True)
class B(A):
    x = 1
    def copy(self: TB) -> TB:
        reveal_type(self.x)  # E: Revealed type is 'builtins.int'
        return cast(TB, None)

[builtins fixtures/bool.pyi]

-- # TODO: fail for this
-- [case testSelfTypeBare]
-- from typing import TypeVar, Type
--
-- T = TypeVar('T', bound='E')
--
-- class E:
--     def copy(self: T, other: T) -> T: pass

[case testSelfTypeClone]
from typing import TypeVar, Type
T = TypeVar('T', bound='C')

class C:
    def copy(self: T) -> T:
        return self

    @classmethod
    def new(cls: Type[T]) -> T:
        return cls()

class D(C): pass

reveal_type(D.new)  # E: Revealed type is 'def () -> __main__.D*'
reveal_type(D().new)  # E: Revealed type is 'def () -> __main__.D*'
reveal_type(D.new())  # E: Revealed type is '__main__.D*'
reveal_type(D().new())  # E: Revealed type is '__main__.D*'

Q = TypeVar('Q', bound=C)

def clone(arg: Q) -> Q:
    reveal_type(arg.copy)  # E: Revealed type is 'def () -> Q`-1'
    reveal_type(arg.copy())  # E: Revealed type is 'Q`-1'
    reveal_type(arg.new)  # E: Revealed type is 'def () -> Q`-1'
    reveal_type(arg.new())  # E: Revealed type is 'Q`-1'
    return arg.copy()

def make(cls: Type[Q]) -> Q:
    reveal_type(cls.new)  # E: Revealed type is 'def () -> Q`-1'
    reveal_type(cls().new)  # E: Revealed type is 'def () -> Q`-1'
    reveal_type(cls().new())  # E: Revealed type is 'Q`-1'
    return cls.new()

[builtins fixtures/classmethod.pyi]

[case testSelfTypeGeneric]
from typing import TypeVar

T = TypeVar('T', int, str)

class A:
    pass

class B(A):
    def __init__(self, arg: T) -> None:
        super(B, self).__init__()

[case testSelfTypeNonsensical]
from typing import TypeVar, Type

T = TypeVar('T', bound=str)
class A:
    def foo(self: T) -> T:   # E: The erased type of self 'builtins.str' is not a supertype of its class '__main__.A'
        return self

    @classmethod
    def cfoo(cls: Type[T]) -> T:  # E: The erased type of self 'Type[builtins.str]' is not a supertype of its class 'Type[__main__.A]'
        return cls()

Q = TypeVar('Q', bound='B')
class B:
    def foo(self: Q) -> Q:
        return self

    @classmethod
    def cfoo(cls: Type[Q]) -> Q:
        return cls()

class C:
    def foo(self: C) -> C: return self

    @classmethod
    def cfoo(cls: Type[C]) -> C:
        return cls()

class D:
    def foo(self: Q) -> Q:  # E: The erased type of self '__main__.B' is not a supertype of its class '__main__.D'
        return self

    @staticmethod
    def bar(self: str) -> str:
        return self

    @classmethod
    def cfoo(cls: Type[Q]) -> Q:  # E: The erased type of self 'Type[__main__.B]' is not a supertype of its class 'Type[__main__.D]'
        return cls()

[builtins fixtures/classmethod.pyi]

[case testSelfTypeLambdaDefault]
from typing import Callable
class C:
    @classmethod
    def foo(cls,
            arg: Callable[[int], str] = lambda a: ''
            ) -> None:
        pass

    def bar(self,
            arg: Callable[[int], str] = lambda a: ''
            ) -> None:
        pass
[builtins fixtures/classmethod.pyi]

[case testSelfTypeNew]
from typing import TypeVar, Type

T = TypeVar('T', bound=A)
class A:
    def __new__(cls: Type[T]) -> T:
        return cls()

    def __init_subclass__(cls: Type[T]) -> None:
        pass

class B:
    def __new__(cls: Type[T]) -> T:  # E: The erased type of self 'Type[__main__.A]' is not a supertype of its class 'Type[__main__.B]'
        return cls()

    def __init_subclass__(cls: Type[T]) -> None:  # E: The erased type of self 'Type[__main__.A]' is not a supertype of its class 'Type[__main__.B]'
        pass

class C:
    def __new__(cls: Type[C]) -> C:
        return cls()

    def __init_subclass__(cls: Type[C]) -> None:
        pass

class D:
    def __new__(cls: D) -> D:  # E: The erased type of self '__main__.D' is not a supertype of its class 'Type[__main__.D]'
        return cls

    def __init_subclass__(cls: D) -> None:  # E: The erased type of self '__main__.D' is not a supertype of its class 'Type[__main__.D]'
        pass

class E:
    def __new__(cls) -> E:
        reveal_type(cls)  # E: Revealed type is 'def () -> __main__.E'
        return cls()

    def __init_subclass__(cls) -> None:
        reveal_type(cls)  # E: Revealed type is 'def () -> __main__.E'

[case testSelfTypePropertyUnion]
from typing import Union
class A:
    @property
    def f(self: A) -> int: pass

class B:
    @property
    def f(self: B) -> int: pass
x: Union[A, B]
reveal_type(x.f)  # E: Revealed type is 'builtins.int'

[builtins fixtures/property.pyi]

[case testSelfTypeProperSupertypeAttribute]
from typing import Callable, TypeVar
class K: pass
T = TypeVar('T', bound=K)
class A(K):
    @property
    def g(self: K) -> int: return 0
    @property
    def gt(self: T) -> T: return self
    f: Callable[[object], int]
    ft: Callable[[T], T]

class B(A):
    pass

reveal_type(A().g)  # E: Revealed type is 'builtins.int'
reveal_type(A().gt)  # E: Revealed type is '__main__.A*'
reveal_type(A().f())  # E: Revealed type is 'builtins.int'
reveal_type(A().ft())  # E: Revealed type is '__main__.A*'
reveal_type(B().g)  # E: Revealed type is 'builtins.int'
reveal_type(B().gt)  # E: Revealed type is '__main__.B*'
reveal_type(B().f())  # E: Revealed type is 'builtins.int'
reveal_type(B().ft())  # E: Revealed type is '__main__.B*'

[builtins fixtures/property.pyi]

[case testSelfTypeProperSupertypeAttributeTuple]
from typing import Callable, TypeVar, Tuple
T = TypeVar('T')
class A(Tuple[int, int]):
    @property
    def g(self: object) -> int: return 0
    @property
    def gt(self: T) -> T: return self
    f: Callable[[object], int]
    ft: Callable[[T], T]

class B(A):
    pass

reveal_type(A().g)  # E: Revealed type is 'builtins.int'
reveal_type(A().gt)  # E: Revealed type is 'Tuple[builtins.int, builtins.int, fallback=__main__.A]'
reveal_type(A().f())  # E: Revealed type is 'builtins.int'
reveal_type(A().ft())  # E: Revealed type is 'Tuple[builtins.int, builtins.int, fallback=__main__.A]'
reveal_type(B().g)  # E: Revealed type is 'builtins.int'
reveal_type(B().gt)  # E: Revealed type is 'Tuple[builtins.int, builtins.int, fallback=__main__.B]'
reveal_type(B().f())  # E: Revealed type is 'builtins.int'
reveal_type(B().ft())  # E: Revealed type is 'Tuple[builtins.int, builtins.int, fallback=__main__.B]'

[builtins fixtures/property.pyi]

[case testSelfTypeProperSupertypeAttributeMeta]
from typing import Callable, TypeVar, Type
T = TypeVar('T')
class A(type):
    @property
    def g(cls: object) -> int: return 0
    @property
    def gt(cls: T) -> T: return cls
    f: Callable[[object], int]
    ft: Callable[[T], T]

class B(A):
    pass

class X(metaclass=B):
    def __init__(self, x: int) -> None: pass
class Y(X): pass
X1: Type[X]
reveal_type(X.g)  # E: Revealed type is 'builtins.int'
reveal_type(X.gt)  # E: Revealed type is 'def (x: builtins.int) -> __main__.X'
reveal_type(X.f())  # E: Revealed type is 'builtins.int'
reveal_type(X.ft())  # E: Revealed type is 'def (x: builtins.int) -> __main__.X'
reveal_type(Y.g)  # E: Revealed type is 'builtins.int'
reveal_type(Y.gt)  # E: Revealed type is 'def (x: builtins.int) -> __main__.Y'
reveal_type(Y.f())  # E: Revealed type is 'builtins.int'
reveal_type(Y.ft())  # E: Revealed type is 'def (x: builtins.int) -> __main__.Y'
reveal_type(X1.g)  # E: Revealed type is 'builtins.int'
reveal_type(X1.gt)  # E: Revealed type is 'Type[__main__.X]'
reveal_type(X1.f())  # E: Revealed type is 'builtins.int'
reveal_type(X1.ft())  # E: Revealed type is 'Type[__main__.X]'

[builtins fixtures/property.pyi]

[case testSelfTypeProperSupertypeAttributeGeneric]
from typing import Callable, TypeVar, Generic
Q = TypeVar('Q', covariant=True)
class K(Generic[Q]):
    q: Q
T = TypeVar('T')
class A(K[Q]):
    @property
    def g(self: K[object]) -> int: return 0
    @property
    def gt(self: K[T]) -> T: return self.q
    f: Callable[[object], int]
    ft: Callable[[T], T]

class B(A[Q]):
    pass
a: A[int]
b: B[str]
reveal_type(a.g)  # E: Revealed type is 'builtins.int'
--reveal_type(a.gt)  # E: Revealed type is 'builtins.int'
reveal_type(a.f())  # E: Revealed type is 'builtins.int'
reveal_type(a.ft())  # E: Revealed type is '__main__.A*[builtins.int]'
reveal_type(b.g)  # E: Revealed type is 'builtins.int'
--reveal_type(b.gt)  # E: Revealed type is '__main__.B*[builtins.str]'
reveal_type(b.f())  # E: Revealed type is 'builtins.int'
reveal_type(b.ft())  # E: Revealed type is '__main__.B*[builtins.str]'

[builtins fixtures/property.pyi]

[case testSelfTypeNotSelfType]
# Friendlier error messages for common mistakes. See #2950
class A:
    def f(x: int) -> None: ...
    # def g(self: None) -> None: ... see in check-python2.test
[out]
main:3: error: Self argument missing for a non-static method (or an invalid type for self)

[case testUnionPropertyField]
from typing import Union

class A:
    x: int

class B:
    @property
    def x(self) -> int: return 1

class C:
    @property
    def x(self) -> int: return 1

ab: Union[A, B, C]
reveal_type(ab.x)  # E: Revealed type is 'builtins.int'
[builtins fixtures/property.pyi]
