# Buggy code
def fine_grained_increment_follow_imports(
    self, sources: List[BuildSource]
) -> List[str]:
    """Like fine_grained_increment, but follow imports."""
    t0 = time.time()

    # TODO: Support file events

    assert self.fine_grained_manager is not None
    fine_grained_manager = self.fine_grained_manager
    graph = fine_grained_manager.graph
    manager = fine_grained_manager.manager

    orig_modules = list(graph.keys())

    self.update_sources(sources)
    changed_paths = self.fswatcher.find_changed()
    manager.search_paths = compute_search_paths(
        sources, manager.options, manager.data_dir
    )

    t1 = time.time()
    manager.log("fine-grained increment: find_changed: {:.3f}s".format(t1 - t0))

    seen = {source.module for source in sources}

    # Find changed modules reachable from roots (or in roots) already in graph.
    changed, new_files = self.find_reachable_changed_modules(
        sources, graph, seen, changed_paths
    )
    sources.extend(new_files)

    # Process changes directly reachable from roots.
    messages = fine_grained_manager.update(changed, [])

    # Follow deps from changed modules (still within graph).
    worklist = changed[:]
    while worklist:
        module = worklist.pop()
        if module[0] not in graph:
            continue
        sources2 = self.direct_imports(module, graph)
        # Filter anything already seen before. This prevents
        # infinite looping if there are any self edges. (Self
        # edges are maybe a bug, but...)
        sources2 = [source for source in sources2 if source.module not in seen]
        changed, new_files = self.find_reachable_changed_modules(
            sources2, graph, seen, changed_paths
        )
        self.update_sources(new_files)
        messages = fine_grained_manager.update(changed, [])
        worklist.extend(changed)

    t2 = time.time()

    def refresh_file(module: str, path: str) -> List[str]:
        return fine_grained_manager.update([(module, path)], [])

    for module_id, state in list(graph.items()):
        new_messages = refresh_suppressed_submodules(
            module_id,
            state.path,
            fine_grained_manager.deps,
            graph,
            self.fscache,
            refresh_file,
        )
        if new_messages is not None:
            messages = new_messages

    t3 = time.time()

    # There may be new files that became available, currently treated as
    # suppressed imports. Process them.
    while True:
        new_unsuppressed = self.find_added_suppressed(graph, seen, manager.search_paths)
        if not new_unsuppressed:
            break
        new_files = [BuildSource(mod[1], mod[0]) for mod in new_unsuppressed]
        sources.extend(new_files)
        self.update_sources(new_files)
        messages = fine_grained_manager.update(new_unsuppressed, [])

        for module_id, path in new_unsuppressed:
            new_messages = refresh_suppressed_submodules(
                module_id,
                path,
                fine_grained_manager.deps,
                graph,
                self.fscache,
                refresh_file,
            )
            if new_messages is not None:
                messages = new_messages

    t4 = time.time()

    # Find all original modules in graph that were not reached -- they are deleted.
    to_delete = []
    for module_id in orig_modules:
        if module_id not in graph:
            continue
        if module_id not in seen:
            module_path = graph[module_id].path
            assert module_path is not None
            to_delete.append((module_id, module_path))
    if to_delete:
        messages = fine_grained_manager.update([], to_delete)

    fix_module_deps(graph)

    # Store current file state as side effect
    self.fswatcher.find_changed()

    self.previous_sources = find_all_sources_in_build(graph)
    self.update_sources(self.previous_sources)

    t5 = time.time()

    manager.log("fine-grained increment: update: {:.3f}s".format(t5 - t1))
    manager.add_stats(
        find_changes_time=t1 - t0,
        fg_update_time=t2 - t1,
        refresh_suppressed_time=t3 - t2,
        find_added_supressed_time=t4 - t3,
        cleanup_time=t5 - t4,
    )

    return messages


# Traceback (ValueError)
Daemon crashed!
Traceback (most recent call last):
File "/Users/jukka/src/mypy/mypy/dmypy_server.py", line 221, in serve
resp = self.run_command(command, data)
File "/Users/jukka/src/mypy/mypy/dmypy_server.py", line 264, in run_command
return method(self, **data)
File "/Users/jukka/src/mypy/mypy/dmypy_server.py", line 323, in cmd_run
return self.check(sources, is_tty, terminal_width)
File "/Users/jukka/src/mypy/mypy/dmypy_server.py", line 385, in check
messages = self.fine_grained_increment_follow_imports(sources)
File "/Users/jukka/src/mypy/mypy/dmypy_server.py", line 551, in fine_grained_increment_follow_imports
messages = fine_grained_manager.update(changed, [])
File "/Users/jukka/src/mypy/mypy/server/update.py", line 243, in update
result = self.update_one(changed_modules, initial_set, removed_set)
File "/Users/jukka/src/mypy/mypy/server/update.py", line 309, in update_one
result = self.update_module(next_id, next_path, next_id in removed_set)
File "/Users/jukka/src/mypy/mypy/server/update.py", line 374, in update_module
result = update_module_isolated(module, path, manager, previous_modules, graph,
File "/Users/jukka/src/mypy/mypy/server/update.py", line 603, in update_module_isolated
state.type_check_first_pass()
File "/Users/jukka/src/mypy/mypy/build.py", line 2135, in type_check_first_pass
self.type_checker().check_first_pass()
File "/Users/jukka/src/mypy/mypy/checker.py", line 294, in check_first_pass
self.accept(d)
File "/Users/jukka/src/mypy/mypy/checker.py", line 403, in accept
report_internal_error(err, self.errors.file, stmt.line, self.errors, self.options)
File "/Users/jukka/src/mypy/mypy/errors.py", line 744, in report_internal_error
raise err
File "/Users/jukka/src/mypy/mypy/checker.py", line 401, in accept
stmt.accept(self)
File "/Users/jukka/src/mypy/mypy/nodes.py", line 1073, in accept
return visitor.visit_assignment_stmt(self)
File "/Users/jukka/src/mypy/mypy/checker.py", line 2010, in visit_assignment_stmt
self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None, s.new_syntax)
File "/Users/jukka/src/mypy/mypy/checker.py", line 2121, in check_assignment
rvalue_type = self.check_simple_assignment(lvalue_type, rvalue, context=rvalue,
File "/Users/jukka/src/mypy/mypy/checker.py", line 2975, in check_simple_assignment
rvalue_type = self.expr_checker.accept(rvalue, lvalue_type,
File "/Users/jukka/src/mypy/mypy/checkexpr.py", line 3905, in accept
report_internal_error(err, self.chk.errors.file,
File "/Users/jukka/src/mypy/mypy/errors.py", line 744, in report_internal_error
raise err
File "/Users/jukka/src/mypy/mypy/checkexpr.py", line 3903, in accept
typ = node.accept(self)
File "/Users/jukka/src/mypy/mypy/nodes.py", line 1490, in accept
return visitor.visit_name_expr(self)
File "/Users/jukka/src/mypy/mypy/checkexpr.py", line 179, in visit_name_expr
result = self.analyze_ref_expr(e)
File "/Users/jukka/src/mypy/mypy/checkexpr.py", line 206, in analyze_ref_expr
result = type_object_type(node, self.named_type)
File "/Users/jukka/src/mypy/mypy/checkmember.py", line 929, in type_object_type
init_index = info.mro.index(init_method.node.info)
ValueError: <TypeInfo datetime.time> is not in list

# Fixed code
def fine_grained_increment_follow_imports(
    self, sources: List[BuildSource]
) -> List[str]:
    """Like fine_grained_increment, but follow imports."""
    t0 = time.time()

    # TODO: Support file events

    assert self.fine_grained_manager is not None
    fine_grained_manager = self.fine_grained_manager
    graph = fine_grained_manager.graph
    manager = fine_grained_manager.manager

    orig_modules = list(graph.keys())

    self.update_sources(sources)
    changed_paths = self.fswatcher.find_changed()
    manager.search_paths = compute_search_paths(
        sources, manager.options, manager.data_dir
    )

    t1 = time.time()
    manager.log("fine-grained increment: find_changed: {:.3f}s".format(t1 - t0))

    seen = {source.module for source in sources}

    # Find changed modules reachable from roots (or in roots) already in graph.
    changed, new_files = self.find_reachable_changed_modules(
        sources, graph, seen, changed_paths
    )
    sources.extend(new_files)

    # Process changes directly reachable from roots.
    messages = fine_grained_manager.update(changed, [])

    # Follow deps from changed modules (still within graph).
    worklist = changed[:]
    while worklist:
        module = worklist.pop()
        if module[0] not in graph:
            continue
        sources2 = self.direct_imports(module, graph)
        # Filter anything already seen before. This prevents
        # infinite looping if there are any self edges. (Self
        # edges are maybe a bug, but...)
        sources2 = [source for source in sources2 if source.module not in seen]
        changed, new_files = self.find_reachable_changed_modules(
            sources2, graph, seen, changed_paths
        )
        self.update_sources(new_files)
        messages = fine_grained_manager.update(changed, [])
        worklist.extend(changed)

    t2 = time.time()

    def refresh_file(module: str, path: str) -> List[str]:
        return fine_grained_manager.update([(module, path)], [])

    for module_id, state in list(graph.items()):
        new_messages = refresh_suppressed_submodules(
            module_id,
            state.path,
            fine_grained_manager.deps,
            graph,
            self.fscache,
            refresh_file,
        )
        if new_messages is not None:
            messages = new_messages

    t3 = time.time()

    # There may be new files that became available, currently treated as
    # suppressed imports. Process them.
    while True:
        new_unsuppressed = self.find_added_suppressed(graph, seen, manager.search_paths)
        if not new_unsuppressed:
            break
        new_files = [BuildSource(mod[1], mod[0]) for mod in new_unsuppressed]
        sources.extend(new_files)
        self.update_sources(new_files)
        messages = fine_grained_manager.update(new_unsuppressed, [])

        for module_id, path in new_unsuppressed:
            new_messages = refresh_suppressed_submodules(
                module_id,
                path,
                fine_grained_manager.deps,
                graph,
                self.fscache,
                refresh_file,
            )
            if new_messages is not None:
                messages = new_messages

    t4 = time.time()

    # Find all original modules in graph that were not reached -- they are deleted.
    to_delete = []
    for module_id in orig_modules:
        if module_id not in graph:
            continue
        if module_id not in seen:
            module_path = graph[module_id].path
            assert module_path is not None
            to_delete.append((module_id, module_path))
    if to_delete:
        messages = fine_grained_manager.update([], to_delete)

    fix_module_deps(graph)

    self.previous_sources = find_all_sources_in_build(graph)
    self.update_sources(self.previous_sources)

    # Store current file state as side effect
    self.fswatcher.find_changed()

    t5 = time.time()

    manager.log("fine-grained increment: update: {:.3f}s".format(t5 - t1))
    manager.add_stats(
        find_changes_time=t1 - t0,
        fg_update_time=t2 - t1,
        refresh_suppressed_time=t3 - t2,
        find_added_supressed_time=t4 - t3,
        cleanup_time=t5 - t4,
    )

    return messages