[cfe] Add front-end support for for and for-in

In collection literals, support for and for-in in Fasta's body
builder.  They are removed when encountered during type inference and
their lowering to block expressions is not yet implemented.

Change-Id: I41e6a7a4aca7ffafdc12119e1503e9c0df5a6589
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97628
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index da0c696..07f8ed9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -2270,22 +2270,18 @@
 
   @override
   void endForControlFlow(Token token) {
-    debugEvent("endForControlFlow");
-    // TODO(danrubel) implement control flow support
-
+    debugEvent("ForControlFlow");
     var entry = pop();
     int updateExpressionCount = pop();
     pop(); // left separator
     pop(); // left parenthesis
     Token forToken = pop();
-
-    popListForEffect(updateExpressionCount); // updates
-    popStatement(); // condition
+    List<Expression> updates = popListForEffect(updateExpressionCount);
+    Statement conditionStatement = popStatement(); // condition
     Object variableOrExpression = pop();
+    exitLocalScope();
 
-    if (entry != invalidCollectionElement) {
-      // TODO(danrubel): Replace with control flow structures
-      buildVariableDeclarations(variableOrExpression); // variables
+    if (!library.loader.target.enableControlFlowCollections) {
       // TODO(danrubel): Report a more user friendly error message
       // when an experiment is not enabled
       handleRecoverableError(
@@ -2293,9 +2289,27 @@
           forToken,
           forToken);
       push(invalidCollectionElement);
-    } else {
-      // TODO(danrubel): Remove once unified collections enabled by default
+      return;
+    }
+    if (entry == invalidCollectionElement) {
       push(invalidCollectionElement);
+      return;
+    }
+    transformCollections = true;
+    List<VariableDeclaration> variables =
+        buildVariableDeclarations(variableOrExpression);
+    Expression condition;
+    if (forest.isExpressionStatement(conditionStatement)) {
+      condition =
+          forest.getExpressionFromExpressionStatement(conditionStatement);
+    } else {
+      assert(forest.isEmptyStatement(conditionStatement));
+    }
+    if (entry is MapEntry) {
+      push(forest.forMapEntry(variables, condition, updates, entry, forToken));
+    } else {
+      push(forest.forElement(
+          variables, condition, updates, toValue(entry), forToken));
     }
   }
 
@@ -4040,18 +4054,16 @@
 
   @override
   void endForInControlFlow(Token token) {
-    debugEvent("endForInControlFlow");
-    // TODO(danrubel) implement control flow support
-
+    debugEvent("ForInControlFlow");
     var entry = pop();
-    pop(); // `in` keyword
+    Token inToken = pop();
     Token forToken = pop();
-    pop(NullValue.AwaitToken); // await token
-    popForValue(); // expression
-    pop(); // lvalue
+    pop(NullValue.AwaitToken);
+    Expression iterable = popForValue();
+    Object lvalue = pop(); // lvalue
+    exitLocalScope();
 
-    if (entry != invalidCollectionElement) {
-      // TODO(danrubel): Replace this with control flow element
+    if (!library.loader.target.enableControlFlowCollections) {
       // TODO(danrubel): Report a more user friendly error message
       // when an experiment is not enabled
       handleRecoverableError(
@@ -4059,10 +4071,96 @@
           forToken,
           forToken);
       push(invalidCollectionElement);
-    } else {
-      // TODO(danrubel): Remove once unified collections enabled by default
-      push(invalidCollectionElement);
+      return;
     }
+    if (entry == invalidCollectionElement) {
+      push(invalidCollectionElement);
+      return;
+    }
+    transformCollections = true;
+    VariableDeclaration variable = buildForInVariable(lvalue);
+    Expression problem = checkForInVariable(lvalue, variable, forToken);
+    Statement prologue = buildForInBody(lvalue, variable, forToken, inToken);
+    if (entry is MapEntry) {
+      push(forest.forInMapEntry(
+          variable, iterable, prologue, entry, problem, forToken));
+    } else {
+      push(forest.forInElement(
+          variable, iterable, prologue, toValue(entry), problem, forToken));
+    }
+  }
+
+  VariableDeclaration buildForInVariable(Object lvalue) {
+    if (lvalue is VariableDeclaration) return lvalue;
+    return new VariableDeclarationJudgment.forValue(null, functionNestingLevel);
+  }
+
+  Expression checkForInVariable(
+      Object lvalue, VariableDeclaration variable, Token forToken) {
+    if (lvalue is VariableDeclaration) {
+      if (variable.isConst) {
+        return buildProblem(fasta.messageForInLoopWithConstVariable,
+            variable.fileOffset, variable.name.length);
+      }
+    } else if (lvalue is! Generator) {
+      Message message = forest.isVariablesDeclaration(lvalue)
+          ? fasta.messageForInLoopExactlyOneVariable
+          : fasta.messageForInLoopNotAssignable;
+      Token token = forToken.next.next;
+      return buildProblem(
+          message, offsetForToken(token), lengthForToken(token));
+    }
+    return null;
+  }
+
+  Statement buildForInBody(Object lvalue, VariableDeclaration variable,
+      Token forToken, Token inKeyword) {
+    if (lvalue is VariableDeclaration) return null;
+    if (lvalue is Generator) {
+      /// We are in this case, where `lvalue` isn't a [VariableDeclaration]:
+      ///
+      ///     for (lvalue in expression) body
+      ///
+      /// This is normalized to:
+      ///
+      ///     for (final #t in expression) {
+      ///       lvalue = #t;
+      ///       body;
+      ///     }
+      TypePromotionFact fact =
+          typePromoter?.getFactForAccess(variable, functionNestingLevel);
+      TypePromotionScope scope = typePromoter?.currentScope;
+      Expression syntheticAssignment = lvalue.buildAssignment(
+          new VariableGetJudgment(variable, fact, scope)
+            ..fileOffset = inKeyword.offset,
+          voidContext: true);
+      if (syntheticAssignment is shadow.SyntheticExpressionJudgment) {
+        syntheticAssignment = wrapSyntheticExpression(
+            desugarSyntheticExpression(syntheticAssignment),
+            offsetForToken(lvalue.token));
+      }
+      return forest.expressionStatement(syntheticAssignment, null);
+    }
+    Message message = forest.isVariablesDeclaration(lvalue)
+        ? fasta.messageForInLoopExactlyOneVariable
+        : fasta.messageForInLoopNotAssignable;
+    Token token = forToken.next.next;
+    Statement body;
+    if (forest.isVariablesDeclaration(lvalue)) {
+      body = forest.block(
+          null,
+          // New list because the declarations are not a growable list.
+          new List<Statement>.from(
+              forest.variablesDeclarationExtractDeclarations(lvalue)),
+          null);
+    } else {
+      body = forest.expressionStatement(lvalue, null);
+    }
+    return combineStatements(
+        forest.expressionStatement(
+            buildProblem(message, offsetForToken(token), lengthForToken(token)),
+            null),
+        body);
   }
 
   @override
@@ -4083,67 +4181,22 @@
       body = forest.syntheticLabeledStatement(body);
       continueTarget.resolveContinues(forest, body);
     }
-    VariableDeclaration variable;
-    Expression problem;
-    if (lvalue is VariableDeclaration) {
-      variable = lvalue;
-      if (variable.isConst) {
-        problem = buildProblem(fasta.messageForInLoopWithConstVariable,
-            variable.fileOffset, variable.name.length);
-      }
-    } else if (lvalue is Generator) {
-      /// We are in this case, where `lvalue` isn't a [VariableDeclaration]:
-      ///
-      ///     for (lvalue in expression) body
-      ///
-      /// This is normalized to:
-      ///
-      ///     for (final #t in expression) {
-      ///       lvalue = #t;
-      ///       body;
-      ///     }
-      variable =
-          new VariableDeclarationJudgment.forValue(null, functionNestingLevel);
-      TypePromotionFact fact =
-          typePromoter?.getFactForAccess(variable, functionNestingLevel);
-      TypePromotionScope scope = typePromoter?.currentScope;
-      Expression syntheticAssignment = lvalue.buildAssignment(
-          new VariableGetJudgment(variable, fact, scope)
-            ..fileOffset = inKeyword.offset,
-          voidContext: true);
-      if (syntheticAssignment is shadow.SyntheticExpressionJudgment) {
-        syntheticAssignment = wrapSyntheticExpression(
-            desugarSyntheticExpression(syntheticAssignment),
-            offsetForToken(lvalue.token));
-      }
-      body = combineStatements(
-          forest.expressionStatement(syntheticAssignment, null), body);
-    } else {
-      Message message = forest.isVariablesDeclaration(lvalue)
-          ? fasta.messageForInLoopExactlyOneVariable
-          : fasta.messageForInLoopNotAssignable;
-      Token token = forToken.next.next;
-      variable =
-          new VariableDeclarationJudgment.forValue(null, functionNestingLevel);
-      problem =
-          buildProblem(message, offsetForToken(token), lengthForToken(token));
-      if (forest.isVariablesDeclaration(lvalue)) {
-        body = forest.block(
-            null,
-            <Statement>[]
-              ..addAll(forest.variablesDeclarationExtractDeclarations(lvalue))
-              ..add(body),
-            null);
+    VariableDeclaration variable = buildForInVariable(lvalue);
+    Expression problem = checkForInVariable(lvalue, variable, forToken);
+    Statement prologue = buildForInBody(lvalue, variable, forToken, inKeyword);
+    if (prologue != null) {
+      if (prologue is Block) {
+        if (body is Block) {
+          for (Statement statement in body.statements) {
+            prologue.addStatement(statement);
+          }
+        } else {
+          prologue.addStatement(body);
+        }
+        body = prologue;
       } else {
-        body =
-            combineStatements(forest.expressionStatement(lvalue, null), body);
+        body = combineStatements(prologue, body);
       }
-      body = combineStatements(
-          forest.expressionStatement(
-              buildProblem(
-                  message, offsetForToken(token), lengthForToken(token)),
-              null),
-          body);
     }
     Statement result = new ForInStatement(variable, expression, body,
         isAsync: awaitToken != null)
diff --git a/pkg/front_end/lib/src/fasta/kernel/collections.dart b/pkg/front_end/lib/src/fasta/kernel/collections.dart
index 7afb5a0..05cc74f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/collections.dart
@@ -11,6 +11,7 @@
         Expression,
         MapEntry,
         setParents,
+        Statement,
         transformList,
         TreeNode,
         VariableDeclaration,
@@ -150,19 +151,27 @@
 class ForInElement extends Expression with ControlFlowElement {
   VariableDeclaration variable; // Has no initializer.
   Expression iterable;
+  Statement prologue; // May be null.
   Expression body;
+  Expression problem; // May be null.
   bool isAsync; // True if this is an 'await for' loop.
 
-  ForInElement(this.variable, this.iterable, this.body, {this.isAsync: false}) {
+  ForInElement(
+      this.variable, this.iterable, this.prologue, this.body, this.problem,
+      {this.isAsync: false}) {
     variable?.parent = this;
     iterable?.parent = this;
+    prologue?.parent = this;
     body?.parent = this;
+    problem?.parent = this;
   }
 
   visitChildren(Visitor<Object> v) {
     variable?.accept(v);
     iterable?.accept(v);
+    prologue?.accept(v);
     body?.accept(v);
+    problem?.accept(v);
   }
 
   transformChildren(Transformer v) {
@@ -174,10 +183,18 @@
       iterable = iterable.accept(v);
       iterable?.parent = this;
     }
+    if (prologue != null) {
+      prologue = prologue.accept(v);
+      prologue?.parent = this;
+    }
     if (body != null) {
       body = body.accept(v);
       body?.parent = this;
     }
+    if (problem != null) {
+      problem = problem.accept(v);
+      problem?.parent = this;
+    }
   }
 }
 
@@ -306,20 +323,27 @@
 class ForInMapEntry extends TreeNode with ControlFlowMapEntry {
   VariableDeclaration variable; // Has no initializer.
   Expression iterable;
+  Statement prologue; // May be null.
   MapEntry body;
+  Expression problem; // May be null.
   bool isAsync; // True if this is an 'await for' loop.
 
-  ForInMapEntry(this.variable, this.iterable, this.body,
+  ForInMapEntry(
+      this.variable, this.iterable, this.prologue, this.body, this.problem,
       {this.isAsync: false}) {
     variable?.parent = this;
     iterable?.parent = this;
+    prologue?.parent = this;
     body?.parent = this;
+    problem?.parent = this;
   }
 
   visitChildren(Visitor<Object> v) {
     variable?.accept(v);
     iterable?.accept(v);
+    prologue?.accept(v);
     body?.accept(v);
+    problem?.accept(v);
   }
 
   transformChildren(Transformer v) {
@@ -331,9 +355,17 @@
       iterable = iterable.accept(v);
       iterable?.parent = this;
     }
+    if (prologue != null) {
+      prologue = prologue.accept(v);
+      prologue?.parent = this;
+    }
     if (body != null) {
       body = body.accept(v);
       body?.parent = this;
     }
+    if (problem != null) {
+      problem = problem.accept(v);
+      problem?.parent = this;
+    }
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index 005376d..baeda38 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -53,7 +53,15 @@
 
 import 'body_builder.dart' show LabelTarget;
 
-import 'collections.dart' show IfElement, IfMapEntry, SpreadElement;
+import 'collections.dart'
+    show
+        ForElement,
+        ForInElement,
+        ForInMapEntry,
+        ForMapEntry,
+        IfElement,
+        IfMapEntry,
+        SpreadElement;
 
 import 'kernel_expression_generator.dart'
     show
@@ -297,6 +305,42 @@
   }
 
   @override
+  Expression forElement(
+      List<VariableDeclaration> variables,
+      Expression condition,
+      List<Expression> updates,
+      Expression body,
+      Token token) {
+    return new ForElement(variables, condition, updates, body)
+      ..fileOffset = offsetForToken(token);
+  }
+
+  @override
+  MapEntry forMapEntry(
+      List<VariableDeclaration> variables,
+      Expression condition,
+      List<Expression> updates,
+      MapEntry body,
+      Token token) {
+    return new ForMapEntry(variables, condition, updates, body)
+      ..fileOffset = offsetForToken(token);
+  }
+
+  @override
+  Expression forInElement(VariableDeclaration variable, Expression iterable,
+      Statement prologue, Expression body, Expression problem, Token token) {
+    return new ForInElement(variable, iterable, prologue, body, problem)
+      ..fileOffset = offsetForToken(token);
+  }
+
+  @override
+  MapEntry forInMapEntry(VariableDeclaration variable, Expression iterable,
+      Statement prologue, MapEntry body, Expression problem, Token token) {
+    return new ForInMapEntry(variable, iterable, prologue, body, problem)
+      ..fileOffset = offsetForToken(token);
+  }
+
+  @override
   AssertInitializer assertInitializer(
       Token assertKeyword,
       Token leftParenthesis,
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 8cf916f..0cda9bd 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -196,6 +196,26 @@
   MapEntry ifMapEntry(
       Expression condition, MapEntry then, MapEntry otherwise, Token token);
 
+  Expression forElement(
+      List<VariableDeclaration> variables,
+      Expression condition,
+      List<Expression> updates,
+      Expression body,
+      Token token);
+
+  MapEntry forMapEntry(
+      List<VariableDeclaration> variables,
+      Expression condition,
+      List<Expression> updates,
+      MapEntry body,
+      Token token);
+
+  Expression forInElement(VariableDeclaration variable, Expression iterable,
+      Statement prologue, Expression body, Expression problem, Token token);
+
+  MapEntry forInMapEntry(VariableDeclaration variable, Expression iterable,
+      Statement prologue, MapEntry body, Expression problem, Token token);
+
   /// Return a representation of an assert that appears in a constructor's
   /// initializer list.
   Object assertInitializer(Token assertKeyword, Token leftParenthesis,
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 11ae0bb..6360473 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -11,6 +11,14 @@
 
   @override
   void defaultExpression(Expression node, DartType typeContext) {
+    if (node is ForElement) {
+      visitForElement(node, typeContext);
+      return;
+    }
+    if (node is ForInElement) {
+      visitForInElement(node, typeContext);
+      return;
+    }
     unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
         inferrer.helper.uri);
   }
@@ -21,6 +29,18 @@
         inferrer.helper.uri);
   }
 
+  void visitForElement(ForElement node, DartType typeContext) {
+    node.parent.replaceChild(node,
+        new InvalidExpression('unhandled for element in collection literal'));
+  }
+
+  void visitForInElement(ForInElement node, DartType typeContext) {
+    node.parent.replaceChild(
+        node,
+        new InvalidExpression(
+            'unhandled for-in element in collection literal'));
+  }
+
   @override
   void visitInvalidExpression(InvalidExpression node, DartType typeContext) {}
 
@@ -908,6 +928,27 @@
         actualTypes.add(const DynamicType());
       }
       return null;
+    } else if (entry is ForMapEntry || entry is ForInMapEntry) {
+      MapEntry replacement = new MapEntry(
+          new InvalidExpression('unhandled loop entry in map literal'),
+          new NullLiteral())
+        ..fileOffset = entry.fileOffset;
+      if (nested) {
+        // VisitChildren doesn't work so replaceChild doesn't work either.
+        IfMapEntry parent = entry.parent;
+        replacement.parent = parent;
+        if (parent.then == entry) {
+          parent.then = replacement;
+        } else {
+          parent.otherwise = replacement;
+        }
+      } else {
+        MapLiteral parent = entry.parent;
+        parent.entries[index] = replacement..parent = parent;
+        actualTypes.add(const BottomType());
+        actualTypes.add(inferrer.coreTypes.nullClass.rawType);
+      }
+      return null;
     } else {
       Expression key = entry.key;
       inferrer.inferExpression(key, inferredKeyType, true, isVoidAllowed: true);
@@ -984,7 +1025,7 @@
         typeChecksNeeded ? new List<DartType>(node.entries.length) : null;
     for (int i = 0; i < node.entries.length; i++) {
       MapEntry entry = node.entries[i];
-      if (entry is! SpreadMapEntry && entry is! IfMapEntry) {
+      if (entry is! ControlFlowMapEntry) {
         cachedKeys[i] = node.entries[i].key;
         cachedValues[i] = node.entries[i].value;
       }
diff --git a/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
index 05513ad..d747545 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
@@ -28,11 +28,25 @@
 
   @override
   DartType defaultExpression(Expression node, TypeInferrerImpl inferrer) {
+    if (node is ForElement) {
+      return visitForElement(node, inferrer);
+    }
+    if (node is ForInElement) {
+      return visitForInElement(node, inferrer);
+    }
     unhandled("${node.runtimeType}", "getInferredType", node.fileOffset,
         inferrer.uri);
     return const InvalidType();
   }
 
+  DartType visitForElement(ForElement node, TypeInferrerImpl inferrer) {
+    return const BottomType();
+  }
+
+  DartType visitForInElement(ForInElement node, TypeInferrerImpl inferrer) {
+    return const BottomType();
+  }
+
   @override
   DartType visitIntLiteral(IntLiteral node, TypeInferrerImpl inferrer) {
     return inferrer.coreTypes.intClass.rawType;
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 b0ebe25..9c46480 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
@@ -83,7 +83,16 @@
 import 'body_builder.dart' show combineStatements;
 
 import 'collections.dart'
-    show IfElement, SpreadElement, IfMapEntry, SpreadMapEntry;
+    show
+        ControlFlowMapEntry,
+        ForElement,
+        ForInElement,
+        ForInMapEntry,
+        ForMapEntry,
+        IfElement,
+        IfMapEntry,
+        SpreadElement,
+        SpreadMapEntry;
 
 import 'implicit_type_argument.dart' show ImplicitTypeArgument;
 
diff --git a/pkg/front_end/lib/src/fasta/source/scope_listener.dart b/pkg/front_end/lib/src/fasta/source/scope_listener.dart
index c49ce08..80db65e 100644
--- a/pkg/front_end/lib/src/fasta/source/scope_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/scope_listener.dart
@@ -94,6 +94,12 @@
   }
 
   @override
+  void beginForControlFlow(Token awaitToken, Token forToken) {
+    debugEvent("beginForControlFlow");
+    enterLocalScope("for in a collection");
+  }
+
+  @override
   void beginBlock(Token token) {
     debugEvent("beginBlock");
     enterLocalScope("block");
@@ -102,7 +108,7 @@
   @override
   void beginSwitchBlock(Token token) {
     debugEvent("beginSwitchBlock");
-    enterLocalScope("swithc block");
+    enterLocalScope("switch block");
     enterBreakTarget(token.charOffset);
   }
 
diff --git a/pkg/front_end/testcases/for_in_without_declaration.dart.legacy.expect b/pkg/front_end/testcases/for_in_without_declaration.dart.legacy.expect
index 8e5c9f4..9cc7892 100644
--- a/pkg/front_end/testcases/for_in_without_declaration.dart.legacy.expect
+++ b/pkg/front_end/testcases/for_in_without_declaration.dart.legacy.expect
@@ -142,10 +142,8 @@
          ^^^";
         dynamic x;
         dynamic y;
-        {
-          core::print(x);
-          core::print(y);
-        }
+        core::print(x);
+        core::print(y);
       }
     }
     const core::int constant = 0;
diff --git a/pkg/front_end/testcases/for_in_without_declaration.dart.legacy.transformed.expect b/pkg/front_end/testcases/for_in_without_declaration.dart.legacy.transformed.expect
index 8e5c9f4..9cc7892 100644
--- a/pkg/front_end/testcases/for_in_without_declaration.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/for_in_without_declaration.dart.legacy.transformed.expect
@@ -142,10 +142,8 @@
          ^^^";
         dynamic x;
         dynamic y;
-        {
-          core::print(x);
-          core::print(y);
-        }
+        core::print(x);
+        core::print(y);
       }
     }
     const core::int constant = 0;
diff --git a/pkg/front_end/testcases/for_in_without_declaration.dart.strong.expect b/pkg/front_end/testcases/for_in_without_declaration.dart.strong.expect
index cc7b291..9e758ec 100644
--- a/pkg/front_end/testcases/for_in_without_declaration.dart.strong.expect
+++ b/pkg/front_end/testcases/for_in_without_declaration.dart.strong.expect
@@ -172,10 +172,8 @@
          ^^^";
         dynamic x;
         dynamic y;
-        {
-          core::print(x);
-          core::print(y);
-        }
+        core::print(x);
+        core::print(y);
       }
     }
     const core::int constant = 0;
diff --git a/pkg/front_end/testcases/for_in_without_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/for_in_without_declaration.dart.strong.transformed.expect
index cc7b291..9e758ec 100644
--- a/pkg/front_end/testcases/for_in_without_declaration.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/for_in_without_declaration.dart.strong.transformed.expect
@@ -172,10 +172,8 @@
          ^^^";
         dynamic x;
         dynamic y;
-        {
-          core::print(x);
-          core::print(y);
-        }
+        core::print(x);
+        core::print(y);
       }
     }
     const core::int constant = 0;
diff --git a/pkg/front_end/testcases/rasta/issue_000042.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.expect
index 356e6a0..da8f0c6 100644
--- a/pkg/front_end/testcases/rasta/issue_000042.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.expect
@@ -34,7 +34,6 @@
        ^^^";
       dynamic x;
       dynamic y;
-      {}
     }
   }
   #L1:
diff --git a/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect
index 356e6a0..da8f0c6 100644
--- a/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect
@@ -34,7 +34,6 @@
        ^^^";
       dynamic x;
       dynamic y;
-      {}
     }
   }
   #L1:
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index 6a346c7..c0b00c3 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -132,47 +132,54 @@
 LanguageFeatures/Control-flow-collections/const_collections_A06_t02: CompileTimeError
 LanguageFeatures/Control-flow-collections/const_collections_A07_t01: CompileTimeError
 LanguageFeatures/Control-flow-collections/const_collections_A07_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_list_A04_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A02_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_map_A04_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A02_t01: CompileTimeError
 LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A04_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/scoping_A01_t01: CompileTimeError
 LanguageFeatures/Control-flow-collections/scoping_A02_t01: CompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A01_t01/01: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A01_t01/02: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A01_t01/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A01_t01/04: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A01_t01/05: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A02_t01/01: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A02_t01/02: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A02_t01/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A02_t01/04: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A02_t01/05: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A03_t01/01: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A03_t01/02: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A03_t01/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A03_t01/04: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A03_t01/05: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A04_t01/01: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A04_t01/02: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A04_t01/03: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_errors_A04_t01/04: MissingCompileTimeError
-LanguageFeatures/Control-flow-collections/static_semantics_A01_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A05_t01/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A05_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A06_t01/01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A06_t01/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A07_t01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A08_t01: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_errors_A11_t01: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/01: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/02: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/03: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/04: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/05: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/06: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/07: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/08: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/09: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/10: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/11: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A01_t02/12: MissingCompileTimeError
-LanguageFeatures/Control-flow-collections/static_semantics_A02_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/05: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/06: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/07: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/08: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/13: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/14: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/15: MissingCompileTimeError
+LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/16: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/17: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/18: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/19: MissingCompileTimeError
@@ -181,18 +188,12 @@
 LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/22: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/23: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/static_semantics_A02_t02/24: MissingCompileTimeError
-LanguageFeatures/Control-flow-collections/syntax_A01_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/syntax_A01_t02: CompileTimeError
-LanguageFeatures/Control-flow-collections/syntax_A01_t03: CompileTimeError
-LanguageFeatures/Control-flow-collections/syntax_A02_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/syntax_A02_t02: CompileTimeError
 LanguageFeatures/Control-flow-collections/syntax_A03_t01/02: MissingCompileTimeError
-LanguageFeatures/Control-flow-collections/type_inference_A01_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/type_inference_A04_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/type_inference_A05_t01: CompileTimeError
+LanguageFeatures/Control-flow-collections/syntax_A03_t01/03: MissingCompileTimeError
 LanguageFeatures/Control-flow-collections/type_inference_A06_t01: CompileTimeError
-LanguageFeatures/Control-flow-collections/type_inference_A08_t01: CompileTimeError
 LanguageFeatures/Control-flow-collections/type_promotion_A01_t01: CompileTimeError
+LanguageFeatures/Set-literals/disambiguating_A06_t01/06: MissingCompileTimeError
+LanguageFeatures/Set-literals/disambiguating_A06_t01/07: MissingCompileTimeError
 LanguageFeatures/Spread-collections/Ambiguity_A02_t02/01: MissingCompileTimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/01: MissingCompileTimeError
 LanguageFeatures/Spread-collections/ConstSpreads_A04_t01/02: MissingCompileTimeError
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index f3b7552..7dd43a6 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -201,6 +201,13 @@
 constructor5_test: CompileTimeError # Verification error
 constructor6_test: CompileTimeError # Verification error
 control_flow_collections/for_await_test: CompileTimeError
+control_flow_collections/for_const_test/00: MissingCompileTimeError
+control_flow_collections/for_const_test/01: MissingCompileTimeError
+control_flow_collections/for_const_test/03: MissingCompileTimeError
+control_flow_collections/for_const_test/04: MissingCompileTimeError
+control_flow_collections/for_const_test/06: MissingCompileTimeError
+control_flow_collections/for_const_test/07: MissingCompileTimeError
+control_flow_collections/for_const_test/08: MissingCompileTimeError
 control_flow_collections/for_inference_test: CompileTimeError
 control_flow_collections/for_test: CompileTimeError
 control_flow_collections/for_variable_test: CompileTimeError
@@ -224,8 +231,6 @@
 control_flow_collections/if_promotion_test/none: CompileTimeError
 control_flow_collections/if_test: CompileTimeError
 control_flow_collections/map_set_ambiguity_test: CompileTimeError
-control_flow_collections/syntax_error_test/09: Crash
-control_flow_collections/syntax_error_test/10: Crash
 control_flow_collections/syntax_test: CompileTimeError
 control_flow_collections/type_error_test/00: MissingCompileTimeError
 control_flow_collections/type_error_test/01: MissingCompileTimeError
@@ -238,6 +243,25 @@
 control_flow_collections/type_error_test/11: MissingCompileTimeError
 control_flow_collections/type_error_test/12: MissingCompileTimeError
 control_flow_collections/type_error_test/13: MissingCompileTimeError
+control_flow_collections/type_error_test/14: MissingCompileTimeError
+control_flow_collections/type_error_test/15: MissingCompileTimeError
+control_flow_collections/type_error_test/16: MissingCompileTimeError
+control_flow_collections/type_error_test/20: MissingCompileTimeError
+control_flow_collections/type_error_test/21: MissingCompileTimeError
+control_flow_collections/type_error_test/22: MissingCompileTimeError
+control_flow_collections/type_error_test/23: MissingCompileTimeError
+control_flow_collections/type_error_test/24: MissingCompileTimeError
+control_flow_collections/type_error_test/25: MissingCompileTimeError
+control_flow_collections/type_error_test/26: MissingCompileTimeError
+control_flow_collections/type_error_test/27: MissingCompileTimeError
+control_flow_collections/type_error_test/28: MissingCompileTimeError
+control_flow_collections/type_error_test/29: MissingCompileTimeError
+control_flow_collections/type_error_test/30: MissingCompileTimeError
+control_flow_collections/type_error_test/31: MissingCompileTimeError
+control_flow_collections/type_error_test/32: MissingCompileTimeError
+control_flow_collections/type_error_test/33: MissingCompileTimeError
+control_flow_collections/type_error_test/34: MissingCompileTimeError
+control_flow_collections/type_error_test/35: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e1: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e10: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e11: MissingCompileTimeError