# Buggy code
def visit_decorator(self, dec: Decorator) -> None:
    """Try to infer the type of the decorated function.

    This lets us resolve references to decorated functions during
    type checking when there are cyclic imports, as otherwise the
    type might not be available when we need it.

    This basically uses a simple special-purpose type inference
    engine just for decorators.
    """
    # Don't just call the super method since we don't unconditionally traverse the decorated
    # function.
    dec.var.accept(self)
    for decorator in dec.decorators:
        decorator.accept(self)
    if self.recurse_into_functions:
        dec.func.accept(self)
    if dec.var.is_property:
        # Decorators are expected to have a callable type (it's a little odd).
        if dec.func.type is None:
            dec.var.type = CallableType(
                [AnyType(TypeOfAny.special_form)],
                [ARG_POS],
                [None],
                AnyType(TypeOfAny.special_form),
                self.builtin_type("function"),
                name=dec.var.name(),
            )
        elif isinstance(dec.func.type, CallableType):
            dec.var.type = dec.func.type
        return
    decorator_preserves_type = True
    for expr in dec.decorators:
        preserve_type = False
        if isinstance(expr, RefExpr) and isinstance(expr.node, FuncDef):
            if expr.node.type and is_identity_signature(expr.node.type):
                preserve_type = True
        if not preserve_type:
            decorator_preserves_type = False
            break
    if decorator_preserves_type:
        # No non-identity decorators left. We can trivially infer the type
        # of the function here.
        dec.var.type = function_type(dec.func, self.builtin_type("function"))
    if dec.decorators:
        return_type = calculate_return_type(dec.decorators[0])
        if return_type and isinstance(return_type, AnyType):
            # The outermost decorator will return Any so we know the type of the
            # decorated function.
            dec.var.type = AnyType(TypeOfAny.from_another_any, source_any=return_type)
        sig = find_fixed_callable_return(dec.decorators[0])
        if sig:
            # The outermost decorator always returns the same kind of function,
            # so we know that this is the type of the decoratored function.
            orig_sig = function_type(dec.func, self.builtin_type("function"))
            sig.name = orig_sig.items()[0].name
            dec.var.type = sig


# Traceback (RuntimeError)
$ mypy -p common --show-traceback
/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/aio_pika/patterns/rpc.py:186: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.550
Traceback (most recent call last):
File "/usr/lib64/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib64/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/__main__.py", line 11, in <module>
main(None)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/main.py", line 66, in main
res = type_check_only(sources, bin_dir, options)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/main.py", line 119, in type_check_only
options=options)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/build.py", line 214, in build
graph = dispatch(sources, manager)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/build.py", line 1935, in dispatch
process_graph(graph, manager)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/build.py", line 2199, in process_graph
process_stale_scc(graph, scc, manager)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/build.py", line 2327, in process_stale_scc
graph[id].type_check_first_pass()
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/build.py", line 1836, in type_check_first_pass
self.type_checker.check_first_pass()
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 196, in check_first_pass
self.accept(d)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 283, in accept
stmt.accept(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/nodes.py", line 690, in accept
return visitor.visit_class_def(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 1185, in visit_class_def
self.accept(defn.defs)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 283, in accept
stmt.accept(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/nodes.py", line 750, in accept
return visitor.visit_block(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 1305, in visit_block
self.accept(s)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 283, in accept
stmt.accept(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/nodes.py", line 567, in accept
return visitor.visit_decorator(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 2470, in visit_decorator
self.check_func_item(e.func, name=e.func.name())
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 591, in check_func_item
self.check_func_def(defn, typ, name)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 751, in check_func_def
self.accept(item.body)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 283, in accept
stmt.accept(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/nodes.py", line 750, in accept
return visitor.visit_block(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 1305, in visit_block
self.accept(s)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 283, in accept
stmt.accept(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/nodes.py", line 952, in accept
return visitor.visit_try_stmt(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 2265, in visit_try_stmt
self.visit_try_without_finally(s, try_frame=bool(s.finally_body))
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 2300, in visit_try_without_finally
self.accept(s.body)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 283, in accept
stmt.accept(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/nodes.py", line 750, in accept
return visitor.visit_block(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 1305, in visit_block
self.accept(s)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 283, in accept
stmt.accept(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/nodes.py", line 794, in accept
return visitor.visit_assignment_stmt(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 1312, in visit_assignment_stmt
self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None, s.new_syntax)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checker.py", line 1406, in check_assignment
self.infer_variable_type(inferred, lvalue, self.expr_checker.accept(rvalue),
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checkexpr.py", line 2363, in accept
typ = node.accept(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/nodes.py", line 1245, in accept
return visitor.visit_yield_from_expr(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checkexpr.py", line 2486, in visit_yield_from_expr
subexpr_type = self.accept(e.expr)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checkexpr.py", line 2363, in accept
typ = node.accept(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/nodes.py", line 1235, in accept
return visitor.visit_call_expr(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checkexpr.py", line 268, in visit_call_expr
ret_type = self.check_call_expr_with_callee_type(callee_type, e, fullname, object_type)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checkexpr.py", line 505, in check_call_expr_with_callee_type
object_type=object_type)[0]
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/checkexpr.py", line 563, in check_call
callee = freshen_function_type_vars(callee)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/expandtype.py", line 46, in freshen_function_type_vars
fresh = cast(CallableType, expand_type(callee, tvmap)).copy_modified(variables=tvdefs)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/expandtype.py", line 16, in expand_type
return typ.accept(ExpandTypeVisitor(env))
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/types.py", line 748, in accept
return visitor.visit_callable_type(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/expandtype.py", line 97, in visit_callable_type
return t.copy_modified(arg_types=self.expand_types(t.arg_types),
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/expandtype.py", line 132, in expand_types
a.append(t.accept(self))
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/types.py", line 1424, in accept
return visitor.visit_forwardref_type(self)
File "/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/mypy/types.py", line 1509, in visit_forwardref_type
raise RuntimeError('Internal error: unresolved forward reference')
RuntimeError: Internal error: unresolved forward reference
/home/USER/.virtualenvs/backoffice-py/lib64/python3.6/site-packages/aio_pika/patterns/rpc.py:186: : note: use --pdb to drop into pdb

# Fixed code
def visit_decorator(self, dec: Decorator) -> None:
    """Try to infer the type of the decorated function.

    This lets us resolve references to decorated functions during
    type checking when there are cyclic imports, as otherwise the
    type might not be available when we need it.

    This basically uses a simple special-purpose type inference
    engine just for decorators.
    """
    # Don't just call the super method since we don't unconditionally traverse the decorated
    # function.
    dec.var.accept(self)
    for decorator in dec.decorators:
        decorator.accept(self)
    if self.recurse_into_functions:
        dec.func.accept(self)
    if dec.var.is_property:
        # Decorators are expected to have a callable type (it's a little odd).
        if dec.func.type is None:
            dec.var.type = CallableType(
                [AnyType(TypeOfAny.special_form)],
                [ARG_POS],
                [None],
                AnyType(TypeOfAny.special_form),
                self.builtin_type("function"),
                name=dec.var.name(),
            )
        elif isinstance(dec.func.type, CallableType):
            dec.var.type = dec.func.type
            self.analyze(dec.var.type, dec.var)
        return
    decorator_preserves_type = True
    for expr in dec.decorators:
        preserve_type = False
        if isinstance(expr, RefExpr) and isinstance(expr.node, FuncDef):
            if expr.node.type and is_identity_signature(expr.node.type):
                preserve_type = True
        if not preserve_type:
            decorator_preserves_type = False
            break
    if decorator_preserves_type:
        # No non-identity decorators left. We can trivially infer the type
        # of the function here.
        dec.var.type = function_type(dec.func, self.builtin_type("function"))
    if dec.decorators:
        return_type = calculate_return_type(dec.decorators[0])
        if return_type and isinstance(return_type, AnyType):
            # The outermost decorator will return Any so we know the type of the
            # decorated function.
            dec.var.type = AnyType(TypeOfAny.from_another_any, source_any=return_type)
        sig = find_fixed_callable_return(dec.decorators[0])
        if sig:
            # The outermost decorator always returns the same kind of function,
            # so we know that this is the type of the decoratored function.
            orig_sig = function_type(dec.func, self.builtin_type("function"))
            sig.name = orig_sig.items()[0].name
            dec.var.type = sig
    self.analyze(dec.var.type, dec.var)