Repository: python/mypy

Issue:
Support bare Callable types
```
from typing import Iterable, TypeVar, Callable, Iterator, Generic

T = TypeVar("T")

def gen(f: Callable, *args) -> Callable[[], Iterator[T]]:
    return lambda: f(*args)
```

Related question: is it currently possible to type argument `f: Callable[..., Iterator[T]]`? 



Discussion:
Hmm, I don't think that PEP 484 says that `Callable` is a valid type, but mypy shouldn't crash when you try to use it. It should give an error.

Answer to the question: not yet, but it will become possible: https://github.com/JukkaL/mypy/issues/393

PEP 484 actually supports using `Callable` as a type, so mypy should support as well.

`Callable` should be equivalent to `Callable[..., Any]`.


Resolving patch:
diff --git a/mypy/typeanal.py b/mypy/typeanal.py
--- a/mypy/typeanal.py
+++ b/mypy/typeanal.py
@@ -208,30 +208,35 @@ def visit_ellipsis_type(self, t: EllipsisType) -> Type:
         return AnyType()
 
     def analyze_callable_type(self, t: UnboundType) -> Type:
-        if len(t.args) != 2:
-            self.fail('Invalid function type', t)
-            return AnyType()
-        ret_type = t.args[1].accept(self)
         fallback = self.builtin_type('builtins.function')
-        if isinstance(t.args[0], TypeList):
-            # Callable[[ARG, ...], RET] (ordinary callable type)
-            args = t.args[0].items
-            return CallableType(self.anal_array(args),
-                                [nodes.ARG_POS] * len(args),
-                                [None] * len(args),
-                                ret_type=ret_type,
-                                fallback=fallback)
-        elif isinstance(t.args[0], EllipsisType):
-            # Callable[..., RET] (with literal ellipsis; accept arbitrary arguments)
+        if len(t.args) == 0:
+            # Callable (bare)
             return CallableType([AnyType(), AnyType()],
                                 [nodes.ARG_STAR, nodes.ARG_STAR2],
                                 [None, None],
-                                ret_type=ret_type,
-                                fallback=fallback,
-                                is_ellipsis_args=True)
-        else:
-            self.fail('Invalid function type', t)
-            return AnyType()
+                                ret_type=AnyType(),
+                                fallback=fallback)
+        elif len(t.args) == 2:
+            ret_type = t.args[1].accept(self)
+            if isinstance(t.args[0], TypeList):
+                # Callable[[ARG, ...], RET] (ordinary callable type)
+                args = t.args[0].items
+                return CallableType(self.anal_array(args),
+                                    [nodes.ARG_POS] * len(args),
+                                    [None] * len(args),
+                                    ret_type=ret_type,
+                                    fallback=fallback)
+            elif isinstance(t.args[0], EllipsisType):
+                # Callable[..., RET] (with literal ellipsis; accept arbitrary arguments)
+                return CallableType([AnyType(), AnyType()],
+                                    [nodes.ARG_STAR, nodes.ARG_STAR2],
+                                    [None, None],
+                                    ret_type=ret_type,
+                                    fallback=fallback,
+                                    is_ellipsis_args=True)
+
+        self.fail('Invalid function type', t)
+        return AnyType()
 
     def anal_array(self, a: List[Type]) -> List[Type]:
         res = []  # type: List[Type]


Test patch:
diff --git a/mypy/test/data/check-functions.test b/mypy/test/data/check-functions.test
--- a/mypy/test/data/check-functions.test
+++ b/mypy/test/data/check-functions.test
@@ -1360,3 +1360,10 @@ for _ in [1]:
     def f(): pass
 f()
 [builtins fixtures/list.py]
+
+[case testBareCallable]
+from typing import Callable, Any
+
+def foo(f: Callable) -> bool:
+    return f()
+[builtins fixtures/bool.py]