# Buggy code
def Bindings(self, viewpoint, strict=True):
    """Filters down the possibilities of bindings for this variable.

    It determines this by analyzing the control flow graph. Any definition for
    this variable that is invisible from the current point in the CFG is
    filtered out. This function differs from Filter() in that it only honors the
    CFG, not the source sets. As such, it's much faster.

    Arguments:
      viewpoint: The CFG node at which to determine the possible bindings.
      strict: Whether to allow approximations for speed.

    Returns:
      A filtered list of bindings for this variable.
    """
    if viewpoint is None or (not strict and len(self.bindings) == 1):
        return self.bindings

    num_bindings = len(self.bindings)
    result = set()
    seen = set()
    stack = [viewpoint]
    while stack:
        if len(result) == num_bindings:
            break
        node = stack.pop()
        seen.add(node)
        bindings = self._cfgnode_to_bindings.get(node)
        if bindings is not None:
            assert bindings, "empty binding list"
            result.update(bindings)
            # Don't expand this node - previous assignments to this variable will
            # be invisible, since they're overwritten here.
            continue
        else:
            stack.extend(set(node.incoming) - seen)
    return result


# Traceback (AttributeError)
from typing import Any
def __getattr__(name: Any) -> Any: ...
# Caught error in pytype: 'set' object has no attribute 'extend'
# Traceback (most recent call last):
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/io.py", line 156, in check_or_generate_pyi
#     errorlog, result, ast = generate_pyi(
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/io.py", line 113, in generate_pyi
#     errorlog, (mod, builtins) = _call(
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/io.py", line 66, in wrapper
#     return f(*args, **kwargs)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/io.py", line 79, in _call
#     return errorlog, analyze_types(
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/analyze.py", line 695, in infer_types
#     tracer.exitpoint = tracer.analyze(loc, defs, maximum_depth)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/analyze.py", line 433, in analyze
#     return self.analyze_toplevel(node, defs)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/analyze.py", line 408, in analyze_toplevel
#     new_node = self.analyze_function(node, value)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/analyze.py", line 385, in analyze_function
#     node2 = self.maybe_analyze_method(node1, val)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/analyze.py", line 181, in maybe_analyze_method
#     node, _ = self.call_function_with_args(node, val, args)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/analyze.py", line 143, in call_function_with_args
#     new_node, ret = self.call_function_in_frame(node, fvar, *args)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/analyze.py", line 152, in call_function_in_frame
#     state, ret = self.call_function_with_state(
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/vm.py", line 1019, in call_function_with_state
#     node, ret = self.call_function(state.node, funcu, function.Args(
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/vm.py", line 1057, in call_function
#     new_node, one_result = func.call(node, funcv, args)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/abstract.py", line 3354, in call
#     node2, ret = self.vm.run_frame(frame, node, annotated_locals)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/vm.py", line 332, in run_frame
#     state = self.run_instruction(op, state)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/vm.py", line 288, in run_instruction
#     state = bytecode_fn(state, op)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/vm.py", line 2209, in byte_LOAD_ATTR
#     state, val = self.load_attr(state, obj, name)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/vm.py", line 1428, in load_attr
#     node, result, errors = self._retrieve_attr(state.node, obj, attr)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/vm.py", line 1398, in _retrieve_attr
#     node2, attr_var = self.attribute_handler.get_attribute(
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/attribute.py", line 59, in get_attribute
#     return self._get_instance_attribute(node, obj, name, valself)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/attribute.py", line 228, in _get_instance_attribute
#     return self._get_attribute(node, obj, obj.cls, name, valself)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/attribute.py", line 279, in _get_attribute
#     attr = self._filter_var(node, attr)
#   File "/home/manu/.local/lib/python3.8/site-packages/pytype/attribute.py", line 444, in _filter_var
#     bindings.extend(var_bindings)
# AttributeError: 'set' object has no attribute 'extend'

# Fixed code
def Bindings(self, viewpoint, strict=True):
    """Filters down the possibilities of bindings for this variable.

    It determines this by analyzing the control flow graph. Any definition for
    this variable that is invisible from the current point in the CFG is
    filtered out. This function differs from Filter() in that it only honors the
    CFG, not the source sets. As such, it's much faster.

    Arguments:
      viewpoint: The CFG node at which to determine the possible bindings.
      strict: Whether to allow approximations for speed.

    Returns:
      A filtered list of bindings for this variable.
    """
    if viewpoint is None or (not strict and len(self.bindings) == 1):
        return self.bindings

    num_bindings = len(self.bindings)
    result = set()
    seen = set()
    stack = [viewpoint]
    while stack:
        if len(result) == num_bindings:
            break
        node = stack.pop()
        seen.add(node)
        bindings = self._cfgnode_to_bindings.get(node)
        if bindings is not None:
            assert bindings, "empty binding list"
            result.update(bindings)
            # Don't expand this node - previous assignments to this variable will
            # be invisible, since they're overwritten here.
            continue
        else:
            stack.extend(set(node.incoming) - seen)
    return list(result)