Use special error templates for for-in loops.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: I7006468db607cf53d202b37c01913fb20bd722e7
Reviewed-on: https://dart-review.googlesource.com/65034
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_kernel_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_kernel_test.dart
index 9bd78f3..367a85e 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_kernel_test.dart
@@ -43,27 +43,6 @@
 
   @override
   @failingTest
-  test_awaitForIn_declaredVariableWrongType() async {
-    // Expected 1 errors of type StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, found 0
-    await super.test_awaitForIn_declaredVariableWrongType();
-  }
-
-  @override
-  @failingTest
-  test_awaitForIn_existingVariableWrongType() async {
-    // Expected 1 errors of type StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, found 0
-    await super.test_awaitForIn_existingVariableWrongType();
-  }
-
-  @override
-  @failingTest
-  test_awaitForIn_notStream() async {
-    // Expected 1 errors of type StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, found 0
-    await super.test_awaitForIn_notStream();
-  }
-
-  @override
-  @failingTest
   test_expectedTwoMapTypeArguments_one() async {
     // Bad state: Found 2 argument types for 1 type arguments
     await super.test_expectedTwoMapTypeArguments_one();
@@ -78,34 +57,6 @@
 
   @override
   @failingTest
-  test_forIn_declaredVariableWrongType() async {
-    // Expected 1 errors of type StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, found 0
-    await super.test_forIn_declaredVariableWrongType();
-  }
-
-  @override
-  @failingTest
-  test_forIn_existingVariableWrongType() async {
-    // Expected 1 errors of type StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, found 0
-    await super.test_forIn_existingVariableWrongType();
-  }
-
-  @override
-  @failingTest
-  test_forIn_notIterable() async {
-    // Expected 1 errors of type StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, found 0
-    await super.test_forIn_notIterable();
-  }
-
-  @override
-  @failingTest
-  test_forIn_typeBoundBad() async {
-    // Expected 1 errors of type StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, found 0
-    await super.test_forIn_typeBoundBad();
-  }
-
-  @override
-  @failingTest
   test_illegalAsyncGeneratorReturnType_function_nonStream() async {
     // Expected 1 errors of type StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, found 0
     await super.test_illegalAsyncGeneratorReturnType_function_nonStream();
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 700338f..ebef208 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -2888,6 +2888,46 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateForInLoopElementTypeNotAssignable = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""A value of type '#type' can't be assigned to a variable of type '#type2'.""",
+    tipTemplate: r"""Try changing the type of the variable.""",
+    withArguments: _withArgumentsForInLoopElementTypeNotAssignable);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeForInLoopElementTypeNotAssignable =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "ForInLoopElementTypeNotAssignable",
+        templateForInLoopElementTypeNotAssignable,
+        analyzerCode: "FOR_IN_OF_INVALID_ELEMENT_TYPE",
+        dart2jsCode: "*fatal*");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsForInLoopElementTypeNotAssignable(
+    DartType _type, DartType _type2) {
+  NameSystem nameSystem = new NameSystem();
+  StringBuffer buffer = new StringBuffer();
+  new Printer(buffer, syntheticNames: nameSystem).writeNode(_type);
+  String type = '$buffer';
+
+  buffer = new StringBuffer();
+  new Printer(buffer, syntheticNames: nameSystem).writeNode(_type2);
+  String type2 = '$buffer';
+
+  return new Message(codeForInLoopElementTypeNotAssignable,
+      message:
+          """A value of type '${type}' can't be assigned to a variable of type '${type2}'.""",
+      tip: """Try changing the type of the variable.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeForInLoopExactlyOneVariable =
     messageForInLoopExactlyOneVariable;
 
@@ -2908,6 +2948,42 @@
         r"""Can't assign to this, so it can't be used in a for-in loop.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateForInLoopTypeNotIterable = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The type '#type' used in the 'for' loop must implement '#type2'.""",
+    withArguments: _withArgumentsForInLoopTypeNotIterable);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeForInLoopTypeNotIterable =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "ForInLoopTypeNotIterable", templateForInLoopTypeNotIterable,
+        analyzerCode: "FOR_IN_OF_INVALID_TYPE", dart2jsCode: "*fatal*");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsForInLoopTypeNotIterable(
+    DartType _type, DartType _type2) {
+  NameSystem nameSystem = new NameSystem();
+  StringBuffer buffer = new StringBuffer();
+  new Printer(buffer, syntheticNames: nameSystem).writeNode(_type);
+  String type = '$buffer';
+
+  buffer = new StringBuffer();
+  new Printer(buffer, syntheticNames: nameSystem).writeNode(_type2);
+  String type2 = '$buffer';
+
+  return new Message(codeForInLoopTypeNotIterable,
+      message:
+          """The type '${type}' used in the 'for' loop must implement '${type2}'.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeFunctionTypeDefaultValue = messageFunctionTypeDefaultValue;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index bee205f..af4f102 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -41,7 +41,9 @@
     show
         noLength,
         templateCantInferTypeDueToCircularity,
-        templateCantUseSuperBoundedTypeForInstanceCreation;
+        templateCantUseSuperBoundedTypeForInstanceCreation,
+        templateForInLoopElementTypeNotAssignable,
+        templateForInLoopTypeNotIterable;
 
 import '../problems.dart' show unhandled, unsupported;
 
@@ -1125,7 +1127,8 @@
         inferrer.wrapType(const DynamicType(), iterableClass),
         inferredExpressionType,
         iterable,
-        iterable.fileOffset);
+        iterable.fileOffset,
+        template: templateForInLoopTypeNotIterable);
 
     DartType inferredType;
     if (typeNeeded || typeChecksNeeded) {
@@ -1159,7 +1162,8 @@
       var variableGet = new VariableGet(tempVar)
         ..fileOffset = this.variable.fileOffset;
       var implicitDowncast = inferrer.ensureAssignable(
-          variable.type, inferredType, variableGet, fileOffset);
+          variable.type, inferredType, variableGet, fileOffset,
+          template: templateForInLoopElementTypeNotAssignable);
       if (implicitDowncast != null) {
         this.variable = tempVar..parent = this;
         variable.initializer = implicitDowncast..parent = variable;
@@ -1171,7 +1175,8 @@
             greatestClosure(inferrer.coreTypes, syntheticWriteType),
             this.variable.type,
             syntheticAssignment.rhs,
-            syntheticAssignment.rhs.fileOffset);
+            syntheticAssignment.rhs.fileOffset,
+            template: templateForInLoopElementTypeNotAssignable);
         if (syntheticAssignment is PropertyAssignmentJudgment) {
           syntheticAssignment._handleWriteContravariance(
               inferrer, inferrer.thisType);
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 8517bbc..43e7f0b 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -172,10 +172,12 @@
 FinalAndCovariant/script2: Fail
 FinalFieldWithoutInitializer/example: Fail
 FinalInstanceVariableAlreadyInitialized/example: Fail
+ForInLoopElementTypeNotAssignable/example: Fail
 ForInLoopExactlyOneVariable/analyzerCode: Fail # The analyzer doesn't recover well.
 ForInLoopExactlyOneVariable/statement: Fail # Fasta reports too many errors.
 ForInLoopNotAssignable/analyzerCode: Fail # The analyzer reports a different error.
 ForInLoopNotAssignable/statement: Fail
+ForInLoopTypeNotIterable/example: Fail
 FunctionTypeDefaultValue/example: Fail
 FunctionTypedParameterVar/script1: Fail
 GeneratorReturnsValue/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 4e00d0d..60f4061 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -2407,6 +2407,17 @@
   severity: ERROR
   statement: "for (var x, y in []) {}"
 
+ForInLoopElementTypeNotAssignable:
+  template: "A value of type '#type' can't be assigned to a variable of type '#type2'."
+  tip: "Try changing the type of the variable."
+  analyzerCode: FOR_IN_OF_INVALID_ELEMENT_TYPE
+  dart2jsCode: "*fatal*"
+
+ForInLoopTypeNotIterable:
+  template: "The type '#type' used in the 'for' loop must implement '#type2'."
+  analyzerCode: FOR_IN_OF_INVALID_TYPE
+  dart2jsCode: "*fatal*"
+
 InitializingFormalTypeMismatch:
   template: "The type of parameter '#name' (#type) is not a subtype of the corresponding field's type (#type2)."
   tip: "Try changing the type of parameter '#name' to a subtype of #type2."
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.expect
index 4b7c312..f79f8f4 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.expect
@@ -48,7 +48,7 @@
   }
   for (final self::Foo #t7 in list) {
     core::String x = let dynamic _ = null in let final dynamic #t8 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart:39:15: Error: A value of type 'test::Foo' can't be assigned to a variable of type 'dart.core::String'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::String'.
+Try changing the type of the variable.
   for (String x in /*error:FOR_IN_OF_INVALID_ELEMENT_TYPE*/ list) {
               ^" in let final dynamic #t9 = #t7 in null;
     core::String y = x;
@@ -69,8 +69,7 @@
     self::Foo y = x;
   }
   core::Map<core::String, self::Foo> map = <core::String, self::Foo>{};
-  for (dynamic x in let dynamic _ = null in let final dynamic #t13 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart:60:68: Error: A value of type 'dart.core::Map<dart.core::String, test::Foo>' can't be assigned to a variable of type 'dart.core::Iterable<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::Iterable<dynamic>'.
+  for (dynamic x in let dynamic _ = null in let final dynamic #t13 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart:60:68: Error: The type 'dart.core::Map<dart.core::String, test::Foo>' used in the 'for' loop must implement 'dart.core::Iterable<dynamic>'.
   for (var /*@type=dynamic*/ x in /*error:FOR_IN_OF_INVALID_TYPE*/ map) {
                                                                    ^" in let final dynamic #t14 = map in null) {
     core::String y = x as{TypeError} core::String;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect
index 674ff5c..c3336c2 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect
@@ -48,7 +48,7 @@
   }
   for (final self::Foo #t7 in list) {
     core::String x = let<BottomType> _ = null in let final dynamic #t8 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart:39:15: Error: A value of type 'test::Foo' can't be assigned to a variable of type 'dart.core::String'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::String'.
+Try changing the type of the variable.
   for (String x in /*error:FOR_IN_OF_INVALID_ELEMENT_TYPE*/ list) {
               ^" in let final self::Foo #t9 = #t7 in null;
     core::String y = x;
@@ -69,8 +69,7 @@
     self::Foo y = x;
   }
   core::Map<core::String, self::Foo> map = <core::String, self::Foo>{};
-  for (dynamic x in let<BottomType> _ = null in let final dynamic #t13 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart:60:68: Error: A value of type 'dart.core::Map<dart.core::String, test::Foo>' can't be assigned to a variable of type 'dart.core::Iterable<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::Iterable<dynamic>'.
+  for (dynamic x in let<BottomType> _ = null in let final dynamic #t13 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart:60:68: Error: The type 'dart.core::Map<dart.core::String, test::Foo>' used in the 'for' loop must implement 'dart.core::Iterable<dynamic>'.
   for (var /*@type=dynamic*/ x in /*error:FOR_IN_OF_INVALID_TYPE*/ map) {
                                                                    ^" in let final core::Map<core::String, self::Foo> #t14 = map in null) {
     core::String y = x as{TypeError} core::String;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.expect
index 5ebd147..a915514 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.expect
@@ -53,7 +53,7 @@
   }
   await for (final self::Foo #t7 in myStream) {
     core::String x = let dynamic _ = null in let final dynamic #t8 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:45:21: Error: A value of type 'test::Foo' can't be assigned to a variable of type 'dart.core::String'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::String'.
+Try changing the type of the variable.
   await for (String x in /*error:FOR_IN_OF_INVALID_ELEMENT_TYPE*/ myStream) {
                     ^" in let final dynamic #t9 = #t7 in null;
     core::String y = x;
@@ -74,8 +74,7 @@
     self::Foo y = x;
   }
   core::Map<core::String, self::Foo> map = <core::String, self::Foo>{};
-  await for (dynamic x in let dynamic _ = null in let final dynamic #t13 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:66:74: Error: A value of type 'dart.core::Map<dart.core::String, test::Foo>' can't be assigned to a variable of type 'dart.async::Stream<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.async::Stream<dynamic>'.
+  await for (dynamic x in let dynamic _ = null in let final dynamic #t13 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:66:74: Error: The type 'dart.core::Map<dart.core::String, test::Foo>' used in the 'for' loop must implement 'dart.async::Stream<dynamic>'.
   await for (var /*@type=dynamic*/ x in /*error:FOR_IN_OF_INVALID_TYPE*/ map) {
                                                                          ^" in let final dynamic #t14 = map in null) {
     core::String y = x as{TypeError} core::String;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
index f191019..a3426db 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
@@ -202,7 +202,7 @@
                 final self::Foo #t16 = :for-iterator.{asy::_StreamIterator::current};
                 {
                   core::String x = let<BottomType> _ = null in let final dynamic #t17 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:45:21: Error: A value of type 'test::Foo' can't be assigned to a variable of type 'dart.core::String'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::String'.
+Try changing the type of the variable.
   await for (String x in /*error:FOR_IN_OF_INVALID_ELEMENT_TYPE*/ myStream) {
                     ^" in let final self::Foo #t18 = #t16 in null;
                   core::String y = x;
@@ -288,8 +288,7 @@
         }
         core::Map<core::String, self::Foo> map = <core::String, self::Foo>{};
         {
-          asy::_StreamIterator<dynamic> :for-iterator = new asy::_StreamIterator::•<dynamic>(let<BottomType> _ = null in let final dynamic #t29 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:66:74: Error: A value of type 'dart.core::Map<dart.core::String, test::Foo>' can't be assigned to a variable of type 'dart.async::Stream<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.async::Stream<dynamic>'.
+          asy::_StreamIterator<dynamic> :for-iterator = new asy::_StreamIterator::•<dynamic>(let<BottomType> _ = null in let final dynamic #t29 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:66:74: Error: The type 'dart.core::Map<dart.core::String, test::Foo>' used in the 'for' loop must implement 'dart.async::Stream<dynamic>'.
   await for (var /*@type=dynamic*/ x in /*error:FOR_IN_OF_INVALID_TYPE*/ map) {
                                                                          ^" in let final core::Map<core::String, self::Foo> #t30 = map in null);
           try
diff --git a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart
index 5360fa7..da9ed77 100644
--- a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart
+++ b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart
@@ -7,11 +7,11 @@
 
 test() async {
   String s;
-  for (int x in /*@error=InvalidAssignment*/ s) {}
-  await for (int x in /*@error=InvalidAssignment*/ s) {}
+  for (int x in /*@error=ForInLoopTypeNotIterable*/ s) {}
+  await for (int x in /*@error=ForInLoopTypeNotIterable*/ s) {}
   int y;
-  for (y in /*@error=InvalidAssignment*/ s) {}
-  await for (y in /*@error=InvalidAssignment*/ s) {}
+  for (y in /*@error=ForInLoopTypeNotIterable*/ s) {}
+  await for (y in /*@error=ForInLoopTypeNotIterable*/ s) {}
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.expect b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.expect
index cb323c5..9e2999f 100644
--- a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.expect
@@ -4,29 +4,25 @@
 
 static method test() → dynamic async {
   core::String s;
-  for (final dynamic #t1 in let dynamic _ = null in let final dynamic #t2 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:10:46: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.core::Iterable<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::Iterable<dynamic>'.
-  for (int x in /*@error=InvalidAssignment*/ s) {}
-                                             ^" in let final dynamic #t3 = s in null) {
+  for (final dynamic #t1 in let dynamic _ = null in let final dynamic #t2 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:10:53: Error: The type 'dart.core::String' used in the 'for' loop must implement 'dart.core::Iterable<dynamic>'.
+  for (int x in /*@error=ForInLoopTypeNotIterable*/ s) {}
+                                                    ^" in let final dynamic #t3 = s in null) {
     core::int x = #t1 as{TypeError} core::int;
   }
-  await for (final dynamic #t4 in let dynamic _ = null in let final dynamic #t5 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:11:52: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.async::Stream<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.async::Stream<dynamic>'.
-  await for (int x in /*@error=InvalidAssignment*/ s) {}
-                                                   ^" in let final dynamic #t6 = s in null) {
+  await for (final dynamic #t4 in let dynamic _ = null in let final dynamic #t5 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:11:59: Error: The type 'dart.core::String' used in the 'for' loop must implement 'dart.async::Stream<dynamic>'.
+  await for (int x in /*@error=ForInLoopTypeNotIterable*/ s) {}
+                                                          ^" in let final dynamic #t6 = s in null) {
     core::int x = #t4 as{TypeError} core::int;
   }
   core::int y;
-  for (final dynamic #t7 in let dynamic _ = null in let final dynamic #t8 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:13:42: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.core::Iterable<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::Iterable<dynamic>'.
-  for (y in /*@error=InvalidAssignment*/ s) {}
-                                         ^" in let final dynamic #t9 = s in null) {
+  for (final dynamic #t7 in let dynamic _ = null in let final dynamic #t8 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:13:49: Error: The type 'dart.core::String' used in the 'for' loop must implement 'dart.core::Iterable<dynamic>'.
+  for (y in /*@error=ForInLoopTypeNotIterable*/ s) {}
+                                                ^" in let final dynamic #t9 = s in null) {
     y = #t7 as{TypeError} core::int;
   }
-  await for (final dynamic #t10 in let dynamic _ = null in let final dynamic #t11 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:14:48: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.async::Stream<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.async::Stream<dynamic>'.
-  await for (y in /*@error=InvalidAssignment*/ s) {}
-                                               ^" in let final dynamic #t12 = s in null) {
+  await for (final dynamic #t10 in let dynamic _ = null in let final dynamic #t11 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:14:55: Error: The type 'dart.core::String' used in the 'for' loop must implement 'dart.async::Stream<dynamic>'.
+  await for (y in /*@error=ForInLoopTypeNotIterable*/ s) {}
+                                                      ^" in let final dynamic #t12 = s in null) {
     y = #t10 as{TypeError} core::int;
   }
 }
diff --git a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect
index 475b64a..ca1eeb2 100644
--- a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect
@@ -20,17 +20,15 @@
       #L1:
       {
         core::String s;
-        for (final dynamic #t1 in let<BottomType> _ = null in let final dynamic #t2 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:10:46: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.core::Iterable<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::Iterable<dynamic>'.
-  for (int x in /*@error=InvalidAssignment*/ s) {}
-                                             ^" in let final core::String #t3 = s in null) {
+        for (final dynamic #t1 in let<BottomType> _ = null in let final dynamic #t2 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:10:53: Error: The type 'dart.core::String' used in the 'for' loop must implement 'dart.core::Iterable<dynamic>'.
+  for (int x in /*@error=ForInLoopTypeNotIterable*/ s) {}
+                                                    ^" in let final core::String #t3 = s in null) {
           core::int x = #t1 as{TypeError} core::int;
         }
         {
-          asy::_StreamIterator<dynamic> :for-iterator = new asy::_StreamIterator::•<dynamic>(let<BottomType> _ = null in let final dynamic #t4 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:11:52: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.async::Stream<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.async::Stream<dynamic>'.
-  await for (int x in /*@error=InvalidAssignment*/ s) {}
-                                                   ^" in let final core::String #t5 = s in null);
+          asy::_StreamIterator<dynamic> :for-iterator = new asy::_StreamIterator::•<dynamic>(let<BottomType> _ = null in let final dynamic #t4 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:11:59: Error: The type 'dart.core::String' used in the 'for' loop must implement 'dart.async::Stream<dynamic>'.
+  await for (int x in /*@error=ForInLoopTypeNotIterable*/ s) {}
+                                                          ^" in let final core::String #t5 = s in null);
           try
             #L2:
             while (true) {
@@ -51,17 +49,15 @@
             }
         }
         core::int y;
-        for (final dynamic #t9 in let<BottomType> _ = null in let final dynamic #t10 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:13:42: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.core::Iterable<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::Iterable<dynamic>'.
-  for (y in /*@error=InvalidAssignment*/ s) {}
-                                         ^" in let final core::String #t11 = s in null) {
+        for (final dynamic #t9 in let<BottomType> _ = null in let final dynamic #t10 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:13:49: Error: The type 'dart.core::String' used in the 'for' loop must implement 'dart.core::Iterable<dynamic>'.
+  for (y in /*@error=ForInLoopTypeNotIterable*/ s) {}
+                                                ^" in let final core::String #t11 = s in null) {
           y = #t9 as{TypeError} core::int;
         }
         {
-          asy::_StreamIterator<dynamic> :for-iterator = new asy::_StreamIterator::•<dynamic>(let<BottomType> _ = null in let final dynamic #t12 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:14:48: Error: A value of type 'dart.core::String' can't be assigned to a variable of type 'dart.async::Stream<dynamic>'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.async::Stream<dynamic>'.
-  await for (y in /*@error=InvalidAssignment*/ s) {}
-                                               ^" in let final core::String #t13 = s in null);
+          asy::_StreamIterator<dynamic> :for-iterator = new asy::_StreamIterator::•<dynamic>(let<BottomType> _ = null in let final dynamic #t12 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart:14:55: Error: The type 'dart.core::String' used in the 'for' loop must implement 'dart.async::Stream<dynamic>'.
+  await for (y in /*@error=ForInLoopTypeNotIterable*/ s) {}
+                                                      ^" in let final core::String #t13 = s in null);
           try
             #L3:
             while (true) {
diff --git a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart
index 06ba28b..9ffdfe8 100644
--- a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart
+++ b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart
@@ -23,8 +23,8 @@
   await for (a in stream) {}
   for (b in iterable) {}
   await for (b in stream) {}
-  for (i /*@error=InvalidAssignment*/ in iterable) {}
-  await for (i /*@error=InvalidAssignment*/ in stream) {}
+  for (i /*@error=ForInLoopElementTypeNotAssignable*/ in iterable) {}
+  await for (i /*@error=ForInLoopElementTypeNotAssignable*/ in stream) {}
   for (a in /*@typeArgs=Iterable<A>*/ f()) {}
   await for (a in /*@typeArgs=Stream<A>*/ f()) {}
 }
diff --git a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.expect b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.expect
index 4c88501..9ac5ea0 100644
--- a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.expect
@@ -34,16 +34,16 @@
     b = #t4 as{TypeError} self::B;
   }
   for (final self::A #t5 in iterable) {
-    i = let dynamic _ = null in let final dynamic #t6 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart:26:39: Error: A value of type 'test::A' can't be assigned to a variable of type 'dart.core::int'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::int'.
-  for (i /*@error=InvalidAssignment*/ in iterable) {}
-                                      ^" in let final dynamic #t7 = #t5 in null;
+    i = let dynamic _ = null in let final dynamic #t6 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart:26:55: Error: A value of type 'test::A' can't be assigned to a variable of type 'dart.core::int'.
+Try changing the type of the variable.
+  for (i /*@error=ForInLoopElementTypeNotAssignable*/ in iterable) {}
+                                                      ^" in let final dynamic #t7 = #t5 in null;
   }
   await for (final self::A #t8 in stream) {
-    i = let dynamic _ = null in let final dynamic #t9 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart:27:45: Error: A value of type 'test::A' can't be assigned to a variable of type 'dart.core::int'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::int'.
-  await for (i /*@error=InvalidAssignment*/ in stream) {}
-                                            ^" in let final dynamic #t10 = #t8 in null;
+    i = let dynamic _ = null in let final dynamic #t9 = let dynamic _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart:27:61: Error: A value of type 'test::A' can't be assigned to a variable of type 'dart.core::int'.
+Try changing the type of the variable.
+  await for (i /*@error=ForInLoopElementTypeNotAssignable*/ in stream) {}
+                                                            ^" in let final dynamic #t10 = #t8 in null;
   }
   for (final self::A #t11 in self::f<core::Iterable<self::A>>()) {
     a = #t11;
diff --git a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect
index 399a9d4..e371b6c 100644
--- a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect
@@ -85,10 +85,10 @@
             }
         }
         for (final self::A #t9 in iterable) {
-          i = let<BottomType> _ = null in let final dynamic #t10 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart:26:39: Error: A value of type 'test::A' can't be assigned to a variable of type 'dart.core::int'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::int'.
-  for (i /*@error=InvalidAssignment*/ in iterable) {}
-                                      ^" in let final self::A #t11 = #t9 in null;
+          i = let<BottomType> _ = null in let final dynamic #t10 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart:26:55: Error: A value of type 'test::A' can't be assigned to a variable of type 'dart.core::int'.
+Try changing the type of the variable.
+  for (i /*@error=ForInLoopElementTypeNotAssignable*/ in iterable) {}
+                                                      ^" in let final self::A #t11 = #t9 in null;
         }
         {
           asy::_StreamIterator<self::A> :for-iterator = new asy::_StreamIterator::•<self::A>(stream);
@@ -99,10 +99,10 @@
               if(:result) {
                 final self::A #t13 = :for-iterator.{asy::_StreamIterator::current};
                 {
-                  i = let<BottomType> _ = null in let final dynamic #t14 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart:27:45: Error: A value of type 'test::A' can't be assigned to a variable of type 'dart.core::int'.
-Try changing the type of the left hand side, or casting the right hand side to 'dart.core::int'.
-  await for (i /*@error=InvalidAssignment*/ in stream) {}
-                                            ^" in let final self::A #t15 = #t13 in null;
+                  i = let<BottomType> _ = null in let final dynamic #t14 = let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart:27:61: Error: A value of type 'test::A' can't be assigned to a variable of type 'dart.core::int'.
+Try changing the type of the variable.
+  await for (i /*@error=ForInLoopElementTypeNotAssignable*/ in stream) {}
+                                                            ^" in let final self::A #t15 = #t13 in null;
                 }
               }
               else