Repository: python/mypy

Issue:
kwargs expension with `Mapping` raise `AttributeError: 'NoneType' object has no attribute 'get_line'`
``` python
from typing import Mapping

a = {}  # type: Mapping
dict(**a)
```

raise

``` python
Traceback (most recent call last):
  File "/usr/lib/python-exec/python3.4/mypy", line 6, in <module>
    main(__file__)
  File "/usr/lib64/python3.4/site-packages/mypy/main.py", line 54, in main
    res = type_check_only(sources, bin_dir, options)
  File "/usr/lib64/python3.4/site-packages/mypy/main.py", line 102, in type_check_only
    python_path=options.python_path)
  File "/usr/lib64/python3.4/site-packages/mypy/build.py", line 209, in build
    dispatch(sources, manager)
  File "/usr/lib64/python3.4/site-packages/mypy/build.py", line 1325, in dispatch
    process_graph(graph, manager)
  File "/usr/lib64/python3.4/site-packages/mypy/build.py", line 1456, in process_graph
    process_stale_scc(graph, scc)
  File "/usr/lib64/python3.4/site-packages/mypy/build.py", line 1486, in process_stale_scc
    graph[id].type_check()
  File "/usr/lib64/python3.4/site-packages/mypy/build.py", line 1305, in type_check
    manager.type_checker.visit_file(self.tree, self.xpath)
  File "/usr/lib64/python3.4/site-packages/mypy/checker.py", line 424, in visit_file
    self.accept(d)
  File "/usr/lib64/python3.4/site-packages/mypy/checker.py", line 465, in accept
    typ = node.accept(self)
  File "/usr/lib64/python3.4/site-packages/mypy/nodes.py", line 729, in accept
    return visitor.visit_expression_stmt(self)
  File "/usr/lib64/python3.4/site-packages/mypy/checker.py", line 1570, in visit_expression_stmt
    self.accept(s.expr)
  File "/usr/lib64/python3.4/site-packages/mypy/checker.py", line 465, in accept
    typ = node.accept(self)
  File "/usr/lib64/python3.4/site-packages/mypy/nodes.py", line 1185, in accept
    return visitor.visit_call_expr(self)
  File "/usr/lib64/python3.4/site-packages/mypy/checker.py", line 1997, in visit_call_expr
    return self.expr_checker.visit_call_expr(e)
  File "/usr/lib64/python3.4/site-packages/mypy/checkexpr.py", line 141, in visit_call_expr
    return self.check_call_expr_with_callee_type(callee_type, e)
  File "/usr/lib64/python3.4/site-packages/mypy/checkexpr.py", line 192, in check_call_expr_with_callee_type
    e.arg_names, callable_node=e.callee)[0]
  File "/usr/lib64/python3.4/site-packages/mypy/checkexpr.py", line 257, in check_call
    messages=arg_messages)
  File "/usr/lib64/python3.4/site-packages/mypy/checkexpr.py", line 666, in overload_call_target
    typ)
  File "/usr/lib64/python3.4/site-packages/mypy/checkexpr.py", line 742, in erased_signature_similarity
    None, check_arg=check_arg)
  File "/usr/lib64/python3.4/site-packages/mypy/checkexpr.py", line 614, in check_argument_types
    messages.invalid_keyword_var_arg(arg_type, context)
  File "/usr/lib64/python3.4/site-packages/mypy/messages.py", line 687, in invalid_keyword_var_arg
    context)
  File "/usr/lib64/python3.4/site-packages/mypy/messages.py", line 147, in fail
    self.report(msg, context, 'error', file=file)
  File "/usr/lib64/python3.4/site-packages/mypy/messages.py", line 143, in report
    self.errors.report(context.get_line(), msg.strip(), severity=severity, file=file)
AttributeError: 'NoneType' object has no attribute 'get_line'
```

but using

``` python
from typing import Dict

a = {}  # type: Dict
dict(**a)
```

does nothing, it seems to be specific to `Mapping` or `MutableMapping`.



Discussion:

Resolving patch:
diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py
--- a/mypy/checkexpr.py
+++ b/mypy/checkexpr.py
@@ -663,7 +663,7 @@ def overload_call_target(self, arg_types: List[Type], arg_kinds: List[int],
         best_match = 0
         for typ in overload.items():
             similarity = self.erased_signature_similarity(arg_types, arg_kinds, arg_names,
-                                                          typ)
+                                                          typ, context=context)
             if similarity > 0 and similarity >= best_match:
                 if (match and not is_same_type(match[-1].ret_type,
                                                typ.ret_type) and
@@ -702,12 +702,14 @@ def overload_call_target(self, arg_types: List[Type], arg_kinds: List[int],
                 # matching signature, or default to the first one if none
                 # match.
                 for m in match:
-                    if self.match_signature_types(arg_types, arg_kinds, arg_names, m):
+                    if self.match_signature_types(arg_types, arg_kinds, arg_names, m,
+                                                  context=context):
                         return m
                 return match[0]
 
     def erased_signature_similarity(self, arg_types: List[Type], arg_kinds: List[int],
-                                    arg_names: List[str], callee: CallableType) -> int:
+                                    arg_names: List[str], callee: CallableType,
+                                    context: Context) -> int:
         """Determine whether arguments could match the signature at runtime.
 
         Return similarity level (0 = no match, 1 = can match, 2 = non-promotion match). See
@@ -739,14 +741,15 @@ def check_arg(caller_type: Type, original_caller_type: Type, caller_kind: int,
 
         try:
             self.check_argument_types(arg_types, arg_kinds, callee, formal_to_actual,
-                                      None, check_arg=check_arg)
+                                      context=context, check_arg=check_arg)
         except Finished:
             pass
 
         return similarity
 
     def match_signature_types(self, arg_types: List[Type], arg_kinds: List[int],
-                              arg_names: List[str], callee: CallableType) -> bool:
+                              arg_names: List[str], callee: CallableType,
+                              context: Context) -> bool:
         """Determine whether arguments types match the signature.
 
         Assume that argument counts are compatible.
@@ -768,7 +771,7 @@ def check_arg(caller_type: Type, original_caller_type: Type, caller_kind: int,
                 ok = False
 
         self.check_argument_types(arg_types, arg_kinds, callee, formal_to_actual,
-                                  None, check_arg=check_arg)
+                                  context=context, check_arg=check_arg)
         return ok
 
     def apply_generic_arguments(self, callable: CallableType, types: List[Type],
diff --git a/mypy/messages.py b/mypy/messages.py
--- a/mypy/messages.py
+++ b/mypy/messages.py
@@ -140,7 +140,8 @@ def is_errors(self) -> bool:
     def report(self, msg: str, context: Context, severity: str, file: str = None) -> None:
         """Report an error or note (unless disabled)."""
         if self.disable_count <= 0:
-            self.errors.report(context.get_line(), msg.strip(), severity=severity, file=file)
+            self.errors.report(context.get_line() if context else -1,
+                               msg.strip(), severity=severity, file=file)
 
     def fail(self, msg: str, context: Context, file: str = None) -> None:
         """Report an error message (unless disabled)."""


Test patch: