Repository: python/mypy

Issue:
Two crashes in fine grained mode with invalid types inside synthetic constructs
First traceback:
```
  File "mypy/dmypy_server.py", line 215, in serve
  File "mypy/dmypy_server.py", line 252, in run_command
  File "mypy/dmypy_server.py", line 300, in cmd_check
  File "mypy/dmypy_server.py", line 335, in check
  File "mypy/dmypy_server.py", line 382, in initialize_fine_grained
  File "mypy/server/update.py", line 235, in update
  File "mypy/server/update.py", line 287, in update_one
  File "mypy/server/update.py", line 342, in update_module
  File "mypy/server/update.py", line 549, in update_module_isolated
  File "mypy/server/update.py", line 715, in replace_modules_with_new_variants
  File "mypy/server/astmerge.py", line 88, in merge_asts
  File "mypy/server/astmerge.py", line 133, in replace_nodes_in_ast
  File "mypy/nodes.py", line 257, in accept
  File "mypy/server/astmerge.py", line 151, in visit_mypy_file__NodeVisitor_glue
  File "mypy/server/astmerge.py", line 154, in visit_mypy_file
  File "mypy/traverser.py", line 33, in visit_mypy_file
  File "mypy/nodes.py", line 968, in accept
  File "mypy/server/astmerge.py", line 195, in visit_assignment_stmt__StatementVisitor_glue
  File "mypy/server/astmerge.py", line 197, in visit_assignment_stmt
  File "mypy/traverser.py", line 79, in visit_assignment_stmt
  File "mypy/nodes.py", line 1421, in accept
  File "mypy/server/astmerge.py", line 231, in visit_call_expr__ExpressionVisitor_glue
  File "mypy/server/astmerge.py", line 232, in visit_call_expr
  File "mypy/traverser.py", line 166, in visit_call_expr
  File "mypy/nodes.py", line 2062, in accept
  File "mypy/server/astmerge.py", line 236, in visit_newtype_expr__ExpressionVisitor_glue
  File "mypy/server/astmerge.py", line 239, in visit_newtype_expr
  File "mypy/server/astmerge.py", line 318, in process_synthetic_type_info
  File "mypy/nodes.py", line 610, in accept__Node_glue
  File "mypy/nodes.py", line 611, in accept
  File "mypy/server/astmerge.py", line 160, in visit_func_def__StatementVisitor_glue
  File "mypy/server/astmerge.py", line 162, in visit_func_def
  File "mypy/server/astmerge.py", line 188, in process_base_func
  File "mypy/server/astmerge.py", line 292, in fixup_type
  File "mypy/types.py", line 838, in accept
  File "mypy/server/astmerge.py", line 346, in visit_callable_type__TypeVisitor_glue
  File "mypy/server/astmerge.py", line 348, in visit_callable_type
  File "mypy/types.py", line 541, in accept
  File "mypy/server/astmerge.py", line 335, in visit_instance__TypeVisitor_glue
  File "mypy/server/astmerge.py", line 338, in visit_instance
  File "mypy/types.py", line 1409, in accept
  File "mypy/server/astmerge.py", line 417, in visit_union_type__TypeVisitor_glue
  File "mypy/server/astmerge.py", line 419, in visit_union_type
  File "mypy/types.py", line 541, in accept
  File "mypy/server/astmerge.py", line 335, in visit_instance__TypeVisitor_glue
  File "mypy/server/astmerge.py", line 338, in visit_instance
  File "mypy/types.py", line 1597, in accept
  File "mypy/type_visitor.py", line 105, in visit_forwardref_type
RuntimeError: Internal error: unresolved forward reference
```
Second traceback:
```
File "mypy/dmypy_server.py", line 205, in serve
File "mypy/dmypy_server.py", line 242, in run_command
File "mypy/dmypy_server.py", line 290, in cmd_check
File "mypy/dmypy_server.py", line 325, in check
File "mypy/dmypy_server.py", line 372, in initialize_fine_grained
File "mypy/server/update.py", line 254, in update
File "mypy/server/update.py", line 767, in propagate_changes_using_dependencies
File "mypy/server/update.py", line 927, in reprocess_nodes
File "mypy/server/astdiff.py", line 154, in snapshot_symbol_table
File "mypy/server/astdiff.py", line 237, in snapshot_optional_type
File "mypy/server/astdiff.py", line 232, in snapshot_type
File "mypy/types.py", line 1409, in accept
File "mypy/server/astdiff.py", line 321, in visit_union_type__TypeVisitor_glue
File "mypy/server/astdiff.py", line 324, in visit_union_type
File "mypy/server/astdiff.py", line 232, in snapshot_type
File "mypy/types.py", line 1597, in accept
File "mypy/type_visitor.py", line 105, in visit_forwardref_type
RuntimeError: Internal error: unresolved forward reference
```


Discussion:
Also there is something about mypyc tracebacks: why `xxx__ClassName_glue` has line number of `xxx` _minus two_ (or one, or three)?
Note: this error will be likely fixed by the upcoming semantic analyzer refactoring.
OK, here is a simple possible repro:
```
[case testNamedTupleForwardFunction]
from typing import NamedTuple
from a import A

NT = NamedTuple('NT', [('x', A)])
[file a.py]
from b import B
A = B
[file b.py.2]
def func(x): pass
B = func
[out]
```
I am not sure what is the crux, but most likely using alias to a function as a field type in named tuple is problematic. It crashes instead of giving an `Invalid type`-like error.
A repro for the second crash (very similar):
```
[case testAliasForwardFunction]
from typing import Optional
from a import A

Alias = Optional[A]
[file a.py]
from b import B
A = B
[file b.py.2]
def func(x): pass
B = func
[out]
```

Resolving patch:
diff --git a/mypy/semanal_pass3.py b/mypy/semanal_pass3.py
--- a/mypy/semanal_pass3.py
+++ b/mypy/semanal_pass3.py
@@ -133,6 +133,7 @@ def refresh_top_level(self, file_node: MypyFile) -> None:
         """Reanalyze a stale module top-level in fine-grained incremental mode."""
         for d in file_node.defs:
             self.accept(d)
+        self.analyze_symbol_table(file_node.names)
 
     def accept(self, node: Node) -> None:
         try:


Test patch:
diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test
--- a/test-data/unit/fine-grained.test
+++ b/test-data/unit/fine-grained.test
@@ -8134,3 +8134,32 @@ x = 'no way'
 ==
 ==
 main:10: error: Incompatible types in assignment (expression has type "str", variable has type "int")
+
+[case testAliasForwardFunctionDirect]
+# flags: --ignore-missing-imports
+from typing import Optional
+from b import B
+
+Alias = Optional[B]
+[file b.py.2]
+def func(x): pass
+B = int()
+[out]
+==
+main:5: error: Invalid type "b.B"
+
+[case testAliasForwardFunctionIndirect]
+# flags: --ignore-missing-imports
+from typing import Optional
+from a import A
+
+Alias = Optional[A]
+[file a.py]
+from b import B
+A = B
+[file b.py.2]
+def func(x): pass
+B = func
+[out]
+==
+main:5: error: Invalid type "a.A"