# Buggy code
def visit_class_def(self, tdef: ClassDef) -> None:
    # NamedTuple base classes are validated in check_namedtuple_classdef; we don't have to
    # check them again here.
    if not tdef.info.is_named_tuple:
        types = list(tdef.info.bases)  # type: List[Type]
        for tvar in tdef.type_vars:
            if tvar.upper_bound:
                types.append(tvar.upper_bound)
            if tvar.values:
                types.extend(tvar.values)
        self.analyze_types(types, tdef.info)
        for type in tdef.info.bases:
            if tdef.info.is_protocol:
                if not isinstance(type, Instance) or not type.type.is_protocol:
                    if type.type.fullname() != "builtins.object":
                        self.fail("All bases of a protocol must be protocols", tdef)
    # Recompute MRO now that we have analyzed all modules, to pick
    # up superclasses of bases imported from other modules in an
    # import loop. (Only do so if we succeeded the first time.)
    if tdef.info.mro:
        tdef.info.mro = []  # Force recomputation
        mypy.semanal.calculate_class_mro(tdef, self.fail_blocker)
        if tdef.info.is_protocol:
            add_protocol_members(tdef.info)
    if tdef.analyzed is not None:
        # Also check synthetic types associated with this ClassDef.
        # Currently these are TypedDict, and NamedTuple.
        if isinstance(tdef.analyzed, TypedDictExpr):
            self.analyze(tdef.analyzed.info.typeddict_type, tdef.analyzed, warn=True)
        elif isinstance(tdef.analyzed, NamedTupleExpr):
            self.analyze(tdef.analyzed.info.tuple_type, tdef.analyzed, warn=True)
            for name in tdef.analyzed.info.names:
                sym = tdef.analyzed.info.names[name]
                if isinstance(sym.node, (FuncDef, Decorator)):
                    self.accept(sym.node)
                if isinstance(sym.node, Var):
                    self.analyze(sym.node.type, sym.node)
    super().visit_class_def(tdef)


# Traceback (AssertionError)
Traceback (most recent call last):
File "/Users/daenyth/Curata/cmp/.tox/mypy/bin/mypy", line 11, in <module>
sys.exit(console_entry())
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/__main__.py", line 7, in console_entry
main(None)
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/main.py", line 50, in main
res = type_check_only(sources, bin_dir, options)
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/main.py", line 103, in type_check_only
options=options)
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/build.py", line 198, in build
graph = dispatch(sources, manager)
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/build.py", line 1841, in dispatch
process_graph(graph, manager)
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/build.py", line 2091, in process_graph
process_stale_scc(graph, scc, manager)
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/build.py", line 2203, in process_stale_scc
graph[id].write_cache()
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/build.py", line 1822, in write_cache
self.manager)
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/build.py", line 1088, in write_cache
data = tree.serialize()
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 238, in serialize
'names': self.names.serialize(self._fullname),
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 2432, in serialize
data[key] = value.serialize(fullname, key)
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 2371, in serialize
data['node'] = self.node.serialize()
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 2194, in serialize
'names': self.names.serialize(self.fullname()),
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 2432, in serialize
data[key] = value.serialize(fullname, key)
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 2371, in serialize
data['node'] = self.node.serialize()
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 533, in serialize
'type': None if self.type is None else self.type.serialize(),
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/types.py", line 857, in serialize
'arg_types': [t.serialize() for t in self.arg_types],
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/types.py", line 857, in <listcomp>
'arg_types': [t.serialize() for t in self.arg_types],
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/types.py", line 496, in serialize
data['args'] = [arg.serialize() for arg in self.args]
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/types.py", line 496, in <listcomp>
data['args'] = [arg.serialize() for arg in self.args]
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/types.py", line 994, in serialize
'items': [t.serialize() for t in self.items],
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/types.py", line 994, in <listcomp>
'items': [t.serialize() for t in self.items],
File "/Users/daenyth/Curata/cmp/.tox/mypy/lib/python3.6/site-packages/mypy/types.py", line 1410, in serialize
assert False, "Internal error: Unresolved forward reference to {}".format(name)
AssertionError: Internal error: Unresolved forward reference to UnboundType

# Fixed code
def visit_class_def(self, tdef: ClassDef) -> None:
    # NamedTuple base classes are validated in check_namedtuple_classdef; we don't have to
    # check them again here.
    if not tdef.info.is_named_tuple:
        types = list(tdef.info.bases)  # type: List[Type]
        for tvar in tdef.type_vars:
            if tvar.upper_bound:
                types.append(tvar.upper_bound)
            if tvar.values:
                types.extend(tvar.values)
        self.analyze_types(types, tdef.info)
        for type in tdef.info.bases:
            if tdef.info.is_protocol:
                if not isinstance(type, Instance) or not type.type.is_protocol:
                    if type.type.fullname() != "builtins.object":
                        self.fail("All bases of a protocol must be protocols", tdef)
    # Recompute MRO now that we have analyzed all modules, to pick
    # up superclasses of bases imported from other modules in an
    # import loop. (Only do so if we succeeded the first time.)
    if tdef.info.mro:
        tdef.info.mro = []  # Force recomputation
        mypy.semanal.calculate_class_mro(tdef, self.fail_blocker)
        if tdef.info.is_protocol:
            add_protocol_members(tdef.info)
    if tdef.analyzed is not None:
        # Also check synthetic types associated with this ClassDef.
        # Currently these are TypedDict, and NamedTuple.
        if isinstance(tdef.analyzed, TypedDictExpr):
            self.analyze(tdef.analyzed.info.typeddict_type, tdef.analyzed, warn=True)
        elif isinstance(tdef.analyzed, NamedTupleExpr):
            self.analyze(tdef.analyzed.info.tuple_type, tdef.analyzed, warn=True)
            self.analyze_info(tdef.analyzed.info)
    super().visit_class_def(tdef)