# Buggy code
def infer_lambda_type_using_context(
    self, e: LambdaExpr
) -> Tuple[Optional[CallableType], Optional[CallableType]]:
    """Try to infer lambda expression type using context.

    Return None if could not infer type.
    The second item in the return type is the type_override parameter for check_func_item.
    """
    # TODO also accept 'Any' context
    ctx = self.type_context[-1]

    if isinstance(ctx, UnionType):
        callables = [t for t in ctx.relevant_items() if isinstance(t, CallableType)]
        if len(callables) == 1:
            ctx = callables[0]

    if not ctx or not isinstance(ctx, CallableType):
        return None, None

    # The context may have function type variables in it. We replace them
    # since these are the type variables we are ultimately trying to infer;
    # they must be considered as indeterminate. We use ErasedType since it
    # does not affect type inference results (it is for purposes like this
    # only).
    callable_ctx = replace_meta_vars(ctx, ErasedType())
    assert isinstance(callable_ctx, CallableType)

    arg_kinds = [arg.kind for arg in e.arguments]

    if callable_ctx.is_ellipsis_args:
        # Fill in Any arguments to match the arguments of the lambda.
        callable_ctx = callable_ctx.copy_modified(
            is_ellipsis_args=False,
            arg_types=[AnyType(TypeOfAny.special_form)] * len(arg_kinds),
            arg_kinds=arg_kinds,
        )

    if ARG_STAR in arg_kinds or ARG_STAR2 in arg_kinds:
        # TODO treat this case appropriately
        return callable_ctx, None
    if callable_ctx.arg_kinds != arg_kinds:
        # Incompatible context; cannot use it to infer types.
        self.chk.fail(messages.CANNOT_INFER_LAMBDA_TYPE, e)
        return None, None

    return callable_ctx, callable_ctx


# Traceback (IndexError)
Traceback (most recent call last):
File "[somewhere]/mypy/main.py", line 80, in main
type_check_only(sources, bin_dir, options, flush_errors)
File "[somewhere]/mypy/main.py", line 129, in type_check_only
flush_errors=flush_errors)
File "[somewhere]/mypy/build.py", line 172, in build
result = _build(sources, options, alt_lib_path, bin_dir, saved_cache, flush_errors)
File "[somewhere]/mypy/build.py", line 258, in _build
graph = dispatch(sources, manager)
File "[somewhere]/mypy/build.py", line 2048, in dispatch
process_graph(graph, manager)
File "[somewhere]/mypy/build.py", line 2349, in process_graph
process_stale_scc(graph, scc, manager)
File "[somewhere]/mypy/build.py", line 2525, in process_stale_scc
graph[id].type_check_first_pass()
File "[somewhere]/mypy/build.py", line 1923, in type_check_first_pass
self.type_checker().check_first_pass()
File "[somewhere]/mypy/checker.py", line 228, in check_first_pass
self.accept(d)
File "[somewhere]/mypy/checker.py", line 323, in accept
stmt.accept(self)
File "[somewhere]/mypy/nodes.py", line 701, in accept
return visitor.visit_class_def(self)
File "[somewhere]/mypy/checker.py", line 1251, in visit_class_def
self.accept(defn.defs)
File "[somewhere]/mypy/checker.py", line 323, in accept
stmt.accept(self)
File "[somewhere]/mypy/nodes.py", line 763, in accept
return visitor.visit_block(self)
File "[somewhere]/mypy/checker.py", line 1371, in visit_block
self.accept(s)
File "[somewhere]/mypy/checker.py", line 323, in accept
stmt.accept(self)
File "[somewhere]/mypy/nodes.py", line 574, in accept
return visitor.visit_decorator(self)
File "[somewhere]/mypy/checker.py", line 2537, in visit_decorator
self.check_func_item(e.func, name=e.func.name())
File "[somewhere]/mypy/checker.py", line 640, in check_func_item
self.check_func_def(defn, typ, name)
File "[somewhere]/mypy/checker.py", line 803, in check_func_def
self.accept(item.body)
File "[somewhere]/mypy/checker.py", line 323, in accept
stmt.accept(self)
File "[somewhere]/mypy/nodes.py", line 763, in accept
return visitor.visit_block(self)
File "[somewhere]/mypy/checker.py", line 1371, in visit_block
self.accept(s)
File "[somewhere]/mypy/checker.py", line 323, in accept
stmt.accept(self)
File "[somewhere]/mypy/nodes.py", line 928, in accept
return visitor.visit_if_stmt(self)
File "[somewhere]/mypy/checker.py", line 2244, in visit_if_stmt
self.accept(s.else_body)
File "...lib/python3.5/contextlib.py", line 66, in __exit__
next(self.gen)
File "[somewhere]/mypy/binder.py", line 379, in frame_context
self.pop_frame(can_skip, fall_through)
File "[somewhere]/mypy/binder.py", line 223, in pop_frame
self.last_pop_changed = self.update_from_options(options)
File "[somewhere]/mypy/binder.py", line 199, in update_from_options
type = join_simple(self.declarations[key], type, other)
File "[somewhere]/mypy/join.py", line 34, in join_simple
if is_proper_subtype(s, t):
File "[somewhere]/mypy/subtypes.py", line 835, in is_proper_subtype
return left.accept(ProperSubtypeVisitor(right))
File "[somewhere]/mypy/types.py", line 742, in accept
return visitor.visit_callable_type(self)
File "[somewhere]/mypy/subtypes.py", line 917, in visit_callable_type
use_proper_subtype=True)
File "[somewhere]/mypy/subtypes.py", line 726, in is_callable_subtype
if left_arg.pos is not None
File "[somewhere]/mypy/types.py", line 818, in argument_by_position
self.arg_kinds[position],
IndexError: list index out of range

# Fixed code
def infer_lambda_type_using_context(
    self, e: LambdaExpr
) -> Tuple[Optional[CallableType], Optional[CallableType]]:
    """Try to infer lambda expression type using context.

    Return None if could not infer type.
    The second item in the return type is the type_override parameter for check_func_item.
    """
    # TODO also accept 'Any' context
    ctx = self.type_context[-1]

    if isinstance(ctx, UnionType):
        callables = [t for t in ctx.relevant_items() if isinstance(t, CallableType)]
        if len(callables) == 1:
            ctx = callables[0]

    if not ctx or not isinstance(ctx, CallableType):
        return None, None

    # The context may have function type variables in it. We replace them
    # since these are the type variables we are ultimately trying to infer;
    # they must be considered as indeterminate. We use ErasedType since it
    # does not affect type inference results (it is for purposes like this
    # only).
    callable_ctx = replace_meta_vars(ctx, ErasedType())
    assert isinstance(callable_ctx, CallableType)

    arg_kinds = [arg.kind for arg in e.arguments]

    if callable_ctx.is_ellipsis_args:
        # Fill in Any arguments to match the arguments of the lambda.
        callable_ctx = callable_ctx.copy_modified(
            is_ellipsis_args=False,
            arg_types=[AnyType(TypeOfAny.special_form)] * len(arg_kinds),
            arg_kinds=arg_kinds,
            arg_names=[None] * len(arg_kinds),
        )

    if ARG_STAR in arg_kinds or ARG_STAR2 in arg_kinds:
        # TODO treat this case appropriately
        return callable_ctx, None
    if callable_ctx.arg_kinds != arg_kinds:
        # Incompatible context; cannot use it to infer types.
        self.chk.fail(messages.CANNOT_INFER_LAMBDA_TYPE, e)
        return None, None

    return callable_ctx, callable_ctx