diff --git a/mypy/checkmember.py b/mypy/checkmember.py index eb731d5996a8..fbdc313cff9d 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -467,8 +467,12 @@ def analyze_class_attribute_access(itype: Instance, return builtin_type('types.ModuleType') if is_decorated: - # TODO: Return type of decorated function. This is quick hack to work around #998. - return AnyType(TypeOfAny.special_form) + assert isinstance(node.node, Decorator) + if node.node.type: + return node.node.type + else: + not_ready_callback(name, context) + return AnyType(TypeOfAny.from_error) else: return function_type(cast(FuncBase, node.node), builtin_type('builtins.function')) diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test index 3bcdf2d6d276..eb43404d81a7 100644 --- a/test-data/unit/check-inference.test +++ b/test-data/unit/check-inference.test @@ -1786,6 +1786,31 @@ y = 0 tmp/m.py:2: error: "int" not callable main:3: error: "int" not callable +[case testForwardReferenceToDecoratedClassMethod] +from typing import TypeVar, Callable + +T = TypeVar('T') +def dec() -> Callable[[T], T]: pass + +A.g # E: Cannot determine type of 'g' + +class A: + @classmethod + def f(cls) -> None: + reveal_type(cls.g) # E: Revealed type is 'def (x: builtins.str)' + + @classmethod + @dec() + def g(cls, x: str) -> None: + pass + + @classmethod + def h(cls) -> None: + reveal_type(cls.g) # E: Revealed type is 'def (x: builtins.str)' + +reveal_type(A.g) # E: Revealed type is 'def (x: builtins.str)' +[builtins fixtures/classmethod.pyi] + -- Tests for special cases of unification -- --------------------------------------