Repository: python/mypy

Issue:
regression: assignment of 'builtins.type' now type-inferred as 'builtins.object'

**Bug Report**

#7963 causes a serious regression

After this commit, the use of `from __future__ import annotations` causes assignments of `builtins.type` to be typed as `builtins.object`, which prevents the assigned variable from being used as a callable later on

This is especially bad because the semantic analyzer is shared and does not maintain the state of `__future__` flags on a per-module basis, therefore *any* file with that import will affect *all* files that are typechecked after it (which makes it hard to pinpoint in a large codebase, given the way the graph is processed...)

**To Reproduce**

Simple reproducer in a single file:

```
from __future__ import annotations
reveal_type(type)
_TYPE = type
reveal_type(_TYPE)
_TYPE('bar')
```

**Expected Behavior**

```
simple.py:2: note: Revealed type is 'Overload(def (o: builtins.object) -> builtins.type, def (name: builtins.str, bases: builtins.tuple[builtins.type], dict: builtins.dict[builtins.str, Any]) -> builtins.type)'
simple.py:4: note: Revealed type is 'Overload(def (o: builtins.object) -> builtins.type, def (name: builtins.str, bases: builtins.tuple[builtins.type], dict: builtins.dict[builtins.str, Any]) -> builtins.type)'
```

**Actual Behavior**

```
simple.py:2: note: Revealed type is 'Overload(def (o: builtins.object) -> builtins.type, def (name: builtins.str, bases: builtins.tuple[builtins.type], dict: builtins.dict[builtins.str, Any]) -> builtins.type)'
simple.py:4: note: Revealed type is 'builtins.object'
simple.py:5: error: "object" not callable
```


**Your Environment**

- Mypy version used: 0.790+dev.720b77e2ded8c46b66647cdde9218769d33aec41 (or any commit thereafter)
- Mypy command-line flags: `--python-version 3.7`
- Mypy configuration options from `mypy.ini` (and other config files): N/A
- Python version used: 3.7
- Operating system and version: macOS 10.14




Discussion:
@TH3CHARLie Can you look into this?

Resolving patch:
diff --git a/mypy/typeanal.py b/mypy/typeanal.py
--- a/mypy/typeanal.py
+++ b/mypy/typeanal.py
@@ -307,8 +307,13 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Opt
         elif (fullname == 'typing.Type' or
              (fullname == 'builtins.type' and self.api.is_future_flag_set('annotations'))):
             if len(t.args) == 0:
-                any_type = self.get_omitted_any(t)
-                return TypeType(any_type, line=t.line, column=t.column)
+                if fullname == 'typing.Type':
+                    any_type = self.get_omitted_any(t)
+                    return TypeType(any_type, line=t.line, column=t.column)
+                else:
+                    # To prevent assignment of 'builtins.type' inferred as 'builtins.object'
+                    # See https://github.com/python/mypy/issues/9476 for more information
+                    return None
             type_str = 'Type[...]' if fullname == 'typing.Type' else 'type[...]'
             if len(t.args) != 1:
                 self.fail(type_str + ' must have exactly one type argument', t)


Test patch:
diff --git a/test-data/unit/check-callable.test b/test-data/unit/check-callable.test
--- a/test-data/unit/check-callable.test
+++ b/test-data/unit/check-callable.test
@@ -473,3 +473,14 @@ else:
     reveal_type(fn) # N: Revealed type is 'None'
 
 [builtins fixtures/callable.pyi]
+
+[case testBuiltinsTypeAsCallable]
+# flags: --python-version 3.7
+from __future__ import annotations
+
+reveal_type(type)  # N: Revealed type is 'def (x: Any) -> builtins.type'
+_TYPE = type
+reveal_type(_TYPE)  # N: Revealed type is 'def (x: Any) -> builtins.type'
+_TYPE('bar')
+
+[builtins fixtures/callable.pyi]