Repository: python/mypy

Issue:
AttributeError: 'AnyType' object has no attribute 'type' in try/except/else
``` python
def f(): ...  # just to have something returning Any

def lookup_field(name, obj):
    try:
        pass
    except:
        attr = f()
    else:
        attr = None
```

with `--check-untyped-defs --strict-optional` gives

```
Traceback (most recent call last):
  File "/usr/lib/python-exec/python3.4/mypy", line 6, in <module>
    main(__file__)
  File "/usr/lib64/python3.4/site-packages/mypy/main.py", line 40, in main
    res = type_check_only(sources, bin_dir, options)
  File "/usr/lib64/python3.4/site-packages/mypy/main.py", line 81, in type_check_only
    options=options)
  File "/usr/lib64/python3.4/site-packages/mypy/build.py", line 178, in build
    dispatch(sources, manager)
  File "/usr/lib64/python3.4/site-packages/mypy/build.py", line 1325, in dispatch
    process_graph(graph, manager)
  File "/usr/lib64/python3.4/site-packages/mypy/build.py", line 1468, in process_graph
    process_stale_scc(graph, scc)
  File "/usr/lib64/python3.4/site-packages/mypy/build.py", line 1545, in process_stale_scc
    graph[id].type_check()
  File "/usr/lib64/python3.4/site-packages/mypy/build.py", line 1303, in type_check
    manager.type_checker.visit_file(self.tree, self.xpath)
  File "/usr/lib64/python3.4/site-packages/mypy/checker.py", line 152, in visit_file
    self.accept(d)
  File "/usr/lib64/python3.4/site-packages/mypy/checker.py", line 201, in accept
    typ = node.accept(self)
  File "/usr/lib64/python3.4/site-packages/mypy/nodes.py", line 476, in accept
    return visitor.visit_func_def(self)
  File "/usr/lib64/python3.4/site-packages/mypy/checker.py", line 399, in visit_func_def
    self.check_func_item(defn, name=defn.name())
  File "/usr/lib64/python3.4/site-packages/mypy/checker.py", line 466, in check_func_item
    self.leave_partial_types()
  File "/usr/lib64/python3.4/site-packages/mypy/checker.py", line 2191, in leave_partial_types
    if experiments.STRICT_OPTIONAL and cast(PartialType, var.type).type is None:
AttributeError: 'AnyType' object has no attribute 'type'

*** INTERNAL ERROR ***

/tmp/asd8.py:3: error: Internal error -- please report a bug at https://github.com/python/mypy/issues

NOTE: you can use "mypy --pdb ..." to drop into the debugger when this happens.
```

This is a small repro based on [django:django/contrib/admin/utils.py:276](https://github.com/django/django/blob/master/django/contrib/admin/utils.py#L276).



Discussion:
Thanks for reporting this! Definitely a bug in `--strict-optional`.

It looks like the `cast` is mistaken -- `var.type` is actually an `AnyType`, not a `PartialType`.


Resolving patch:
diff --git a/mypy/checker.py b/mypy/checker.py
--- a/mypy/checker.py
+++ b/mypy/checker.py
@@ -2247,7 +2247,8 @@ def leave_partial_types(self) -> None:
         partial_types = self.partial_types.pop()
         if not self.current_node_deferred:
             for var, context in partial_types.items():
-                if experiments.STRICT_OPTIONAL and cast(PartialType, var.type).type is None:
+                if (experiments.STRICT_OPTIONAL and
+                        isinstance(var.type, PartialType) and var.type.type is None):
                     # None partial type: assume variable is intended to have type None
                     var.type = NoneTyp()
                 else:
diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py
--- a/mypy/checkexpr.py
+++ b/mypy/checkexpr.py
@@ -157,8 +157,10 @@ def try_infer_partial_type(self, e: CallExpr) -> None:
             var = cast(Var, e.callee.expr.node)
             partial_types = self.chk.find_partial_types(var)
             if partial_types is not None and not self.chk.current_node_deferred:
-                partial_type = cast(PartialType, var.type)
-                if partial_type is None or partial_type.type is None:
+                partial_type = var.type
+                if (partial_type is None or
+                        not isinstance(partial_type, PartialType) or
+                        partial_type.type is None):
                     # A partial None type -> can't infer anything.
                     return
                 typename = partial_type.type.fullname()


Test patch:
diff --git a/test-data/unit/check-optional.test b/test-data/unit/check-optional.test
--- a/test-data/unit/check-optional.test
+++ b/test-data/unit/check-optional.test
@@ -315,3 +315,18 @@ x = f  # type: Callable[[], None]
 [case testOptionalCallable]
 from typing import Callable, Optional
 T = Optional[Callable[..., None]]
+
+[case testAnyTypeInPartialTypeList]
+# options: check_untyped_defs
+def f(): ...
+
+def lookup_field(name, obj):
+    try:
+        pass
+    except:
+        attr = f()
+    else:
+        attr = None
+[out]
+main: note: In function "lookup_field":
+main:10: error: Need type annotation for variable