# Buggy code
def make_method(
    vm,
    node,
    name,
    params=None,
    kwonly_params=None,
    return_type=None,
    self_param=None,
    varargs=None,
    kwargs=None,
):
    """Make a method from params.

    Args:
      vm: vm
      node: Node to create the method variable at
      name: The method name
      params: Positional params [type: [Param]]
      kwonly_params: Keyword only params [type: [Param]]
      return_type: Return type [type: PARAM_TYPES]
      self_param: Self param [type: Param, defaults to self: Any]
      varargs: Varargs param [type: Param, allows *args to be named and typed]
      kwargs: Kwargs param [type: Param, allows **kwargs to be named and typed]

    Returns:
      A new method wrapped in a variable.
    """

    def _process_annotation(param):
        """Process a single param into either annotations or late_annotations."""
        if not param.typ:
            return
        elif isinstance(param.typ, cfg.Variable):
            if all(t.cls for t in param.typ.data):
                types = param.typ.data
                if len(types) == 1:
                    annotations[param.name] = types[0].cls
                else:
                    t = abstract.Union([t.cls for t in types], vm)
                    annotations[param.name] = t
        elif isinstance(param.typ, abstract.LateAnnotation):
            late_annotations[param.name] = param.typ
        else:
            annotations[param.name] = param.typ

    # Set default values
    params = params or []
    kwonly_params = kwonly_params or []
    self_param = self_param or Param("self", None, None)
    annotations = {}
    late_annotations = {}

    params = [self_param] + params

    return_param = Param("return", return_type, None) if return_type else None
    special_params = [x for x in (return_param, varargs, kwargs) if x]
    for param in special_params + params + kwonly_params:
        _process_annotation(param)

    if vm.PY2:
        assert not kwonly_params, "kwonly_params is unsupported in python2"

    names = lambda xs: tuple(x.name for x in xs)
    param_names = names(params)
    kwonly_names = names(kwonly_params)
    defaults = {x.name: x.default for x in params if x.default}
    varargs_name = varargs.name if varargs else None
    kwargs_name = kwargs.name if kwargs else None

    ret = abstract.SimpleFunction(
        name=name,
        param_names=param_names,
        varargs_name=varargs_name,
        kwonly_params=kwonly_names,
        kwargs_name=kwargs_name,
        defaults=defaults,
        annotations=annotations,
        late_annotations=late_annotations,
        vm=vm,
    )
    if late_annotations:
        vm.functions_with_late_annotations.append(ret)

    # Check that the constructed function has a valid signature
    bad_param = ret.signature.check_defaults()
    if bad_param:
        msg = "In method %s, non-default argument %s follows default argument" % (
            name,
            bad_param,
        )
        vm.errorlog.invalid_function_definition(vm.frames, msg)

    return ret.to_variable(node)


# Traceback (AttributeError)
from typing import Any
def __getattr__(name: Any) -> Any: ...
# Caught error in pytype: 'LateAnnotation' object has no attribute 'Bindings'
# Traceback (most recent call last):
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/io.py", line 131, in check_or_generate_pyi
#     input_filename=options.input, options=options, loader=loader)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/io.py", line 89, in generate_pyi
#     analyze.infer_types, input_filename, options, loader)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/io.py", line 62, in _call
#     deep=deep)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/analyze.py", line 668, in infer_types
#     tracer.exitpoint = tracer.analyze(loc, defs, maximum_depth)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/analyze.py", line 407, in analyze
#     return self.analyze_toplevel(node, defs)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/analyze.py", line 370, in analyze_toplevel
#     new_node = self.analyze_class(node, value)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/analyze.py", line 352, in analyze_class
#     node = self.analyze_method_var(node, name, b)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/analyze.py", line 202, in analyze_method_var
#     node2 = self.maybe_analyze_method(node1, val)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/analyze.py", line 157, in maybe_analyze_method
#     node, _ = self.call_function_with_args(node, val, args)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/analyze.py", line 121, in call_function_with_args
#     new_node, ret = self.call_function_in_frame(node, fvar, *args)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/analyze.py", line 132, in call_function_in_frame
#     state, var, args, kwargs, starargs, starstarargs)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/vm.py", line 917, in call_function_with_state
#     starstarargs=starstarargs), fallback_to_unsolvable, allow_noreturn=True)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/vm.py", line 953, in call_function
#     new_node, one_result = func.call(node, funcv, args)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/abstract.py", line 3247, in call
#     alias_map=self.alias_map)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/abstract.py", line 3051, in call
#     node2, ret = self.vm.run_frame(frame, node)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/vm.py", line 292, in run_frame
#     state = self.run_instruction(op, state)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/vm.py", line 253, in run_instruction
#     state = bytecode_fn(state, op)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/vm.py", line 1980, in byte_LOAD_ATTR
#     state, val = self.load_attr(state, obj, name)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/vm.py", line 1224, in load_attr
#     node, result, errors = self._retrieve_attr(state.node, obj, attr)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/vm.py", line 1195, in _retrieve_attr
#     node, val.data, attr, val)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/attribute.py", line 65, in get_attribute
#     return self._get_instance_attribute(node, obj, name, valself)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/attribute.py", line 234, in _get_instance_attribute
#     return self._get_attribute(node, obj, obj.cls, name, valself)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/attribute.py", line 270, in _get_attribute
#     node, attr = self.get_attribute(node, cls, name, valself)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/attribute.py", line 58, in get_attribute
#     return self._get_class_attribute(node, obj, name, valself)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/attribute.py", line 229, in _get_class_attribute
#     return self._get_attribute(node, cls, meta, name, valself)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/attribute.py", line 284, in _get_attribute
#     attr = self._filter_var(node, attr)
#   File "/Users/name/.pyenv/versions/3.7.3/envs/venv/lib/python3.7/site-packages/pytype/attribute.py", line 426, in _filter_var
#     bindings = var.Bindings(node, strict=False)
# AttributeError: 'LateAnnotation' object has no attribute 'Bindings'

# Fixed code
def make_method(
    vm,
    node,
    name,
    params=None,
    kwonly_params=None,
    return_type=None,
    self_param=None,
    varargs=None,
    kwargs=None,
):
    """Make a method from params.

    Args:
      vm: vm
      node: Node to create the method variable at
      name: The method name
      params: Positional params [type: [Param]]
      kwonly_params: Keyword only params [type: [Param]]
      return_type: Return type [type: PARAM_TYPES]
      self_param: Self param [type: Param, defaults to self: Any]
      varargs: Varargs param [type: Param, allows *args to be named and typed]
      kwargs: Kwargs param [type: Param, allows **kwargs to be named and typed]

    Returns:
      A new method wrapped in a variable.
    """

    def _process_annotation(param):
        """Process a single param into annotations."""
        if not param.typ:
            return
        elif isinstance(param.typ, cfg.Variable):
            if all(t.cls for t in param.typ.data):
                types = param.typ.data
                if len(types) == 1:
                    annotations[param.name] = types[0].cls
                else:
                    t = abstract.Union([t.cls for t in types], vm)
                    annotations[param.name] = t
        else:
            annotations[param.name] = param.typ

    # Set default values
    params = params or []
    kwonly_params = kwonly_params or []
    self_param = self_param or Param("self", None, None)
    annotations = {}

    params = [self_param] + params

    return_param = Param("return", return_type, None) if return_type else None
    special_params = [x for x in (return_param, varargs, kwargs) if x]
    for param in special_params + params + kwonly_params:
        _process_annotation(param)

    if vm.PY2:
        assert not kwonly_params, "kwonly_params is unsupported in python2"

    names = lambda xs: tuple(x.name for x in xs)
    param_names = names(params)
    kwonly_names = names(kwonly_params)
    defaults = {x.name: x.default for x in params if x.default}
    varargs_name = varargs.name if varargs else None
    kwargs_name = kwargs.name if kwargs else None

    ret = abstract.SimpleFunction(
        name=name,
        param_names=param_names,
        varargs_name=varargs_name,
        kwonly_params=kwonly_names,
        kwargs_name=kwargs_name,
        defaults=defaults,
        annotations=annotations,
        vm=vm,
    )

    # Check that the constructed function has a valid signature
    bad_param = ret.signature.check_defaults()
    if bad_param:
        msg = "In method %s, non-default argument %s follows default argument" % (
            name,
            bad_param,
        )
        vm.errorlog.invalid_function_definition(vm.frames, msg)

    return ret.to_variable(node)