# Buggy code
def perform_transform(
    self, node: Union[Node, SymbolTableNode], transform: Callable[[Type], Type]
) -> None:
    """Apply transform to all types associated with node."""
    if isinstance(node, ForStmt):
        if node.index_type:
            node.index_type = transform(node.index_type)
        self.transform_types_in_lvalue(node.index, transform)
    if isinstance(node, WithStmt):
        if node.target_type:
            node.target_type = transform(node.target_type)
        for n in node.target:
            if isinstance(n, NameExpr) and isinstance(n.node, Var) and n.node.type:
                n.node.type = transform(n.node.type)
    if isinstance(node, (FuncDef, CastExpr, AssignmentStmt, TypeAliasExpr, Var)):
        assert node.type, "Scheduled patch for non-existent type"
        node.type = transform(node.type)
    if isinstance(node, NewTypeExpr):
        assert node.old_type, "Scheduled patch for non-existent type"
        node.old_type = transform(node.old_type)
    if isinstance(node, TypeVarExpr):
        if node.upper_bound:
            node.upper_bound = transform(node.upper_bound)
        if node.values:
            node.values = [transform(v) for v in node.values]
    if isinstance(node, TypedDictExpr):
        assert node.info.typeddict_type, "Scheduled patch for non-existent type"
        node.info.typeddict_type = cast(
            TypedDictType, transform(node.info.typeddict_type)
        )
    if isinstance(node, NamedTupleExpr):
        assert node.info.tuple_type, "Scheduled patch for non-existent type"
        node.info.tuple_type = cast(TupleType, transform(node.info.tuple_type))
    if isinstance(node, TypeApplication):
        node.types = [transform(t) for t in node.types]
    if isinstance(node, SymbolTableNode):
        assert node.type_override, "Scheduled patch for non-existent type"
        node.type_override = transform(node.type_override)
    if isinstance(node, TypeInfo):
        for tvar in node.defn.type_vars:
            if tvar.upper_bound:
                tvar.upper_bound = transform(tvar.upper_bound)
            if tvar.values:
                tvar.values = [transform(v) for v in tvar.values]
        new_bases = []
        for base in node.bases:
            new_base = transform(base)
            if isinstance(new_base, Instance):
                new_bases.append(new_base)
            else:
                # Don't fix the NamedTuple bases, they are Instance's intentionally.
                # Patch the 'args' just in case, although generic tuple type are
                # not supported yet.
                alt_base = Instance(base.type, [transform(a) for a in base.args])
                new_bases.append(alt_base)
        node.bases = new_bases


# 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 perform_transform(
    self, node: Union[Node, SymbolTableNode], transform: Callable[[Type], Type]
) -> None:
    """Apply transform to all types associated with node."""
    if isinstance(node, ForStmt):
        if node.index_type:
            node.index_type = transform(node.index_type)
        self.transform_types_in_lvalue(node.index, transform)
    if isinstance(node, WithStmt):
        if node.target_type:
            node.target_type = transform(node.target_type)
        for n in node.target:
            if isinstance(n, NameExpr) and isinstance(n.node, Var) and n.node.type:
                n.node.type = transform(n.node.type)
    if isinstance(
        node, (FuncDef, OverloadedFuncDef, CastExpr, AssignmentStmt, TypeAliasExpr, Var)
    ):
        assert node.type, "Scheduled patch for non-existent type"
        node.type = transform(node.type)
    if isinstance(node, NewTypeExpr):
        assert node.old_type, "Scheduled patch for non-existent type"
        node.old_type = transform(node.old_type)
        if node.info:
            new_bases = []  # type: List[Instance]
            for b in node.info.bases:
                new_b = transform(b)
                # TODO: this code can be combined with code in second pass.
                if isinstance(new_b, Instance):
                    new_bases.append(new_b)
                elif isinstance(new_b, TupleType):
                    new_bases.append(new_b.fallback)
                else:
                    self.fail(
                        "Argument 2 to NewType(...) must be subclassable"
                        " (got {})".format(new_b),
                        node,
                    )
                    new_bases.append(self.builtin_type("object"))
            node.info.bases = new_bases
    if isinstance(node, TypeVarExpr):
        if node.upper_bound:
            node.upper_bound = transform(node.upper_bound)
        if node.values:
            node.values = [transform(v) for v in node.values]
    if isinstance(node, TypedDictExpr):
        assert node.info.typeddict_type, "Scheduled patch for non-existent type"
        node.info.typeddict_type = cast(
            TypedDictType, transform(node.info.typeddict_type)
        )
    if isinstance(node, NamedTupleExpr):
        assert node.info.tuple_type, "Scheduled patch for non-existent type"
        node.info.tuple_type = cast(TupleType, transform(node.info.tuple_type))
    if isinstance(node, TypeApplication):
        node.types = [transform(t) for t in node.types]
    if isinstance(node, SymbolTableNode):
        assert node.type_override, "Scheduled patch for non-existent type"
        node.type_override = transform(node.type_override)
    if isinstance(node, TypeInfo):
        for tvar in node.defn.type_vars:
            if tvar.upper_bound:
                tvar.upper_bound = transform(tvar.upper_bound)
            if tvar.values:
                tvar.values = [transform(v) for v in tvar.values]
        new_bases = []
        for base in node.bases:
            new_base = transform(base)
            if isinstance(new_base, Instance):
                new_bases.append(new_base)
            else:
                # Don't fix the NamedTuple bases, they are Instance's intentionally.
                # Patch the 'args' just in case, although generic tuple types are
                # not supported yet.
                alt_base = Instance(base.type, [transform(a) for a in base.args])
                new_bases.append(alt_base)
        node.bases = new_bases