From 5a1c7fc616a9324504f60646378d2247668a382b Mon Sep 17 00:00:00 2001 From: Erik Soma Date: Thu, 5 Nov 2020 19:04:35 -0500 Subject: [PATCH 01/10] Limit **kwarg mapping to parameters that have a matching type. --- mypy/argmap.py | 42 ++++++++++--- mypy/checkexpr.py | 70 ++++++++++++++++----- mypy/messages.py | 21 +++++++ mypy/stats.py | 55 +++++++++++++++- test-data/unit/check-columns.test | 4 +- test-data/unit/check-ctypes.test | 3 +- test-data/unit/check-expressions.test | 3 +- test-data/unit/check-kwargs.test | 91 ++++++++++++++++++++++++--- test-data/unit/check-typeddict.test | 7 ++- 9 files changed, 258 insertions(+), 38 deletions(-) diff --git a/mypy/argmap.py b/mypy/argmap.py index ff7e94e93cbe..0237b33c2f5f 100644 --- a/mypy/argmap.py +++ b/mypy/argmap.py @@ -3,7 +3,8 @@ from typing import List, Optional, Sequence, Callable, Set from mypy.types import ( - Type, Instance, TupleType, AnyType, TypeOfAny, TypedDictType, get_proper_type + Type, Instance, TupleType, AnyType, TypeOfAny, TypedDictType, get_proper_type, + TypeVarType, ) from mypy import nodes @@ -12,8 +13,8 @@ def map_actuals_to_formals(actual_kinds: List[int], actual_names: Optional[Sequence[Optional[str]]], formal_kinds: List[int], formal_names: Sequence[Optional[str]], - actual_arg_type: Callable[[int], - Type]) -> List[List[int]]: + actual_arg_type: Callable[[int], Type], + formal_types: List[Type]) -> List[List[int]]: """Calculate mapping between actual (caller) args and formals. The result contains a list of caller argument indexes mapping to each @@ -82,7 +83,8 @@ def map_actuals_to_formals(actual_kinds: List[int], ambiguous_actual_kwargs.append(ai) if ambiguous_actual_kwargs: - # Assume the ambiguous kwargs will fill the remaining arguments. + # Assume the ambiguous kwargs will fill the remaining arguments where + # their types are compatible. # # TODO: If there are also tuple varargs, we might be missing some potential # matches if the tuple was short enough to not match everything. @@ -93,24 +95,46 @@ def map_actuals_to_formals(actual_kinds: List[int], and formal_kinds[fi] != nodes.ARG_STAR) or formal_kinds[fi] == nodes.ARG_STAR2] for ai in ambiguous_actual_kwargs: - for fi in unmatched_formals: + for fi in map_kwargs_to_actuals(get_proper_type(actual_arg_type(ai)), + actual_kinds[ai], unmatched_formals, + formal_types, formal_names, formal_kinds): formal_to_actual[fi].append(ai) - return formal_to_actual +def map_kwargs_to_actuals(actual_type: Type, actual_kind: int, + formals: List[int], + formal_types: List[Type], + formal_names: Sequence[Optional[str]], + formal_kinds: List[int]) -> List[int]: + mapped_formals = [] # type: List[int] + from mypy.subtypes import is_subtype + for fi in formals: + if formal_kinds[fi] == nodes.ARG_STAR: + continue + mapper = ArgTypeExpander() + expanded_actual_type = mapper.expand_actual_type(actual_type, actual_kind, + formal_names[fi], + formal_kinds[fi]) + formal_type = formal_types[fi] + if is_subtype(expanded_actual_type, formal_type) or isinstance(formal_type, TypeVarType): + mapped_formals.append(fi) + return mapped_formals + + def map_formals_to_actuals(actual_kinds: List[int], actual_names: Optional[Sequence[Optional[str]]], formal_kinds: List[int], formal_names: List[Optional[str]], - actual_arg_type: Callable[[int], - Type]) -> List[List[int]]: + actual_arg_type: Callable[[int], Type], + formal_types: List[Type]) -> List[List[int]]: """Calculate the reverse mapping of map_actuals_to_formals.""" formal_to_actual = map_actuals_to_formals(actual_kinds, actual_names, formal_kinds, formal_names, - actual_arg_type) + actual_arg_type, + formal_types) # Now reverse the mapping. actual_to_formal = [[] for _ in actual_kinds] # type: List[List[int]] for formal, actuals in enumerate(formal_to_actual): diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 40204e7c9ccf..a2b9ee76df9b 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -50,7 +50,9 @@ from mypy import applytype from mypy import erasetype from mypy.checkmember import analyze_member_access, type_object_type -from mypy.argmap import ArgTypeExpander, map_actuals_to_formals, map_formals_to_actuals +from mypy.argmap import ( + ArgTypeExpander, map_actuals_to_formals, map_formals_to_actuals, map_kwargs_to_actuals +) from mypy.checkstrformat import StringFormatterChecker from mypy.expandtype import expand_type, expand_type_by_instance, freshen_function_type_vars from mypy.util import split_module_names @@ -309,8 +311,8 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) -> formal_to_actual = map_actuals_to_formals( e.arg_kinds, e.arg_names, e.callee.arg_kinds, e.callee.arg_names, - lambda i: self.accept(e.args[i])) - + lambda i: self.accept(e.args[i]), + [Any] * len(e.callee.arg_names)) arg_types = [join.join_type_list([self.accept(e.args[j]) for j in formal_to_actual[i]]) for i in range(len(e.callee.arg_kinds))] type_context = CallableType(arg_types, e.callee.arg_kinds, e.callee.arg_names, @@ -748,7 +750,8 @@ def apply_signature_hook( formal_to_actual = map_actuals_to_formals( arg_kinds, arg_names, callee.arg_kinds, callee.arg_names, - lambda i: self.accept(args[i])) + lambda i: self.accept(args[i]), + callee.arg_types) formal_arg_exprs = [[] for _ in range(num_formals)] # type: List[List[Expression]] for formal, actuals in enumerate(formal_to_actual): for actual in actuals: @@ -990,7 +993,8 @@ def check_callable_call(self, formal_to_actual = map_actuals_to_formals( arg_kinds, arg_names, callee.arg_kinds, callee.arg_names, - lambda i: self.accept(args[i])) + lambda i: self.accept(args[i]), + callee.arg_types) if callee.is_generic(): callee = freshen_function_type_vars(callee) @@ -1383,6 +1387,31 @@ def check_argument_count(self, ok = False return ok + def check_for_incompatible_kwargs(self, + callee: CallableType, + actual_types: List[Type], + actual_kinds: List[int], + context: Context, + messages: MessageBuilder, + formal_to_actual: List[List[int]]) -> bool: + """Each **kwarg supplied to a callable should map to at least one formal + parameter. + """ + ambiguous_kwargs = [(i, actualt, actualk) + for i, (actualt, actualk) in enumerate(zip(actual_types, actual_kinds)) + if actualk == nodes.ARG_STAR2 and not isinstance(actualt, TypedDictType)] + for i, actualt, actualk in ambiguous_kwargs: + potential_formals = [] # type: List[int] + actual_formals = [] # type: List[int] + for fi in map_kwargs_to_actuals(actualt, actualk, list(range(len(callee.arg_types))), + callee.arg_types, callee.arg_names, callee.arg_kinds): + potential_formals.append(fi) + if i in formal_to_actual[fi]: + actual_formals.append(fi) + if not actual_formals: + messages.kwargs_has_no_compatible_parameter(callee, context, i, actualt, + potential_formals) + def check_for_extra_actual_arguments(self, callee: CallableType, actual_types: List[Type], @@ -1401,11 +1430,14 @@ def check_for_extra_actual_arguments(self, ok = True # False if we've found any error for i, kind in enumerate(actual_kinds): - if i not in all_actuals and ( - kind != nodes.ARG_STAR or + if (i not in all_actuals and # We accept the other iterables than tuple (including Any) # as star arguments because they could be empty, resulting no arguments. - is_non_empty_tuple(actual_types[i])): + (kind != nodes.ARG_STAR or is_non_empty_tuple(actual_types[i])) #and + # Accept all types for double-starred arguments, because they could be empty + # dictionaries and we can't tell it from their types + #kind != nodes.ARG_STAR2 + ): # Extra actual: not matched by a formal argument. ok = False if kind != nodes.ARG_NAMED: @@ -1454,6 +1486,8 @@ def check_argument_types(self, """ messages = messages or self.msg check_arg = check_arg or self.check_arg + self.check_for_incompatible_kwargs(callee, arg_types, arg_kinds, + context, messages, formal_to_actual) # Keep track of consumed tuple *arg items. mapper = ArgTypeExpander() for i, actuals in enumerate(formal_to_actual): @@ -1492,7 +1526,6 @@ def check_arg(self, caller_type = get_proper_type(caller_type) original_caller_type = get_proper_type(original_caller_type) callee_type = get_proper_type(callee_type) - if isinstance(caller_type, DeletedType): messages.deleted_as_rvalue(caller_type, context) # Only non-abstract non-protocol class can be given where Type[...] is expected... @@ -1502,7 +1535,8 @@ def check_arg(self, isinstance(callee_type.item, Instance) and (callee_type.item.type.is_abstract or callee_type.item.type.is_protocol)): self.msg.concrete_only_call(callee_type, context) - elif not is_subtype(caller_type, callee_type): + elif not is_subtype(caller_type, callee_type) and (caller_kind != nodes.ARG_STAR2 + or isinstance(original_caller_type, TypedDictType)): if self.chk.should_suppress_optional_error([caller_type, callee_type]): return code = messages.incompatible_argument(n, @@ -1657,7 +1691,8 @@ def has_shape(typ: Type) -> bool: for typ in overload.items(): formal_to_actual = map_actuals_to_formals(arg_kinds, arg_names, typ.arg_kinds, typ.arg_names, - lambda i: arg_types[i]) + lambda i: arg_types[i], + typ.arg_types) if self.check_argument_count(typ, arg_types, arg_kinds, arg_names, formal_to_actual, None, None): @@ -1733,7 +1768,7 @@ def infer_overload_return_type(self, if len(matches) == 0: # No match was found return None - elif any_causes_overload_ambiguity(matches, return_types, arg_types, arg_kinds, arg_names): + elif any_causes_overload_ambiguity(matches, return_types, arg_types, arg_kinds, arg_names, self.chk): # An argument of type or containing the type 'Any' caused ambiguity. # We try returning a precise type if we can. If not, we give up and just return 'Any'. if all_same_types(return_types): @@ -1959,7 +1994,8 @@ def erased_signature_similarity(self, arg_names, callee.arg_kinds, callee.arg_names, - lambda i: arg_types[i]) + lambda i: arg_types[i], + callee.arg_types) if not self.check_argument_count(callee, arg_types, arg_kinds, arg_names, formal_to_actual, None, None): @@ -4363,7 +4399,8 @@ def any_causes_overload_ambiguity(items: List[CallableType], return_types: List[Type], arg_types: List[Type], arg_kinds: List[int], - arg_names: Optional[Sequence[Optional[str]]]) -> bool: + arg_names: Optional[Sequence[Optional[str]]], + checker: 'checker.TypeChecker') -> bool: """May an argument containing 'Any' cause ambiguous result type on call to overloaded function? Note that this sometimes returns True even if there is no ambiguity, since a correct @@ -4381,7 +4418,10 @@ def any_causes_overload_ambiguity(items: List[CallableType], actual_to_formal = [ map_formals_to_actuals( - arg_kinds, arg_names, item.arg_kinds, item.arg_names, lambda i: arg_types[i]) + arg_kinds, arg_names, + item.arg_kinds, item.arg_names, + lambda i: arg_types[i], + item.arg_types) for item in items ] diff --git a/mypy/messages.py b/mypy/messages.py index 6c1a6f734d89..9d0fcbf2f837 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -615,6 +615,27 @@ def too_many_arguments(self, callee: CallableType, context: Context) -> None: msg = 'Too many arguments' + for_function(callee) self.fail(msg, context, code=codes.CALL_ARG) + def kwargs_has_no_compatible_parameter(self, callee: CallableType, context: Context, + kwargs_index: int, kwargs_type: Type, + formals: List[int]) -> None: + callee_name = callable_name(callee) + kwargs_type_str = format_type(kwargs_type) + argument_number = kwargs_index + 1 + if formals: + msg = ('Argument {} in call to {} with type {} cannot unpack into any expected parameters; ' + '{} in use'. + format(argument_number, + callee_name, + kwargs_type_str, + ', '.join('"' + callee.arg_names[fi] + '"' for fi in formals))) + else: + msg = ('Argument {} in call to {} cannot unpack into any parameters; ' + 'no parameter accepts type {}'. + format(argument_number, + callee_name, + kwargs_type_str)) + self.fail(msg, context, code=codes.CALL_ARG) + def too_many_arguments_from_typed_dict(self, callee: CallableType, arg_type: TypedDictType, diff --git a/mypy/stats.py b/mypy/stats.py index 17725ac86bdc..5142c4a00e3e 100644 --- a/mypy/stats.py +++ b/mypy/stats.py @@ -19,7 +19,8 @@ Expression, FuncDef, TypeApplication, AssignmentStmt, NameExpr, CallExpr, MypyFile, MemberExpr, OpExpr, ComparisonExpr, IndexExpr, UnaryExpr, YieldFromExpr, RefExpr, ClassDef, AssignmentExpr, ImportFrom, Import, ImportAll, PassStmt, BreakStmt, ContinueStmt, StrExpr, - BytesExpr, UnicodeExpr, IntExpr, FloatExpr, ComplexExpr, EllipsisExpr, ExpressionStmt, Node + BytesExpr, UnicodeExpr, IntExpr, FloatExpr, ComplexExpr, EllipsisExpr, ExpressionStmt, Node, + TypeInfo, SymbolTableNode ) from mypy.util import correct_relative_import from mypy.argmap import map_formals_to_actuals @@ -250,7 +251,8 @@ def record_callable_target_precision(self, o: CallExpr, callee: CallableType) -> o.arg_names, callee.arg_kinds, callee.arg_names, - lambda n: typemap[o.args[n]]) + lambda n: typemap[o.args[n]], + callee.arg_types) for formals in actual_to_formal: for n in formals: formal = get_proper_type(callee.arg_types[n]) @@ -321,6 +323,55 @@ def record_precise_if_checked_scope(self, node: Node) -> None: kind = TYPE_ANY self.record_line(node.line, kind) + def lookup_typeinfo(self, fullname: str) -> TypeInfo: + # Assume that the name refers to a class. + sym = self.lookup_qualified(fullname) + node = sym.node + assert isinstance(node, TypeInfo) + return node + + def lookup_qualified(self, name: str) -> SymbolTableNode: + if '.' not in name: + return self.lookup(name, GDEF) # FIX kind + else: + parts = name.split('.') + n = self.modules[parts[0]] + for i in range(1, len(parts) - 1): + sym = n.names.get(parts[i]) + assert sym is not None, "Internal error: attempted lookup of unknown name" + n = cast(MypyFile, sym.node) + last = parts[-1] + if last in n.names: + return n.names[last] + elif len(parts) == 2 and parts[0] == 'builtins': + fullname = 'builtins.' + last + if fullname in SUGGESTED_TEST_FIXTURES: + suggestion = ", e.g. add '[builtins fixtures/{}]' to your test".format( + SUGGESTED_TEST_FIXTURES[fullname]) + else: + suggestion = '' + raise KeyError("Could not find builtin symbol '{}' (If you are running a " + "test case, use a fixture that " + "defines this symbol{})".format(last, suggestion)) + else: + msg = "Failed qualified lookup: '{}' (fullname = '{}')." + raise KeyError(msg.format(last, name)) + + def named_type(self, name: str) -> Instance: + """Return an instance type with given name and implicit Any type args. + + For example, named_type('builtins.object') produces the 'object' type. + """ + # Assume that the name refers to a type. + sym = self.lookup_qualified(name) + node = sym.node + if isinstance(node, TypeAlias): + assert isinstance(node.target, Instance) # type: ignore + node = node.target.type + assert isinstance(node, TypeInfo) + any_type = AnyType(TypeOfAny.from_omitted_generics) + return Instance(node, [any_type] * len(node.defn.type_vars)) + def type(self, t: Optional[Type]) -> None: t = get_proper_type(t) diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test index 339d0ce863a7..58263669a828 100644 --- a/test-data/unit/check-columns.test +++ b/test-data/unit/check-columns.test @@ -72,7 +72,9 @@ def g(**x: int) -> None: pass a = [''] f(*a) # E:4: Argument 1 to "f" has incompatible type "*List[str]"; expected "int" b = {'x': 'y'} -g(**b) # E:5: Argument 1 to "g" has incompatible type "**Dict[str, str]"; expected "int" +# TODO: "too many arguments" error will not appear after #9629 is merged +g(**b) # E:1: Too many arguments for "g" \ + # E:1: Argument 1 in call to "g" cannot unpack into any parameters; no parameter accepts type "Dict[str, str]" [builtins fixtures/dict.pyi] [case testColumnsMultipleStatementsPerLine] diff --git a/test-data/unit/check-ctypes.test b/test-data/unit/check-ctypes.test index f6e55a451794..49b23029994d 100644 --- a/test-data/unit/check-ctypes.test +++ b/test-data/unit/check-ctypes.test @@ -182,6 +182,7 @@ import ctypes intarr4 = ctypes.c_int * 4 x = {"a": 1, "b": 2} -intarr4(**x) # E: Too many arguments for "Array" +intarr4(**x) # E: Too many arguments for "Array" \ + # E: Argument 1 in call to "Array" cannot unpack into any parameters; no parameter accepts type "Dict[str, int]" [builtins fixtures/floatdict.pyi] diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index 4eb52be6f8bd..edd08e4f3609 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -2217,7 +2217,8 @@ kw2 = {'x': ''} d2 = dict(it, **kw2) d2() # E: "Dict[str, object]" not callable -d3 = dict(it, **kw2) # type: Dict[str, int] # E: Argument 2 to "dict" has incompatible type "**Dict[str, str]"; expected "int" +d3 = dict(it, **kw2) # type: Dict[str, int] \ + # E: Argument 2 in call to "dict" cannot unpack into any parameters; no parameter accepts type "Dict[str, str]" [builtins fixtures/dict.pyi] [case testDictFromIterableAndStarStarArgs2] diff --git a/test-data/unit/check-kwargs.test b/test-data/unit/check-kwargs.test index 96669e7eea36..df9b41cf402e 100644 --- a/test-data/unit/check-kwargs.test +++ b/test-data/unit/check-kwargs.test @@ -299,8 +299,11 @@ d = None # type: Dict[str, A] f(**d) f(x=A(), **d) d2 = None # type: Dict[str, B] -f(**d2) # E: Argument 1 to "f" has incompatible type "**Dict[str, B]"; expected "A" -f(x=A(), **d2) # E: Argument 2 to "f" has incompatible type "**Dict[str, B]"; expected "A" +# TODO: "too many arguments" errors will not appear after #9629 is merged +f(**d2) # E: Too many arguments for "f" \ + # E: Argument 1 in call to "f" cannot unpack into any parameters; no parameter accepts type "Dict[str, B]" +f(x=A(), **d2) # E: Too many arguments for "f" \ + # E: Argument 2 in call to "f" cannot unpack into any parameters; no parameter accepts type "Dict[str, B]" class A: pass class B: pass [builtins fixtures/dict.pyi] @@ -363,7 +366,7 @@ def f(a: 'A', b: 'B') -> None: pass d = None # type: Dict[str, Any] f(**d) d2 = None # type: Dict[str, A] -f(**d2) # E: Argument 1 to "f" has incompatible type "**Dict[str, A]"; expected "B" +f(**d2) # E: Too few arguments for "f" class A: pass class B: pass [builtins fixtures/dict.pyi] @@ -396,7 +399,8 @@ class A: pass from typing import Any, Dict def f(*args: 'A') -> None: pass d = None # type: Dict[Any, Any] -f(**d) # E: Too many arguments for "f" +f(**d) # E: Too many arguments for "f" \ + # E: Argument 1 in call to "f" cannot unpack into any parameters; no parameter accepts type "Dict[Any, Any]" class A: pass [builtins fixtures/dict.pyi] @@ -440,7 +444,10 @@ f(**a) # okay b = {'': ''} f(b) # E: Argument 1 to "f" has incompatible type "Dict[str, str]"; expected "int" -f(**b) # E: Argument 1 to "f" has incompatible type "**Dict[str, str]"; expected "int" +# TODO: "too many arguments" error will not appear after #9629 is merged +f(**b) # E: Too many arguments for "f" \ + # E: Too few arguments for "f" \ + # E: Argument 1 in call to "f" cannot unpack into any parameters; no parameter accepts type "Dict[str, str]" c = {0: 0} f(**c) # E: Keywords must be strings @@ -451,6 +458,76 @@ def f(**k): pass f(*(1, 2)) # E: Too many arguments for "f" [builtins fixtures/dict.pyi] +[case testCallKwargsDifferentTypes] +from typing import Dict +class A: pass +class B: pass +class C: pass + +ad = None # type: Dict[str, A] +bd = None # type: Dict[str, B] +cd = None # type: Dict[str, C] + +# TODO: "too many arguments" errors will not appear after #9629 is merged + +def f1(a: A, b: B): pass +f1(**ad, **bd) +f1(**bd, **ad) +f1(a=A(), **ad, **bd) # E: Too many arguments for "f1" \ + # E: Argument 2 in call to "f1" with type "Dict[str, A]" cannot unpack into any expected parameters; "a" in use +f1(b=B(), **ad, **bd) # E: Too many arguments for "f1" \ + # E: Argument 3 in call to "f1" with type "Dict[str, B]" cannot unpack into any expected parameters; "b" in use +f1(a=A(), b=B(), **ad, **bd) # E: Too many arguments for "f1" \ + # E: Argument 3 in call to "f1" with type "Dict[str, A]" cannot unpack into any expected parameters; "a" in use \ + # E: Argument 4 in call to "f1" with type "Dict[str, B]" cannot unpack into any expected parameters; "b" in use +f1(**ad) # E: Too few arguments for "f1" +f1(b=B(), **ad) +f1(**bd) # E: Too few arguments for "f1" +f1(A(), **bd) +f1(**ad, **bd, **cd) # E: Too many arguments for "f1" \ + # E: Argument 3 in call to "f1" cannot unpack into any parameters; no parameter accepts type "Dict[str, C]" + +def f2(a: A = A(), b: B = B()): pass +f2(**ad, **bd) +f2(**bd, **ad) +f2(a=A(), **ad, **bd) # E: Too many arguments for "f2" \ + # E: Argument 2 in call to "f2" with type "Dict[str, A]" cannot unpack into any expected parameters; "a" in use +f2(b=B(), **ad, **bd) # E: Too many arguments for "f2" \ + # E: Argument 3 in call to "f2" with type "Dict[str, B]" cannot unpack into any expected parameters; "b" in use +f2(a=A(), b=B(), **ad, **bd) # E: Too many arguments for "f2" \ + # E: Argument 3 in call to "f2" with type "Dict[str, A]" cannot unpack into any expected parameters; "a" in use \ + # E: Argument 4 in call to "f2" with type "Dict[str, B]" cannot unpack into any expected parameters; "b" in use +f2(**ad) +f2(A(), **ad) # E: Too many arguments for "f2" \ + # E: Argument 2 in call to "f2" with type "Dict[str, A]" cannot unpack into any expected parameters; "a" in use +f2(**bd) +f2(b=B(), **bd) # E: Too many arguments for "f2" \ + # E: Argument 2 in call to "f2" with type "Dict[str, B]" cannot unpack into any expected parameters; "b" in use +f2(**ad, **bd, **cd) # E: Too many arguments for "f2" \ + # E: Argument 3 in call to "f2" cannot unpack into any parameters; no parameter accepts type "Dict[str, C]" +f2(**cd) # E: Too many arguments for "f2" \ + # E: Argument 1 in call to "f2" cannot unpack into any parameters; no parameter accepts type "Dict[str, C]" + +def f3(a: A = A(), **bs: B): pass +f3(**ad, **bd) +f3(**bd, **ad) + +f3(a=A(), **ad, **bd) # E: Too many arguments for "f3" \ + # E: Argument 2 in call to "f3" with type "Dict[str, A]" cannot unpack into any expected parameters; "a" in use +f3(b=B(), **ad, **bd) +f3(a=A(), b=B(), **ad, **bd) # E: Too many arguments for "f3" \ + # E: Argument 3 in call to "f3" with type "Dict[str, A]" cannot unpack into any expected parameters; "a" in use +f3(**ad) +f3(A(), **ad) # E: Too many arguments for "f3" \ + # E: Argument 2 in call to "f3" with type "Dict[str, A]" cannot unpack into any expected parameters; "a" in use +f3(**bd) +f3(b=B(), **bd) +f3(**ad, **bd, **cd) # E: Too many arguments for "f3" \ + # E: Argument 3 in call to "f3" cannot unpack into any parameters; no parameter accepts type "Dict[str, C]" +f3(**cd) # E: Too many arguments for "f3" \ + # E: Argument 1 in call to "f3" cannot unpack into any parameters; no parameter accepts type "Dict[str, C]" +[builtins fixtures/dict.pyi] + [case testUnexpectedMethodKwargInNestedClass] class A: class B: @@ -485,9 +562,9 @@ def g(arg: int = 0, **kwargs: object) -> None: d = {} # type: Dict[str, object] f(**d) -g(**d) # E: Argument 1 to "g" has incompatible type "**Dict[str, object]"; expected "int" +g(**d) m = {} # type: Mapping[str, object] f(**m) -g(**m) # TODO: Should be an error +g(**m) [builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index 2c474f389ad4..b8156dfa04df 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -1584,8 +1584,11 @@ d = None # type: Dict[Any, Any] f1(**td, **d) f1(**d, **td) -f2(**td, **d) # E: Too many arguments for "f2" -f2(**d, **td) # E: Too many arguments for "f2" +# TODO: the "too many arguments" errors will go away with #9269 +f2(**td, **d) # E: Too many arguments for "f2" \ + # E: Argument 2 in call to "f2" with type "Dict[Any, Any]" cannot unpack into any expected parameters; "x", "y" in use +f2(**d, **td) # E: Too many arguments for "f2" \ + # E: Argument 1 in call to "f2" with type "Dict[Any, Any]" cannot unpack into any expected parameters; "x", "y" in use [builtins fixtures/dict.pyi] [case testTypedDictNonMappingMethods] From aca901cf917bff03c27138b428f8fd73ca9c8121 Mon Sep 17 00:00:00 2001 From: Erik Soma Date: Thu, 5 Nov 2020 19:17:27 -0500 Subject: [PATCH 02/10] Some cleanup. --- mypy/checkexpr.py | 15 ++++++------- mypy/stats.py | 37 +------------------------------- test-data/unit/check-kwargs.test | 2 +- 3 files changed, 8 insertions(+), 46 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index a2b9ee76df9b..556e98e0c7c9 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1430,14 +1430,11 @@ def check_for_extra_actual_arguments(self, ok = True # False if we've found any error for i, kind in enumerate(actual_kinds): - if (i not in all_actuals and + if i not in all_actuals and ( + kind != nodes.ARG_STAR or # We accept the other iterables than tuple (including Any) # as star arguments because they could be empty, resulting no arguments. - (kind != nodes.ARG_STAR or is_non_empty_tuple(actual_types[i])) #and - # Accept all types for double-starred arguments, because they could be empty - # dictionaries and we can't tell it from their types - #kind != nodes.ARG_STAR2 - ): + is_non_empty_tuple(actual_types[i])): # Extra actual: not matched by a formal argument. ok = False if kind != nodes.ARG_NAMED: @@ -1526,6 +1523,7 @@ def check_arg(self, caller_type = get_proper_type(caller_type) original_caller_type = get_proper_type(original_caller_type) callee_type = get_proper_type(callee_type) + if isinstance(caller_type, DeletedType): messages.deleted_as_rvalue(caller_type, context) # Only non-abstract non-protocol class can be given where Type[...] is expected... @@ -1768,7 +1766,7 @@ def infer_overload_return_type(self, if len(matches) == 0: # No match was found return None - elif any_causes_overload_ambiguity(matches, return_types, arg_types, arg_kinds, arg_names, self.chk): + elif any_causes_overload_ambiguity(matches, return_types, arg_types, arg_kinds, arg_names): # An argument of type or containing the type 'Any' caused ambiguity. # We try returning a precise type if we can. If not, we give up and just return 'Any'. if all_same_types(return_types): @@ -4399,8 +4397,7 @@ def any_causes_overload_ambiguity(items: List[CallableType], return_types: List[Type], arg_types: List[Type], arg_kinds: List[int], - arg_names: Optional[Sequence[Optional[str]]], - checker: 'checker.TypeChecker') -> bool: + arg_names: Optional[Sequence[Optional[str]]]) -> bool: """May an argument containing 'Any' cause ambiguous result type on call to overloaded function? Note that this sometimes returns True even if there is no ambiguity, since a correct diff --git a/mypy/stats.py b/mypy/stats.py index 5142c4a00e3e..19cffb78db13 100644 --- a/mypy/stats.py +++ b/mypy/stats.py @@ -19,8 +19,7 @@ Expression, FuncDef, TypeApplication, AssignmentStmt, NameExpr, CallExpr, MypyFile, MemberExpr, OpExpr, ComparisonExpr, IndexExpr, UnaryExpr, YieldFromExpr, RefExpr, ClassDef, AssignmentExpr, ImportFrom, Import, ImportAll, PassStmt, BreakStmt, ContinueStmt, StrExpr, - BytesExpr, UnicodeExpr, IntExpr, FloatExpr, ComplexExpr, EllipsisExpr, ExpressionStmt, Node, - TypeInfo, SymbolTableNode + BytesExpr, UnicodeExpr, IntExpr, FloatExpr, ComplexExpr, EllipsisExpr, ExpressionStmt, Node ) from mypy.util import correct_relative_import from mypy.argmap import map_formals_to_actuals @@ -323,40 +322,6 @@ def record_precise_if_checked_scope(self, node: Node) -> None: kind = TYPE_ANY self.record_line(node.line, kind) - def lookup_typeinfo(self, fullname: str) -> TypeInfo: - # Assume that the name refers to a class. - sym = self.lookup_qualified(fullname) - node = sym.node - assert isinstance(node, TypeInfo) - return node - - def lookup_qualified(self, name: str) -> SymbolTableNode: - if '.' not in name: - return self.lookup(name, GDEF) # FIX kind - else: - parts = name.split('.') - n = self.modules[parts[0]] - for i in range(1, len(parts) - 1): - sym = n.names.get(parts[i]) - assert sym is not None, "Internal error: attempted lookup of unknown name" - n = cast(MypyFile, sym.node) - last = parts[-1] - if last in n.names: - return n.names[last] - elif len(parts) == 2 and parts[0] == 'builtins': - fullname = 'builtins.' + last - if fullname in SUGGESTED_TEST_FIXTURES: - suggestion = ", e.g. add '[builtins fixtures/{}]' to your test".format( - SUGGESTED_TEST_FIXTURES[fullname]) - else: - suggestion = '' - raise KeyError("Could not find builtin symbol '{}' (If you are running a " - "test case, use a fixture that " - "defines this symbol{})".format(last, suggestion)) - else: - msg = "Failed qualified lookup: '{}' (fullname = '{}')." - raise KeyError(msg.format(last, name)) - def named_type(self, name: str) -> Instance: """Return an instance type with given name and implicit Any type args. diff --git a/test-data/unit/check-kwargs.test b/test-data/unit/check-kwargs.test index df9b41cf402e..9853379141cb 100644 --- a/test-data/unit/check-kwargs.test +++ b/test-data/unit/check-kwargs.test @@ -566,5 +566,5 @@ g(**d) m = {} # type: Mapping[str, object] f(**m) -g(**m) +g(**m) # TODO: Should be an error [builtins fixtures/dict.pyi] From bf27b0fa1d43762938382ca250ef8c32a5ec34b9 Mon Sep 17 00:00:00 2001 From: Erik Soma Date: Thu, 5 Nov 2020 19:21:12 -0500 Subject: [PATCH 03/10] Additional cleanup. --- mypy/argmap.py | 2 +- mypy/checkexpr.py | 2 +- mypy/stats.py | 15 --------------- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/mypy/argmap.py b/mypy/argmap.py index 0237b33c2f5f..a0d4b58f2c94 100644 --- a/mypy/argmap.py +++ b/mypy/argmap.py @@ -107,8 +107,8 @@ def map_kwargs_to_actuals(actual_type: Type, actual_kind: int, formal_types: List[Type], formal_names: Sequence[Optional[str]], formal_kinds: List[int]) -> List[int]: - mapped_formals = [] # type: List[int] from mypy.subtypes import is_subtype + mapped_formals = [] # type: List[int] for fi in formals: if formal_kinds[fi] == nodes.ARG_STAR: continue diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 556e98e0c7c9..4b37827bb650 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1523,7 +1523,7 @@ def check_arg(self, caller_type = get_proper_type(caller_type) original_caller_type = get_proper_type(original_caller_type) callee_type = get_proper_type(callee_type) - + if isinstance(caller_type, DeletedType): messages.deleted_as_rvalue(caller_type, context) # Only non-abstract non-protocol class can be given where Type[...] is expected... diff --git a/mypy/stats.py b/mypy/stats.py index 19cffb78db13..6f9f2a4ee7c6 100644 --- a/mypy/stats.py +++ b/mypy/stats.py @@ -322,21 +322,6 @@ def record_precise_if_checked_scope(self, node: Node) -> None: kind = TYPE_ANY self.record_line(node.line, kind) - def named_type(self, name: str) -> Instance: - """Return an instance type with given name and implicit Any type args. - - For example, named_type('builtins.object') produces the 'object' type. - """ - # Assume that the name refers to a type. - sym = self.lookup_qualified(name) - node = sym.node - if isinstance(node, TypeAlias): - assert isinstance(node.target, Instance) # type: ignore - node = node.target.type - assert isinstance(node, TypeInfo) - any_type = AnyType(TypeOfAny.from_omitted_generics) - return Instance(node, [any_type] * len(node.defn.type_vars)) - def type(self, t: Optional[Type]) -> None: t = get_proper_type(t) From 0966c8b79c749e3dda847ce44c33641b43cef6c4 Mon Sep 17 00:00:00 2001 From: Erik Soma Date: Thu, 5 Nov 2020 19:22:38 -0500 Subject: [PATCH 04/10] Fix todo. --- test-data/unit/check-kwargs.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/check-kwargs.test b/test-data/unit/check-kwargs.test index 9853379141cb..de3aae73d25e 100644 --- a/test-data/unit/check-kwargs.test +++ b/test-data/unit/check-kwargs.test @@ -566,5 +566,5 @@ g(**d) m = {} # type: Mapping[str, object] f(**m) -g(**m) # TODO: Should be an error +g(**m) # TODO: Should be an error [builtins fixtures/dict.pyi] From 5f6f447d9a9f2f8df96e4277a5582676a352748c Mon Sep 17 00:00:00 2001 From: Erik Soma Date: Thu, 5 Nov 2020 22:11:02 -0500 Subject: [PATCH 05/10] Fix some errors due to changes to argmap api. --- mypy/checkexpr.py | 2 +- mypy/suggestions.py | 3 ++- mypy/test/testinfer.py | 8 +++++--- mypyc/irbuild/ll_builder.py | 4 +++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 4b37827bb650..c65290c120d5 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -312,7 +312,7 @@ def visit_call_expr_inner(self, e: CallExpr, allow_none_return: bool = False) -> e.arg_kinds, e.arg_names, e.callee.arg_kinds, e.callee.arg_names, lambda i: self.accept(e.args[i]), - [Any] * len(e.callee.arg_names)) + [AnyType(TypeOfAny.special_form)] * len(e.callee.arg_names)) arg_types = [join.join_type_list([self.accept(e.args[j]) for j in formal_to_actual[i]]) for i in range(len(e.callee.arg_kinds))] type_context = CallableType(arg_types, e.callee.arg_kinds, e.callee.arg_names, diff --git a/mypy/suggestions.py b/mypy/suggestions.py index 0a41b134db6f..f296e3baf70d 100644 --- a/mypy/suggestions.py +++ b/mypy/suggestions.py @@ -158,7 +158,8 @@ def visit_call_expr(self, o: CallExpr) -> None: formal_to_actual = map_actuals_to_formals( o.arg_kinds, o.arg_names, typ.arg_kinds, typ.arg_names, - lambda n: AnyType(TypeOfAny.special_form)) + lambda n: AnyType(TypeOfAny.special_form), + typ.arg_types) for i, args in enumerate(formal_to_actual): for arg_idx in args: diff --git a/mypy/test/testinfer.py b/mypy/test/testinfer.py index 0c2f55bc69ad..0ecd8319c534 100644 --- a/mypy/test/testinfer.py +++ b/mypy/test/testinfer.py @@ -1,6 +1,6 @@ """Test cases for type inference helper functions.""" -from typing import List, Optional, Tuple, Union, Dict, Set +from typing import Any, List, Optional, Tuple, Union, Dict, Set from mypy.test.helpers import Suite, assert_equal from mypy.argmap import map_actuals_to_formals @@ -181,7 +181,8 @@ def assert_map(self, caller_names, callee_kinds, callee_names, - lambda i: AnyType(TypeOfAny.special_form)) + lambda i: AnyType(TypeOfAny.special_form), + [AnyType(TypeOfAny.special_form)] * len(callee_kinds)) assert_equal(result, expected) def assert_vararg_map(self, @@ -195,7 +196,8 @@ def assert_vararg_map(self, [], callee_kinds, [], - lambda i: vararg_type) + lambda i: vararg_type, + [AnyType(TypeOfAny.special_form)] * len(callee_kinds)) assert_equal(result, expected) diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index e4ca731d2420..5826263d7fe6 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -333,11 +333,13 @@ def native_args_to_positional(self, sig_arg_kinds = [arg.kind for arg in sig.args] sig_arg_names = [arg.name for arg in sig.args] + sig_arg_types = [arg.type for arg in sig.args] formal_to_actual = map_actuals_to_formals(arg_kinds, arg_names, sig_arg_kinds, sig_arg_names, - lambda n: AnyType(TypeOfAny.special_form)) + lambda n: AnyType(TypeOfAny.special_form), + sig_arg_types) # Flatten out the arguments, loading error values for default # arguments, constructing tuples/dicts for star args, and From f56779fd3c69a193e6e2b2efde2891799decedee Mon Sep 17 00:00:00 2001 From: Erik Soma Date: Fri, 6 Nov 2020 17:20:38 -0500 Subject: [PATCH 06/10] Fix some lint and type errors. --- mypy/checkexpr.py | 8 +++++--- mypy/messages.py | 13 +++++++------ mypy/test/testinfer.py | 2 +- mypyc/irbuild/ll_builder.py | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index c65290c120d5..c03745b3ad23 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1393,13 +1393,14 @@ def check_for_incompatible_kwargs(self, actual_kinds: List[int], context: Context, messages: MessageBuilder, - formal_to_actual: List[List[int]]) -> bool: + formal_to_actual: List[List[int]]) -> None: """Each **kwarg supplied to a callable should map to at least one formal parameter. """ ambiguous_kwargs = [(i, actualt, actualk) for i, (actualt, actualk) in enumerate(zip(actual_types, actual_kinds)) - if actualk == nodes.ARG_STAR2 and not isinstance(actualt, TypedDictType)] + if actualk == nodes.ARG_STAR2 + and not isinstance(get_proper_type(actualt), TypedDictType)] for i, actualt, actualk in ambiguous_kwargs: potential_formals = [] # type: List[int] actual_formals = [] # type: List[int] @@ -1534,7 +1535,8 @@ def check_arg(self, (callee_type.item.type.is_abstract or callee_type.item.type.is_protocol)): self.msg.concrete_only_call(callee_type, context) elif not is_subtype(caller_type, callee_type) and (caller_kind != nodes.ARG_STAR2 - or isinstance(original_caller_type, TypedDictType)): + or isinstance(original_caller_type, + TypedDictType)): if self.chk.should_suppress_optional_error([caller_type, callee_type]): return code = messages.incompatible_argument(n, diff --git a/mypy/messages.py b/mypy/messages.py index 9d0fcbf2f837..6ec5d5b8dc85 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -622,12 +622,13 @@ def kwargs_has_no_compatible_parameter(self, callee: CallableType, context: Cont kwargs_type_str = format_type(kwargs_type) argument_number = kwargs_index + 1 if formals: - msg = ('Argument {} in call to {} with type {} cannot unpack into any expected parameters; ' - '{} in use'. - format(argument_number, - callee_name, - kwargs_type_str, - ', '.join('"' + callee.arg_names[fi] + '"' for fi in formals))) + formal_names = ', '.join(('"' + callee.arg_names[fi] + '"') + if callee.arg_names[fi] + else 'parameter {}'.format(fi) + for fi in formals) + msg = ('Argument {} in call to {} with type {} cannot unpack into any expected ' + 'parameters; {} in use'. + format(argument_number, callee_name, kwargs_type_str, formal_names)) else: msg = ('Argument {} in call to {} cannot unpack into any parameters; ' 'no parameter accepts type {}'. diff --git a/mypy/test/testinfer.py b/mypy/test/testinfer.py index 0ecd8319c534..0f3773b3e77c 100644 --- a/mypy/test/testinfer.py +++ b/mypy/test/testinfer.py @@ -1,6 +1,6 @@ """Test cases for type inference helper functions.""" -from typing import Any, List, Optional, Tuple, Union, Dict, Set +from typing import List, Optional, Tuple, Union, Dict, Set from mypy.test.helpers import Suite, assert_equal from mypy.argmap import map_actuals_to_formals diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index 5826263d7fe6..2825a02d0336 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -333,7 +333,7 @@ def native_args_to_positional(self, sig_arg_kinds = [arg.kind for arg in sig.args] sig_arg_names = [arg.name for arg in sig.args] - sig_arg_types = [arg.type for arg in sig.args] + sig_arg_types = [AnyType(TypeOfAny.special_form)] * len(sig_arg_kinds) formal_to_actual = map_actuals_to_formals(arg_kinds, arg_names, sig_arg_kinds, From 7483fd5987d93c47df75a76a1dacce47c30943dd Mon Sep 17 00:00:00 2001 From: Erik Soma Date: Fri, 6 Nov 2020 17:37:34 -0500 Subject: [PATCH 07/10] Fix kwarg mapping function name. --- mypy/argmap.py | 10 ++++++---- mypy/checkexpr.py | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/mypy/argmap.py b/mypy/argmap.py index a0d4b58f2c94..7e2ac716d309 100644 --- a/mypy/argmap.py +++ b/mypy/argmap.py @@ -83,8 +83,7 @@ def map_actuals_to_formals(actual_kinds: List[int], ambiguous_actual_kwargs.append(ai) if ambiguous_actual_kwargs: - # Assume the ambiguous kwargs will fill the remaining arguments where - # their types are compatible. + # Assume the ambiguous kwargs will fill the remaining arguments. # # TODO: If there are also tuple varargs, we might be missing some potential # matches if the tuple was short enough to not match everything. @@ -95,18 +94,21 @@ def map_actuals_to_formals(actual_kinds: List[int], and formal_kinds[fi] != nodes.ARG_STAR) or formal_kinds[fi] == nodes.ARG_STAR2] for ai in ambiguous_actual_kwargs: - for fi in map_kwargs_to_actuals(get_proper_type(actual_arg_type(ai)), + for fi in map_kwargs_to_formals(get_proper_type(actual_arg_type(ai)), actual_kinds[ai], unmatched_formals, formal_types, formal_names, formal_kinds): formal_to_actual[fi].append(ai) return formal_to_actual -def map_kwargs_to_actuals(actual_type: Type, actual_kind: int, +def map_kwargs_to_formals(actual_type: Type, actual_kind: int, formals: List[int], formal_types: List[Type], formal_names: Sequence[Optional[str]], formal_kinds: List[int]) -> List[int]: + """Generate the mapping between the actual **kwargs and formal parameters. Any given **kwarg + will only map to a parameter which it is type compatible with. + """ from mypy.subtypes import is_subtype mapped_formals = [] # type: List[int] for fi in formals: diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index c03745b3ad23..03d3eb8b6718 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -51,7 +51,7 @@ from mypy import erasetype from mypy.checkmember import analyze_member_access, type_object_type from mypy.argmap import ( - ArgTypeExpander, map_actuals_to_formals, map_formals_to_actuals, map_kwargs_to_actuals + ArgTypeExpander, map_actuals_to_formals, map_formals_to_actuals, map_kwargs_to_formals ) from mypy.checkstrformat import StringFormatterChecker from mypy.expandtype import expand_type, expand_type_by_instance, freshen_function_type_vars @@ -1404,7 +1404,7 @@ def check_for_incompatible_kwargs(self, for i, actualt, actualk in ambiguous_kwargs: potential_formals = [] # type: List[int] actual_formals = [] # type: List[int] - for fi in map_kwargs_to_actuals(actualt, actualk, list(range(len(callee.arg_types))), + for fi in map_kwargs_to_formals(actualt, actualk, list(range(len(callee.arg_types))), callee.arg_types, callee.arg_names, callee.arg_kinds): potential_formals.append(fi) if i in formal_to_actual[fi]: From eeefd18421609835ade4f8236b11997fe1139583 Mon Sep 17 00:00:00 2001 From: Erik Soma Date: Fri, 6 Nov 2020 19:00:27 -0500 Subject: [PATCH 08/10] Fix some lint errors. --- mypy/checkexpr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 03d3eb8b6718..a76b352bc2b8 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1400,10 +1400,10 @@ def check_for_incompatible_kwargs(self, ambiguous_kwargs = [(i, actualt, actualk) for i, (actualt, actualk) in enumerate(zip(actual_types, actual_kinds)) if actualk == nodes.ARG_STAR2 - and not isinstance(get_proper_type(actualt), TypedDictType)] + and not isinstance(get_proper_type(actualt), TypedDictType)] for i, actualt, actualk in ambiguous_kwargs: potential_formals = [] # type: List[int] - actual_formals = [] # type: List[int] + actual_formals = [] # type: List[int] for fi in map_kwargs_to_formals(actualt, actualk, list(range(len(callee.arg_types))), callee.arg_types, callee.arg_names, callee.arg_kinds): potential_formals.append(fi) From 8896280f6990fffe5c34e5eb6433dd9386781084 Mon Sep 17 00:00:00 2001 From: Erik Soma Date: Fri, 6 Nov 2020 19:06:25 -0500 Subject: [PATCH 09/10] Fix type error. --- mypy/messages.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index 6ec5d5b8dc85..cd2b5984c6c1 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -622,10 +622,11 @@ def kwargs_has_no_compatible_parameter(self, callee: CallableType, context: Cont kwargs_type_str = format_type(kwargs_type) argument_number = kwargs_index + 1 if formals: - formal_names = ', '.join(('"' + callee.arg_names[fi] + '"') - if callee.arg_names[fi] + formal_names = ', '.join(('"' + name + '"') + if name else 'parameter {}'.format(fi) - for fi in formals) + for fi, name in enumerate(callee.arg_names[fi] + for fi in formals)) msg = ('Argument {} in call to {} with type {} cannot unpack into any expected ' 'parameters; {} in use'. format(argument_number, callee_name, kwargs_type_str, formal_names)) From 17db395e0784109e661e1cbedbfb6256baeaf008 Mon Sep 17 00:00:00 2001 From: Erik Soma Date: Fri, 6 Nov 2020 19:18:28 -0500 Subject: [PATCH 10/10] Fix type error. --- mypyc/irbuild/ll_builder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypyc/irbuild/ll_builder.py b/mypyc/irbuild/ll_builder.py index 2825a02d0336..d2be4655a4b1 100644 --- a/mypyc/irbuild/ll_builder.py +++ b/mypyc/irbuild/ll_builder.py @@ -13,7 +13,7 @@ ) from mypy.nodes import ARG_POS, ARG_NAMED, ARG_STAR, ARG_STAR2, op_methods -from mypy.types import AnyType, TypeOfAny +from mypy.types import AnyType, TypeOfAny, Type from mypy.checkexpr import map_actuals_to_formals from mypyc.ir.ops import ( @@ -333,7 +333,7 @@ def native_args_to_positional(self, sig_arg_kinds = [arg.kind for arg in sig.args] sig_arg_names = [arg.name for arg in sig.args] - sig_arg_types = [AnyType(TypeOfAny.special_form)] * len(sig_arg_kinds) + sig_arg_types = [AnyType(TypeOfAny.special_form)] * len(sig_arg_kinds) # type: List[Type] formal_to_actual = map_actuals_to_formals(arg_kinds, arg_names, sig_arg_kinds,