# Buggy code
def visit_func_def(self, defn: FuncDef) -> None:
    start_line = defn.get_line() - 1
    start_indent = self.indentation_level(start_line)
    cur_line = start_line + 1
    end_line = cur_line
    # After this loop, function body will be lines [start_line, end_line)
    while cur_line < len(self.source):
        cur_indent = self.indentation_level(cur_line)
        if cur_indent is None:
            # Consume the line, but don't mark it as belonging to the function yet.
            cur_line += 1
        elif start_indent is not None and cur_indent > start_indent:
            # A non-blank line that belongs to the function.
            cur_line += 1
            end_line = cur_line
        else:
            # We reached a line outside the function definition.
            break

    is_typed = defn.type is not None
    for line in range(start_line, end_line):
        old_indent, _ = self.lines_covered[line]
        assert start_indent is not None and start_indent > old_indent
        self.lines_covered[line] = (start_indent, is_typed)

    # Visit the body, in case there are nested functions
    super().visit_func_def(defn)


# Traceback (AssertionError)
zerver/templatetags/app_filters.py: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.560
Traceback (most recent call last):
File "/srv/zulip-py3-venv/bin/mypy", line 11, in <module>
sys.exit(console_entry())
File ".../site-packages/mypy/__main__.py", line 7, in console_entry
main(None)
File ".../site-packages/mypy/main.py", line 66, in main
res = type_check_only(sources, bin_dir, options)
File ".../site-packages/mypy/main.py", line 119, in type_check_only
options=options)
File ".../site-packages/mypy/build.py", line 218, in build
graph = dispatch(sources, manager)
File ".../site-packages/mypy/build.py", line 1997, in dispatch
process_graph(graph, manager)
File ".../site-packages/mypy/build.py", line 2299, in process_graph
process_stale_scc(graph, scc, manager)
File ".../site-packages/mypy/build.py", line 2486, in process_stale_scc
graph[id].finish_passes()
File ".../site-packages/mypy/build.py", line 1912, in finish_passes
manager.report_file(self.tree, self.type_map(), self.options)
File "/usr/lib/python3.4/contextlib.py", line 77, in __exit__
self.gen.throw(type, value, traceback)
File ".../site-packages/mypy/build.py", line 1675, in wrap_context
yield
File ".../site-packages/mypy/build.py", line 1912, in finish_passes
manager.report_file(self.tree, self.type_map(), self.options)
File ".../site-packages/mypy/build.py", line 681, in report_file
self.reports.file(file, type_map, options)
File ".../site-packages/mypy/report.py", line 73, in file
reporter.on_file(tree, type_map, options)
File ".../site-packages/mypy/report.py", line 347, in on_file
tree.accept(coverage_visitor)
File ".../site-packages/mypy/nodes.py", line 228, in accept
return visitor.visit_mypy_file(self)
File ".../site-packages/mypy/traverser.py", line 30, in visit_mypy_file
d.accept(self)
File ".../site-packages/mypy/nodes.py", line 573, in accept
return visitor.visit_decorator(self)
File ".../site-packages/mypy/traverser.py", line 64, in visit_decorator
o.func.accept(self)
File ".../site-packages/mypy/nodes.py", line 497, in accept
return visitor.visit_func_def(self)
File ".../site-packages/mypy/report.py", line 317, in visit_func_def
assert start_indent is not None and start_indent > old_indent
AssertionError:
zerver/templatetags/app_filters.py: : note: use --pdb to drop into pdb

# Fixed code
def visit_func_def(self, defn: FuncDef) -> None:
    start_line = defn.get_line() - 1
    start_indent = None
    # When a function is decorated, sometimes the start line will point to
    # whitespace or comments between the decorator and the function, so
    # we have to look for the start.
    while start_line < len(self.source):
        start_indent = self.indentation_level(start_line)
        if start_indent is not None:
            break
        start_line += 1
    # If we can't find the function give up and don't annotate anything.
    # Our line numbers are not reliable enough to be asserting on.
    if start_indent is None:
        return

    cur_line = start_line + 1
    end_line = cur_line
    # After this loop, function body will be lines [start_line, end_line)
    while cur_line < len(self.source):
        cur_indent = self.indentation_level(cur_line)
        if cur_indent is None:
            # Consume the line, but don't mark it as belonging to the function yet.
            cur_line += 1
        elif start_indent is not None and cur_indent > start_indent:
            # A non-blank line that belongs to the function.
            cur_line += 1
            end_line = cur_line
        else:
            # We reached a line outside the function definition.
            break

    is_typed = defn.type is not None
    for line in range(start_line, end_line):
        old_indent, _ = self.lines_covered[line]
        # If there was an old indent level for this line, and the new
        # level isn't increasing the indentation, ignore it.
        # This is to be defensive against funniness in our line numbers,
        # which are not always reliable.
        if old_indent <= start_indent:
            self.lines_covered[line] = (start_indent, is_typed)

    # Visit the body, in case there are nested functions
    super().visit_func_def(defn)