From ac21076110285f0a7b5e00c9a17d1586a5b7fb8b Mon Sep 17 00:00:00 2001 From: Kevin Millikin Date: Tue, 26 Mar 2019 12:16:22 +0000 Subject: [PATCH] [cfe] Implement compilation of loops in lists and sets Implement the translation of for and for-in loops in non-const lists and sets. They are lowered to block expressions containing a loop. It is impossible to target these loops with a break or continue because they do not contain statements in their body. Type inference is not yet implemented. Change-Id: I35ff1650fde54cd376fe0b444891010435c74507 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97922 Reviewed-by: Dmitry Stefantsov --- .../lib/src/fasta/kernel/body_builder.dart | 8 +- .../lib/src/fasta/kernel/fangorn.dart | 12 +- .../lib/src/fasta/kernel/forest.dart | 6 +- .../src/fasta/kernel/inference_visitor.dart | 132 ++++++++++++------ .../fasta/kernel/inferred_type_visitor.dart | 14 -- .../fasta/kernel/transform_collections.dart | 71 ++++++++-- .../testcases/control_flow_collection.dart | 6 + ...control_flow_collection.dart.legacy.expect | 48 +++++-- ..._collection.dart.legacy.transformed.expect | 48 +++++-- ...control_flow_collection.dart.strong.expect | 14 ++ ..._collection.dart.strong.transformed.expect | 14 ++ ...flow_collection.dart.type_promotion.expect | 6 + tests/co19_2/co19_2-kernel.status | 7 - tests/language_2/language_2_kernel.status | 14 +- 14 files changed, 285 insertions(+), 115 deletions(-) create mode 100644 pkg/front_end/testcases/control_flow_collection.dart.type_promotion.expect 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 07f8ed9b9f945..224806d6879a3 100644 --- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart @@ -4058,7 +4058,7 @@ abstract class BodyBuilder extends ScopeListener var entry = pop(); Token inToken = pop(); Token forToken = pop(); - pop(NullValue.AwaitToken); + Token awaitToken = pop(NullValue.AwaitToken); Expression iterable = popForValue(); Object lvalue = pop(); // lvalue exitLocalScope(); @@ -4083,10 +4083,12 @@ abstract class BodyBuilder extends ScopeListener Statement prologue = buildForInBody(lvalue, variable, forToken, inToken); if (entry is MapEntry) { push(forest.forInMapEntry( - variable, iterable, prologue, entry, problem, forToken)); + variable, iterable, prologue, entry, problem, forToken, + isAsync: awaitToken != null)); } else { push(forest.forInElement( - variable, iterable, prologue, toValue(entry), problem, forToken)); + variable, iterable, prologue, toValue(entry), problem, forToken, + isAsync: awaitToken != null)); } } diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart index baeda38a122b7..1616ce7df8dde 100644 --- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart +++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart @@ -328,15 +328,19 @@ class Fangorn extends Forest { @override Expression forInElement(VariableDeclaration variable, Expression iterable, - Statement prologue, Expression body, Expression problem, Token token) { - return new ForInElement(variable, iterable, prologue, body, problem) + Statement prologue, Expression body, Expression problem, Token token, + {bool isAsync: false}) { + return new ForInElement(variable, iterable, prologue, body, problem, + isAsync: isAsync) ..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) + Statement prologue, MapEntry body, Expression problem, Token token, + {bool isAsync: false}) { + return new ForInMapEntry(variable, iterable, prologue, body, problem, + isAsync: isAsync) ..fileOffset = offsetForToken(token); } diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart index 0cda9bd9b4220..818a3b1c07b45 100644 --- a/pkg/front_end/lib/src/fasta/kernel/forest.dart +++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart @@ -211,10 +211,12 @@ abstract class Forest { Token token); Expression forInElement(VariableDeclaration variable, Expression iterable, - Statement prologue, Expression body, Expression problem, Token token); + Statement prologue, Expression body, Expression problem, Token token, + {bool isAsync: false}); MapEntry forInMapEntry(VariableDeclaration variable, Expression iterable, - Statement prologue, MapEntry body, Expression problem, Token token); + Statement prologue, MapEntry body, Expression problem, Token token, + {bool isAsync: false}); /// Return a representation of an assert that appears in a constructor's /// initializer list. 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 63604730b37e9..4e50c703fc282 100644 --- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart +++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart @@ -11,14 +11,6 @@ class InferenceVisitor extends BodyVisitor1 { @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); } @@ -29,18 +21,6 @@ class InferenceVisitor extends BodyVisitor1 { 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) {} @@ -264,11 +244,12 @@ class InferenceVisitor extends BodyVisitor1 { node.field.type, initializerType, node.value, node.fileOffset); } - void handleForInStatementDeclaringVariable(ForInStatement node) { + void handleForInDeclaringVariable( + VariableDeclaration variable, Expression iterable, Statement body, + {bool isAsync: false}) { DartType elementType; bool typeNeeded = false; bool typeChecksNeeded = !inferrer.isTopLevel; - final VariableDeclaration variable = node.variable; if (VariableDeclarationJudgment.isImplicitlyTyped(variable)) { typeNeeded = true; elementType = const UnknownType(); @@ -276,45 +257,52 @@ class InferenceVisitor extends BodyVisitor1 { elementType = variable.type; } - DartType inferredType = - inferForInIterable(node, elementType, typeNeeded || typeChecksNeeded); + DartType inferredType = inferForInIterable( + iterable, elementType, typeNeeded || typeChecksNeeded, + isAsync: isAsync); if (typeNeeded) { inferrer.instrumentation?.record(inferrer.uri, variable.fileOffset, 'type', new InstrumentationValueForType(inferredType)); variable.type = inferredType; } - inferrer.inferStatement(node.body); + if (body != null) inferrer.inferStatement(body); VariableDeclaration tempVar = new VariableDeclaration(null, type: inferredType, isFinal: true); VariableGet variableGet = new VariableGet(tempVar) ..fileOffset = variable.fileOffset; + TreeNode parent = variable.parent; Expression implicitDowncast = inferrer.ensureAssignable( - variable.type, inferredType, variableGet, node.fileOffset, + variable.type, inferredType, variableGet, parent.fileOffset, template: templateForInLoopElementTypeNotAssignable); if (implicitDowncast != null) { - node.variable = tempVar..parent = node; + parent.replaceChild(variable, tempVar); variable.initializer = implicitDowncast..parent = variable; - node.body = combineStatements(variable, node.body)..parent = node; + if (body == null) { + ForInElement element = parent; + element.prologue = variable; + } else { + parent.replaceChild(body, combineStatements(variable, body)); + } } } DartType inferForInIterable( - ForInStatement node, DartType elementType, bool typeNeeded) { - Class iterableClass = node.isAsync + Expression iterable, DartType elementType, bool typeNeeded, + {bool isAsync: false}) { + Class iterableClass = isAsync ? inferrer.coreTypes.streamClass : inferrer.coreTypes.iterableClass; DartType context = inferrer.wrapType(elementType, iterableClass); - Expression iterable = node.iterable; inferrer.inferExpression(iterable, context, typeNeeded); DartType inferredExpressionType = inferrer.resolveTypeParameter(getInferredType(iterable, inferrer)); inferrer.ensureAssignable( inferrer.wrapType(const DynamicType(), iterableClass), inferredExpressionType, - node.iterable, - node.iterable.fileOffset, + iterable, + iterable.fileOffset, template: templateForInLoopTypeNotIterable); DartType inferredType; if (typeNeeded) { @@ -330,15 +318,17 @@ class InferenceVisitor extends BodyVisitor1 { return inferredType; } - void handleForInStatementWithoutVariable(ForInStatement node) { + void handleForInWithoutVariable( + VariableDeclaration variable, Expression iterable, Statement body, + {bool isAsync: false}) { DartType elementType; bool typeChecksNeeded = !inferrer.isTopLevel; DartType syntheticWriteType; Expression syntheticAssignment; - Block block = node.body; - ExpressionStatement statement = block.statements[0]; - SyntheticExpressionJudgment judgment = statement.expression; Expression rhs; + ExpressionStatement statement = + body is Block ? body.statements.first : body; + SyntheticExpressionJudgment judgment = statement.expression; syntheticAssignment = judgment.desugared; if (syntheticAssignment is VariableSet) { syntheticWriteType = elementType = syntheticAssignment.variable.type; @@ -368,18 +358,19 @@ class InferenceVisitor extends BodyVisitor1 { inferrer.helper.uri); } - DartType inferredType = - inferForInIterable(node, elementType, typeChecksNeeded); + DartType inferredType = inferForInIterable( + iterable, elementType, typeChecksNeeded, + isAsync: isAsync); if (typeChecksNeeded) { - node.variable.type = inferredType; + variable.type = inferredType; } - inferrer.inferStatement(node.body); + inferrer.inferStatement(body); if (syntheticWriteType != null) { inferrer.ensureAssignable( greatestClosure(inferrer.coreTypes, syntheticWriteType), - node.variable.type, + variable.type, rhs, rhs.fileOffset, template: templateForInLoopElementTypeNotAssignable, @@ -390,9 +381,11 @@ class InferenceVisitor extends BodyVisitor1 { @override void visitForInStatement(ForInStatement node, _) { if (node.variable.name == null) { - handleForInStatementWithoutVariable(node); + handleForInWithoutVariable(node.variable, node.iterable, node.body, + isAsync: node.isAsync); } else { - handleForInStatementDeclaringVariable(node); + handleForInDeclaringVariable(node.variable, node.iterable, node.body, + isAsync: node.isAsync); } } @@ -697,16 +690,59 @@ class InferenceVisitor extends BodyVisitor1 { return getSpreadElementType(spreadType, element.isNullAware) ?? const DynamicType(); } else if (element is IfElement) { + // TODO(kmillikin): Implement inference rules for if elements. inferrer.inferExpression(element.condition, inferrer.coreTypes.boolClass.rawType, typeChecksNeeded, - isVoidAllowed: false); + isVoidAllowed: false); // Should be void allowed + runtime check? inferElement(element.then, index, inferredTypeArgument, spreadTypes, inferenceNeeded, typeChecksNeeded); if (element.otherwise != null) { inferElement(element.otherwise, index, inferredTypeArgument, spreadTypes, inferenceNeeded, typeChecksNeeded); } - // TODO(kmillikin): Implement inference rules for if elements. + return const DynamicType(); + } else if (element is ForElement) { + // TODO(kmillikin): Implement inference rules for for elements. + for (VariableDeclaration declaration in element.variables) { + if (declaration.initializer != null) { + inferrer.inferExpression(declaration.initializer, declaration.type, + inferenceNeeded || typeChecksNeeded, + isVoidAllowed: true); + } + } + if (element.condition != null) { + inferrer.inferExpression( + element.condition, + inferrer.coreTypes.boolClass.rawType, + inferenceNeeded || typeChecksNeeded, + isVoidAllowed: false); // Should be void allowed + runtime check. + } + for (Expression expression in element.updates) { + inferrer.inferExpression(expression, const UnknownType(), + inferenceNeeded || typeChecksNeeded, + isVoidAllowed: true); + } + inferElement(element.body, index, inferredTypeArgument, spreadTypes, + inferenceNeeded, typeChecksNeeded); + return const DynamicType(); + } else if (element is ForInElement) { + // TODO(kmillikin): Implement inference rules for for-in elements. + if (element.variable.name == null) { + handleForInWithoutVariable( + element.variable, element.iterable, element.prologue, + isAsync: element.isAsync); + } else { + handleForInDeclaringVariable( + element.variable, element.iterable, element.prologue, + isAsync: element.isAsync); + } + if (element.problem != null) { + inferrer.inferExpression(element.problem, const UnknownType(), + inferenceNeeded || typeChecksNeeded, + isVoidAllowed: true); + } + inferElement(element.body, index, inferredTypeArgument, spreadTypes, + inferenceNeeded, typeChecksNeeded); return const DynamicType(); } else { return inferrer.inferExpression( @@ -813,6 +849,8 @@ class InferenceVisitor extends BodyVisitor1 { } } else if (item is IfElement) { // TODO(kmillikin): Insert type checks on if elements. + } else if (item is ForElement || item is ForInElement) { + // TODO(kmillikin): Insert type checks on loop elements. } else { inferrer.ensureAssignable( node.typeArgument, actualTypes[i], item, item.fileOffset, @@ -1553,6 +1591,8 @@ class InferenceVisitor extends BodyVisitor1 { } } else if (item is IfElement) { // TODO(kmillikin): Insert type checks on if elements. + } else if (item is ForElement || item is ForInElement) { + // TODO(kmillikin): Insert type checks on loop elements. } else { inferrer.ensureAssignable(node.typeArgument, actualTypes[i], node.expressions[i], node.expressions[i].fileOffset, 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 d74754560c83e..05513ad01554d 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,25 +28,11 @@ class InferredTypeVisitor @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/transform_collections.dart b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart index 1ea7bbc4f9f06..6e284131ee6f4 100644 --- a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart +++ b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart @@ -18,6 +18,7 @@ import 'package:kernel/ast.dart' ExpressionStatement, Field, ForInStatement, + ForStatement, IfStatement, InterfaceType, InvalidExpression, @@ -33,6 +34,7 @@ import 'package:kernel/ast.dart' SetLiteral, Statement, StaticInvocation, + transformList, TreeNode, VariableDeclaration, VariableGet; @@ -45,6 +47,8 @@ import 'collections.dart' show ControlFlowElement, ControlFlowMapEntry, + ForElement, + ForInElement, IfElement, IfMapEntry, SpreadElement, @@ -153,6 +157,10 @@ class CollectionTransformer extends Transformer { _translateSpreadElement(element, elementType, isSet, result, body); } else if (element is IfElement) { _translateIfElement(element, elementType, isSet, result, body); + } else if (element is ForElement) { + _translateForElement(element, elementType, isSet, result, body); + } else if (element is ForInElement) { + _translateForInElement(element, elementType, isSet, result, body); } else { _addExpressionElement(element.accept(this), isSet, result, body); } @@ -169,22 +177,61 @@ class CollectionTransformer extends Transformer { void _translateIfElement(IfElement element, DartType elementType, bool isSet, VariableDeclaration result, List body) { - List thenBody = []; - _translateElement(element.then, elementType, isSet, result, thenBody); - List elseBody; + List thenStatements = []; + _translateElement(element.then, elementType, isSet, result, thenStatements); + List elseStatements; if (element.otherwise != null) { _translateElement(element.otherwise, elementType, isSet, result, - elseBody = []); + elseStatements = []); } - Statement thenStatement = - thenBody.length == 1 ? thenBody.first : new Block(thenBody); - Statement elseStatement; - if (elseBody != null && elseBody.isNotEmpty) { - elseStatement = - elseBody.length == 1 ? elseBody.first : new Block(elseBody); + Statement thenBody = thenStatements.length == 1 + ? thenStatements.first + : new Block(thenStatements); + Statement elseBody; + if (elseStatements != null && elseStatements.isNotEmpty) { + elseBody = elseStatements.length == 1 + ? elseStatements.first + : new Block(elseStatements); } - body.add(new IfStatement( - element.condition.accept(this), thenStatement, elseStatement)); + body.add(new IfStatement(element.condition.accept(this), thenBody, elseBody) + ..fileOffset = element.fileOffset); + } + + void _translateForElement(ForElement element, DartType elementType, + bool isSet, VariableDeclaration result, List body) { + List statements = []; + _translateElement(element.body, elementType, isSet, result, statements); + Statement loopBody = + statements.length == 1 ? statements.first : new Block(statements); + ForStatement loop = new ForStatement(element.variables, + element.condition?.accept(this), element.updates, loopBody) + ..fileOffset = element.fileOffset; + transformList(loop.variables, this, loop); + transformList(loop.updates, this, loop); + body.add(loop); + } + + void _translateForInElement(ForInElement element, DartType elementType, + bool isSet, VariableDeclaration result, List body) { + List statements; + Statement prologue = element.prologue; + if (prologue == null) { + statements = []; + } else { + prologue = prologue.accept(this); + statements = + prologue is Block ? prologue.statements : [prologue]; + } + _translateElement(element.body, elementType, isSet, result, statements); + Statement loopBody = + statements.length == 1 ? statements.first : new Block(statements); + if (element.problem != null) { + body.add(new ExpressionStatement(element.problem.accept(this))); + } + body.add(new ForInStatement( + element.variable, element.iterable.accept(this), loopBody, + isAsync: element.isAsync) + ..fileOffset = element.fileOffset); } void _translateSpreadElement(SpreadElement element, DartType elementType, diff --git a/pkg/front_end/testcases/control_flow_collection.dart b/pkg/front_end/testcases/control_flow_collection.dart index e6d645cc42699..6c1ea1627aee4 100644 --- a/pkg/front_end/testcases/control_flow_collection.dart +++ b/pkg/front_end/testcases/control_flow_collection.dart @@ -8,12 +8,18 @@ main() { if (oracle()) 2, if (oracle()) 3 else -1, if (oracle()) if (oracle()) 4, + for (int i in [5, 6, 7]) i, + for (int i in [8, 9, 10]) if (oracle()) i, + for (int i = 11; i <= 14; ++i) i, ]; final aSet = { 1, if (oracle()) 2, if (oracle()) 3 else -1, if (oracle()) if (oracle()) 4, + for (int i in [5, 6, 7]) i, + for (int i in [8, 9, 10]) if (oracle()) i, + for (int i = 11; i <= 14; ++i) i, }; final aMap = { 1: 1, diff --git a/pkg/front_end/testcases/control_flow_collection.dart.legacy.expect b/pkg/front_end/testcases/control_flow_collection.dart.legacy.expect index e8d44f8d43c1e..d0d69e1bffeaa 100644 --- a/pkg/front_end/testcases/control_flow_collection.dart.legacy.expect +++ b/pkg/front_end/testcases/control_flow_collection.dart.legacy.expect @@ -18,35 +18,67 @@ library; // if (oracle()) if (oracle()) 4, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:14:7: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:11:7: Error: Unexpected token 'for'. +// for (int i in [5, 6, 7]) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:12:38: Error: Unexpected token 'if'. +// for (int i in [8, 9, 10]) if (oracle()) i, +// ^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:12:7: Error: Unexpected token 'for'. +// for (int i in [8, 9, 10]) if (oracle()) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:13:7: Error: Unexpected token 'for'. +// for (int i = 11; i <= 14; ++i) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:17:7: Error: Unexpected token 'if'. // if (oracle()) 2, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:15:7: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:18:7: Error: Unexpected token 'if'. // if (oracle()) 3 else -1, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:16:21: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:19:21: Error: Unexpected token 'if'. // if (oracle()) if (oracle()) 4, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:16:7: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:19:7: Error: Unexpected token 'if'. // if (oracle()) if (oracle()) 4, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:20:5: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:20:7: Error: Unexpected token 'for'. +// for (int i in [5, 6, 7]) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:21:38: Error: Unexpected token 'if'. +// for (int i in [8, 9, 10]) if (oracle()) i, +// ^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:21:7: Error: Unexpected token 'for'. +// for (int i in [8, 9, 10]) if (oracle()) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:22:7: Error: Unexpected token 'for'. +// for (int i = 11; i <= 14; ++i) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:26:5: Error: Unexpected token 'if'. // if (oracle()) 2: 2, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:21:5: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:27:5: Error: Unexpected token 'if'. // if (oracle()) 3: 3 else -1: -1, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:22:19: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:28:19: Error: Unexpected token 'if'. // if (oracle()) if (oracle()) 4: 4, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:22:5: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:28:5: Error: Unexpected token 'if'. // if (oracle()) if (oracle()) 4: 4, // ^^ // diff --git a/pkg/front_end/testcases/control_flow_collection.dart.legacy.transformed.expect b/pkg/front_end/testcases/control_flow_collection.dart.legacy.transformed.expect index e8d44f8d43c1e..d0d69e1bffeaa 100644 --- a/pkg/front_end/testcases/control_flow_collection.dart.legacy.transformed.expect +++ b/pkg/front_end/testcases/control_flow_collection.dart.legacy.transformed.expect @@ -18,35 +18,67 @@ library; // if (oracle()) if (oracle()) 4, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:14:7: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:11:7: Error: Unexpected token 'for'. +// for (int i in [5, 6, 7]) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:12:38: Error: Unexpected token 'if'. +// for (int i in [8, 9, 10]) if (oracle()) i, +// ^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:12:7: Error: Unexpected token 'for'. +// for (int i in [8, 9, 10]) if (oracle()) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:13:7: Error: Unexpected token 'for'. +// for (int i = 11; i <= 14; ++i) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:17:7: Error: Unexpected token 'if'. // if (oracle()) 2, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:15:7: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:18:7: Error: Unexpected token 'if'. // if (oracle()) 3 else -1, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:16:21: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:19:21: Error: Unexpected token 'if'. // if (oracle()) if (oracle()) 4, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:16:7: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:19:7: Error: Unexpected token 'if'. // if (oracle()) if (oracle()) 4, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:20:5: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:20:7: Error: Unexpected token 'for'. +// for (int i in [5, 6, 7]) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:21:38: Error: Unexpected token 'if'. +// for (int i in [8, 9, 10]) if (oracle()) i, +// ^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:21:7: Error: Unexpected token 'for'. +// for (int i in [8, 9, 10]) if (oracle()) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:22:7: Error: Unexpected token 'for'. +// for (int i = 11; i <= 14; ++i) i, +// ^^^ +// +// pkg/front_end/testcases/control_flow_collection.dart:26:5: Error: Unexpected token 'if'. // if (oracle()) 2: 2, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:21:5: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:27:5: Error: Unexpected token 'if'. // if (oracle()) 3: 3 else -1: -1, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:22:19: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:28:19: Error: Unexpected token 'if'. // if (oracle()) if (oracle()) 4: 4, // ^^ // -// pkg/front_end/testcases/control_flow_collection.dart:22:5: Error: Unexpected token 'if'. +// pkg/front_end/testcases/control_flow_collection.dart:28:5: Error: Unexpected token 'if'. // if (oracle()) if (oracle()) 4: 4, // ^^ // diff --git a/pkg/front_end/testcases/control_flow_collection.dart.strong.expect b/pkg/front_end/testcases/control_flow_collection.dart.strong.expect index edd1a1432069d..a86c82b3c909d 100644 --- a/pkg/front_end/testcases/control_flow_collection.dart.strong.expect +++ b/pkg/front_end/testcases/control_flow_collection.dart.strong.expect @@ -16,6 +16,13 @@ static method main() → dynamic { if(self::oracle()) if(self::oracle()) #t1.{core::List::add}(4); + for (core::int i in [5, 6, 7]) + #t1.{core::List::add}(i); + for (core::int i in [8, 9, 10]) + if(self::oracle()) + #t1.{core::List::add}(i); + for (core::int i = 11; i.{core::num::<=}(14); i = i.{core::num::+}(1)) + #t1.{core::List::add}(i); } =>#t1; final core::Set aSet = block { final core::Set #t2 = col::LinkedHashSet::•(); @@ -29,6 +36,13 @@ static method main() → dynamic { if(self::oracle()) if(self::oracle()) #t2.{core::Set::add}(4); + for (core::int i in [5, 6, 7]) + #t2.{core::Set::add}(i); + for (core::int i in [8, 9, 10]) + if(self::oracle()) + #t2.{core::Set::add}(i); + for (core::int i = 11; i.{core::num::<=}(14); i = i.{core::num::+}(1)) + #t2.{core::Set::add}(i); } =>#t2; final core::Map aMap = block { final core::Map #t3 = {}; diff --git a/pkg/front_end/testcases/control_flow_collection.dart.strong.transformed.expect b/pkg/front_end/testcases/control_flow_collection.dart.strong.transformed.expect index edd1a1432069d..a86c82b3c909d 100644 --- a/pkg/front_end/testcases/control_flow_collection.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/control_flow_collection.dart.strong.transformed.expect @@ -16,6 +16,13 @@ static method main() → dynamic { if(self::oracle()) if(self::oracle()) #t1.{core::List::add}(4); + for (core::int i in [5, 6, 7]) + #t1.{core::List::add}(i); + for (core::int i in [8, 9, 10]) + if(self::oracle()) + #t1.{core::List::add}(i); + for (core::int i = 11; i.{core::num::<=}(14); i = i.{core::num::+}(1)) + #t1.{core::List::add}(i); } =>#t1; final core::Set aSet = block { final core::Set #t2 = col::LinkedHashSet::•(); @@ -29,6 +36,13 @@ static method main() → dynamic { if(self::oracle()) if(self::oracle()) #t2.{core::Set::add}(4); + for (core::int i in [5, 6, 7]) + #t2.{core::Set::add}(i); + for (core::int i in [8, 9, 10]) + if(self::oracle()) + #t2.{core::Set::add}(i); + for (core::int i = 11; i.{core::num::<=}(14); i = i.{core::num::+}(1)) + #t2.{core::Set::add}(i); } =>#t2; final core::Map aMap = block { final core::Map #t3 = {}; diff --git a/pkg/front_end/testcases/control_flow_collection.dart.type_promotion.expect b/pkg/front_end/testcases/control_flow_collection.dart.type_promotion.expect new file mode 100644 index 0000000000000..ba820778fc837 --- /dev/null +++ b/pkg/front_end/testcases/control_flow_collection.dart.type_promotion.expect @@ -0,0 +1,6 @@ +pkg/front_end/testcases/control_flow_collection.dart:13:33: Context: Write to i@364 + for (int i = 11; i <= 14; ++i) i, + ^^ +pkg/front_end/testcases/control_flow_collection.dart:22:33: Context: Write to i@364 + for (int i = 11; i <= 14; ++i) i, + ^^ diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status index c0b00c327aa21..97752491c9f04 100644 --- a/tests/co19_2/co19_2-kernel.status +++ b/tests/co19_2/co19_2-kernel.status @@ -133,7 +133,6 @@ LanguageFeatures/Control-flow-collections/const_collections_A06_t02: CompileTime LanguageFeatures/Control-flow-collections/const_collections_A07_t01: CompileTimeError LanguageFeatures/Control-flow-collections/const_collections_A07_t02: CompileTimeError LanguageFeatures/Control-flow-collections/dynamic_semantics_set_A03_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 @@ -153,12 +152,6 @@ LanguageFeatures/Control-flow-collections/static_errors_A04_t01/01: MissingCompi 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_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 diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status index 65fbccdb782a2..d12394f0797d1 100644 --- a/tests/language_2/language_2_kernel.status +++ b/tests/language_2/language_2_kernel.status @@ -202,30 +202,24 @@ constructor5_test: CompileTimeError # Verification error constructor6_test: CompileTimeError # Verification error control_flow_collections/await_for_inference_test: CompileTimeError control_flow_collections/await_for_test: CompileTimeError -control_flow_collections/await_for_type_error_test/01: MissingCompileTimeError control_flow_collections/await_for_type_error_test/02: MissingCompileTimeError -control_flow_collections/await_for_type_error_test/03: MissingCompileTimeError control_flow_collections/await_for_type_error_test/04: MissingCompileTimeError control_flow_collections/await_for_type_error_test/05: MissingCompileTimeError control_flow_collections/await_for_type_error_test/06: MissingCompileTimeError -control_flow_collections/await_for_type_error_test/07: MissingCompileTimeError control_flow_collections/await_for_type_error_test/08: MissingCompileTimeError -control_flow_collections/await_for_type_error_test/09: MissingCompileTimeError control_flow_collections/await_for_type_error_test/10: MissingCompileTimeError control_flow_collections/await_for_type_error_test/11: MissingCompileTimeError control_flow_collections/await_for_type_error_test/12: MissingCompileTimeError control_flow_collections/await_for_type_error_test/13: MissingCompileTimeError control_flow_collections/for_await_test: CompileTimeError +control_flow_collections/for_await_test: Crash 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 control_flow_collections/if_await_test: Crash control_flow_collections/if_const_error_test/02: MissingCompileTimeError control_flow_collections/if_const_error_test/07: MissingCompileTimeError @@ -261,19 +255,17 @@ 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: Crash control_flow_collections/type_error_test/23: MissingCompileTimeError control_flow_collections/type_error_test/24: MissingCompileTimeError +control_flow_collections/type_error_test/25: Crash 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