Repository: python/mypy

Issue:
Improve error message for bad indexed assignment
The error message generated for this fragment is not very informative:

```py
from typing import Optional, List

def f(d: Optional[List[int]]) -> None:
    d[0] = 1  # Unsupported target for indexed assignment
```

It would be better to include the type in the message, such as like this:

```
t.py:4: error: Unsupported target for indexed assignment ("Optional[List[int]]")
```

#2900 is related, but this issue is more general.


Discussion:
May I try this? I want to this issue. @JukkaL 
@ndjman7 Sure, go ahead!
@ndjman7 how is your progress on this? Are you still working on it?  
@akerami sure. I'm working on it.

Resolving patch:
diff --git a/mypy/messages.py b/mypy/messages.py
--- a/mypy/messages.py
+++ b/mypy/messages.py
@@ -265,7 +265,8 @@ def has_no_attr(self,
                     format_type(original_type)), context, code=codes.INDEX)
         elif member == '__setitem__':
             # Indexed set.
-            self.fail('Unsupported target for indexed assignment', context, code=codes.INDEX)
+            self.fail('Unsupported target for indexed assignment ({})'.format(
+                format_type(original_type)), context, code=codes.INDEX)
         elif member == '__call__':
             if isinstance(original_type, Instance) and \
                     (original_type.type.fullname == 'builtins.function'):


Test patch:
diff --git a/test-data/unit/check-abstract.test b/test-data/unit/check-abstract.test
--- a/test-data/unit/check-abstract.test
+++ b/test-data/unit/check-abstract.test
@@ -953,7 +953,7 @@ Config = NewType('Config', Mapping[str, str])
 bad = Mapping[str, str]()  # E: Cannot instantiate abstract class 'Mapping' with abstract attribute '__iter__'
 default = Config({'cannot': 'modify'})  # OK
 
-default[1] = 2  # E: Unsupported target for indexed assignment
+default[1] = 2  # E: Unsupported target for indexed assignment ("Config")
 [builtins fixtures/dict.pyi]
 [typing fixtures/typing-full.pyi]
 
diff --git a/test-data/unit/check-class-namedtuple.test b/test-data/unit/check-class-namedtuple.test
--- a/test-data/unit/check-class-namedtuple.test
+++ b/test-data/unit/check-class-namedtuple.test
@@ -578,7 +578,7 @@ class Base(NamedTuple):
     def good_override(self) -> int:
         reveal_type(self)  # N: Revealed type is 'Tuple[builtins.int, fallback=__main__.Base]'
         reveal_type(self[0])  # N: Revealed type is 'builtins.int'
-        self[0] = 3  # E: Unsupported target for indexed assignment
+        self[0] = 3  # E: Unsupported target for indexed assignment ("Base")
         reveal_type(self.x)  # N: Revealed type is 'builtins.int'
         self.x = 3  # E: Property "x" defined in "Base" is read-only
         self[1]  # E: Tuple index out of range
@@ -591,7 +591,7 @@ class Child(Base):
     def new_method(self) -> int:
         reveal_type(self)  # N: Revealed type is 'Tuple[builtins.int, fallback=__main__.Child]'
         reveal_type(self[0])  # N: Revealed type is 'builtins.int'
-        self[0] = 3  # E: Unsupported target for indexed assignment
+        self[0] = 3  # E: Unsupported target for indexed assignment ("Child")
         reveal_type(self.x)  # N: Revealed type is 'builtins.int'
         self.x = 3  # E: Property "x" defined in "Base" is read-only
         self[1]  # E: Tuple index out of range
diff --git a/test-data/unit/check-columns.test b/test-data/unit/check-columns.test
--- a/test-data/unit/check-columns.test
+++ b/test-data/unit/check-columns.test
@@ -243,7 +243,7 @@ from typing import List
 ([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
+    1[1] = 1 # E:5: Unsupported target for indexed assignment ("int")
 [builtins fixtures/list.pyi]
 
 [case testColumnTypedDict]
diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test
--- a/test-data/unit/check-errorcodes.test
+++ b/test-data/unit/check-errorcodes.test
@@ -381,7 +381,7 @@ from typing import Dict
 x: Dict[int, int]
 x['']  # E: Invalid index type "str" for "Dict[int, int]"; expected type "int"  [index]
 1['']  # E: Value of type "int" is not indexable  [index]
-1[''] = 1  # E: Unsupported target for indexed assignment  [index]
+1[''] = 1  # E: Unsupported target for indexed assignment ("int")  [index]
 [builtins fixtures/dict.pyi]
 
 [case testErrorCodeInvalidTypeArg]
diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test
--- a/test-data/unit/check-expressions.test
+++ b/test-data/unit/check-expressions.test
@@ -911,7 +911,7 @@ class C:
 [out]
 main:3: error: Invalid index type "C" for "A"; expected type "B"
 main:4: error: Incompatible types in assignment (expression has type "A", target has type "C")
-main:5: error: Unsupported target for indexed assignment
+main:5: error: Unsupported target for indexed assignment ("B")
 
 [case testOverloadedIndexing]
 from foo import *
diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test
--- a/test-data/unit/check-inference.test
+++ b/test-data/unit/check-inference.test
@@ -2276,7 +2276,7 @@ T = TypeVar('T')
 class C(Sequence[T], Generic[T]): pass
 C[0] = 0
 [out]
-main:4: error: Unsupported target for indexed assignment
+main:4: error: Unsupported target for indexed assignment ("Type[C[Any]]")
 main:4: error: Invalid type: try using Literal[0] instead?
 
 [case testNoCrashOnPartialMember]
diff --git a/test-data/unit/check-newsyntax.test b/test-data/unit/check-newsyntax.test
--- a/test-data/unit/check-newsyntax.test
+++ b/test-data/unit/check-newsyntax.test
@@ -96,7 +96,7 @@ class X:
 
 [out]
 main:4: error: Unexpected type declaration
-main:4: error: Unsupported target for indexed assignment
+main:4: error: Unsupported target for indexed assignment ("str")
 main:5: error: Type cannot be declared in assignment to non-self attribute
 main:5: error: "str" has no attribute "x"
 
diff --git a/test-data/unit/check-tuples.test b/test-data/unit/check-tuples.test
--- a/test-data/unit/check-tuples.test
+++ b/test-data/unit/check-tuples.test
@@ -250,9 +250,9 @@ from typing import Tuple
 t = None # type: Tuple[A, B]
 n = 0
 
-t[0] = A() # E: Unsupported target for indexed assignment
-t[2] = A() # E: Unsupported target for indexed assignment
-t[n] = A() # E: Unsupported target for indexed assignment
+t[0] = A() # E: Unsupported target for indexed assignment ("Tuple[A, B]")
+t[2] = A() # E: Unsupported target for indexed assignment ("Tuple[A, B]")
+t[n] = A() # E: Unsupported target for indexed assignment ("Tuple[A, B]")
 
 class A: pass
 class B: pass