# Buggy code
def visit_func_def(self, defn: FuncDef) -> None:
    phase_info = self.postpone_nested_functions_stack[-1]
    if phase_info != FUNCTION_SECOND_PHASE:
        self.function_stack.append(defn)
        # First phase of analysis for function.
        self.errors.push_function(defn.name())
        if defn.type:
            assert isinstance(defn.type, CallableType)
            self.update_function_type_variables(defn.type, defn)
        self.errors.pop_function()
        self.function_stack.pop()

        defn.is_conditional = self.block_depth[-1] > 0

        # TODO(jukka): Figure out how to share the various cases. It doesn't
        #   make sense to have (almost) duplicate code (here and elsewhere) for
        #   3 cases: module-level, class-level and local names. Maybe implement
        #   a common stack of namespaces. As the 3 kinds of namespaces have
        #   different semantics, this wouldn't always work, but it might still
        #   be a win.
        if self.is_class_scope():
            # Method definition
            defn.info = self.type
            if not defn.is_decorated and not defn.is_overload:
                if (
                    defn.name() in self.type.names
                    and self.type.names[defn.name()].node != defn
                ):
                    # Redefinition. Conditional redefinition is okay.
                    n = self.type.names[defn.name()].node
                    if not self.set_original_def(n, defn):
                        self.name_already_defined(defn.name(), defn)
                self.type.names[defn.name()] = SymbolTableNode(MDEF, defn)
            self.prepare_method_signature(defn)
        elif self.is_func_scope():
            # Nested function
            if not defn.is_decorated and not defn.is_overload:
                if defn.name() in self.locals[-1]:
                    # Redefinition. Conditional redefinition is okay.
                    n = self.locals[-1][defn.name()].node
                    if not self.set_original_def(n, defn):
                        self.name_already_defined(defn.name(), defn)
                else:
                    self.add_local(defn, defn)
        else:
            # Top-level function
            if not defn.is_decorated and not defn.is_overload:
                symbol = self.globals.get(defn.name())
                if isinstance(symbol.node, FuncDef) and symbol.node != defn:
                    # This is redefinition. Conditional redefinition is okay.
                    if not self.set_original_def(symbol.node, defn):
                        # Report error.
                        self.check_no_global(defn.name(), defn, True)
        if phase_info == FUNCTION_FIRST_PHASE_POSTPONE_SECOND:
            # Postpone this function (for the second phase).
            self.postponed_functions_stack[-1].append(defn)
            return
    if phase_info != FUNCTION_FIRST_PHASE_POSTPONE_SECOND:
        # Second phase of analysis for function.
        self.errors.push_function(defn.name())
        self.analyze_function(defn)
        if defn.is_coroutine and isinstance(defn.type, CallableType):
            if defn.is_async_generator:
                # Async generator types are handled elsewhere
                pass
            else:
                # A coroutine defined as `async def foo(...) -> T: ...`
                # has external return type `Awaitable[T]`.
                defn.type = defn.type.copy_modified(
                    ret_type=self.named_type_or_none(
                        "typing.Awaitable", [defn.type.ret_type]
                    )
                )
        self.errors.pop_function()


# Traceback (KeyError)
(e2e) Adam@Adams-MacBook-Pro ~/Desktop> mypy example.py --show-traceback
example.py:2: error: Unexpected keyword argument "example" for "Popen"
example.py:2: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.511
Traceback (most recent call last):
File "/Users/Adam/.virtualenvs/e2e/bin/mypy", line 6, in <module>
main(__file__)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/main.py", line 46, in main
res = type_check_only(sources, bin_dir, options)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/main.py", line 93, in type_check_only
options=options)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/build.py", line 188, in build
graph = dispatch(sources, manager)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/build.py", line 1595, in dispatch
process_graph(graph, manager)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/build.py", line 1838, in process_graph
process_stale_scc(graph, scc, manager)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/build.py", line 1937, in process_stale_scc
graph[id].type_check_first_pass()
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/build.py", line 1510, in type_check_first_pass
self.type_checker.check_first_pass()
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/checker.py", line 177, in check_first_pass
self.accept(d)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/checker.py", line 264, in accept
stmt.accept(self)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/nodes.py", line 825, in accept
return visitor.visit_expression_stmt(self)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/checker.py", line 1823, in visit_expression_stmt
self.expr_checker.accept(s.expr, allow_none_return=True)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/checkexpr.py", line 2054, in accept
typ = self.visit_call_expr(node, allow_none_return=True)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/checkexpr.py", line 201, in visit_call_expr
ret_type = self.check_call_expr_with_callee_type(callee_type, e)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/checkexpr.py", line 341, in check_call_expr_with_callee_type
e.arg_names, callable_node=e.callee)[0]
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/checkexpr.py", line 396, in check_call
arg_names, formal_to_actual, context, self.msg)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/checkexpr.py", line 759, in check_argument_count
callee, actual_names[i], context)
File "/Users/Adam/.virtualenvs/e2e/lib/python3.6/site-packages/mypy/messages.py", line 619, in unexpected_keyword_argument
path = self.modules[module_name].path
KeyError: 'subprocess.Popen'
example.py:2: note: use --pdb to drop into pdb

# Fixed code
def visit_func_def(self, defn: FuncDef) -> None:
    phase_info = self.postpone_nested_functions_stack[-1]
    if phase_info != FUNCTION_SECOND_PHASE:
        self.function_stack.append(defn)
        # First phase of analysis for function.
        self.errors.push_function(defn.name())
        if not defn._fullname:
            defn._fullname = self.qualified_name(defn.name())
        if defn.type:
            assert isinstance(defn.type, CallableType)
            self.update_function_type_variables(defn.type, defn)
        self.errors.pop_function()
        self.function_stack.pop()

        defn.is_conditional = self.block_depth[-1] > 0

        # TODO(jukka): Figure out how to share the various cases. It doesn't
        #   make sense to have (almost) duplicate code (here and elsewhere) for
        #   3 cases: module-level, class-level and local names. Maybe implement
        #   a common stack of namespaces. As the 3 kinds of namespaces have
        #   different semantics, this wouldn't always work, but it might still
        #   be a win.
        if self.is_class_scope():
            # Method definition
            defn.info = self.type
            if not defn.is_decorated and not defn.is_overload:
                if (
                    defn.name() in self.type.names
                    and self.type.names[defn.name()].node != defn
                ):
                    # Redefinition. Conditional redefinition is okay.
                    n = self.type.names[defn.name()].node
                    if not self.set_original_def(n, defn):
                        self.name_already_defined(defn.name(), defn)
                self.type.names[defn.name()] = SymbolTableNode(MDEF, defn)
            self.prepare_method_signature(defn)
        elif self.is_func_scope():
            # Nested function
            if not defn.is_decorated and not defn.is_overload:
                if defn.name() in self.locals[-1]:
                    # Redefinition. Conditional redefinition is okay.
                    n = self.locals[-1][defn.name()].node
                    if not self.set_original_def(n, defn):
                        self.name_already_defined(defn.name(), defn)
                else:
                    self.add_local(defn, defn)
        else:
            # Top-level function
            if not defn.is_decorated and not defn.is_overload:
                symbol = self.globals.get(defn.name())
                if isinstance(symbol.node, FuncDef) and symbol.node != defn:
                    # This is redefinition. Conditional redefinition is okay.
                    if not self.set_original_def(symbol.node, defn):
                        # Report error.
                        self.check_no_global(defn.name(), defn, True)
        if phase_info == FUNCTION_FIRST_PHASE_POSTPONE_SECOND:
            # Postpone this function (for the second phase).
            self.postponed_functions_stack[-1].append(defn)
            return
    if phase_info != FUNCTION_FIRST_PHASE_POSTPONE_SECOND:
        # Second phase of analysis for function.
        self.errors.push_function(defn.name())
        self.analyze_function(defn)
        if defn.is_coroutine and isinstance(defn.type, CallableType):
            if defn.is_async_generator:
                # Async generator types are handled elsewhere
                pass
            else:
                # A coroutine defined as `async def foo(...) -> T: ...`
                # has external return type `Awaitable[T]`.
                defn.type = defn.type.copy_modified(
                    ret_type=self.named_type_or_none(
                        "typing.Awaitable", [defn.type.ret_type]
                    )
                )
        self.errors.pop_function()