Repository: python/mypy

Issue:
mypy does not recognize that result of type() is callable
mypy does not recognize that the result of e.g. `type(1)` is callable. This leads to the following code to fail type checking, even though it is correct:

```
import argparse

parser =  argparse.ArgumentParser()

# No error from this
parser.add_argument('--test1', type=int)

# Does not typecheck: Argument 2 to "add_argument" of "ArgumentParser" has incompatible type Type[int]; expected "Union[Callable[[str], None], FileType]"
parser.add_argument('--test2', type=type(1))

print(type(1) == int) # Yet they are the same

print(parser.parse_args()) # Both produce identical results (argument is read as an integer)
```


Discussion:
Here is a simple repro:
```python
from typing  import Type, Callable

x: Callable[..., int]
y: Type[int]

y = x # error: Incompatible types in assignment (expression has type Callable[..., int], variable has type Type[int])
x = y # error: Incompatible types in assignment (expression has type Type[int], variable has type Callable[..., int])
```
(Note, ``type(1)`` is inferred as ``Type[int]``)
I think this should be quite easy to fix by simply adding a corresponding case in ``subtypes.py``
Alternatively, we could make ``type`` return callable type generated by ``type_object_type``.
Changes to subtyping don't fully fix this. There is another problem:

```python
from typing import Callable, TypeVar
T = TypeVar('T')
def f(x: Callable[..., T], y: T = None) -> None: return None
class A: pass
x: Type[A]
f(x)  # E: Argument 1 to "f" has incompatible type Type[A]; expected Callable[..., None]
y: A
f(x, y)  # OK
```
(with strict-optional `None` is substituted with `<uninhabited>`)

I'd like to tackle this.

edit:
Another repro

```python
from typing import Callable, Type
def f(x: Callable[..., T]) -> T: return x()
class A: pass
x: Type[A]
f(x)  # E: Argument 1 to "f" has incompatible type Type[A]; expected Callable[..., None]
```

Both examples pass with `Type[Any]`.

Resolving patch:
diff --git a/mypy/constraints.py b/mypy/constraints.py
--- a/mypy/constraints.py
+++ b/mypy/constraints.py
@@ -362,6 +362,8 @@ def visit_callable_type(self, template: CallableType) -> List[Constraint]:
             return res
         elif isinstance(self.actual, Overloaded):
             return self.infer_against_overloaded(self.actual, template)
+        elif isinstance(self.actual, TypeType):
+            return infer_constraints(template.ret_type, self.actual.item, self.direction)
         else:
             return []
 
@@ -423,9 +425,9 @@ def visit_overloaded(self, template: Overloaded) -> List[Constraint]:
         return res
 
     def visit_type_type(self, template: TypeType) -> List[Constraint]:
-        if isinstance(self.actual, CallableType) and self.actual.is_type_obj():
+        if isinstance(self.actual, CallableType):
             return infer_constraints(template.item, self.actual.ret_type, self.direction)
-        elif isinstance(self.actual, Overloaded) and self.actual.is_type_obj():
+        elif isinstance(self.actual, Overloaded):
             return infer_constraints(template.item, self.actual.items()[0].ret_type,
                                      self.direction)
         elif isinstance(self.actual, TypeType):


Test patch:
diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test
--- a/test-data/unit/check-inference.test
+++ b/test-data/unit/check-inference.test
@@ -664,6 +664,14 @@ lb = [b]
 l = lb # E: Incompatible types in assignment (expression has type List[bool], variable has type List[A])
 [builtins fixtures/for.pyi]
 
+[case testGenericFunctionWithTypeTypeAsCallable]
+from typing import Callable, Type, TypeVar
+T = TypeVar('T')
+def f(x: Callable[..., T]) -> T: return x()
+class A: pass
+x = None  # type: Type[A]
+y = f(x)
+reveal_type(y)  # E: Revealed type is '__main__.A*'
 
 -- Generic function inference with unions
 -- --------------------------------------