diff --git a/mypy/checkmember.py b/mypy/checkmember.py index cc0be2058fbf..af8e51ba4601 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -12,7 +12,7 @@ from mypy.messages import MessageBuilder from mypy.maptype import map_instance_to_supertype from mypy.expandtype import expand_type_by_instance -from mypy.nodes import method_type, method_type_with_fallback +from mypy.nodes import method_callable, method_type, method_type_with_fallback from mypy.semanal import self_type from mypy import messages from mypy import subtypes @@ -300,6 +300,11 @@ def analyze_class_attribute_access(itype: Instance, t = node.type if t: + if isinstance(node.node, Decorator): + info = node.node.var.info + elif isinstance(node.node, (Var, FuncBase)): + info = node.node.info + t = map_type_from_supertype(t, itype.type, info) if isinstance(t, PartialType): return handle_partial_attribute_type(t, is_lvalue, msg, node.node) is_classmethod = is_decorated and cast(Decorator, node.node).func.is_class @@ -321,18 +326,9 @@ def analyze_class_attribute_access(itype: Instance, def add_class_tvars(t: Type, info: TypeInfo, is_classmethod: bool, builtin_type: Callable[[str], Instance]) -> Type: if isinstance(t, CallableType): - # TODO: Should we propagate type variable values? - vars = [TypeVarDef(n, i + 1, None, builtin_type('builtins.object'), tv.variance) - for (i, n), tv in zip(enumerate(info.type_vars), info.defn.type_vars)] - arg_types = t.arg_types - arg_kinds = t.arg_kinds - arg_names = t.arg_names if is_classmethod: - arg_types = arg_types[1:] - arg_kinds = arg_kinds[1:] - arg_names = arg_names[1:] - return t.copy_modified(arg_types=arg_types, arg_kinds=arg_kinds, arg_names=arg_names, - variables=vars + t.variables) + t = method_callable(t) + return t.copy_modified(variables=info.defn.type_vars + t.variables) elif isinstance(t, Overloaded): return Overloaded([cast(CallableType, add_class_tvars(i, info, is_classmethod, builtin_type)) diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index 142ce38f5667..2b63df8e18b2 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -188,6 +188,71 @@ main:9: error: Incompatible types in assignment (expression has type A[C, B], va main:10: error: Incompatible types in assignment (expression has type A[B, B], variable has type A[B, C]) +[case testClassMethodOfGenericClass] +from typing import TypeVar, Generic +T = TypeVar('T') +U = TypeVar('U') +class X(Generic[T,U]): + def __init__(self, t: T, u: U) -> None: + pass + +class A(Generic[T]): + @classmethod + def f(cls, x: T) -> T: + pass + @classmethod + def g(cls) -> T: + pass +class B(A[X[int, T]], Generic[T]): + pass +class C(B[str]): + pass + +A.f(3)() # E: "int" not callable +B.f(3) # E: Argument 1 to "f" of "A" has incompatible type "int"; expected X[int, None] +B.f(X(3, 4))() # E: X[int, int] not callable +C.f(X(3, 4)) # E: Argument 2 to "X" has incompatible type "int"; expected "str" +C.f(X(3, 'a'))() # E: X[int, str] not callable + +ga = A.g() # E: Need type annotation for variable +gb = B.g() # E: Need type annotation for variable +gc = C.g() +gc() # E: X[int, str] not callable +[builtins fixtures/classmethod.py] + +[case testStaticMethodOfGenericClass] +from typing import TypeVar, Generic +T = TypeVar('T') +U = TypeVar('U') +class X(Generic[T,U]): + def __init__(self, t: T, u: U) -> None: + pass + +class A(Generic[T]): + @staticmethod + def f(x: T) -> T: + pass + @staticmethod + def g() -> T: + pass +class B(A[X[int, T]], Generic[T]): + pass +class C(B[str]): + pass + +A.f(3)() # E: "int" not callable +B.f(3) # E: Argument 1 to "f" of "A" has incompatible type "int"; expected X[int, None] +B.f(X(3, 4))() # E: X[int, int] not callable +C.f(X(3, 4)) # E: Argument 2 to "X" has incompatible type "int"; expected "str" +C.f(X(3, 'a'))() # E: X[int, str] not callable + +ga = A.g() # E: Need type annotation for variable +gb = B.g() # E: Need type annotation for variable +gc = C.g() +gc() # E: X[int, str] not callable +[builtins fixtures/staticmethod.py] + + -- Simple generic type bodies -- --------------------------