# Buggy code
def check_argument_count(
    self,
    callee: CallableType,
    actual_types: List[Type],
    actual_kinds: List[int],
    actual_names: List[str],
    formal_to_actual: List[List[int]],
    context: Context,
) -> None:
    """Check that the number of arguments to a function are valid.

    Also check that there are no duplicate values for arguments.
    """
    formal_kinds = callee.arg_kinds

    # Collect list of all actual arguments matched to formal arguments.
    all_actuals = []  # type: List[int]
    for actuals in formal_to_actual:
        all_actuals.extend(actuals)

    is_error = False  # Keep track of errors to avoid duplicate errors.
    for i, kind in enumerate(actual_kinds):
        if i not in all_actuals and (
            kind != nodes.ARG_STAR or not is_empty_tuple(actual_types[i])
        ):
            # Extra actual: not matched by a formal argument.
            if kind != nodes.ARG_NAMED:
                self.msg.too_many_arguments(callee, context)
            else:
                self.msg.unexpected_keyword_argument(callee, actual_names[i], context)
                is_error = True
        elif kind == nodes.ARG_STAR and (nodes.ARG_STAR not in formal_kinds):
            actual_type = actual_types[i]
            if isinstance(actual_type, TupleType):
                if all_actuals.count(i) < len(actual_type.items):
                    # Too many tuple items as some did not match.
                    self.msg.too_many_arguments(callee, context)
            # *args can be applied even if the function takes a fixed
            # number of positional arguments. This may succeed at runtime.

    for i, kind in enumerate(formal_kinds):
        if kind == nodes.ARG_POS and (not formal_to_actual[i] and not is_error):
            # No actual for a mandatory positional formal.
            self.msg.too_few_arguments(callee, context, actual_names)
        elif kind in [
            nodes.ARG_POS,
            nodes.ARG_OPT,
            nodes.ARG_NAMED,
        ] and is_duplicate_mapping(formal_to_actual[i], actual_kinds):
            if self.chk.typing_mode_full() or isinstance(actual_type, TupleType):
                self.msg.duplicate_argument_value(callee, i, context)
        elif (
            kind == nodes.ARG_NAMED
            and formal_to_actual[i]
            and actual_kinds[formal_to_actual[i][0]] != nodes.ARG_NAMED
        ):
            # Positional argument when expecting a keyword argument.
            self.msg.too_many_positional_arguments(callee, context)


# Traceback (UnboundLocalError)
Traceback (most recent call last):
File "/usr/bin/mypy", line 6, in <module>
main(__file__)
File "/usr/lib/python3.5/site-packages/mypy/main.py", line 50, in main
type_check_only(sources, bin_dir, options)
File "/usr/lib/python3.5/site-packages/mypy/main.py", line 93, in type_check_only
python_path=options.python_path)
File "/usr/lib/python3.5/site-packages/mypy/build.py", line 203, in build
result = manager.process(initial_states)
File "/usr/lib/python3.5/site-packages/mypy/build.py", line 385, in process
next.process()
File "/usr/lib/python3.5/site-packages/mypy/build.py", line 882, in process
self.type_checker().visit_file(self.tree, self.tree.path)
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 385, in visit_file
self.accept(d)
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 394, in accept
typ = node.accept(self)
File "/usr/lib/python3.5/site-packages/mypy/nodes.py", line 381, in accept
return visitor.visit_func_def(self)
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 449, in visit_func_def
self.check_func_item(defn, name=defn.name())
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 484, in check_func_item
self.check_func_def(defn, typ, name)
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 567, in check_func_def
self.accept_in_frame(item.body)
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 409, in accept_in_frame
answer = self.accept(node, type_context)
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 394, in accept
typ = node.accept(self)
File "/usr/lib/python3.5/site-packages/mypy/nodes.py", line 525, in accept
return visitor.visit_block(self)
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 984, in visit_block
self.accept(s)
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 394, in accept
typ = node.accept(self)
File "/usr/lib/python3.5/site-packages/mypy/nodes.py", line 622, in accept
return visitor.visit_return_stmt(self)
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 1386, in visit_return_stmt
typ = self.accept(s.expr, self.return_types[-1])
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 394, in accept
typ = node.accept(self)
File "/usr/lib/python3.5/site-packages/mypy/nodes.py", line 984, in accept
return visitor.visit_call_expr(self)
File "/usr/lib/python3.5/site-packages/mypy/checker.py", line 1841, in visit_call_expr
return self.expr_checker.visit_call_expr(e)
File "/usr/lib/python3.5/site-packages/mypy/checkexpr.py", line 126, in visit_call_expr
return self.check_call_expr_with_callee_type(callee_type, e)
File "/usr/lib/python3.5/site-packages/mypy/checkexpr.py", line 177, in check_call_expr_with_callee_type
e.arg_names, callable_node=e.callee)[0]
File "/usr/lib/python3.5/site-packages/mypy/checkexpr.py", line 224, in check_call
arg_names, formal_to_actual, context)
File "/usr/lib/python3.5/site-packages/mypy/checkexpr.py", line 535, in check_argument_count
isinstance(actual_type, TupleType)):
UnboundLocalError: local variable 'actual_type' referenced before assignment

*** INTERNAL ERROR ***

tmp.py:3: error: Internal error -- please report a bug at https://github.com/JukkaL/mypy/issues

# Fixed code
def check_argument_count(
    self,
    callee: CallableType,
    actual_types: List[Type],
    actual_kinds: List[int],
    actual_names: List[str],
    formal_to_actual: List[List[int]],
    context: Context,
) -> None:
    """Check that the number of arguments to a function are valid.

    Also check that there are no duplicate values for arguments.
    """
    formal_kinds = callee.arg_kinds

    # Collect list of all actual arguments matched to formal arguments.
    all_actuals = []  # type: List[int]
    for actuals in formal_to_actual:
        all_actuals.extend(actuals)

    is_error = False  # Keep track of errors to avoid duplicate errors.
    for i, kind in enumerate(actual_kinds):
        if i not in all_actuals and (
            kind != nodes.ARG_STAR or not is_empty_tuple(actual_types[i])
        ):
            # Extra actual: not matched by a formal argument.
            if kind != nodes.ARG_NAMED:
                self.msg.too_many_arguments(callee, context)
            else:
                self.msg.unexpected_keyword_argument(callee, actual_names[i], context)
                is_error = True
        elif kind == nodes.ARG_STAR and (nodes.ARG_STAR not in formal_kinds):
            actual_type = actual_types[i]
            if isinstance(actual_type, TupleType):
                if all_actuals.count(i) < len(actual_type.items):
                    # Too many tuple items as some did not match.
                    self.msg.too_many_arguments(callee, context)
            # *args can be applied even if the function takes a fixed
            # number of positional arguments. This may succeed at runtime.

    for i, kind in enumerate(formal_kinds):
        if kind == nodes.ARG_POS and (not formal_to_actual[i] and not is_error):
            # No actual for a mandatory positional formal.
            self.msg.too_few_arguments(callee, context, actual_names)
        elif kind in [
            nodes.ARG_POS,
            nodes.ARG_OPT,
            nodes.ARG_NAMED,
        ] and is_duplicate_mapping(formal_to_actual[i], actual_kinds):
            if self.chk.typing_mode_full() or isinstance(
                actual_types[formal_to_actual[i][0]], TupleType
            ):
                self.msg.duplicate_argument_value(callee, i, context)
        elif (
            kind == nodes.ARG_NAMED
            and formal_to_actual[i]
            and actual_kinds[formal_to_actual[i][0]] != nodes.ARG_NAMED
        ):
            # Positional argument when expecting a keyword argument.
            self.msg.too_many_positional_arguments(callee, context)