# Buggy code
def build_namedtuple_typeinfo(
    self,
    name: str,
    items: List[str],
    types: List[Type],
    default_items: Dict[str, Expression],
) -> TypeInfo:
    strtype = self.str_type()
    implicit_any = AnyType(TypeOfAny.special_form)
    basetuple_type = self.named_type("__builtins__.tuple", [implicit_any])
    dictype = (
        self.named_type_or_none("builtins.dict", [strtype, implicit_any])
        or self.object_type()
    )
    # Actual signature should return OrderedDict[str, Union[types]]
    ordereddictype = (
        self.named_type_or_none("builtins.dict", [strtype, implicit_any])
        or self.object_type()
    )
    fallback = self.named_type("__builtins__.tuple", [implicit_any])
    # Note: actual signature should accept an invariant version of Iterable[UnionType[types]].
    # but it can't be expressed. 'new' and 'len' should be callable types.
    iterable_type = self.named_type_or_none("typing.Iterable", [implicit_any])
    function_type = self.named_type("__builtins__.function")

    info = self.basic_new_typeinfo(name, fallback)
    info.is_named_tuple = True
    info.tuple_type = TupleType(types, fallback)

    def patch() -> None:
        # Calculate the correct value type for the fallback tuple.
        assert info.tuple_type, "TupleType type deleted before calling the patch"
        fallback.args[0] = join.join_type_list(list(info.tuple_type.items))

    # We can't calculate the complete fallback type until after semantic
    # analysis, since otherwise MROs might be incomplete. Postpone a callback
    # function that patches the fallback.
    self.patches.append(patch)

    def add_field(
        var: Var, is_initialized_in_class: bool = False, is_property: bool = False
    ) -> None:
        var.info = info
        var.is_initialized_in_class = is_initialized_in_class
        var.is_property = is_property
        var._fullname = "%s.%s" % (info.fullname(), var.name())
        info.names[var.name()] = SymbolTableNode(MDEF, var)

    vars = [Var(item, typ) for item, typ in zip(items, types)]
    for var in vars:
        add_field(var, is_property=True)

    tuple_of_strings = TupleType([strtype for _ in items], basetuple_type)
    add_field(Var("_fields", tuple_of_strings), is_initialized_in_class=True)
    add_field(Var("_field_types", dictype), is_initialized_in_class=True)
    add_field(Var("_field_defaults", dictype), is_initialized_in_class=True)
    add_field(Var("_source", strtype), is_initialized_in_class=True)
    add_field(Var("__annotations__", ordereddictype), is_initialized_in_class=True)
    add_field(Var("__doc__", strtype), is_initialized_in_class=True)

    tvd = TypeVarDef("NT", "NT", 1, [], info.tuple_type)
    selftype = TypeVarType(tvd)

    def add_method(
        funcname: str,
        ret: Type,
        args: List[Argument],
        name: Optional[str] = None,
        is_classmethod: bool = False,
    ) -> None:
        if is_classmethod:
            first = [
                Argument(Var("cls"), TypeType.make_normalized(selftype), None, ARG_POS)
            ]
        else:
            first = [Argument(Var("self"), selftype, None, ARG_POS)]
        args = first + args

        types = [arg.type_annotation for arg in args]
        items = [arg.variable.name() for arg in args]
        arg_kinds = [arg.kind for arg in args]
        assert None not in types
        signature = CallableType(
            cast(List[Type], types), arg_kinds, items, ret, function_type
        )
        signature.variables = [tvd]
        func = FuncDef(funcname, args, Block([]))
        func.info = info
        func.is_class = is_classmethod
        func.type = set_callable_name(signature, func)
        func._fullname = info.fullname() + "." + funcname
        if is_classmethod:
            v = Var(funcname, func.type)
            v.is_classmethod = True
            v.info = info
            v._fullname = func._fullname
            dec = Decorator(func, [NameExpr("classmethod")], v)
            info.names[funcname] = SymbolTableNode(MDEF, dec)
        else:
            info.names[funcname] = SymbolTableNode(MDEF, func)

    add_method(
        "_replace",
        ret=selftype,
        args=[Argument(var, var.type, EllipsisExpr(), ARG_NAMED_OPT) for var in vars],
    )

    def make_init_arg(var: Var) -> Argument:
        default = default_items.get(var.name(), None)
        kind = ARG_POS if default is None else ARG_OPT
        return Argument(var, var.type, default, kind)

    add_method(
        "__init__",
        ret=NoneTyp(),
        name=info.name(),
        args=[make_init_arg(var) for var in vars],
    )
    add_method("_asdict", args=[], ret=ordereddictype)
    special_form_any = AnyType(TypeOfAny.special_form)
    add_method(
        "_make",
        ret=selftype,
        is_classmethod=True,
        args=[
            Argument(Var("iterable", iterable_type), iterable_type, None, ARG_POS),
            Argument(Var("new"), special_form_any, EllipsisExpr(), ARG_NAMED_OPT),
            Argument(Var("len"), special_form_any, EllipsisExpr(), ARG_NAMED_OPT),
        ],
    )
    return info


# Traceback (RuntimeError)
forward.py:1: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.540
Traceback (most recent call last):
File "/Users/joshstaiger/anaconda/bin/mypy", line 11, in <module>
sys.exit(console_entry())
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/__main__.py", line 7, in console_entry
main(None)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/main.py", line 50, in main
res = type_check_only(sources, bin_dir, options)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/main.py", line 103, in type_check_only
options=options)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/build.py", line 201, in build
graph = dispatch(sources, manager)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/build.py", line 1867, in dispatch
process_graph(graph, manager)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/build.py", line 2117, in process_graph
process_stale_scc(graph, scc, manager)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/build.py", line 2214, in process_stale_scc
graph[id].semantic_analysis_pass_three()
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/build.py", line 1760, in semantic_analysis_pass_three
self.options, patches)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/semanal_pass3.py", line 56, in visit_file
self.accept(file_node)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/semanal_pass3.py", line 73, in accept
node.accept(self)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/nodes.py", line 228, in accept
return visitor.visit_mypy_file(self)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/traverser.py", line 30, in visit_mypy_file
d.accept(self)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/nodes.py", line 794, in accept
return visitor.visit_assignment_stmt(self)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/semanal_pass3.py", line 187, in visit_assignment_stmt
self.analyze(s.rvalue.analyzed.type, s.rvalue.analyzed, warn=True)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/semanal_pass3.py", line 311, in analyze
type.accept(analyzer)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/types.py", line 476, in accept
return visitor.visit_instance(self)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/typeanal.py", line 716, in visit_instance
if not is_subtype(arg, bound):
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/subtypes.py", line 83, in is_subtype
ignore_declared_variance=ignore_declared_variance))
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/types.py", line 1227, in accept
return visitor.visit_union_type(self)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/subtypes.py", line 312, in visit_union_type
for item in left.items)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/subtypes.py", line 312, in <genexpr>
for item in left.items)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/subtypes.py", line 83, in is_subtype
ignore_declared_variance=ignore_declared_variance))
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/types.py", line 1412, in accept
return visitor.visit_forwardref_type(self)
File "/Users/joshstaiger/anaconda/lib/python3.6/site-packages/mypy/types.py", line 1497, in visit_forwardref_type
raise RuntimeError('Internal error: unresolved forward reference')
RuntimeError: Internal error: unresolved forward reference
forward.py:1: : note: use --pdb to drop into pdb

# Fixed code
def build_namedtuple_typeinfo(
    self,
    name: str,
    items: List[str],
    types: List[Type],
    default_items: Dict[str, Expression],
) -> TypeInfo:
    strtype = self.str_type()
    implicit_any = AnyType(TypeOfAny.special_form)
    basetuple_type = self.named_type("__builtins__.tuple", [implicit_any])
    dictype = (
        self.named_type_or_none("builtins.dict", [strtype, implicit_any])
        or self.object_type()
    )
    # Actual signature should return OrderedDict[str, Union[types]]
    ordereddictype = (
        self.named_type_or_none("builtins.dict", [strtype, implicit_any])
        or self.object_type()
    )
    fallback = self.named_type("__builtins__.tuple", [implicit_any])
    # Note: actual signature should accept an invariant version of Iterable[UnionType[types]].
    # but it can't be expressed. 'new' and 'len' should be callable types.
    iterable_type = self.named_type_or_none("typing.Iterable", [implicit_any])
    function_type = self.named_type("__builtins__.function")

    info = self.basic_new_typeinfo(name, fallback)
    info.is_named_tuple = True
    info.tuple_type = TupleType(types, fallback)

    def patch() -> None:
        # Calculate the correct value type for the fallback tuple.
        assert info.tuple_type, "TupleType type deleted before calling the patch"
        fallback.args[0] = join.join_type_list(list(info.tuple_type.items))

    # We can't calculate the complete fallback type until after semantic
    # analysis, since otherwise MROs might be incomplete. Postpone a callback
    # function that patches the fallback.
    self.patches.append((PRIORITY_FALLBACKS, patch))

    def add_field(
        var: Var, is_initialized_in_class: bool = False, is_property: bool = False
    ) -> None:
        var.info = info
        var.is_initialized_in_class = is_initialized_in_class
        var.is_property = is_property
        var._fullname = "%s.%s" % (info.fullname(), var.name())
        info.names[var.name()] = SymbolTableNode(MDEF, var)

    vars = [Var(item, typ) for item, typ in zip(items, types)]
    for var in vars:
        add_field(var, is_property=True)

    tuple_of_strings = TupleType([strtype for _ in items], basetuple_type)
    add_field(Var("_fields", tuple_of_strings), is_initialized_in_class=True)
    add_field(Var("_field_types", dictype), is_initialized_in_class=True)
    add_field(Var("_field_defaults", dictype), is_initialized_in_class=True)
    add_field(Var("_source", strtype), is_initialized_in_class=True)
    add_field(Var("__annotations__", ordereddictype), is_initialized_in_class=True)
    add_field(Var("__doc__", strtype), is_initialized_in_class=True)

    tvd = TypeVarDef("NT", "NT", 1, [], info.tuple_type)
    selftype = TypeVarType(tvd)

    def add_method(
        funcname: str,
        ret: Type,
        args: List[Argument],
        name: Optional[str] = None,
        is_classmethod: bool = False,
    ) -> None:
        if is_classmethod:
            first = [
                Argument(Var("cls"), TypeType.make_normalized(selftype), None, ARG_POS)
            ]
        else:
            first = [Argument(Var("self"), selftype, None, ARG_POS)]
        args = first + args

        types = [arg.type_annotation for arg in args]
        items = [arg.variable.name() for arg in args]
        arg_kinds = [arg.kind for arg in args]
        assert None not in types
        signature = CallableType(
            cast(List[Type], types), arg_kinds, items, ret, function_type
        )
        signature.variables = [tvd]
        func = FuncDef(funcname, args, Block([]))
        func.info = info
        func.is_class = is_classmethod
        func.type = set_callable_name(signature, func)
        func._fullname = info.fullname() + "." + funcname
        if is_classmethod:
            v = Var(funcname, func.type)
            v.is_classmethod = True
            v.info = info
            v._fullname = func._fullname
            dec = Decorator(func, [NameExpr("classmethod")], v)
            info.names[funcname] = SymbolTableNode(MDEF, dec)
        else:
            info.names[funcname] = SymbolTableNode(MDEF, func)

    add_method(
        "_replace",
        ret=selftype,
        args=[Argument(var, var.type, EllipsisExpr(), ARG_NAMED_OPT) for var in vars],
    )

    def make_init_arg(var: Var) -> Argument:
        default = default_items.get(var.name(), None)
        kind = ARG_POS if default is None else ARG_OPT
        return Argument(var, var.type, default, kind)

    add_method(
        "__init__",
        ret=NoneTyp(),
        name=info.name(),
        args=[make_init_arg(var) for var in vars],
    )
    add_method("_asdict", args=[], ret=ordereddictype)
    special_form_any = AnyType(TypeOfAny.special_form)
    add_method(
        "_make",
        ret=selftype,
        is_classmethod=True,
        args=[
            Argument(Var("iterable", iterable_type), iterable_type, None, ARG_POS),
            Argument(Var("new"), special_form_any, EllipsisExpr(), ARG_NAMED_OPT),
            Argument(Var("len"), special_form_any, EllipsisExpr(), ARG_NAMED_OPT),
        ],
    )
    return info