From 83d09fdb99a56184a24b2134bb7fd697244bf456 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 27 Jun 2019 11:54:12 +0100 Subject: [PATCH 01/13] Point error message to incompatible argument expression Previously we just pointed to the beginning of the call expression, which is not great if there are multiple arguments. Also point to incompatible list/dict/set item instead of the beginning of a list/dict/set expression. Note that this may require some `# type: ignore` comments to be updated. --- mypy/checkexpr.py | 23 ++++++++++---- test-data/unit/check-columns.test | 53 ++++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 2466dbaf619a..188f08cb77d8 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -842,7 +842,7 @@ def check_callable_call(self, self.check_argument_count(callee, arg_types, arg_kinds, arg_names, formal_to_actual, context, self.msg) - self.check_argument_types(arg_types, arg_kinds, callee, formal_to_actual, context, + self.check_argument_types(arg_types, arg_kinds, args, callee, formal_to_actual, context, messages=arg_messages) if (callee.is_type_obj() and (len(arg_types) == 1) @@ -1271,6 +1271,7 @@ def check_for_extra_actual_arguments(self, def check_argument_types(self, arg_types: List[Type], arg_kinds: List[int], + args: List[Expression], callee: CallableType, formal_to_actual: List[List[int]], context: Context, @@ -1303,7 +1304,7 @@ def check_argument_types(self, callee.arg_names[i], callee.arg_kinds[i]) check_arg(expanded_actual, actual_type, arg_kinds[actual], callee.arg_types[i], - actual + 1, i + 1, callee, context, messages) + actual + 1, i + 1, callee, args[actual], messages) def check_arg(self, caller_type: Type, original_caller_type: Type, caller_kind: int, @@ -1404,7 +1405,7 @@ def check_overload_call(self, # Neither alternative matches, but we can guess the user probably wants the # second one. erased_targets = self.overload_erased_call_targets(plausible_targets, arg_types, - arg_kinds, arg_names, context) + arg_kinds, arg_names, args, context) # Step 5: We try and infer a second-best alternative if possible. If not, fall back # to using 'Any'. @@ -1569,6 +1570,7 @@ def overload_erased_call_targets(self, arg_types: List[Type], arg_kinds: List[int], arg_names: Optional[Sequence[Optional[str]]], + args: List[Expression], context: Context) -> List[CallableType]: """Returns a list of all targets that match the caller after erasing types. @@ -1576,7 +1578,8 @@ def overload_erased_call_targets(self, """ matches = [] # type: List[CallableType] for typ in plausible_targets: - if self.erased_signature_similarity(arg_types, arg_kinds, arg_names, typ, context): + if self.erased_signature_similarity(arg_types, arg_kinds, arg_names, args, typ, + context): matches.append(typ) return matches @@ -1755,8 +1758,11 @@ def combine_function_signatures(self, types: Sequence[Type]) -> Union[AnyType, C variables=variables, implicit=True) - def erased_signature_similarity(self, arg_types: List[Type], arg_kinds: List[int], + def erased_signature_similarity(self, + arg_types: List[Type], + arg_kinds: List[int], arg_names: Optional[Sequence[Optional[str]]], + args: List[Expression], callee: CallableType, context: Context) -> bool: """Determine whether arguments could match the signature at runtime, after @@ -1781,7 +1787,7 @@ def check_arg(caller_type: Type, original_caller_type: Type, caller_kind: int, raise Finished try: - self.check_argument_types(arg_types, arg_kinds, callee, + self.check_argument_types(arg_types, arg_kinds, args, callee, formal_to_actual, context=context, check_arg=check_arg) return True except Finished: @@ -3063,7 +3069,10 @@ def visit_dict_expr(self, e: DictExpr) -> Type: if key is None: stargs.append(value) else: - args.append(TupleExpr([key, value])) + tup = TupleExpr([key, value]) + tup.line = key.line + tup.column = key.column + args.append(tup) # Define type variables (used in constructors below). ktdef = TypeVarDef('KT', 'KT', -1, [], self.object_type()) vtdef = TypeVarDef('VT', 'VT', -2, [], self.object_type()) diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test index 7dbe55db92e7..cf1e8dd89da6 100644 --- a/test-data/unit/check-columns.test +++ b/test-data/unit/check-columns.test @@ -22,10 +22,47 @@ class A: pass A().f() A().f(1) -(A().f('')) # E:2: Argument 1 to "f" of "A" has incompatible type "str"; expected "int" -( A().f(1, 1)) # E:3: Argument 2 to "f" of "A" has incompatible type "int"; expected "str" +A().f('') # E:7: Argument 1 to "f" of "A" has incompatible type "str"; expected "int" +A().f(1, 1) # E:10: Argument 2 to "f" of "A" has incompatible type "int"; expected "str" (A().f(1, 'hello', 'hi')) # E:2: Too many arguments for "f" of "A" +[case testColumnsInvalidArgumentType] +# flags: --strict-optional +def f(x: int, y: str) -> None: ... +def g(*x: int) -> None: pass +def h(**x: int) -> None: pass +def ff(x: int) -> None: pass + +class A: + x: str + def __neg__(self) -> str: pass + def __add__(self, other: int) -> str: pass + def __lt__(self, other: int) -> str: pass + +f( + y=0, x=0) # E:4: Argument 1 to "f" has incompatible type "int"; expected "str" +f(x=0, + y=None) # E:6: Argument 2 to "f" has incompatible type "None"; expected "str" +g(1, '', 2) # E:6: Argument 2 to "g" has incompatible type "str"; expected "int" +aaa: str +h(x=1, y=aaa, z=2) # E:10: Argument 2 to "h" has incompatible type "str"; expected "int" +a: A +ff(a.x) # E:4: Argument 1 to "ff" has incompatible type "str"; expected "int" +ff([1]) # E:4: Argument 1 to "ff" has incompatible type "List[int]"; expected "int" +ff([1 for x in [1]]) # E:5: Argument 1 to "ff" has incompatible type "List[int]"; expected "int" +ff({1: 2}) # E:4: Argument 1 to "ff" has incompatible type "Dict[int, int]"; expected "int" +ff(1.1) # E:4: Argument 1 to "ff" has incompatible type "float"; expected "int" +ff( ( 1, 1)) # E:7: Argument 1 to "ff" has incompatible type "Tuple[int, int]"; expected "int" +ff(-a) # E:4: Argument 1 to "ff" has incompatible type "str"; expected "int" +ff(a + 1) # E:4: Argument 1 to "ff" has incompatible type "str"; expected "int" +ff(a < 1) # E:4: Argument 1 to "ff" has incompatible type "str"; expected "int" +ff([''][0]) # E:4: Argument 1 to "ff" has incompatible type "str"; expected "int" + +class B(A): + def f(self) -> None: + ff(super().__neg__()) # E:12: Argument 1 to "ff" has incompatible type "str"; expected "int" +[builtins fixtures/dict.pyi] + [case testColumnsMultipleStatementsPerLine] x = 15 y = 'hello' @@ -33,7 +70,7 @@ if int(): x = 2; y = x; y += 1 [out] main:4:12: error: Incompatible types in assignment (expression has type "int", variable has type "str") -main:4:19: error: Unsupported operand types for + ("str" and "int") +main:4:24: error: Unsupported operand types for + ("str" and "int") [case testColumnsSimpleIsinstance] import typing @@ -131,10 +168,10 @@ def f(x, y): pass [case testColumnListOrDictItemHasIncompatibleType] from typing import List, Dict # TODO: Point to the actual item since a list/dict literal can span many lines -x: List[int] = [ # E:16: List item 0 has incompatible type "str"; expected "int" - 'x'] -y: Dict[int, int] = { # E:21: Dict entry 0 has incompatible type "str": "int"; expected "int": "int" - 'x': 1 +x: List[int] = [ + 'x'] # E:5: List item 0 has incompatible type "str"; expected "int" +y: Dict[int, int] = { + 'x': 1 # E:5: Dict entry 0 has incompatible type "str": "int"; expected "int": "int" } [builtins fixtures/dict.pyi] @@ -144,7 +181,7 @@ x = None [case testColumnInvalidIndexing] from typing import List -([1]['']) # E:2: Invalid index type "str" for "List[int]"; expected type "int" +([1]['']) # E:6: Invalid index type "str" for "List[int]"; expected type "int" (1[1]) # E:2: Value of type "int" is not indexable def f() -> None: 1[1] = 1 # E:5: Unsupported target for indexed assignment From 4db0af3a741614b163073b923f08837f5e507618 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 27 Jun 2019 12:44:09 +0100 Subject: [PATCH 02/13] Turn off column numbers by default --- mypy/checker.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 1de0876e9367..8de180563412 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -3307,7 +3307,7 @@ def visit_decorator(self, e: Decorator) -> None: self.fail(message_registry.MULTIPLE_OVERLOADS_REQUIRED, e) continue dec = self.expr_checker.accept(d) - temp = self.temp_node(sig) + temp = self.temp_node(sig, context=e) fullname = None if isinstance(d, RefExpr): fullname = d.fullname @@ -4043,7 +4043,7 @@ def temp_node(self, t: Type, context: Optional[Context] = None) -> TempNode: """Create a temporary node with the given, fixed type.""" temp = TempNode(t) if context: - temp.set_line(context.get_line()) + temp.set_line(context.get_line(), context.get_column()) return temp def fail(self, msg: str, context: Context, *, code: Optional[ErrorCode] = None) -> None: From ade34e22029624d2bfb21b67ffbf5091a3a157b1 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 4 Sep 2019 16:56:37 +0100 Subject: [PATCH 03/13] Fix issues --- mypy/checkexpr.py | 48 +++++++++++++++++++++++++++++++++++++---------- mypy/messages.py | 14 ++++++++++---- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 188f08cb77d8..a118e997c58f 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -64,7 +64,16 @@ # Type of callback user for checking individual function arguments. See # check_args() below for details. -ArgChecker = Callable[[Type, Type, int, Type, int, int, CallableType, Context, MessageBuilder], +ArgChecker = Callable[[Type, + Type, + int, + Type, + int, + int, + CallableType, + Context, + Context, + MessageBuilder], None] # Maximum nesting level for math union in overloads, setting this to large values @@ -1304,12 +1313,19 @@ def check_argument_types(self, callee.arg_names[i], callee.arg_kinds[i]) check_arg(expanded_actual, actual_type, arg_kinds[actual], callee.arg_types[i], - actual + 1, i + 1, callee, args[actual], messages) + actual + 1, i + 1, callee, args[actual], context, messages) - def check_arg(self, caller_type: Type, original_caller_type: Type, + def check_arg(self, + caller_type: Type, + original_caller_type: Type, caller_kind: int, - callee_type: Type, n: int, m: int, callee: CallableType, - context: Context, messages: MessageBuilder) -> None: + callee_type: Type, + n: int, + m: int, + callee: CallableType, + context: Context, + outer_context: Context, + messages: MessageBuilder) -> None: """Check the type of a single argument in a call.""" caller_type = get_proper_type(caller_type) original_caller_type = get_proper_type(original_caller_type) @@ -1327,8 +1343,13 @@ def check_arg(self, caller_type: Type, original_caller_type: Type, elif not is_subtype(caller_type, callee_type): if self.chk.should_suppress_optional_error([caller_type, callee_type]): return - code = messages.incompatible_argument(n, m, callee, original_caller_type, - caller_kind, context) + code = messages.incompatible_argument(n, + m, + callee, + original_caller_type, + caller_kind, + context=context, + outer_context=outer_context) messages.incompatible_argument_note(original_caller_type, callee_type, context, code=code) @@ -1778,9 +1799,16 @@ def erased_signature_similarity(self, # Too few or many arguments -> no match. return False - def check_arg(caller_type: Type, original_caller_type: Type, caller_kind: int, - callee_type: Type, n: int, m: int, callee: CallableType, - context: Context, messages: MessageBuilder) -> None: + def check_arg(caller_type: Type, + original_ccaller_type: Type, + caller_kind: int, + callee_type: Type, + n: int, + m: int, + callee: CallableType, + context: Context, + outer_context: Context, + messages: MessageBuilder) -> None: if not arg_approximate_similarity(caller_type, callee_type): # No match -- exit early since none of the remaining work can change # the result. diff --git a/mypy/messages.py b/mypy/messages.py index 8e0d3ba38e0a..7703bf29e32f 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -324,8 +324,14 @@ def untyped_function_call(self, callee: CallableType, context: Context) -> Type: code=codes.NO_UNTYPED_CALL) return AnyType(TypeOfAny.from_error) - def incompatible_argument(self, n: int, m: int, callee: CallableType, arg_type: Type, - arg_kind: int, context: Context) -> Optional[ErrorCode]: + def incompatible_argument(self, + n: int, + m: int, + callee: CallableType, + arg_type: Type, + arg_kind: int, + context: Context, + outer_context: Context) -> Optional[ErrorCode]: """Report an error about an incompatible argument type. The argument type is arg_type, argument number is n and the @@ -456,8 +462,8 @@ def incompatible_argument(self, n: int, m: int, callee: CallableType, arg_type: # For function calls with keyword arguments, display the argument name rather than the # number. arg_label = str(n) - if isinstance(context, CallExpr) and len(context.arg_names) >= n: - arg_name = context.arg_names[n - 1] + if isinstance(outer_context, CallExpr) and len(outer_context.arg_names) >= n: + arg_name = outer_context.arg_names[n - 1] if arg_name is not None: arg_label = '"{}"'.format(arg_name) From aeb8f2b0dd1dd10d02112d41a84fdbcab1100ac4 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Wed, 4 Sep 2019 17:57:32 +0100 Subject: [PATCH 04/13] Fix line/column of slice expressions --- mypy/fastparse.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 27501bc92271..76ad3cb32109 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -1169,7 +1169,12 @@ def visit_Attribute(self, n: Attribute) -> Union[MemberExpr, SuperExpr]: # Subscript(expr value, slice slice, expr_context ctx) def visit_Subscript(self, n: ast3.Subscript) -> IndexExpr: e = IndexExpr(self.visit(n.value), self.visit(n.slice)) - return self.set_line(e, n) + e = self.set_line(e, n) + if isinstance(e.index, SliceExpr): + # Slice has no line/column in the raw ast. + e.index.line = e.line + e.index.column = e.line + return e # Starred(expr value, expr_context ctx) def visit_Starred(self, n: Starred) -> StarExpr: From 00fc08acd5130fd888dd9acad9e102c9154ceb36 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 5 Sep 2019 14:44:40 +0100 Subject: [PATCH 05/13] Fix various issues with wrong lines/columns; fix tests --- mypy/checker.py | 20 ++++++++++--------- mypy/checkexpr.py | 22 +++++++++++---------- mypy/checkmember.py | 3 ++- mypy/fastparse.py | 4 ++-- mypy/fastparse2.py | 4 ++-- mypy/nodes.py | 12 +++++++++-- test-data/unit/check-classes.test | 10 +++++----- test-data/unit/check-columns.test | 8 ++++---- test-data/unit/check-expressions.test | 6 +++--- test-data/unit/check-inference-context.test | 5 +++-- test-data/unit/check-isinstance.test | 4 ++-- test-data/unit/check-namedtuple.test | 2 +- test-data/unit/check-overloading.test | 7 ++++--- test-data/unit/check-unions.test | 4 ++-- 14 files changed, 63 insertions(+), 48 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 8de180563412..a608eb92d2fe 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1683,7 +1683,7 @@ def visit_class_def(self, defn: ClassDef) -> None: continue dec = self.expr_checker.accept(decorator) - temp = self.temp_node(sig) + temp = self.temp_node(sig, context=decorator) fullname = None if isinstance(decorator, RefExpr): fullname = decorator.fullname @@ -2796,15 +2796,20 @@ def check_member_assignment(self, instance_type: Type, attribute_type: Type, # For this we use the rvalue as type context. self.msg.disable_errors() _, inferred_dunder_set_type = self.expr_checker.check_call( - dunder_set_type, [TempNode(instance_type), rvalue], - [nodes.ARG_POS, nodes.ARG_POS], context) + dunder_set_type, + [TempNode(instance_type, context=context), rvalue], + [nodes.ARG_POS, nodes.ARG_POS], + context) self.msg.enable_errors() # And now we type check the call second time, to show errors related # to wrong arguments count, etc. self.expr_checker.check_call( - dunder_set_type, [TempNode(instance_type), TempNode(AnyType(TypeOfAny.special_form))], - [nodes.ARG_POS, nodes.ARG_POS], context) + dunder_set_type, + [TempNode(instance_type, context=context), + TempNode(AnyType(TypeOfAny.special_form), context=context)], + [nodes.ARG_POS, nodes.ARG_POS], + context) # should be handled by get_method above assert isinstance(inferred_dunder_set_type, CallableType) # type: ignore @@ -4041,10 +4046,7 @@ def find_partial_types_in_all_scopes( def temp_node(self, t: Type, context: Optional[Context] = None) -> TempNode: """Create a temporary node with the given, fixed type.""" - temp = TempNode(t) - if context: - temp.set_line(context.get_line(), context.get_column()) - return temp + return TempNode(t, context=context) def fail(self, msg: str, context: Context, *, code: Optional[ErrorCode] = None) -> None: """Produce an error message.""" diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index a118e997c58f..22029c875637 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1178,7 +1178,8 @@ def check_argument_count(self, if messages: assert context, "Internal error: messages given without context" elif context is None: - context = TempNode(AnyType(TypeOfAny.special_form)) # Avoid "is None" checks + # Avoid "is None" checks + context = TempNode(AnyType(TypeOfAny.special_form), context=context) # TODO(jukka): We could return as soon as we find an error if messages is None. @@ -2462,7 +2463,7 @@ def check_op(self, method: str, base_type: Type, result, inferred = self.check_op_reversible( op_name=method, left_type=left_possible_type, - left_expr=TempNode(left_possible_type), + left_expr=TempNode(left_possible_type, context=context), right_type=right_type, right_expr=arg, context=context, @@ -2489,7 +2490,8 @@ def check_op(self, method: str, base_type: Type, right_variants = [(right_type, arg)] right_type = get_proper_type(right_type) if isinstance(right_type, UnionType): - right_variants = [(item, TempNode(item)) for item in right_type.relevant_items()] + right_variants = [(item, TempNode(item, context=context)) + for item in right_type.relevant_items()] msg = self.msg.clean_copy() msg.disable_count = 0 @@ -2501,7 +2503,7 @@ def check_op(self, method: str, base_type: Type, result, inferred = self.check_op_reversible( op_name=method, left_type=left_possible_type, - left_expr=TempNode(left_possible_type), + left_expr=TempNode(left_possible_type, context=context), right_type=right_possible_type, right_expr=right_expr, context=context, @@ -2514,9 +2516,9 @@ def check_op(self, method: str, base_type: Type, if len(left_variants) >= 2 and len(right_variants) >= 2: self.msg.warn_both_operands_are_from_unions(context) elif len(left_variants) >= 2: - self.msg.warn_operand_was_from_union("Left", base_type, context) + self.msg.warn_operand_was_from_union("Left", base_type, context=right_expr) elif len(right_variants) >= 2: - self.msg.warn_operand_was_from_union("Right", right_type, context) + self.msg.warn_operand_was_from_union("Right", right_type, context=right_expr) # See the comment in 'check_overload_call' for more details on why # we call 'combine_function_signature' instead of just unioning the inferred @@ -2845,10 +2847,10 @@ def visit_reveal_expr(self, expr: RevealExpr) -> Type: assert expr.expr is not None revealed_type = self.accept(expr.expr, type_context=self.type_context[-1]) if not self.chk.current_node_deferred: - self.msg.reveal_type(revealed_type, expr) + self.msg.reveal_type(revealed_type, expr.expr) if not self.chk.in_checked_function(): self.msg.note("'reveal_type' always outputs 'Any' in unchecked functions", - expr) + expr.expr) return revealed_type else: # REVEAL_LOCALS @@ -3098,8 +3100,8 @@ def visit_dict_expr(self, e: DictExpr) -> Type: stargs.append(value) else: tup = TupleExpr([key, value]) - tup.line = key.line - tup.column = key.column + tup.line = value.line + tup.column = value.column args.append(tup) # Define type variables (used in constructors below). ktdef = TypeVarDef('KT', 'KT', -1, [], self.object_type()) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 5efda9a70447..2f8b57f11d6c 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -469,7 +469,8 @@ def analyze_descriptor_access(instance_type: Type, _, inferred_dunder_get_type = chk.expr_checker.check_call( dunder_get_type, - [TempNode(instance_type), TempNode(TypeType.make_normalized(owner_type))], + [TempNode(instance_type, context=context), + TempNode(TypeType.make_normalized(owner_type), context=context)], [ARG_POS, ARG_POS], context) inferred_dunder_get_type = get_proper_type(inferred_dunder_get_type) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 76ad3cb32109..7264117d88da 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -944,8 +944,8 @@ def visit_UnaryOp(self, n: ast3.UnaryOp) -> UnaryExpr: # Lambda(arguments args, expr body) def visit_Lambda(self, n: ast3.Lambda) -> LambdaExpr: body = ast3.Return(n.body) - body.lineno = n.lineno - body.col_offset = n.col_offset + body.lineno = n.body.lineno + body.col_offset = n.body.col_offset e = LambdaExpr(self.transform_args(n.args, n.lineno), self.as_required_block([body], n.lineno)) diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 7dc6261ea858..8fb1e42c574a 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -834,8 +834,8 @@ def visit_Lambda(self, n: ast27.Lambda) -> LambdaExpr: args, decompose_stmts = self.transform_args(n.args, n.lineno) n_body = ast27.Return(n.body) - n_body.lineno = n.lineno - n_body.col_offset = n.col_offset + n_body.lineno = n.body.lineno + n_body.col_offset = n.body.col_offset body = self.as_required_block([n_body], n.lineno) if decompose_stmts: body.body = decompose_stmts + body.body diff --git a/mypy/nodes.py b/mypy/nodes.py index 79343f4ad212..500069f082c0 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -2224,13 +2224,21 @@ class TempNode(Expression): # (e.g. for 'x: int' the rvalue is TempNode(AnyType(TypeOfAny.special_form), no_rhs=True)) no_rhs = False # type: bool - def __init__(self, typ: 'mypy.types.Type', no_rhs: bool = False) -> None: + def __init__(self, + typ: 'mypy.types.Type', + no_rhs: bool = False, + *, + context: Optional[Context] = None) -> None: + """Construct a dummy node; optionally borrow line/column from context object.""" super().__init__() self.type = typ self.no_rhs = no_rhs + if context is not None: + self.line = context.line + self.column = context.column def __repr__(self) -> str: - return 'TempNode(%s)' % str(self.type) + return 'TempNode:%d(%s)' % (self.line, str(self.type)) def accept(self, visitor: ExpressionVisitor[T]) -> T: return visitor.visit_temp_node(self) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index c00ffd076a56..9010b0130953 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -1377,14 +1377,13 @@ class D: def __get__(self, inst: Base, own: Type[Base]) -> str: pass [builtins fixtures/bool.pyi] [out] -main:5: note: Revealed type is 'd.D' main:5: error: Argument 2 to "__get__" of "D" has incompatible type "Type[A]"; expected "Type[Base]" -main:6: note: Revealed type is 'Any' +main:5: note: Revealed type is 'd.D' main:6: error: No overload variant of "__get__" of "D" matches argument types "A", "Type[A]" main:6: note: Possible overload variants: main:6: note: def __get__(self, inst: None, own: Type[Base]) -> D main:6: note: def __get__(self, inst: Base, own: Type[Base]) -> str - +main:6: note: Revealed type is 'Any' [case testAccessingGenericNonDataDescriptor] from typing import TypeVar, Type, Generic, Any @@ -4844,8 +4843,9 @@ def f() -> type: return M class C1(six.with_metaclass(M), object): pass # E: Unsupported dynamic base class "six.with_metaclass" class C2(C1, six.with_metaclass(M)): pass # E: Unsupported dynamic base class "six.with_metaclass" class C3(six.with_metaclass(A)): pass # E: Metaclasses not inheriting from 'type' are not supported -@six.add_metaclass(A) # E: Argument 1 to "add_metaclass" has incompatible type "Type[A]"; expected "Type[type]" \ - # E: Metaclasses not inheriting from 'type' are not supported +@six.add_metaclass(A) # E: Metaclasses not inheriting from 'type' are not supported \ + # E: Argument 1 to "add_metaclass" has incompatible type "Type[A]"; expected "Type[type]" + class D3(A): pass class C4(six.with_metaclass(M), metaclass=M): pass # E: Multiple metaclass definitions @six.add_metaclass(M) diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test index cf1e8dd89da6..b574dfe1a94b 100644 --- a/test-data/unit/check-columns.test +++ b/test-data/unit/check-columns.test @@ -40,12 +40,12 @@ class A: def __lt__(self, other: int) -> str: pass f( - y=0, x=0) # E:4: Argument 1 to "f" has incompatible type "int"; expected "str" + y=0, x=0) # E:4: Argument "y" to "f" has incompatible type "int"; expected "str" f(x=0, - y=None) # E:6: Argument 2 to "f" has incompatible type "None"; expected "str" + y=None) # E:6: Argument "y" to "f" has incompatible type "None"; expected "str" g(1, '', 2) # E:6: Argument 2 to "g" has incompatible type "str"; expected "int" aaa: str -h(x=1, y=aaa, z=2) # E:10: Argument 2 to "h" has incompatible type "str"; expected "int" +h(x=1, y=aaa, z=2) # E:10: Argument "y" to "h" has incompatible type "str"; expected "int" a: A ff(a.x) # E:4: Argument 1 to "ff" has incompatible type "str"; expected "int" ff([1]) # E:4: Argument 1 to "ff" has incompatible type "List[int]"; expected "int" @@ -338,7 +338,7 @@ def f(x: T) -> T: g(y=x) # E:5: Unexpected keyword argument "y" for "g" y: List[int, str] # E:8: "list" expects 1 type argument, but 2 given del 1[0] # E:5: "int" has no attribute "__delitem__" - bb: List[int] = [''] # E:21: List item 0 has incompatible type "str"; expected "int" + bb: List[int] = [''] # E:22: List item 0 has incompatible type "str"; expected "int" # XXX: Disabled because the column differs in 3.8 # aa: List[int] = ['' for x in [1]] # :22: List comprehension has incompatible type List[str]; expected List[int] cc = (1).bad # E:11: "int" has no attribute "bad" diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index 234837091bf9..dfccf23aff1f 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -1671,8 +1671,8 @@ def f(x: int) -> None: [builtins fixtures/for.pyi] [out] main:1: error: The return type of a generator function should be "Generator" or one of its supertypes -main:2: error: Argument 1 to "f" has incompatible type "str"; expected "int" main:2: error: "f" does not return a value +main:2: error: Argument 1 to "f" has incompatible type "str"; expected "int" [case testYieldExpressionWithNone] from typing import Iterator @@ -1919,8 +1919,8 @@ from typing import Dict, Callable def things() -> int: return 42 -stuff: Dict[int, Callable[[], str]] = { # E: Dict entry 0 has incompatible type "int": "Callable[[], int]"; expected "int": "Callable[[], str]" - 1: things +stuff: Dict[int, Callable[[], str]] = { + 1: things # E: Dict entry 0 has incompatible type "int": "Callable[[], int]"; expected "int": "Callable[[], str]" } [builtins fixtures/dict.pyi] diff --git a/test-data/unit/check-inference-context.test b/test-data/unit/check-inference-context.test index 048abc483e57..095c55bb4904 100644 --- a/test-data/unit/check-inference-context.test +++ b/test-data/unit/check-inference-context.test @@ -697,8 +697,9 @@ def f(func: Callable[[T], S], *z: T, r: S = None) -> S: pass f(lambda x: 0 if isinstance(x, B) else 1) # E: Cannot infer type argument 1 of "f" f(lambda x: 0 if isinstance(x, B) else 1, A())() # E: "int" not callable f(lambda x: x if isinstance(x, B) else B(), A(), r=B())() # E: "B" not callable -f( # E: Argument 1 to "f" has incompatible type "Callable[[A], A]"; expected "Callable[[A], B]" - lambda x: B() if isinstance(x, B) else x, # E: Incompatible return value type (got "A", expected "B") +f( + lambda x: # E: Argument 1 to "f" has incompatible type "Callable[[A], A]"; expected "Callable[[A], B]" + B() if isinstance(x, B) else x, # E: Incompatible return value type (got "A", expected "B") A(), r=B()) [builtins fixtures/isinstance.pyi] diff --git a/test-data/unit/check-isinstance.test b/test-data/unit/check-isinstance.test index ca3b2fb176ea..8729b87a297b 100644 --- a/test-data/unit/check-isinstance.test +++ b/test-data/unit/check-isinstance.test @@ -968,8 +968,8 @@ def foo() -> Union[int, str, A]: pass def bar() -> None: x = foo() - x + 1 # E: Unsupported operand types for + ("str" and "int") \ - # E: Unsupported left operand type for + ("A") \ + x + 1 # E: Unsupported left operand type for + ("A") \ + # E: Unsupported operand types for + ("str" and "int") \ # N: Left operand is of type "Union[int, str, A]" if isinstance(x, A): x.a diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index 992a89c53dea..6d8626456403 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -134,7 +134,7 @@ X(0, 1) # ok X(0, 1, 2) # E: Too many arguments for "X" Y = namedtuple('Y', ['x', 'y'], defaults=(1, 2, 3)) # E: Too many defaults given in call to namedtuple() -Z = namedtuple('Z', ['x', 'y'], defaults='not a tuple') # E: Argument "defaults" to "namedtuple" has incompatible type "str"; expected "Optional[Iterable[Any]]" # E: List or tuple literal expected as the defaults argument to namedtuple() +Z = namedtuple('Z', ['x', 'y'], defaults='not a tuple') # E: List or tuple literal expected as the defaults argument to namedtuple() # E: Argument "defaults" to "namedtuple" has incompatible type "str"; expected "Optional[Iterable[Any]]" [builtins fixtures/list.pyi] diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index f08d0bd22d61..68cf443f9cb8 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -4563,6 +4563,7 @@ def f(*args): x: Union[int, str] f(x, x, x, x, x, x, x, x) [out] +main:11: note: Not all union combinations were tried because there are too many unions main:11: error: Argument 1 to "f" has incompatible type "Union[int, str]"; expected "int" main:11: error: Argument 2 to "f" has incompatible type "Union[int, str]"; expected "int" main:11: error: Argument 3 to "f" has incompatible type "Union[int, str]"; expected "int" @@ -4571,7 +4572,6 @@ main:11: error: Argument 5 to "f" has incompatible type "Union[int, str]"; expec main:11: error: Argument 6 to "f" has incompatible type "Union[int, str]"; expected "int" main:11: error: Argument 7 to "f" has incompatible type "Union[int, str]"; expected "int" main:11: error: Argument 8 to "f" has incompatible type "Union[int, str]"; expected "int" -main:11: note: Not all union combinations were tried because there are too many unions [case testSafeDunderOverlapInSubclass] from typing import overload @@ -4959,8 +4959,9 @@ def foo() -> None: ... def foo(iterable: Iterable[_T]) -> None: ... def foo(iterable = None) -> None: pass -foo(bar('lol').foo()) # E: Argument 1 to "bar" has incompatible type "str"; expected "int" \ - # E: Item "int" of "Union[A, int]" has no attribute "foo" +foo(bar('lol').foo()) # E: Item "int" of "Union[A, int]" has no attribute "foo" \ + # E: Argument 1 to "bar" has incompatible type "str"; expected "int" + [case testOverloadInferringArgumentsUsingContext1] from typing import Optional, List, overload, TypeVar diff --git a/test-data/unit/check-unions.test b/test-data/unit/check-unions.test index dfad64ac202e..39dddb77c332 100644 --- a/test-data/unit/check-unions.test +++ b/test-data/unit/check-unions.test @@ -302,9 +302,9 @@ reveal_type(u('', 1, 1)) # N: Revealed type is 'Union[builtins.int*, builtins.s from typing import Union class A: pass def f(x: Union[int, str, A]): - x + object() # E: Unsupported operand types for + ("int" and "object") \ + x + object() # E: Unsupported left operand type for + ("A") \ + # E: Unsupported operand types for + ("int" and "object") \ # E: Unsupported operand types for + ("str" and "object") \ - # E: Unsupported left operand type for + ("A") \ # N: Left operand is of type "Union[int, str, A]" [case testNarrowingDownNamedTupleUnion] From 32615409eb0fa8c924ebd14e234b9dda33c889bf Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 5 Sep 2019 15:05:41 +0100 Subject: [PATCH 06/13] Fix various tests --- mypy/checkexpr.py | 8 +++- test-data/unit/check-classes.test | 7 ++- test-data/unit/check-columns.test | 3 +- test-data/unit/check-expressions.test | 2 +- test-data/unit/check-generics.test | 4 +- test-data/unit/check-literal.test | 61 +++++++++++++-------------- test-data/unit/check-modules.test | 10 ++--- test-data/unit/check-newsemanal.test | 4 +- test-data/unit/check-tuples.test | 10 ++--- test-data/unit/check-typeddict.test | 8 ++-- test-data/unit/fine-grained.test | 2 +- 11 files changed, 60 insertions(+), 59 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 22029c875637..06b89c19ebc1 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -3100,8 +3100,12 @@ def visit_dict_expr(self, e: DictExpr) -> Type: stargs.append(value) else: tup = TupleExpr([key, value]) - tup.line = value.line - tup.column = value.column + if key.line >= 0: + tup.line = key.line + tup.column = key.column + else: + tup.line = value.line + tup.column = value.column args.append(tup) # Define type variables (used in constructors below). ktdef = TypeVarDef('KT', 'KT', -1, [], self.object_type()) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 9010b0130953..938b868eff14 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -1479,12 +1479,11 @@ class D(Generic[T, V]): def __get__(self, inst: T, own: Type[T]) -> V: pass [builtins fixtures/bool.pyi] [out] -main:5: note: Revealed type is 'Any' main:5: error: No overload variant of "__get__" of "D" matches argument types "None", "Type[A]" main:5: note: Possible overload variants: main:5: note: def __get__(self, inst: None, own: None) -> D[A, int] main:5: note: def __get__(self, inst: A, own: Type[A]) -> int - +main:5: note: Revealed type is 'Any' [case testAccessingNonDataDescriptorSubclass] from typing import Any @@ -4970,8 +4969,8 @@ def decorate_forward_ref() -> Callable[[Type[A]], Type[A]]: @decorate(11) class A: pass -@decorate -class A2: pass # E: Argument 1 to "decorate" has incompatible type "Type[A2]"; expected "int" +@decorate # E: Argument 1 to "decorate" has incompatible type "Type[A2]"; expected "int" +class A2: pass [case testClassDecoratorIncorrect] def not_a_class_decorator(x: int) -> int: ... diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test index b574dfe1a94b..1696f22717bc 100644 --- a/test-data/unit/check-columns.test +++ b/test-data/unit/check-columns.test @@ -167,7 +167,6 @@ def f(x, y): pass [case testColumnListOrDictItemHasIncompatibleType] from typing import List, Dict -# TODO: Point to the actual item since a list/dict literal can span many lines x: List[int] = [ 'x'] # E:5: List item 0 has incompatible type "str"; expected "int" y: Dict[int, int] = { @@ -259,7 +258,7 @@ if int(): [case testColumnRevealedType] if int(): - reveal_type(1) # N:5: Revealed type is 'builtins.int' + reveal_type(1) # N:17: Revealed type is 'builtins.int' [case testColumnNonOverlappingEqualityCheck] # flags: --strict-equality diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test index dfccf23aff1f..362d32e793c1 100644 --- a/test-data/unit/check-expressions.test +++ b/test-data/unit/check-expressions.test @@ -1847,8 +1847,8 @@ main:4: note: z: builtins.int [case testUndefinedRevealType] reveal_type(x) [out] -main:1: note: Revealed type is 'Any' main:1: error: Name 'x' is not defined +main:1: note: Revealed type is 'Any' [case testUserDefinedRevealType] def reveal_type(x: int) -> None: pass diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index baa8d845e1aa..e1f37260e5e2 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -616,8 +616,8 @@ main:15:10: error: "list" expects 1 type argument, but 2 given main:16:19: error: "list" expects 1 type argument, but 2 given main:17:25: error: "Node" expects 2 type arguments, but 1 given main:19:5: error: Bad number of arguments for type alias, expected: 1, given: 2 -main:22:1: note: Revealed type is '__main__.Node[builtins.int, builtins.str]' -main:24:1: note: Revealed type is '__main__.Node[__main__.Node[builtins.int, builtins.int], builtins.list[builtins.int]]' +main:22:13: note: Revealed type is '__main__.Node[builtins.int, builtins.str]' +main:24:13: note: Revealed type is '__main__.Node[__main__.Node[builtins.int, builtins.int], builtins.list[builtins.int]]' main:26:5: error: Type variable "__main__.T" is invalid as target for type alias [case testGenericTypeAliasesForAliases] diff --git a/test-data/unit/check-literal.test b/test-data/unit/check-literal.test index 03e93857ec38..56d9feac3fd4 100644 --- a/test-data/unit/check-literal.test +++ b/test-data/unit/check-literal.test @@ -1579,19 +1579,19 @@ reveal_type(func(c)) # N: Revealed type is 'Union[__main__.B, __main__.A]' reveal_type(func(d)) # N: Revealed type is '__main__.B' \ # E: Argument 1 to "func" has incompatible type "Union[Literal[6], Literal[7]]"; expected "Union[Literal[3], Literal[4], Literal[5], Literal[6]]" -reveal_type(func(e)) # N: Revealed type is 'Any' \ - # E: No overload variant of "func" matches argument type "int" \ +reveal_type(func(e)) # E: No overload variant of "func" matches argument type "int" \ # N: Possible overload variants: \ # N: def func(x: Literal[-40]) -> A \ # N: def func(x: Union[Literal[3], Literal[4], Literal[5], Literal[6]]) -> B \ - # N: def func(x: Literal['foo']) -> C + # N: def func(x: Literal['foo']) -> C \ + # N: Revealed type is 'Any' -reveal_type(func(f)) # N: Revealed type is 'Any' \ - # E: No overload variant of "func" matches argument type "Union[Literal[7], Literal['bar']]" \ +reveal_type(func(f)) # E: No overload variant of "func" matches argument type "Union[Literal[7], Literal['bar']]" \ # N: Possible overload variants: \ # N: def func(x: Literal[-40]) -> A \ # N: def func(x: Union[Literal[3], Literal[4], Literal[5], Literal[6]]) -> B \ - # N: def func(x: Literal['foo']) -> C + # N: def func(x: Literal['foo']) -> C \ + # N: Revealed type is 'Any' [out] [case testLiteralInferredInOverloadContextUnionMathOverloadingReturnsBestType] @@ -1941,12 +1941,12 @@ reveal_type(func1) # N: Revealed type is 'def [TLiteral <: Literal[3]] (x: reveal_type(func1(3)) # N: Revealed type is 'Literal[3]' reveal_type(func1(a)) # N: Revealed type is 'Literal[3]' -reveal_type(func1(4)) # N: Revealed type is 'Literal[4]' \ - # E: Value of type variable "TLiteral" of "func1" cannot be "Literal[4]" -reveal_type(func1(b)) # N: Revealed type is 'Literal[4]' \ - # E: Value of type variable "TLiteral" of "func1" cannot be "Literal[4]" -reveal_type(func1(c)) # N: Revealed type is 'builtins.int*' \ - # E: Value of type variable "TLiteral" of "func1" cannot be "int" +reveal_type(func1(4)) # E: Value of type variable "TLiteral" of "func1" cannot be "Literal[4]" \ + # N: Revealed type is 'Literal[4]' +reveal_type(func1(b)) # E: Value of type variable "TLiteral" of "func1" cannot be "Literal[4]" \ + # N: Revealed type is 'Literal[4]' +reveal_type(func1(c)) # E: Value of type variable "TLiteral" of "func1" cannot be "int" \ + # N: Revealed type is 'builtins.int*' reveal_type(func2(3)) # N: Revealed type is 'builtins.int*' reveal_type(func2(a)) # N: Revealed type is 'Literal[3]' @@ -1986,21 +1986,20 @@ reveal_type(func1) # N: Revealed type is 'def [TLiteral in (Literal[3], reveal_type(func1(3)) # N: Revealed type is 'Literal[3]' reveal_type(func1(i1)) # N: Revealed type is 'Literal[3]' -reveal_type(func1(4)) # N: Revealed type is 'Literal[4]' \ - # E: Value of type variable "TLiteral" of "func1" cannot be "Literal[4]" -reveal_type(func1(i2)) # N: Revealed type is 'Literal[4]' \ - # E: Value of type variable "TLiteral" of "func1" cannot be "Literal[4]" -reveal_type(func1(i)) # N: Revealed type is 'builtins.int*' \ - # E: Value of type variable "TLiteral" of "func1" cannot be "int" - +reveal_type(func1(4)) # E: Value of type variable "TLiteral" of "func1" cannot be "Literal[4]" \ + # N: Revealed type is 'Literal[4]' +reveal_type(func1(i2)) # E: Value of type variable "TLiteral" of "func1" cannot be "Literal[4]" \ + # N: Revealed type is 'Literal[4]' +reveal_type(func1(i)) # E: Value of type variable "TLiteral" of "func1" cannot be "int" \ + # N: Revealed type is 'builtins.int*' reveal_type(func1("foo")) # N: Revealed type is 'Literal['foo']' reveal_type(func1(s1)) # N: Revealed type is 'Literal['foo']' -reveal_type(func1("bar")) # N: Revealed type is 'Literal['bar']' \ - # E: Value of type variable "TLiteral" of "func1" cannot be "Literal['bar']" -reveal_type(func1(s2)) # N: Revealed type is 'Literal['bar']' \ - # E: Value of type variable "TLiteral" of "func1" cannot be "Literal['bar']" -reveal_type(func1(s)) # N: Revealed type is 'builtins.str*' \ - # E: Value of type variable "TLiteral" of "func1" cannot be "str" +reveal_type(func1("bar")) # E: Value of type variable "TLiteral" of "func1" cannot be "Literal['bar']" \ + # N: Revealed type is 'Literal['bar']' +reveal_type(func1(s2)) # E: Value of type variable "TLiteral" of "func1" cannot be "Literal['bar']" \ + # N: Revealed type is 'Literal['bar']' +reveal_type(func1(s)) # E: Value of type variable "TLiteral" of "func1" cannot be "str" \ + # N: Revealed type is 'builtins.str*' reveal_type(func2(3)) # N: Revealed type is 'builtins.int*' reveal_type(func2(i1)) # N: Revealed type is 'builtins.int*' @@ -2061,8 +2060,8 @@ reveal_type(arr5) # N: Revealed type is 'builtins.list[def (Literal[1]) -> buil # Inspect just only one interesting one lit: Literal[1] -reveal_type(arr2[0](lit)) # N: Revealed type is 'Any' \ - # E: Cannot call function of unknown type +reveal_type(arr2[0](lit)) # E: Cannot call function of unknown type \ + # N: Revealed type is 'Any' T = TypeVar('T') def unify(func: Callable[[T, T], None]) -> T: pass @@ -2092,8 +2091,8 @@ lit: Literal[1] arr = [a, b] reveal_type(arr) # N: Revealed type is 'builtins.list[builtins.function*]' -reveal_type(arr[0](lit)) # N: Revealed type is 'Any' \ - # E: Cannot call function of unknown type +reveal_type(arr[0](lit)) # E: Cannot call function of unknown type \ + # N: Revealed type is 'Any' T = TypeVar('T') def unify(func: Callable[[T, T], None]) -> T: pass @@ -2177,8 +2176,8 @@ reveal_type(d.get(a_key, u)) # N: Revealed type is 'Union[builtins.int, __main_ reveal_type(d.get(b_key, u)) # N: Revealed type is 'Union[builtins.str, __main__.Unrelated]' d.get(c_key, u) # E: TypedDict "Outer" has no key 'c' -reveal_type(d.pop(a_key)) # N: Revealed type is 'builtins.int' \ - # E: Key 'a' of TypedDict "Outer" cannot be deleted +reveal_type(d.pop(a_key)) # E: Key 'a' of TypedDict "Outer" cannot be deleted \ + # N: Revealed type is 'builtins.int' reveal_type(d.pop(b_key)) # N: Revealed type is 'builtins.str' d.pop(c_key) # E: TypedDict "Outer" has no key 'c' diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index e1780c017955..7ed4c137961f 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -1860,8 +1860,8 @@ class C: import stub reveal_type(stub.y) # N: Revealed type is 'builtins.int' -reveal_type(stub.z) # N: Revealed type is 'Any' \ - # E: Module has no attribute "z" +reveal_type(stub.z) # E: Module has no attribute "z" \ + # N: Revealed type is 'Any' [file stub.pyi] from substub import y as y @@ -2028,8 +2028,8 @@ def __getattr__(name): ... [case testModuleLevelGetattrNotStub36] # flags: --python-version 3.6 import has_getattr -reveal_type(has_getattr.any_attribute) # N: Revealed type is 'Any' # E: Module has no attribute "any_attribute" - +reveal_type(has_getattr.any_attribute) # E: Module has no attribute "any_attribute" \ + # N: Revealed type is 'Any' [file has_getattr.py] def __getattr__(name) -> str: ... @@ -2093,7 +2093,7 @@ def __getattr__(name: str) -> Any: ... [case testModuleLevelGetattrImportFromAs] from has_attr import name as n -reveal_type(name) # N: Revealed type is 'Any' # E: Name 'name' is not defined +reveal_type(name) # E: Name 'name' is not defined # N: Revealed type is 'Any' reveal_type(n) # N: Revealed type is 'Any' [file has_attr.pyi] diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test index f5071ef8698e..38319d5ebe46 100644 --- a/test-data/unit/check-newsemanal.test +++ b/test-data/unit/check-newsemanal.test @@ -3049,8 +3049,8 @@ reveal_type(x) # N: Revealed type is '__main__.C' [case testNewAnalyzerIdentityAssignment7] C = C # E: Name 'C' is not defined -reveal_type(C) # N: Revealed type is 'Any' \ - # E: Name 'C' is not defined +reveal_type(C) # E: Name 'C' is not defined \ + # N: Revealed type is 'Any' [case testNewAnalyzerIdentityAssignment8] from typing import Final diff --git a/test-data/unit/check-tuples.test b/test-data/unit/check-tuples.test index 99a3157337cb..73c1c9ac6236 100644 --- a/test-data/unit/check-tuples.test +++ b/test-data/unit/check-tuples.test @@ -1216,8 +1216,8 @@ from typing import Union, Tuple tup: Union[Tuple[int, str], Tuple[int, int, str]] reveal_type(tup[0]) # N: Revealed type is 'builtins.int' reveal_type(tup[1]) # N: Revealed type is 'Union[builtins.str, builtins.int]' -reveal_type(tup[2]) # N: Revealed type is 'Union[Any, builtins.str]' \ - # E: Tuple index out of range +reveal_type(tup[2]) # E: Tuple index out of range \ + # N: Revealed type is 'Union[Any, builtins.str]' reveal_type(tup[:]) # N: Revealed type is 'Union[Tuple[builtins.int, builtins.str], Tuple[builtins.int, builtins.int, builtins.str]]' [builtins fixtures/tuple.pyi] @@ -1228,8 +1228,8 @@ from typing import Union, Tuple, List tup: Union[Tuple[int, str], List[int]] reveal_type(tup[0]) # N: Revealed type is 'builtins.int' reveal_type(tup[1]) # N: Revealed type is 'Union[builtins.str, builtins.int*]' -reveal_type(tup[2]) # N: Revealed type is 'Union[Any, builtins.int*]' \ - # E: Tuple index out of range +reveal_type(tup[2]) # E: Tuple index out of range \ + # N: Revealed type is 'Union[Any, builtins.int*]' reveal_type(tup[:]) # N: Revealed type is 'Union[Tuple[builtins.int, builtins.str], builtins.list[builtins.int*]]' [builtins fixtures/tuple.pyi] @@ -1240,4 +1240,4 @@ b = ("bar", 7) reveal_type(a + b) # N: Revealed type is 'Tuple[builtins.int, builtins.str, builtins.int, builtins.str, builtins.int]' -[builtins fixtures/tuple.pyi] \ No newline at end of file +[builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index 51326c64ce43..e867b5a3f92f 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -1612,8 +1612,8 @@ td: Union[TDA, TDB] reveal_type(td.get('a')) # N: Revealed type is 'builtins.int' reveal_type(td.get('b')) # N: Revealed type is 'Union[builtins.str, builtins.int]' -reveal_type(td.get('c')) # N: Revealed type is 'Union[Any, builtins.int]' \ - # E: TypedDict "TDA" has no key 'c' +reveal_type(td.get('c')) # E: TypedDict "TDA" has no key 'c' \ + # N: Revealed type is 'Union[Any, builtins.int]' reveal_type(td['a']) # N: Revealed type is 'builtins.int' reveal_type(td['b']) # N: Revealed type is 'Union[builtins.str, builtins.int]' @@ -1639,8 +1639,8 @@ td: Union[TDA, TDB] reveal_type(td.pop('a')) # N: Revealed type is 'builtins.int' reveal_type(td.pop('b')) # N: Revealed type is 'Union[builtins.str, builtins.int]' -reveal_type(td.pop('c')) # N: Revealed type is 'Union[Any, builtins.int]' \ - # E: TypedDict "TDA" has no key 'c' +reveal_type(td.pop('c')) # E: TypedDict "TDA" has no key 'c' \ + # N: Revealed type is 'Union[Any, builtins.int]' [builtins fixtures/dict.pyi] [typing fixtures/typing-full.pyi] diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index b55d765d4bce..19f2ea54a492 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -2574,11 +2574,11 @@ class Wrapper: [out] main:3: note: Revealed type is 'builtins.int' == -main:3: note: Revealed type is 'Any' main:3: error: No overload variant of "foo" of "Wrapper" matches argument type "int" main:3: note: Possible overload variants: main:3: note: def foo(cls: Wrapper, x: int) -> int main:3: note: def foo(cls: Wrapper, x: str) -> str +main:3: note: Revealed type is 'Any' [case testRefreshGenericClass] from typing import TypeVar, Generic From 80f5fe7b5db3cca18c0abc41fc8781e86a59e8a1 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 5 Sep 2019 15:13:51 +0100 Subject: [PATCH 07/13] Update test case --- test-data/unit/check-columns.test | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test index 1696f22717bc..041160371263 100644 --- a/test-data/unit/check-columns.test +++ b/test-data/unit/check-columns.test @@ -168,7 +168,8 @@ def f(x, y): pass [case testColumnListOrDictItemHasIncompatibleType] from typing import List, Dict x: List[int] = [ - 'x'] # E:5: List item 0 has incompatible type "str"; expected "int" + 'x', # E:5: List item 0 has incompatible type "str"; expected "int" + 1.1] # E:7: List item 1 has incompatible type "float"; expected "int" y: Dict[int, int] = { 'x': 1 # E:5: Dict entry 0 has incompatible type "str": "int"; expected "int": "int" } From e1eb7e284d0fb4a2d6e9f8e015c1f76ba9b5182e Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 5 Sep 2019 15:15:58 +0100 Subject: [PATCH 08/13] Add test case --- test-data/unit/check-columns.test | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test index 041160371263..066d8a503ae8 100644 --- a/test-data/unit/check-columns.test +++ b/test-data/unit/check-columns.test @@ -63,6 +63,16 @@ class B(A): ff(super().__neg__()) # E:12: Argument 1 to "ff" has incompatible type "str"; expected "int" [builtins fixtures/dict.pyi] +[case testColumnsInvalidArgumentTypeVarArgs] +def f(*x: int) -> None: pass +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" +[builtins fixtures/dict.pyi] + [case testColumnsMultipleStatementsPerLine] x = 15 y = 'hello' From a19355810400a8411c8be12c99b4db247fa96c93 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 5 Sep 2019 15:19:00 +0100 Subject: [PATCH 09/13] Fix test case --- test-data/unit/pythoneval.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index c450b1f9ed92..3a0af9fb9af6 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -295,8 +295,8 @@ reveal_type(open(file='x', mode='rb')) mode = 'rb' reveal_type(open(mode=mode, file='r')) [out] -_testOpenReturnTypeInferenceSpecialCases.py:1: note: Revealed type is 'typing.TextIO' _testOpenReturnTypeInferenceSpecialCases.py:1: error: Too few arguments for "open" +_testOpenReturnTypeInferenceSpecialCases.py:1: note: Revealed type is 'typing.TextIO' _testOpenReturnTypeInferenceSpecialCases.py:2: note: Revealed type is 'typing.BinaryIO' _testOpenReturnTypeInferenceSpecialCases.py:3: note: Revealed type is 'typing.BinaryIO' _testOpenReturnTypeInferenceSpecialCases.py:5: note: Revealed type is 'typing.IO[Any]' From 03aad6e43e7a2a7ee4ff64d3071072f61cdc54e8 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 5 Sep 2019 15:25:04 +0100 Subject: [PATCH 10/13] Fix slices --- mypy/fastparse.py | 4 +- mypy/fastparse2.py | 7 +- test-data/unit/parse-python2.test | 6 +- test-data/unit/parse.test | 194 ++++++++++++------------ test-data/unit/semanal-expressions.test | 6 +- 5 files changed, 111 insertions(+), 106 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 7264117d88da..f643081cb412 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -1169,11 +1169,11 @@ def visit_Attribute(self, n: Attribute) -> Union[MemberExpr, SuperExpr]: # Subscript(expr value, slice slice, expr_context ctx) def visit_Subscript(self, n: ast3.Subscript) -> IndexExpr: e = IndexExpr(self.visit(n.value), self.visit(n.slice)) - e = self.set_line(e, n) + self.set_line(e, n) if isinstance(e.index, SliceExpr): # Slice has no line/column in the raw ast. e.index.line = e.line - e.index.column = e.line + e.index.column = e.column return e # Starred(expr value, expr_context ctx) diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 8fb1e42c574a..61dd44228a39 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -1009,7 +1009,12 @@ def visit_Attribute(self, n: Attribute) -> Expression: # Subscript(expr value, slice slice, expr_context ctx) def visit_Subscript(self, n: ast27.Subscript) -> IndexExpr: e = IndexExpr(self.visit(n.value), self.visit(n.slice)) - return self.set_line(e, n) + self.set_line(e, n) + if isinstance(e.index, SliceExpr): + # Slice has no line/column in the raw ast. + e.index.line = e.line + e.index.column = e.column + return e # Name(identifier id, expr_context ctx) def visit_Name(self, n: Name) -> NameExpr: diff --git a/test-data/unit/parse-python2.test b/test-data/unit/parse-python2.test index f175264fd177..0dac6affedff 100644 --- a/test-data/unit/parse-python2.test +++ b/test-data/unit/parse-python2.test @@ -594,19 +594,19 @@ MypyFile:1( ExpressionStmt:1( IndexExpr:1( NameExpr(x) - SliceExpr:-1( + SliceExpr:1( NameExpr(y) ))) ExpressionStmt:2( IndexExpr:2( NameExpr(x) - SliceExpr:-1( + SliceExpr:2( NameExpr(y) NameExpr(z)))) ExpressionStmt:3( IndexExpr:3( NameExpr(x) - SliceExpr:-1( + SliceExpr:3( NameExpr(y))))) diff --git a/test-data/unit/parse.test b/test-data/unit/parse.test index 09a908c5d20f..1538061c9e02 100644 --- a/test-data/unit/parse.test +++ b/test-data/unit/parse.test @@ -1207,25 +1207,25 @@ MypyFile:1( ExpressionStmt:1( IndexExpr:1( NameExpr(x) - SliceExpr:-1( + SliceExpr:1( IntExpr(1) IntExpr(2)))) ExpressionStmt:2( IndexExpr:2( NameExpr(x) - SliceExpr:-1( + SliceExpr:2( IntExpr(1)))) ExpressionStmt:3( IndexExpr:3( NameExpr(x) - SliceExpr:-1( + SliceExpr:3( IntExpr(1) ))) ExpressionStmt:4( IndexExpr:4( NameExpr(x) - SliceExpr:-1( + SliceExpr:4( )))) @@ -1240,35 +1240,35 @@ MypyFile:1( ExpressionStmt:1( IndexExpr:1( NameExpr(x) - SliceExpr:-1( + SliceExpr:1( IntExpr(1) IntExpr(2) IntExpr(3)))) ExpressionStmt:2( IndexExpr:2( NameExpr(x) - SliceExpr:-1( + SliceExpr:2( IntExpr(1) IntExpr(2)))) ExpressionStmt:3( IndexExpr:3( NameExpr(x) - SliceExpr:-1( + SliceExpr:3( IntExpr(1) IntExpr(2)))) ExpressionStmt:4( IndexExpr:4( NameExpr(x) - SliceExpr:-1( + SliceExpr:4( IntExpr(2)))) ExpressionStmt:5( IndexExpr:5( NameExpr(x) - SliceExpr:-1( + SliceExpr:5( IntExpr(1) IntExpr(2))))) @@ -3328,92 +3328,92 @@ MypyFile:1( x = 'mypy' f'Hello {x}' [out] -MypyFile:1( - AssignmentStmt:1( - NameExpr(x) - StrExpr(mypy)) - ExpressionStmt:2( - CallExpr:2( - MemberExpr:2( - StrExpr() - join) - Args( - ListExpr:2( - StrExpr(Hello ) - CallExpr:2( - MemberExpr:2( - StrExpr({:{}}) - format) - Args( +MypyFile:1( + AssignmentStmt:1( + NameExpr(x) + StrExpr(mypy)) + ExpressionStmt:2( + CallExpr:2( + MemberExpr:2( + StrExpr() + join) + Args( + ListExpr:2( + StrExpr(Hello ) + CallExpr:2( + MemberExpr:2( + StrExpr({:{}}) + format) + Args( NameExpr(x)))))))) [case testFStringWithConversion] x = 'mypy' F'Hello {x!r}' [out] -MypyFile:1( - AssignmentStmt:1( - NameExpr(x) - StrExpr(mypy)) - ExpressionStmt:2( - CallExpr:2( - MemberExpr:2( - StrExpr() - join) - Args( - ListExpr:2( - StrExpr(Hello ) - CallExpr:2( - MemberExpr:2( - StrExpr({!r:{}}) - format) - Args( +MypyFile:1( + AssignmentStmt:1( + NameExpr(x) + StrExpr(mypy)) + ExpressionStmt:2( + CallExpr:2( + MemberExpr:2( + StrExpr() + join) + Args( + ListExpr:2( + StrExpr(Hello ) + CallExpr:2( + MemberExpr:2( + StrExpr({!r:{}}) + format) + Args( NameExpr(x)))))))) [case testFStringWithOnlyFormatSpecifier] x = 'mypy' f'Hello {x:<30}' [out] -MypyFile:1( - AssignmentStmt:1( - NameExpr(x) - StrExpr(mypy)) - ExpressionStmt:2( - CallExpr:2( - MemberExpr:2( - StrExpr() - join) - Args( - ListExpr:2( - StrExpr(Hello ) - CallExpr:2( - MemberExpr:2( - StrExpr({:{}}) - format) - Args( +MypyFile:1( + AssignmentStmt:1( + NameExpr(x) + StrExpr(mypy)) + ExpressionStmt:2( + CallExpr:2( + MemberExpr:2( + StrExpr() + join) + Args( + ListExpr:2( + StrExpr(Hello ) + CallExpr:2( + MemberExpr:2( + StrExpr({:{}}) + format) + Args( NameExpr(x)))))))) [case testFStringWithFormatSpecifierAndConversion] x = 'mypy' f'Hello {x!s:<30}' [out] -MypyFile:1( - AssignmentStmt:1( - NameExpr(x) - StrExpr(mypy)) - ExpressionStmt:2( - CallExpr:2( - MemberExpr:2( - StrExpr() - join) - Args( - ListExpr:2( - StrExpr(Hello ) - CallExpr:2( - MemberExpr:2( - StrExpr({!s:{}}) - format) - Args( +MypyFile:1( + AssignmentStmt:1( + NameExpr(x) + StrExpr(mypy)) + ExpressionStmt:2( + CallExpr:2( + MemberExpr:2( + StrExpr() + join) + Args( + ListExpr:2( + StrExpr(Hello ) + CallExpr:2( + MemberExpr:2( + StrExpr({!s:{}}) + format) + Args( NameExpr(x)))))))) [case testFStringWithFormatSpecifierExpression] @@ -3421,24 +3421,24 @@ x = 'mypy' y = 30 f'Hello {x!s:<{y+y}}' [out] -MypyFile:1( - AssignmentStmt:1( - NameExpr(x) - StrExpr(mypy)) - AssignmentStmt:2( - NameExpr(y) - IntExpr(30)) - ExpressionStmt:3( - CallExpr:3( - MemberExpr:3( - StrExpr() - join) - Args( - ListExpr:3( - StrExpr(Hello ) - CallExpr:3( - MemberExpr:3( - StrExpr({!s:{}}) - format) - Args( +MypyFile:1( + AssignmentStmt:1( + NameExpr(x) + StrExpr(mypy)) + AssignmentStmt:2( + NameExpr(y) + IntExpr(30)) + ExpressionStmt:3( + CallExpr:3( + MemberExpr:3( + StrExpr() + join) + Args( + ListExpr:3( + StrExpr(Hello ) + CallExpr:3( + MemberExpr:3( + StrExpr({!s:{}}) + format) + Args( NameExpr(x)))))))) diff --git a/test-data/unit/semanal-expressions.test b/test-data/unit/semanal-expressions.test index 1ddc9c20e587..98bf32708f1b 100644 --- a/test-data/unit/semanal-expressions.test +++ b/test-data/unit/semanal-expressions.test @@ -115,20 +115,20 @@ MypyFile:1( ExpressionStmt:2( IndexExpr:2( NameExpr(x [__main__.x]) - SliceExpr:-1( + SliceExpr:2( NameExpr(y [__main__.y]) NameExpr(z [__main__.z]) NameExpr(x [__main__.x])))) ExpressionStmt:3( IndexExpr:3( NameExpr(x [__main__.x]) - SliceExpr:-1( + SliceExpr:3( ))) ExpressionStmt:4( IndexExpr:4( NameExpr(x [__main__.x]) - SliceExpr:-1( + SliceExpr:4( NameExpr(y [__main__.y]))))) From 629ab4d11be78338f24980069772ebc967bdd343 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 5 Sep 2019 17:13:22 +0100 Subject: [PATCH 11/13] Update test case --- test-data/unit/cmdline.test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test-data/unit/cmdline.test b/test-data/unit/cmdline.test index e303f992344a..9f4eeb357b3c 100644 --- a/test-data/unit/cmdline.test +++ b/test-data/unit/cmdline.test @@ -1405,7 +1405,7 @@ class AnotherCustomClassDefinedBelow: [out] some_file.py:3: error: Unsupported operand types for + ("int" and "str") 42 + 'no way' - ^ + ^ some_file.py:11: error: Incompatible types in assignment (expression has type "AnotherCustomClassDefinedBelow", variable has type "OneCustomClassName") self.very_important_attribute_with_long_name: OneCustomClassNa... @@ -1413,8 +1413,8 @@ some_file.py:11: error: Incompatible types in assignment (expression has type some_file.py:11: error: Argument 1 to "some_interesting_method" of "OneCustomClassName" has incompatible type "Union[int, str, float]"; expected "AnotherCustomClassDefinedBelow" - ...t_attribute_with_long_name: OneCustomClassName = OneCustomClassName().... - ^ + ...OneCustomClassName = OneCustomClassName().some_interesting_method(arg) + ^ [case testShowSourceCodeSnippetsBlockingError] # cmd: mypy --pretty --show-error-codes some_file.py From fbd4dfc55a33c69ddd995e6e5a555e3611bb0421 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 5 Sep 2019 17:26:44 +0100 Subject: [PATCH 12/13] Address review --- mypy/checkexpr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 06b89c19ebc1..00e210cbfd32 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1179,7 +1179,7 @@ def check_argument_count(self, assert context, "Internal error: messages given without context" elif context is None: # Avoid "is None" checks - context = TempNode(AnyType(TypeOfAny.special_form), context=context) + context = TempNode(AnyType(TypeOfAny.special_form)) # TODO(jukka): We could return as soon as we find an error if messages is None. From 49128f1ae1b26ab977605faec0cfe61de4091fa6 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 6 Sep 2019 16:04:41 +0100 Subject: [PATCH 13/13] Fix tests on Python 3.8 --- test-data/unit/check-columns.test | 6 ++++-- test-data/unit/check-python38.test | 14 +++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test index 066d8a503ae8..fcc37087a61e 100644 --- a/test-data/unit/check-columns.test +++ b/test-data/unit/check-columns.test @@ -49,10 +49,12 @@ h(x=1, y=aaa, z=2) # E:10: Argument "y" to "h" has incompatible type "str"; expe a: A ff(a.x) # E:4: Argument 1 to "ff" has incompatible type "str"; expected "int" ff([1]) # E:4: Argument 1 to "ff" has incompatible type "List[int]"; expected "int" -ff([1 for x in [1]]) # E:5: Argument 1 to "ff" has incompatible type "List[int]"; expected "int" +# TODO: Different column in Python 3.8+ +#ff([1 for x in [1]]) # Argument 1 to "ff" has incompatible type "List[int]"; expected "int" ff({1: 2}) # E:4: Argument 1 to "ff" has incompatible type "Dict[int, int]"; expected "int" ff(1.1) # E:4: Argument 1 to "ff" has incompatible type "float"; expected "int" -ff( ( 1, 1)) # E:7: Argument 1 to "ff" has incompatible type "Tuple[int, int]"; expected "int" +# TODO: Different column in Python 3.8+ +#ff( ( 1, 1)) # Argument 1 to "ff" has incompatible type "Tuple[int, int]"; expected "int" ff(-a) # E:4: Argument 1 to "ff" has incompatible type "str"; expected "int" ff(a + 1) # E:4: Argument 1 to "ff" has incompatible type "str"; expected "int" ff(a < 1) # E:4: Argument 1 to "ff" has incompatible type "str"; expected "int" diff --git a/test-data/unit/check-python38.test b/test-data/unit/check-python38.test index 8b27b2b1f76f..eeb964e990ef 100644 --- a/test-data/unit/check-python38.test +++ b/test-data/unit/check-python38.test @@ -30,15 +30,19 @@ def f(): ... # type: ignore [case testIgnoreScopeIssue1032] def f(a: int): ... f( - "IGNORE" + 1, + 2, ) # type: ignore [case testIgnoreScopeNested1] +def g(x: str) -> str: ... def f(a: int) -> int: ... f( f( - "IGNORE" - ) # type: ignore + g( + "IGNORE" + ) # type: ignore + ) ) [case testIgnoreScopeNested2] @@ -86,9 +90,9 @@ def g(x: int): ... [case testIgnoreScopeUnused1] # flags: --warn-unused-ignores ( # type: ignore # E: unused 'type: ignore' comment - "IGNORE" # type: ignore + "IGNORE" # type: ignore # E: unused 'type: ignore' comment + # type: ignore # E: unused 'type: ignore' comment - 0 # type: ignore # E: unused 'type: ignore' comment + 0 # type: ignore ) # type: ignore # E: unused 'type: ignore' comment [case testIgnoreScopeUnused2]