diff --git a/pkg/_js_interop_checks/lib/src/transformations/shared_interop_transformer.dart b/pkg/_js_interop_checks/lib/src/transformations/shared_interop_transformer.dart index 6ac643e6435..f00b095379d 100644 --- a/pkg/_js_interop_checks/lib/src/transformations/shared_interop_transformer.dart +++ b/pkg/_js_interop_checks/lib/src/transformations/shared_interop_transformer.dart @@ -371,7 +371,9 @@ class SharedInteropTransformer extends Transformer { type: dartType, isSynthesized: true, )..fileOffset = invocation.fileOffset; - block.add(dartInstance); + block.add( + VariableStatement(dartInstance)..fileOffset = invocation.fileOffset, + ); var jsExporter = VariableDeclaration( '#jsExporter', @@ -379,7 +381,9 @@ class SharedInteropTransformer extends Transformer { type: ExtensionType(_jsObject, Nullability.nonNullable), isSynthesized: true, )..fileOffset = invocation.fileOffset; - block.add(jsExporter); + block.add( + VariableStatement(jsExporter)..fileOffset = invocation.fileOffset, + ); for (var MapEntry(key: exportName, value: exports) in exportMap.entries) { ExpressionStatement setProperty( @@ -460,7 +464,9 @@ class SharedInteropTransformer extends Transformer { type: ExtensionType(_jsObject, Nullability.nonNullable), isSynthesized: true, )..fileOffset = invocation.fileOffset; - block.add(getSetMap); + block.add( + VariableStatement(getSetMap)..fileOffset = invocation.fileOffset, + ); var (:getter, :setter) = _exportChecker.getGetterSetter(exports); if (getter != null) { final resultType = _staticInteropMockValidator.typeParameterResolver diff --git a/pkg/cfg/lib/front_end/ast_to_ir.dart b/pkg/cfg/lib/front_end/ast_to_ir.dart index 42514101c31..07457ffc45e 100644 --- a/pkg/cfg/lib/front_end/ast_to_ir.dart +++ b/pkg/cfg/lib/front_end/ast_to_ir.dart @@ -898,7 +898,7 @@ class AstToIr extends ast.RecursiveVisitor { } @override - void visitVariableDeclaration(ast.VariableDeclaration node) { + void defaultVariableDeclaration(ast.VariableDeclaration node) { final variable = node.variable; if (node.isConst) return; if (node.isLate) { @@ -921,9 +921,14 @@ class AstToIr extends ast.RecursiveVisitor { } } + @override + void visitLegacyVariableStatement(ast.LegacyVariableStatement node) { + defaultVariableDeclaration(node.variable); + } + @override void visitVariableInitialization(ast.VariableInitialization node) { - visitVariableDeclaration(node); + defaultVariableDeclaration(node.variable); } @override diff --git a/pkg/cfg/lib/front_end/computed_scopes.dart b/pkg/cfg/lib/front_end/computed_scopes.dart index 046c730ba69..8037d1b3b9d 100644 --- a/pkg/cfg/lib/front_end/computed_scopes.dart +++ b/pkg/cfg/lib/front_end/computed_scopes.dart @@ -305,7 +305,12 @@ class _ScopeBuilder extends ast.RecursiveVisitor { } @override - void visitVariableDeclaration(ast.VariableDeclaration node) { + void visitLegacyVariableStatement(ast.LegacyVariableStatement node) { + node.visitChildren(this); + } + + @override + void defaultVariableDeclaration(ast.VariableDeclaration node) { _declareVariable(node.variable); node.visitChildren(this); } diff --git a/pkg/compiler/lib/src/deferred_load/entity_data_info.dart b/pkg/compiler/lib/src/deferred_load/entity_data_info.dart index a97dd2923f9..cb1d6c04b64 100644 --- a/pkg/compiler/lib/src/deferred_load/entity_data_info.dart +++ b/pkg/compiler/lib/src/deferred_load/entity_data_info.dart @@ -578,7 +578,7 @@ class ConstantCollector extends ir.RecursiveVisitor { } @override - void visitVariableDeclaration(ir.VariableDeclaration node) { + void defaultVariableDeclaration(ir.VariableDeclaration node) { // We avoid visiting metadata on the parameter declaration by only visiting // the initializer. The type cannot hold constants so can kan skip that // as well. diff --git a/pkg/compiler/lib/src/inferrer/builder.dart b/pkg/compiler/lib/src/inferrer/builder.dart index 11537531b37..1f637771396 100644 --- a/pkg/compiler/lib/src/inferrer/builder.dart +++ b/pkg/compiler/lib/src/inferrer/builder.dart @@ -939,7 +939,14 @@ class KernelTypeGraphBuilder extends ir.VisitorDefault } @override - TypeInformation? visitVariableDeclaration(ir.VariableDeclaration node) { + TypeInformation? visitLegacyVariableStatement( + ir.LegacyVariableStatement node, + ) { + return defaultVariableDeclaration(node.variable); + } + + @override + TypeInformation? defaultVariableDeclaration(ir.VariableDeclaration node) { assert( node.parent is! ir.FunctionNode, "Unexpected parameter declaration.", @@ -2457,7 +2464,7 @@ class KernelTypeGraphBuilder extends ir.VisitorDefault @override Null visitForStatement(ir.ForStatement node) { - for (ir.VariableDeclaration variable in node.variables) { + for (ir.VariableStatement variable in node.variables) { visit(variable); } return handleLoop(node, _localsMap.getJumpTargetForFor(node), () { diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart index b61767854ef..20324dee283 100644 --- a/pkg/compiler/lib/src/ir/impact_data.dart +++ b/pkg/compiler/lib/src/ir/impact_data.dart @@ -284,7 +284,7 @@ class ImpactBuilder extends ir.RecursiveVisitor implements ImpactRegistry { } @override - void visitVariableDeclaration(ir.VariableDeclaration node) { + void defaultVariableDeclaration(ir.VariableDeclaration node) { if (node.initializer == null) { registerLocalWithoutInitializer(); } diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart index 0bdaa57c06f..577eb13b029 100644 --- a/pkg/compiler/lib/src/ir/scope_visitor.dart +++ b/pkg/compiler/lib/src/ir/scope_visitor.dart @@ -322,8 +322,15 @@ class ScopeModelBuilder extends ir.VisitorDefault } @override - EvaluationComplexity visitVariableDeclaration(ir.VariableDeclaration node) { - _handleVariableDeclaration(node, SimpleVariableUse.localType); + EvaluationComplexity visitLegacyVariableStatement( + ir.LegacyVariableStatement node, + ) { + return defaultVariableDeclaration(node.variable); + } + + @override + EvaluationComplexity defaultVariableDeclaration(ir.VariableDeclaration node) { + _handleVariableDeclaration(node.variable, SimpleVariableUse.localType); return const EvaluationComplexity.lazy(); } @@ -505,9 +512,9 @@ class ScopeModelBuilder extends ir.VisitorDefault // Loop variables that have not been captured yet can safely be flagged as // non-mutated, because no nested function can observe the mutation. - for (ir.VariableDeclaration variable in node.variables) { - if (!_capturedVariables.contains(variable)) { - _mutatedVariables.remove(variable); + for (ir.VariableStatement variableDeclaration in node.variables) { + if (!_capturedVariables.contains(variableDeclaration.variable)) { + _mutatedVariables.remove(variableDeclaration.variable); } } @@ -522,12 +529,12 @@ class ScopeModelBuilder extends ir.VisitorDefault }); // See if we have declared loop variables that need to be boxed. - for (ir.VariableDeclaration variable in node.variables) { + for (ir.VariableStatement variableDeclaration in node.variables) { // Non-mutated variables should not be boxed. The _mutatedVariables set // gets cleared when `enterNewScope` returns, so check it here. - if (_capturedVariables.contains(variable) && - _mutatedVariables.contains(variable)) { - boxedLoopVariables.add(variable); + if (_capturedVariables.contains(variableDeclaration.variable) && + _mutatedVariables.contains(variableDeclaration.variable)) { + boxedLoopVariables.add(variableDeclaration.variable); } } }); diff --git a/pkg/compiler/lib/src/kernel/transformations/modular/late_lowering.dart b/pkg/compiler/lib/src/kernel/transformations/modular/late_lowering.dart index add55135743..25c23c5dcc7 100644 --- a/pkg/compiler/lib/src/kernel/transformations/modular/late_lowering.dart +++ b/pkg/compiler/lib/src/kernel/transformations/modular/late_lowering.dart @@ -312,8 +312,8 @@ class LateLowering { if (!_shouldLowerVariable(variable)) return variable; // A [VariableDeclaration] being used as a statement must be a direct child - // of a [Block]. - if (variable.parent is! Block) return variable; + // of a [VariableStatement]. + if (variable.parent is! VariableStatement) return variable; return _variableCell(variable); } @@ -604,11 +604,11 @@ class LateLowering { VariableGet resultRead() => VariableGet(result)..fileOffset = fileOffset; return Block([ - value, + VariableStatement(value), IfStatement( _callIsSentinel(valueRead(), fileOffset), Block([ - result, + VariableStatement(result), ExpressionStatement( StaticInvocation( _coreTypes.lateInitializeOnceCheck, @@ -653,7 +653,7 @@ class LateLowering { )..fileOffset = fileOffset; VariableGet valueRead() => VariableGet(value)..fileOffset = fileOffset; return Block([ - value, + VariableStatement(value), IfStatement( _callIsSentinel(valueRead(), fileOffset), ExpressionStatement( diff --git a/pkg/compiler/lib/src/kernel/transformations/modular/list_factory_specializer.dart b/pkg/compiler/lib/src/kernel/transformations/modular/list_factory_specializer.dart index 448d2ee7e62..f85cb9ae0ef 100644 --- a/pkg/compiler/lib/src/kernel/transformations/modular/list_factory_specializer.dart +++ b/pkg/compiler/lib/src/kernel/transformations/modular/list_factory_specializer.dart @@ -137,7 +137,7 @@ class ListFactorySpecializer extends BaseSpecializer { final loop = ForStatement( // initializers: _i = 0 - [indexVariable], + [VariableStatement(indexVariable)], // condition: _i < _length InstanceInvocation( InstanceAccessKind.Instance, @@ -170,7 +170,11 @@ class ListFactorySpecializer extends BaseSpecializer { )..fileOffset = node.fileOffset; return BlockExpression( - Block([?lengthVariable, listVariable, loop]), + Block([ + if (lengthVariable != null) VariableStatement(lengthVariable!), + VariableStatement(listVariable), + loop, + ]), VariableGet(listVariable)..fileOffset = node.fileOffset, ); } @@ -316,7 +320,7 @@ class ListGenerateLoopBodyInliner extends CloneVisitorNotMembers { Statement run() { Statement body = cloneInContext(function.body!); - return Block([parameter, body]); + return Block([VariableStatement(parameter), body]); } @override diff --git a/pkg/compiler/lib/src/kernel/transformations/modular/transform.dart b/pkg/compiler/lib/src/kernel/transformations/modular/transform.dart index 117a9c1dd7e..952b0229918 100644 --- a/pkg/compiler/lib/src/kernel/transformations/modular/transform.dart +++ b/pkg/compiler/lib/src/kernel/transformations/modular/transform.dart @@ -77,7 +77,7 @@ class _ModularTransformer extends Transformer { } @override - TreeNode visitVariableDeclaration(VariableDeclaration node) { + TreeNode defaultVariableDeclaration(VariableDeclaration node) { node.transformChildren(this); return _lateLowering.transformVariableDeclaration(node, _currentMember); } diff --git a/pkg/compiler/lib/src/serialization/node_indexer.dart b/pkg/compiler/lib/src/serialization/node_indexer.dart index 91c459b94ec..15ae06855c4 100644 --- a/pkg/compiler/lib/src/serialization/node_indexer.dart +++ b/pkg/compiler/lib/src/serialization/node_indexer.dart @@ -44,11 +44,11 @@ class TreeNodeIndexerVisitor extends ir.VisitorDefault } @override - void visitVariableDeclaration(ir.VariableDeclaration node) { + void defaultVariableDeclaration(ir.VariableDeclaration node) { if (node.parent is! ir.FunctionDeclaration) { registerNode(node); } - super.visitVariableDeclaration(node); + super.defaultVariableDeclaration(node); } @override diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart index 4152cbaa56d..4a5e23f672a 100644 --- a/pkg/compiler/lib/src/ssa/builder.dart +++ b/pkg/compiler/lib/src/ssa/builder.dart @@ -2565,7 +2565,7 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault void visitForStatement(ir.ForStatement node) { assert(_isReachable); void buildInitializer() { - for (ir.VariableDeclaration declaration in node.variables) { + for (ir.VariableStatement declaration in node.variables) { declaration.accept(this); } } @@ -4752,7 +4752,12 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault } @override - void visitVariableDeclaration(ir.VariableDeclaration node) { + void visitLegacyVariableStatement(ir.LegacyVariableStatement node) { + defaultVariableDeclaration(node.variable); + } + + @override + void defaultVariableDeclaration(ir.VariableDeclaration node) { Local local = _localsMap.getLocalVariable(node); if (node.initializer == null) { HInstruction initialValue = graph.addConstantNull(closedWorld); @@ -9693,7 +9698,7 @@ class InlineWeeder extends ir.VisitorDefault with ir.VisitorVoidMixin { } @override - void visitVariableDeclaration(ir.VariableDeclaration node) { + void defaultVariableDeclaration(ir.VariableDeclaration node) { registerRegularNode(); skipReductiveNodes(() { visitList(node.annotations); diff --git a/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart b/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart index df00c38681d..b1276b4d09d 100644 --- a/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart +++ b/pkg/compiler/lib/src/ssa/switch_continue_analysis.dart @@ -120,7 +120,7 @@ class SwitchContinueAnalysis extends ir.VisitorDefault node is ir.ReturnStatement || node is ir.AssertStatement || node is ir.YieldStatement || - node is ir.VariableDeclaration) { + node is ir.VariableStatement) { return false; } throw 'Statement type ${node.runtimeType} not handled in ' diff --git a/pkg/dart2bytecode/lib/bytecode_generator.dart b/pkg/dart2bytecode/lib/bytecode_generator.dart index 4829531df93..3609bb892df 100644 --- a/pkg/dart2bytecode/lib/bytecode_generator.dart +++ b/pkg/dart2bytecode/lib/bytecode_generator.dart @@ -4832,13 +4832,18 @@ class BytecodeGenerator extends RecursiveVisitor { } @override - void visitVariableDeclaration(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { _handleVariableInitialization(node); } + @override + void visitLegacyVariableStatement(LegacyVariableStatement node) { + _handleVariableInitialization(node.variable); + } + @override void visitVariableInitialization(VariableInitialization node) { - _handleVariableInitialization(node); + _handleVariableInitialization(node.variable); } void _handleVariableInitialization(VariableDeclaration node) { diff --git a/pkg/dart2bytecode/lib/local_vars.dart b/pkg/dart2bytecode/lib/local_vars.dart index 73696214902..f46f8ff4df1 100644 --- a/pkg/dart2bytecode/lib/local_vars.dart +++ b/pkg/dart2bytecode/lib/local_vars.dart @@ -527,41 +527,11 @@ class _ScopeBuilder extends RecursiveVisitor { } @override - void visitVariableDeclaration(VariableDeclaration node) { - _handleVariableInitialization(node); - } - - @override - void visitVariableInitialization(VariableInitialization node) { - _handleVariableInitialization(node); - } - - void _handleVariableInitialization(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { _declareVariable(node.variable); node.visitChildren(this); } - @override - void visitPositionalParameter(PositionalParameter node) { - _handleFunctionParameter(node); - } - - @override - void visitNamedParameter(NamedParameter node) { - _handleFunctionParameter(node); - } - - void _handleFunctionParameter(FunctionParameter node) { - _declareVariable(node); - node.visitChildren(this); - } - - @override - void visitCatchVariable(CatchVariable node) { - _declareVariable(node); - node.visitChildren(this); - } - @override void visitVariableGet(VariableGet node) { _useVariable(node.variable); @@ -1063,16 +1033,7 @@ class _Allocator extends RecursiveVisitor { } @override - void visitVariableDeclaration(VariableDeclaration node) { - _handleVariableInitialization(node); - } - - @override - void visitVariableInitialization(VariableInitialization node) { - _handleVariableInitialization(node); - } - - void _handleVariableInitialization(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { _allocateVariable(node.variable); node.visitChildren(this); } diff --git a/pkg/dart2wasm/lib/await_transformer.dart b/pkg/dart2wasm/lib/await_transformer.dart index 78114b45fae..0f54c13af1a 100644 --- a/pkg/dart2wasm/lib/await_transformer.dart +++ b/pkg/dart2wasm/lib/await_transformer.dart @@ -91,7 +91,8 @@ class _AwaitTransformer extends Transformer { Statement newBody = transformer.transform(body); final List newStatements = [ - ...transformer.expressionTransformer.variables, + for (final variable in transformer.expressionTransformer.variables) + VariableStatement(variable), ...transformer.statements, ]; @@ -248,13 +249,13 @@ class _AwaitTransformer extends Transformer { List> initEffects = List>.generate(length, ( int i, ) { - VariableDeclaration decl = stmt.variables[i]; + VariableStatement decl = stmt.variables[i]; List statements = []; - if (decl.initializer != null) { - decl.initializer = expressionTransformer.rewrite( - decl.initializer!, + if (decl.variable.initializer != null) { + decl.variable.initializer = expressionTransformer.rewrite( + decl.variable.initializer!, statements, - )..parent = decl; + )..parent = decl.variable; } isSimple = isSimple && statements.isEmpty; return statements; @@ -345,23 +346,31 @@ class _AwaitTransformer extends Transformer { List updates = []; List newBody = [body]; for (int i = 0; i < stmt.variables.length; ++i) { - VariableDeclaration decl = stmt.variables[i]; + VariableStatement decl = stmt.variables[i]; temps.add( - VariableDeclaration(null, type: decl.type, isSynthesized: true), + VariableDeclaration( + null, + type: decl.variable.type, + isSynthesized: true, + ), ); loopBody.add(decl); if (decl.initializer != null) { initializers.addAll(initEffects[i]); initializers.add( - ExpressionStatement(VariableSet(decl, decl.initializer!)), + ExpressionStatement(VariableSet(decl.variable, decl.initializer!)), ); decl.initializer = null; } updates.add( - ExpressionStatement(VariableSet(decl, VariableGet(temps.last))), + ExpressionStatement( + VariableSet(decl.variable, VariableGet(temps.last)), + ), ); newBody.add( - ExpressionStatement(VariableSet(temps.last, VariableGet(decl))), + ExpressionStatement( + VariableSet(temps.last, VariableGet(decl.variable)), + ), ); } // Add the updates to their guarded list of statements. @@ -387,7 +396,10 @@ class _AwaitTransformer extends Transformer { loopBody.add(IfStatement(cond, Block(newBody), BreakStatement(labeled))); labeled.body = WhileStatement(BoolLiteral(true), Block(loopBody)) ..parent = labeled; - return Block([...temps, labeled]); + return Block([ + for (VariableDeclaration temp in temps) VariableStatement(temp), + labeled, + ]); } @override @@ -537,19 +549,21 @@ class _AwaitTransformer extends Transformer { } return Block([ - continuationVar, - exceptionVar, - stackTraceVar, + VariableStatement(continuationVar), + VariableStatement(exceptionVar), + VariableStatement(stackTraceVar), TryFinally(body, finalizer), ]); } @override - TreeNode visitVariableDeclaration(VariableDeclaration stmt) { - final initializer = stmt.initializer; + TreeNode visitLegacyVariableStatement(LegacyVariableStatement stmt) { + final initializer = stmt.variable.initializer; if (initializer != null) { - stmt.initializer = expressionTransformer.rewrite(initializer, statements) - ..parent = stmt; + stmt.variable.initializer = expressionTransformer.rewrite( + initializer, + statements, + )..parent = stmt.variable; } return stmt; } @@ -1256,7 +1270,7 @@ class _ExpressionTransformer extends Transformer { // // // and return the body's value. - statements.add(variable); + statements.add(VariableStatement(variable)); var index = nameIndex; seenAwait = false; variable.initializer = transform(variable.initializer!) diff --git a/pkg/dart2wasm/lib/closures.dart b/pkg/dart2wasm/lib/closures.dart index 3ae1be209a4..9f29388a465 100644 --- a/pkg/dart2wasm/lib/closures.dart +++ b/pkg/dart2wasm/lib/closures.dart @@ -1626,11 +1626,11 @@ class _CaptureFinder extends RecursiveVisitor { } @override - void visitVariableDeclaration(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { if (depth > 0) { variableDepth[node] = depth; } - super.visitVariableDeclaration(node); + super.defaultVariableDeclaration(node); } @override @@ -1863,7 +1863,7 @@ class _ContextCollector extends RecursiveVisitor { } @override - void visitVariableDeclaration(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { Capture? capture = closures.captures[node]; if (capture != null) { if (isInInitializer == capture.isInInitializer) { @@ -1871,7 +1871,7 @@ class _ContextCollector extends RecursiveVisitor { capture.context = currentContext!; } } - super.visitVariableDeclaration(node); + super.defaultVariableDeclaration(node); } @override diff --git a/pkg/dart2wasm/lib/code_generator.dart b/pkg/dart2wasm/lib/code_generator.dart index 7b374f38cd6..12c47f63088 100644 --- a/pkg/dart2wasm/lib/code_generator.dart +++ b/pkg/dart2wasm/lib/code_generator.dart @@ -672,6 +672,18 @@ abstract class AstCodeGenerator } } + void translateVariableDeclaration(VariableDeclaration node) { + final oldFileOffset = setSourceMapFileOffset(node.fileOffset); + try { + visitVariableDeclaration(node); + } catch (_) { + _printLocation(node); + rethrow; + } finally { + setSourceMapFileOffset(oldFileOffset); + } + } + void translateStatement(Statement node) { final oldFileOffset = setSourceMapFileOffset(node.fileOffset); try { @@ -1266,7 +1278,7 @@ abstract class AstCodeGenerator @override void visitForStatement(ForStatement node) { allocateContext(node); - for (VariableDeclaration variable in node.variables) { + for (VariableStatement variable in node.variables) { translateStatement(variable); } w.Label block = b.block(); @@ -1290,8 +1302,8 @@ abstract class AstCodeGenerator w.Local newContext = context.currentLocal; // Copy the values of captured loop variables to the new context. - for (VariableDeclaration variable in node.variables) { - Capture? capture = closures.captures[variable]; + for (VariableStatement variableDeclaration in node.variables) { + Capture? capture = closures.captures[variableDeclaration.variable]; if (capture != null) { assert(capture.context == context); b.local_get(newContext); @@ -1559,7 +1571,7 @@ abstract class AstCodeGenerator @override w.ValueType visitLet(Let node, w.ValueType expectedType) { - translateStatement(node.variable); + translateVariableDeclaration(node.variable); return translateExpression(node.body, expectedType); } @@ -4440,7 +4452,7 @@ class ConstructorInitializerCodeGenerator extends ConstructorCodeGeneratorBase { @override void visitLocalInitializer(LocalInitializer node) { - translateStatement(node.variable); + translateVariableDeclaration(node.variable); } @override diff --git a/pkg/dart2wasm/lib/deferred_load/dependencies.dart b/pkg/dart2wasm/lib/deferred_load/dependencies.dart index 3e3f346f916..c55c21785fc 100644 --- a/pkg/dart2wasm/lib/deferred_load/dependencies.dart +++ b/pkg/dart2wasm/lib/deferred_load/dependencies.dart @@ -732,12 +732,15 @@ class _ReferenceDependenciesCollector extends RecursiveVisitor { @override void visitEmptyStatement(EmptyStatement node) => node.visitChildren(this); @override - void visitVariableDeclaration(VariableDeclaration node) => + void defaultVariableDeclaration(VariableDeclaration node) => node.visitChildren(this); @override void visitReturnStatement(ReturnStatement node) => node.visitChildren(this); @override void visitYieldStatement(YieldStatement node) => node.visitChildren(this); + @override + void visitLegacyVariableStatement(LegacyVariableStatement node) => + node.visitChildren(this); @override void visitLet(Let node) => node.visitChildren(this); diff --git a/pkg/dart2wasm/lib/js/callback_specializer.dart b/pkg/dart2wasm/lib/js/callback_specializer.dart index 76ec11db72f..92e454de8cd 100644 --- a/pkg/dart2wasm/lib/js/callback_specializer.dart +++ b/pkg/dart2wasm/lib/js/callback_specializer.dart @@ -151,7 +151,7 @@ class CallbackSpecializer { ), ); - body.add(argumentsLength); + body.add(VariableStatement(argumentsLength)); if (castClosureArguments.isNotEmpty) { // Call the cast closure, but only if the arity is okay. In the case where diff --git a/pkg/dart2wasm/lib/state_machine.dart b/pkg/dart2wasm/lib/state_machine.dart index 36eb636d12c..7fa0a85135c 100644 --- a/pkg/dart2wasm/lib/state_machine.dart +++ b/pkg/dart2wasm/lib/state_machine.dart @@ -495,11 +495,11 @@ class Finalizer extends _ExceptionHandler { Finalizer._(this.codeGen, TryFinally node, this.parentFinalizer, super.target) : _continuationVar = - (node.parent as Block).statements[0] as VariableDeclaration, + ((node.parent as Block).statements[0] as VariableStatement).variable, _exceptionVar = - (node.parent as Block).statements[1] as VariableDeclaration, + ((node.parent as Block).statements[1] as VariableStatement).variable, _stackTraceVar = - (node.parent as Block).statements[2] as VariableDeclaration; + ((node.parent as Block).statements[2] as VariableStatement).variable; @override bool get canHandleJSExceptions => true; @@ -869,7 +869,7 @@ abstract class StateMachineCodeGenerator extends AstCodeGenerator { StateTarget after = afterTargets[node]!; allocateContext(node); - for (VariableDeclaration variable in node.variables) { + for (VariableStatement variable in node.variables) { translateStatement(variable); } emitTargetLabel(inner); diff --git a/pkg/dart2wasm/lib/transformers.dart b/pkg/dart2wasm/lib/transformers.dart index 49e6082bc1d..b8fb4a4d9bd 100644 --- a/pkg/dart2wasm/lib/transformers.dart +++ b/pkg/dart2wasm/lib/transformers.dart @@ -278,11 +278,11 @@ class _WasmTransformer extends Transformer { } @override - visitVariableDeclaration(VariableDeclaration node) { + defaultVariableDeclaration(VariableDeclaration node) { if (!node.isFinal) { _implicitFinalVariables.add(node); } - return super.visitVariableDeclaration(node); + return super.defaultVariableDeclaration(node); } @override @@ -440,7 +440,8 @@ class _WasmTransformer extends Transformer { resultType: elementType, )..fileOffset = stmt.bodyOffset); - Block body = Block([variable, stmt.body])..fileOffset = stmt.fileOffset; + Block body = Block([VariableStatement(variable), stmt.body]) + ..fileOffset = stmt.fileOffset; Statement forStatement = ForStatement( const [], @@ -479,8 +480,8 @@ class _WasmTransformer extends Transformer { } return Block([ - iterator, - if (isAsync) jumpSentinel, + VariableStatement(iterator), + if (isAsync) VariableStatement(jumpSentinel), forStatement, ]).accept(this); } @@ -883,17 +884,17 @@ class _WasmTransformer extends Transformer { return FunctionNode( Block([ - pausedVar, - cancelCompleterVar, - isDoneVar, - onCancelCallbackVar, - onResumeCallbackVar, + VariableStatement(pausedVar), + VariableStatement(cancelCompleterVar), + VariableStatement(isDoneVar), + VariableStatement(onCancelCallbackVar), + VariableStatement(onResumeCallbackVar), // var controller = StreamController(sync: true, onCancel: onCancelCallback, onResume: onResumeCallback); - controllerVar, + VariableStatement(controllerVar), // var #body = ...; - bodyVar, + VariableStatement(bodyVar), // controller.onListen = ...; ExpressionStatement(setControllerOnListen), @@ -1346,7 +1347,7 @@ class PushPopWasmArrayTransformer { } final List arrayGrowStatements = [ - newArrayVariable, + VariableStatement(newArrayVariable), ExpressionStatement(newArrayCopy), arrayFieldUpdate, ]; @@ -1475,7 +1476,7 @@ class PushPopWasmArrayTransformer { isFinal: true, type: elementType, ); - blockStatements.add(arrayGetVariable); + blockStatements.add(VariableStatement(arrayGetVariable)); // array[length] = null if (elementIsNullable) { diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart index ca43d5a9dbf..4b0780095bb 100644 --- a/pkg/dev_compiler/lib/src/kernel/compiler.dart +++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart @@ -4861,10 +4861,10 @@ class ProgramCompiler extends ComputeOnceConstantVisitor @override js_ast.Statement visitForStatement(ForStatement node) { return _translateLoop(node, () { - js_ast.VariableInitialization emitForInitializer(VariableDeclaration v) => + js_ast.VariableInitialization emitForInitializer(VariableStatement s) => js_ast.VariableInitialization( - _emitVariableDef(v), - _visitInitializer(v.initializer, v.annotations), + _emitVariableDef(s.variable), + _visitInitializer(s.variable.initializer, s.variable.annotations), ); if (node.variables.any(containsFunctionExpression)) { @@ -4934,30 +4934,34 @@ class ProgramCompiler extends ComputeOnceConstantVisitor js_ast.Statement _rewriteAsWhile(ForStatement node) { var initFlagTempId = _emitScopedId('t#_init'); var loopVariableIds = { - for (var variable in node.variables) variable: _emitVariableDef(variable), + for (var stmt in node.variables) + stmt.variable: _emitVariableDef(stmt.variable), }; var prevVariableTempIds = { - for (var variable in node.variables) - variable: _emitScopedId('t#_prev_${variable.name!}'), + for (var stmt in node.variables) + stmt.variable: _emitScopedId('t#_prev_${stmt.variable.name!}'), }; var inits = js_ast.Block([ // Set init flag to false so the initialization only happens on the first // iteration of the while loop. js.statement('# = false;', [initFlagTempId]), // Initialize fresh loop variables to initial values. - for (var variable in node.variables) + for (var stmt in node.variables) js.statement('# = #;', [ - loopVariableIds[variable]!, - _visitInitializer(variable.initializer, variable.annotations), + loopVariableIds[stmt.variable]!, + _visitInitializer( + stmt.variable.initializer, + stmt.variable.annotations, + ), ]), ]); var prevInits = js_ast.Block([ // Initialize fresh loop variables with the value from the previous // iteration. - for (var variable in node.variables) + for (var stmt in node.variables) js.statement('# = #;', [ - loopVariableIds[variable], - prevVariableTempIds[variable], + loopVariableIds[stmt.variable], + prevVariableTempIds[stmt.variable], ]), // Original update expressions. for (var update in node.updates) _visitExpression(update).toStatement(), @@ -4970,8 +4974,11 @@ class ProgramCompiler extends ComputeOnceConstantVisitor initFlagTempId, js_ast.LiteralBool(true), ), - for (var variable in node.variables) - js_ast.VariableInitialization(prevVariableTempIds[variable]!, null), + for (var stmt in node.variables) + js_ast.VariableInitialization( + prevVariableTempIds[stmt.variable]!, + null, + ), ]).toStatement(), // The for loop transformed into a while loop. js_ast.While( @@ -4980,9 +4987,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor // Create fresh loop variables every iteration. if (node.variables.isNotEmpty) js_ast.VariableDeclarationList('let', [ - for (var variable in node.variables) + for (var stmt in node.variables) js_ast.VariableInitialization( - loopVariableIds[variable]!, + loopVariableIds[stmt.variable]!, null, ), ]).toStatement(), @@ -4995,15 +5002,15 @@ class ProgramCompiler extends ComputeOnceConstantVisitor // Original loop body. _visitScope(_effectiveBodyOf(node, node.body)), // Save previous loop variables - for (var variable in node.variables) + for (var stmt in node.variables) js.statement('# = #;', [ - prevVariableTempIds[variable]!, - _emitVariableRef(variable), + prevVariableTempIds[stmt.variable]!, + _emitVariableRef(stmt.variable), ]) // Map these locations to the variable declaration so stepping // in the Dart debugger doesn't jump to the previous line when // stepping. - ..sourceInformation = _nodeStart(variable), + ..sourceInformation = _nodeStart(stmt.variable), ]), ) // The while loop gets mapped to the original for loop location. diff --git a/pkg/dev_compiler/lib/src/kernel/compiler_new.dart b/pkg/dev_compiler/lib/src/kernel/compiler_new.dart index 922e363bfbe..200cbf49dec 100644 --- a/pkg/dev_compiler/lib/src/kernel/compiler_new.dart +++ b/pkg/dev_compiler/lib/src/kernel/compiler_new.dart @@ -5475,10 +5475,10 @@ class LibraryCompiler extends ComputeOnceConstantVisitor @override js_ast.Statement visitForStatement(ForStatement node) { return _translateLoop(node, () { - js_ast.VariableInitialization emitForInitializer(VariableDeclaration v) => + js_ast.VariableInitialization emitForInitializer(VariableStatement s) => js_ast.VariableInitialization( - _emitVariableDef(v), - _visitInitializer(v.initializer, v.annotations), + _emitVariableDef(s.variable), + _visitInitializer(s.variable.initializer, s.variable.annotations), ); if (node.variables.any(containsFunctionExpression)) { @@ -5548,30 +5548,34 @@ class LibraryCompiler extends ComputeOnceConstantVisitor js_ast.Statement _rewriteAsWhile(ForStatement node) { var initFlagTempId = _emitScopedId('t#_init'); var loopVariableIds = { - for (var variable in node.variables) variable: _emitVariableDef(variable), + for (var stmt in node.variables) + stmt.variable: _emitVariableDef(stmt.variable), }; var prevVariableTempIds = { - for (var variable in node.variables) - variable: _emitScopedId('t#_prev_${variable.name!}'), + for (var stmt in node.variables) + stmt.variable: _emitScopedId('t#_prev_${stmt.variable.name!}'), }; var inits = js_ast.Block([ // Set init flag to false so the initialization only happens on the first // iteration of the while loop. js.statement('# = false;', [initFlagTempId]), // Initialize fresh loop variables to initial values. - for (var variable in node.variables) + for (var stmt in node.variables) js.statement('# = #;', [ - loopVariableIds[variable]!, - _visitInitializer(variable.initializer, variable.annotations), + loopVariableIds[stmt.variable]!, + _visitInitializer( + stmt.variable.initializer, + stmt.variable.annotations, + ), ]), ]); var prevInits = js_ast.Block([ // Intialize fresh loop variables with the value from the previous // iteration. - for (var variable in node.variables) + for (var stmt in node.variables) js.statement('# = #;', [ - loopVariableIds[variable], - prevVariableTempIds[variable], + loopVariableIds[stmt.variable], + prevVariableTempIds[stmt.variable], ]), // Original update expressions. for (var update in node.updates) _visitExpression(update).toStatement(), @@ -5584,8 +5588,11 @@ class LibraryCompiler extends ComputeOnceConstantVisitor initFlagTempId, js_ast.LiteralBool(true), ), - for (var variable in node.variables) - js_ast.VariableInitialization(prevVariableTempIds[variable]!, null), + for (var stmt in node.variables) + js_ast.VariableInitialization( + prevVariableTempIds[stmt.variable]!, + null, + ), ]).toStatement(), // The for loop transformed into a while loop. js_ast.While( @@ -5594,9 +5601,9 @@ class LibraryCompiler extends ComputeOnceConstantVisitor // Create fresh loop variables every iteration. if (node.variables.isNotEmpty) js_ast.VariableDeclarationList('let', [ - for (var variable in node.variables) + for (var stmt in node.variables) js_ast.VariableInitialization( - loopVariableIds[variable]!, + loopVariableIds[stmt.variable]!, null, ), ]).toStatement(), @@ -5609,15 +5616,15 @@ class LibraryCompiler extends ComputeOnceConstantVisitor // Original loop body. _visitScope(_effectiveBodyOf(node, node.body)), // Save previous loop variables - for (var variable in node.variables) + for (var stmt in node.variables) js.statement('# = #;', [ - prevVariableTempIds[variable]!, - _emitVariableRef(variable), + prevVariableTempIds[stmt.variable]!, + _emitVariableRef(stmt.variable), ]) // Map these locations to the variable declaration so stepping // in the Dart debugger doesn't jump to the previous line when // stepping. - ..sourceInformation = _nodeStart(variable), + ..sourceInformation = _nodeStart(stmt.variable), ]), ) // The while loop gets mapped to the original for loop location. diff --git a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart index eea2bfa8cfb..1de9e3ab4d2 100644 --- a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart +++ b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart @@ -187,7 +187,7 @@ class ModuleSymbolsCollector extends RecursiveVisitor { } @override - void visitVariableDeclaration(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { var kind = node.isInitializingFormal ? VariableSymbolKind.formal : VariableSymbolKind.local; diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart index 30ef95e9141..7569c3d05d3 100644 --- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart +++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart @@ -417,7 +417,7 @@ class _NullableVariableInference extends RecursiveVisitor { } @override - void visitVariableDeclaration(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { if (_nullInference.allowNotNullDeclarations) { var annotations = node.annotations; if (annotations.isNotEmpty && diff --git a/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart b/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart index 412e43e4190..7fb1228ddc1 100644 --- a/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart +++ b/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart @@ -339,7 +339,7 @@ Expression? getLateFieldInitializer(Member node) { return staticSet.value; } } else if (block.statements.isNotEmpty && - block.statements.first is VariableDeclaration) { + block.statements.first is VariableStatement) { // We have // // get field { @@ -353,9 +353,9 @@ Expression? getLateFieldInitializer(Member node) { // } // // in case `` is the initializer. - VariableDeclaration variableDeclaration = - block.statements.first as VariableDeclaration; - return variableDeclaration.initializer; + VariableStatement variableStatement = + block.statements.first as VariableStatement; + return variableStatement.variable.initializer; } } return null; diff --git a/pkg/front_end/lib/src/fragment/constructor/encoding.dart b/pkg/front_end/lib/src/fragment/constructor/encoding.dart index 1d10e09f4ca..bcc89d261ef 100644 --- a/pkg/front_end/lib/src/fragment/constructor/encoding.dart +++ b/pkg/front_end/lib/src/fragment/constructor/encoding.dart @@ -778,11 +778,14 @@ mixin _ExtensionTypeConstructorEncodingMixin } if (!_isExternal) { VariableDeclaration thisVariable = this.thisVariable!; - List statements = [thisVariable]; + VariableStatement thisVariableStatement = extern.createVariableStatement( + thisVariable, + ); + List statements = [thisVariableStatement]; _ExtensionTypeInitializerToStatementConverter visitor = new _ExtensionTypeInitializerToStatementConverter( statements, - thisVariable, + thisVariableStatement, ); for (Initializer initializer in _initializers) { initializer.accept(visitor); @@ -847,12 +850,12 @@ mixin _ExtensionTypeConstructorEncodingMixin class _ExtensionTypeInitializerToStatementConverter implements InitializerVisitor { - VariableDeclaration thisVariable; + VariableStatement thisVariableStatement; final List statements; _ExtensionTypeInitializerToStatementConverter( this.statements, - this.thisVariable, + this.thisVariableStatement, ); @override @@ -866,7 +869,7 @@ class _ExtensionTypeInitializerToStatementConverter statements.add( extern.createExpressionStatement( extern.createVariableSet( - thisVariable, + thisVariableStatement.variable, extern.createStaticInvocation( node.target, node.arguments.toArguments( @@ -884,9 +887,10 @@ class _ExtensionTypeInitializerToStatementConverter ); return; } else if (node is ExtensionTypeRepresentationFieldInitializer) { - thisVariable - ..initializer = (node.value..parent = thisVariable) + thisVariableStatement.variable + ..initializer = (node.value..parent = thisVariableStatement.variable) ..fileOffset = node.fileOffset; + thisVariableStatement.fileOffset = node.fileOffset; return; } // Coverage-ignore-block(suite): Not run. @@ -898,9 +902,10 @@ class _ExtensionTypeInitializerToStatementConverter @override // Coverage-ignore(suite): Not run. void visitFieldInitializer(FieldInitializer node) { - thisVariable - ..initializer = (node.value..parent = thisVariable) + thisVariableStatement.variable + ..initializer = (node.value..parent = thisVariableStatement.variable) ..fileOffset = node.fileOffset; + thisVariableStatement.fileOffset = node.fileOffset; } @override @@ -917,7 +922,7 @@ class _ExtensionTypeInitializerToStatementConverter @override void visitLocalInitializer(LocalInitializer node) { - statements.add(node.variable); + statements.add(extern.createVariableStatement(node.variable)); } @override diff --git a/pkg/front_end/lib/src/fragment/setter/declaration.dart b/pkg/front_end/lib/src/fragment/setter/declaration.dart index 33af73ef304..2bcaf5099db 100644 --- a/pkg/front_end/lib/src/fragment/setter/declaration.dart +++ b/pkg/front_end/lib/src/fragment/setter/declaration.dart @@ -18,7 +18,6 @@ import '../../builder/metadata_builder.dart'; import '../../builder/property_builder.dart'; import '../../builder/type_builder.dart'; import '../../kernel/body_builder_context.dart'; -import '../../kernel/external_ast_helper.dart'; import '../../kernel/external_ast_helper.dart' as extern; import '../../kernel/hierarchy/class_member.dart'; import '../../kernel/hierarchy/members_builder.dart'; @@ -332,13 +331,13 @@ class RegularSetterDeclaration // Add them as local variable to put them in scope of the body. List statements = []; for (FormalParameterBuilder parameter in declaredFormals) { - statements.add(parameter.variable); + statements.add(extern.createVariableStatement(parameter.variable)); } statements.add(body); - body = createBlock(statements, fileOffset: fileOffset); + body = extern.createBlock(statements, fileOffset: fileOffset); } - body = createBlock([ - createExpressionStatement( + body = extern.createBlock([ + extern.createExpressionStatement( problemReporting.buildProblem( compilerContext: compilerContext, message: diag.setterWithWrongNumberOfFormals, diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart index 51adcef3699..aa47bdbbe9e 100644 --- a/pkg/front_end/lib/src/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/kernel/body_builder.dart @@ -3345,14 +3345,14 @@ class BodyBuilderImpl extends StackListenerImpl } pushNewLocalVariable(initializer, equalsToken: assignmentOperator); if (isLate) { - VariableDeclaration node = peek() as VariableDeclaration; + VariableStatement node = peek() as VariableStatement; // This is matched by the call to [beginNode] in // [beginVariableInitializer]. // TODO(62401): Remove the cast when the flow analysis uses // [InternalExpressionVariable]s. assignedVariables.storeInfo( - (node.variable as InternalVariable).astVariable, + (node.variable.variable as InternalVariable).astVariable, assignedVariablesInfo!, ); } @@ -3404,7 +3404,7 @@ class BodyBuilderImpl extends StackListenerImpl name = createWildcardVariableName(wildcardVariableIndex); wildcardVariableIndex++; } - VariableDeclaration variableInitialization; + Statement variableInitialization; InternalVariable internalVariable; if (isClosureContextLoweringEnabled) { internalVariable = new InternalLocalVariable( @@ -3428,20 +3428,22 @@ class BodyBuilderImpl extends StackListenerImpl fileOffset: offsetForToken(equalsToken), ); } else { - variableInitialization = internalVariable = new VariableDeclarationImpl( - name, - forSyntheticToken: identifier.token.isSynthetic, - initializer: initializer, - type: currentLocalVariableType, - isFinal: isFinal, - isConst: isConst, - isLate: isLate, - isRequired: isRequired, - hasDeclaredInitializer: initializer != null, - isStaticLate: isFinal && initializer == null, - isWildcard: isWildcard, - fileOffset: identifier.nameOffset, - fileEqualsOffset: offsetForToken(equalsToken), + variableInitialization = intern.createVariableStatement( + internalVariable = new VariableDeclarationImpl( + name, + forSyntheticToken: identifier.token.isSynthetic, + initializer: initializer, + type: currentLocalVariableType, + isFinal: isFinal, + isConst: isConst, + isLate: isLate, + isRequired: isRequired, + hasDeclaredInitializer: initializer != null, + isStaticLate: isFinal && initializer == null, + isWildcard: isWildcard, + fileOffset: identifier.nameOffset, + fileEqualsOffset: offsetForToken(equalsToken), + ), ); } assignedVariables.declare(internalVariable.astVariable); @@ -3530,15 +3532,16 @@ class BodyBuilderImpl extends StackListenerImpl push(node); return; } - VariableDeclaration variableInitialization = node as VariableDeclaration; - variableInitialization.fileOffset = nameToken.charOffset; + VariableStatement variableInitialization = node as VariableStatement; + variableInitialization.variable.fileOffset = + variableInitialization.fileOffset = nameToken.charOffset; push(variableInitialization); // Avoid adding the local identifier to scope if it's a wildcard. // TODO(kallentu): Emit better error on lookup, rather than not adding it to // the scope. if (!(libraryFeatures.wildcardVariables.isEnabled && - variableInitialization.isWildcard)) { + variableInitialization.variable.isWildcard)) { declareVariable(variableInitialization.variable, _localScope); } } @@ -3586,23 +3589,20 @@ class BodyBuilderImpl extends StackListenerImpl push(node); return; } - VariableDeclaration variableInitialization = node as VariableDeclaration; + VariableStatement variableInitialization = node as VariableStatement; if (annotations != null) { for (int i = 0; i < annotations.length; i++) { - variableInitialization.addAnnotation(annotations[i]); + variableInitialization.variable.addAnnotation(annotations[i]); } - _registerSingleTargetAnnotations(variableInitialization); - // (variablesWithMetadata ??= []).add( - // variableInitialization, - // ); + _registerSingleTargetAnnotations(variableInitialization.variable); } push(variableInitialization); } else { - List? variables = - const FixedNullableList().popNonNullable( + List? variables = + const FixedNullableList().popNonNullable( stack, count, - dummyVariableDeclaration, + dummyVariableStatement, ); constantContext = pop() as ConstantContext; currentLocalVariableType = pop(NullValues.Type) as DartType?; @@ -3613,11 +3613,13 @@ class BodyBuilderImpl extends StackListenerImpl return; } if (annotations != null) { - VariableDeclaration first = variables.first; + VariableStatement first = variables.first; for (int i = 0; i < annotations.length; i++) { - first.addAnnotation(annotations[i]); + first.variable.addAnnotation(annotations[i]); } - _registerMultiTargetAnnotations(variables); + _registerMultiTargetAnnotations( + variables.map((v) => v.variable).toList(), + ); } push(intern.variablesDeclaration(variables, uri)); } @@ -3722,7 +3724,7 @@ class BodyBuilderImpl extends StackListenerImpl } } - List? _buildForLoopVariableDeclarations( + List? _buildForLoopVariableDeclarations( variableOrExpression, ) { // TODO(ahe): This can be simplified now that we have the events @@ -3730,40 +3732,40 @@ class BodyBuilderImpl extends StackListenerImpl if (variableOrExpression is Generator) { variableOrExpression = variableOrExpression.buildForEffect(); } - if (variableOrExpression is VariableDeclaration) { + if (variableOrExpression is VariableStatement) { // Late for loop variables are not supported. An error has already been // reported by the parser. - variableOrExpression.isLate = false; - return [variableOrExpression]; + variableOrExpression.variable.isLate = false; + return [variableOrExpression]; } else if (variableOrExpression is Expression) { VariableDeclaration variable = new VariableDeclarationImpl.forEffect( variableOrExpression, ); - return [variable]; + return [intern.createVariableStatement(variable)]; } else if (variableOrExpression is ExpressionStatement) { // Coverage-ignore-block(suite): Not run. VariableDeclaration variable = new VariableDeclarationImpl.forEffect( variableOrExpression.expression, ); - return [variable]; + return [intern.createVariableStatement(variable)]; } else if (intern.isVariablesDeclaration(variableOrExpression)) { return intern.variablesDeclarationExtractDeclarations( variableOrExpression, ); } else if (variableOrExpression is List) { // Coverage-ignore-block(suite): Not run. - List variables = []; + List variables = []; for (Object v in variableOrExpression) { variables.addAll(_buildForLoopVariableDeclarations(v)!); } return variables; } else if (variableOrExpression is PatternVariableDeclaration) { // Coverage-ignore-block(suite): Not run. - return []; + return []; } else if (variableOrExpression is ParserRecovery) { - return []; + return []; } else if (variableOrExpression == null) { - return []; + return []; } return null; } @@ -3794,8 +3796,10 @@ class BodyBuilderImpl extends StackListenerImpl // If the declaration is of the form `for (final x in ...)`, then we may // have erroneously set the `isStaticLate` flag, so un-set it. Object? declaration = peek(); - if (declaration is VariableDeclarationImpl) { - declaration.isStaticLate = false; + if (declaration case VariableStatement( + :VariableDeclarationImpl variable, + )) { + variable.isStaticLate = false; } } else { // This is matched by the call to [deferNode] in [endForStatement] or @@ -3967,10 +3971,12 @@ class BodyBuilderImpl extends StackListenerImpl .popNode(); Object? variableOrExpression = pop(); - List? variables; + List? variables; List? intermediateVariables; if (variableOrExpression is PatternVariableDeclaration) { - variables = pop() as List; // Internal variables. + variables = (pop() as List) + .map(intern.createVariableStatement) + .toList(); // Internal variables. intermediateVariables = pop() as List; } else { variables = _buildForLoopVariableDeclarations(variableOrExpression)!; @@ -4086,10 +4092,12 @@ class BodyBuilderImpl extends StackListenerImpl .deferNode(); Object? variableOrExpression = pop(); - List? variables; + List? variables; List? intermediateVariables; if (variableOrExpression is PatternVariableDeclaration) { - variables = pop() as List; + variables = (pop() as List) + .map(intern.createVariableStatement) + .toList(); // Internal variables. intermediateVariables = pop() as List; } else { variables = _buildForLoopVariableDeclarations(variableOrExpression); @@ -4132,7 +4140,13 @@ class BodyBuilderImpl extends StackListenerImpl result = intern.createBlock( fileOffset: result.fileOffset, fileEndOffset: result.fileOffset, - [variableOrExpression, ...intermediateVariables!, result], + [ + variableOrExpression, + for (VariableDeclaration intermediateVariable + in intermediateVariables!) + intern.createVariableStatement(intermediateVariable), + result, + ], ); } if (variableOrExpression is ParserRecovery) { @@ -8358,46 +8372,46 @@ class BodyBuilderImpl extends StackListenerImpl lvalue.hasDeclaredInitializer = false; // Late for-in variables are not supported. An error has already been // reported by the parser. - lvalue.isLate = false; + lvalue.variable.isLate = false; InvalidExpression? error; - if (lvalue.isConst) { + if (lvalue.variable.isConst) { // Coverage-ignore-block(suite): Not run. error = buildProblem( message: diag.forInLoopWithConstVariable, fileUri: uri, fileOffset: lvalue.fileOffset, - length: lvalue.cosmeticName!.length, + length: lvalue.variable.cosmeticName!.length, ); // As a recovery step, remove the const flag, to not confuse the // constant evaluator further in the pipeline. - lvalue.isConst = false; + lvalue.variable.isConst = false; } return new VariableInitializationForInElement( variableInitialization: lvalue, error: error, ); - } else if (lvalue is VariableDeclaration) { + } else if (lvalue is LegacyVariableStatement) { // Variable initializers are not supported. An error has already been // reported by the parser. - lvalue.initializer = null; - lvalue.hasDeclaredInitializer = false; + lvalue.variable.initializer = null; + lvalue.variable.hasDeclaredInitializer = false; // Late for-in variables are not supported. An error has already been // reported by the parser. - lvalue.isLate = false; + lvalue.variable.isLate = false; InvalidExpression? error; - if (lvalue.isConst) { + if (lvalue.variable.isConst) { error = buildProblem( message: diag.forInLoopWithConstVariable, fileUri: uri, fileOffset: lvalue.fileOffset, - length: lvalue.cosmeticName!.length, + length: lvalue.variable.cosmeticName!.length, ); // As a recovery step, remove the const flag, to not confuse the // constant evaluator further in the pipeline. - lvalue.isConst = false; + lvalue.variable.isConst = false; } return new SingleVariableDeclarationForInElement( - variableDeclaration: lvalue, + variableStatement: lvalue, error: error, ); } else if (lvalue is Generator) { diff --git a/pkg/front_end/lib/src/kernel/collections.dart b/pkg/front_end/lib/src/kernel/collections.dart index c0865b7440b..ef4dd177686 100644 --- a/pkg/front_end/lib/src/kernel/collections.dart +++ b/pkg/front_end/lib/src/kernel/collections.dart @@ -222,10 +222,10 @@ class ForElement extends ControlFlowElement implements ForElementBase { // May be empty, but not null. @override - final List variableInitializations; + final List variableInitializations; @override - List get variables => variableInitializations.cast(); + List get variables => variableInitializations; @override Expression? condition; // May be null. @@ -283,7 +283,7 @@ class ForElement extends ControlFlowElement printer.write(', '); } printer.writeVariableInitialization( - variableInitializations[index], + variableInitializations[index].variable, includeModifiersAndType: index == 0, ); } @@ -462,9 +462,9 @@ class IfCaseElement extends ControlFlowElementImpl } abstract interface class ForElementBase implements AuxiliaryExpression { - List get variableInitializations; + List get variableInitializations; - List get variables; + List get variables; abstract Expression? condition; @@ -481,10 +481,10 @@ class PatternForElement extends ControlFlowElementImpl // May be empty, but not null. @override - final List variableInitializations; + final List variableInitializations; @override - List get variables => variableInitializations.cast(); + List get variables => variableInitializations; @override Expression? condition; // May be null. @@ -498,7 +498,7 @@ class PatternForElement extends ControlFlowElementImpl PatternForElement({ required this.patternVariableDeclaration, required this.intermediateVariables, - required List variables, + required List variables, required this.condition, required this.updates, required this.body, @@ -522,7 +522,7 @@ class PatternForElement extends ControlFlowElementImpl printer.write(', '); } printer.writeVariableInitialization( - variableInitializations[index], + variableInitializations[index].variable, includeModifiersAndType: index == 0, ); } @@ -689,7 +689,7 @@ class IfMapEntry extends TreeNode } abstract interface class ForMapEntryBase implements TreeNode, MapLiteralEntry { - List get variables; + List get variables; abstract Expression? condition; @@ -704,7 +704,7 @@ class ForMapEntry extends TreeNode implements ForMapEntryBase, ControlFlowMapEntry { // May be empty, but not null. @override - final List variables; + final List variables; @override Expression? condition; // May be null. @@ -736,7 +736,7 @@ class ForMapEntry extends TreeNode printer.write(', '); } printer.writeVariableInitialization( - variables[index], + variables[index].variable, includeModifiersAndType: index == 0, ); } @@ -758,7 +758,7 @@ class PatternForMapEntry extends TreeNode List intermediateVariables; @override - final List variables; + final List variables; @override Expression? condition; @@ -788,7 +788,7 @@ class PatternForMapEntry extends TreeNode printer.write(', '); } printer.writeVariableInitialization( - variables[index], + variables[index].variable, includeModifiersAndType: index == 0, ); } diff --git a/pkg/front_end/lib/src/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/kernel/constant_evaluator.dart index c5a38048943..8c453e38ad3 100644 --- a/pkg/front_end/lib/src/kernel/constant_evaluator.dart +++ b/pkg/front_end/lib/src/kernel/constant_evaluator.dart @@ -447,7 +447,28 @@ class ConstantsTransformer extends RemovingTransformer { } @override - TreeNode visitVariableDeclaration( + TreeNode visitLegacyVariableStatement( + LegacyVariableStatement node, + TreeNode? removalSentinel, + ) { + if (removalSentinel != null) { + VariableDeclaration? variable = transformOrRemoveVariableDeclaration( + node.variable, + ); + if (variable == null) { + return removalSentinel; + } + node.variable = variable..parent = node; + return node; + } else { + // Coverage-ignore-block(suite): Not run. + node.variable = transform(node.variable)..parent = node; + return node; + } + } + + @override + TreeNode defaultVariableDeclaration( VariableDeclaration node, TreeNode? removalSentinel, ) { @@ -1107,7 +1128,12 @@ class ConstantsTransformer extends RemovingTransformer { if (isContinueTarget) { // TODO(johnniwinther): In this case it should be an error to have // any variables. This is not currently reported. - replacementStatements.addAll(pattern.declaredVariables); + for (VariableDeclaration declaredVariable + in pattern.declaredVariables) { + replacementStatements.add( + extern.createVariableStatement(declaredVariable), + ); + } for (VariableDeclaration variable in pattern.declaredVariables) { (declaredVariablesByName[variable.name!] ??= []).add(variable); @@ -1247,7 +1273,9 @@ class ConstantsTransformer extends RemovingTransformer { ], [node.fileOffset], extern.createBlock([ - ...switchCase.jointVariables, + for (VariableDeclaration jointVariable + in switchCase.jointVariables) + extern.createVariableStatement(jointVariable), if (body is! Block || body.statements.isNotEmpty) body, ], fileOffset: node.fileOffset), isDefault: switchCase.isDefault, @@ -1269,7 +1297,8 @@ class ConstantsTransformer extends RemovingTransformer { replacementCases.add(replacementCase); } else { caseBlock = extern.createBlock([ - ...switchCase.jointVariables, + for (VariableDeclaration jointVariable in switchCase.jointVariables) + extern.createVariableStatement(jointVariable), if (body is! Block || body.statements.isNotEmpty) body, ], fileOffset: switchCase.fileOffset); } @@ -1302,7 +1331,8 @@ class ConstantsTransformer extends RemovingTransformer { } cases.add( extern.createBlock([ - ...caseVariables, + for (VariableDeclaration caseVariable in caseVariables) + extern.createVariableStatement(caseVariable), caseBlock, if (breakStatement != null) // Coverage-ignore(suite): Not run. @@ -1355,10 +1385,13 @@ class ConstantsTransformer extends RemovingTransformer { ); innerLabeledStatement.body = casesBlock..parent = innerLabeledStatement; replacementStatements = [ - matchResultVariable, + extern.createVariableStatement(matchResultVariable), ...replacementStatements, - ...matchingCache.declarations, - ...declaredVariableHelpers, + for (VariableDeclaration declaration in matchingCache.declarations) + extern.createVariableStatement(declaration), + for (VariableDeclaration declaredVariableHelper + in declaredVariableHelpers) + extern.createVariableStatement(declaredVariableHelper), innerLabeledStatement, extern.createSwitchStatement( extern.createVariableGet(matchResultVariable), @@ -1371,8 +1404,11 @@ class ConstantsTransformer extends RemovingTransformer { } else { replacementStatements = [ ...replacementStatements, - ...matchingCache.declarations, - ...declaredVariableHelpers, + for (VariableDeclaration declaration in matchingCache.declarations) + extern.createVariableStatement(declaration), + for (VariableDeclaration declaredVariableHelper + in declaredVariableHelpers) + extern.createVariableStatement(declaredVariableHelper), ...cases, ]; } @@ -1609,15 +1645,19 @@ class ConstantsTransformer extends RemovingTransformer { } } - List cacheVariables = [...matchingCache.declarations]; - Iterable declarations = + List cacheVariables = [ + for (VariableDeclaration declaration in matchingCache.declarations) + extern.createVariableStatement(declaration), + ]; + Iterable declarations = node.patternGuard.pattern.declaredVariables; Statement ifStatement; if (declarations.isNotEmpty) { // If we need local declarations, create a new block to avoid naming // collision with declarations in the same parent block. ifStatement = extern.createBlock([ - ...declarations, + for (VariableDeclaration declaration in declarations) + extern.createVariableStatement(declaration), extern.createIfStatement( condition, then, @@ -1680,7 +1720,8 @@ class ConstantsTransformer extends RemovingTransformer { replacementStatements, ); replacementStatements = [ - ...matchingCache.declarations, + for (VariableDeclaration declaration in matchingCache.declarations) + extern.createVariableStatement(declaration), ...replacementStatements, ]; } else { @@ -1689,7 +1730,8 @@ class ConstantsTransformer extends RemovingTransformer { inCacheInitializer: false, ); replacementStatements = [ - ...matchingCache.declarations, + for (VariableDeclaration declaration in matchingCache.declarations) + extern.createVariableStatement(declaration), // TODO(cstefantsova): Provide a better diagnostic message. extern.createIfStatement( extern.createNot(readMatchingExpression), @@ -1720,7 +1762,9 @@ class ConstantsTransformer extends RemovingTransformer { ]; } replacementStatements = [ - ...node.pattern.declaredVariables, + for (VariableDeclaration declaredVariable + in node.pattern.declaredVariables) + extern.createVariableStatement(declaredVariable), ...replacementStatements, ]; @@ -1770,8 +1814,12 @@ class ConstantsTransformer extends RemovingTransformer { effects: effects, ); replacementStatements = [ - ...matchingCache.declarations, - ...node.pattern.declaredVariables, + for (VariableDeclaration declaration in matchingCache.declarations) + extern.createVariableStatement(declaration), + for (VariableDeclaration declaredVariable + in node.pattern.declaredVariables) + extern // Coverage-ignore(suite): Not run. + .createVariableStatement(declaredVariable), ...replacementStatements, ...effects, ]; @@ -1784,8 +1832,12 @@ class ConstantsTransformer extends RemovingTransformer { ); replacementStatements = [ - ...matchingCache.declarations, - ...node.pattern.declaredVariables, + for (VariableDeclaration declaration in matchingCache.declarations) + extern.createVariableStatement(declaration), + for (VariableDeclaration declaredVariable + in node.pattern.declaredVariables) + extern // Coverage-ignore(suite): Not run. + .createVariableStatement(declaredVariable), // TODO(cstefantsova): Provide a better diagnostic message. extern.createIfStatement( extern.createNot(readMatchingExpression), @@ -2005,7 +2057,7 @@ class ConstantsTransformer extends RemovingTransformer { )..parent = labeledStatement; replacement = extern.createBlockExpression( extern.createBlock([ - valueVariable, + extern.createVariableStatement(valueVariable), labeledStatement, ], fileOffset: node.fileOffset), extern.createVariableGet(valueVariable), @@ -2110,7 +2162,9 @@ class ConstantsTransformer extends RemovingTransformer { cases.add( extern.createBlock([ - ...pattern.declaredVariables, + for (VariableDeclaration declaredVariable + in pattern.declaredVariables) + extern.createVariableStatement(declaredVariable), extern.createIfStatement( caseCondition, extern.createBlock([ @@ -2173,8 +2227,9 @@ class ConstantsTransformer extends RemovingTransformer { )..parent = labeledStatement; replacement = extern.createBlockExpression( extern.createBlock([ - valueVariable, - ...matchingCache.declarations, + extern.createVariableStatement(valueVariable), + for (VariableDeclaration declaration in matchingCache.declarations) + extern.createVariableStatement(declaration), labeledStatement, ], fileOffset: node.fileOffset), extern.createVariableGet(valueVariable), @@ -6048,8 +6103,12 @@ class ConstantEvaluator } class StatementConstantEvaluator - with StatementVisitorExperimentExclusionMixin - implements StatementVisitor { + with + StatementVisitorExperimentExclusionMixin, + VariableVisitorExperimentExclusionMixin + implements + StatementVisitor, + VariableVisitor { ConstantEvaluator exprEvaluator; StatementConstantEvaluator(this.exprEvaluator); @@ -6145,7 +6204,7 @@ class StatementConstantEvaluator @override ExecutionStatus visitForStatement(ForStatement node) { - for (VariableDeclaration variable in node.variables) { + for (VariableStatement variable in node.variables) { final ExecutionStatus status = variable.accept(this); if (status is! ProceedStatus) return status; } diff --git a/pkg/front_end/lib/src/kernel/dart_scope_calculator.dart b/pkg/front_end/lib/src/kernel/dart_scope_calculator.dart index cbcb0fbda58..10e84e24552 100644 --- a/pkg/front_end/lib/src/kernel/dart_scope_calculator.dart +++ b/pkg/front_end/lib/src/kernel/dart_scope_calculator.dart @@ -376,9 +376,9 @@ class DartScopeBuilder2 extends VisitorDefault with VisitorVoidMixin { } @override - void visitVariableDeclaration(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { if (node.isHoisted) hoistedUnwritten.add(node); - super.visitVariableDeclaration(node); + super.defaultVariableDeclaration(node); // Declare it after. scopes.last.add(node); } diff --git a/pkg/front_end/lib/src/kernel/external_ast_helper.dart b/pkg/front_end/lib/src/kernel/external_ast_helper.dart index 9992bff78b6..5a0a01cd9ba 100644 --- a/pkg/front_end/lib/src/kernel/external_ast_helper.dart +++ b/pkg/front_end/lib/src/kernel/external_ast_helper.dart @@ -916,3 +916,7 @@ Expression createVariableSet( return new VariableSet(variable, value)..fileOffset = fileOffset; } } + +VariableStatement createVariableStatement(VariableDeclaration variable) { + return new VariableStatement(variable)..fileOffset = variable.fileOffset; +} diff --git a/pkg/front_end/lib/src/kernel/internal_ast.dart b/pkg/front_end/lib/src/kernel/internal_ast.dart index f25b4ce1cd3..451dd36a5eb 100644 --- a/pkg/front_end/lib/src/kernel/internal_ast.dart +++ b/pkg/front_end/lib/src/kernel/internal_ast.dart @@ -969,7 +969,7 @@ class ReturnStatementImpl extends ReturnStatement { } /// Front end specific implementation of [VariableDeclaration]. -class VariableDeclarationImpl extends VariableStatement +class VariableDeclarationImpl extends LegacyVariable with InternalVariableMixin implements InternalVariable { @override @@ -1059,7 +1059,6 @@ class VariableDeclarationImpl extends VariableStatement isLate: isLate || lateGetter != null, type: lateType ?? type, ); - printer.write(';'); } @override @@ -1095,11 +1094,11 @@ class InternalLocalVariable extends TreeNode @override // Coverage-ignore(suite): Not run. - R accept(StatementVisitor v) => v.visitLocalVariable(astVariable); + R accept(VariableVisitor v) => v.visitLocalVariable(astVariable); @override // Coverage-ignore(suite): Not run. - R accept1(StatementVisitor1 v, A arg) => + R accept1(VariableVisitor1 v, A arg) => v.visitLocalVariable(astVariable, arg); @override @@ -1125,13 +1124,12 @@ class InternalLocalVariable extends TreeNode int binaryOffsetNoTag = -1; @override - List? get capturedContexts { - throw new UnsupportedError("${this.runtimeType}.capturedContexts"); - } + List? get capturedContexts => + variableInitialization?.capturedContexts; @override void set capturedContexts(List? value) { - throw new UnsupportedError("${this.runtimeType}.capturedContexts="); + variableInitialization!.capturedContexts = value; } @override @@ -1190,11 +1188,11 @@ class InternalPositionalParameter extends TreeNode } @override - R accept(StatementVisitor v) => v.visitPositionalParameter(astVariable); + R accept(VariableVisitor v) => v.visitPositionalParameter(astVariable); @override // Coverage-ignore(suite): Not run. - R accept1(StatementVisitor1 v, A arg) => + R accept1(VariableVisitor1 v, A arg) => v.visitPositionalParameter(astVariable, arg); @override @@ -1296,11 +1294,11 @@ class InternalNamedParameter extends TreeNode } @override - R accept(StatementVisitor v) => v.visitNamedParameter(astVariable); + R accept(VariableVisitor v) => v.visitNamedParameter(astVariable); @override // Coverage-ignore(suite): Not run. - R accept1(StatementVisitor1 v, A arg) => + R accept1(VariableVisitor1 v, A arg) => v.visitNamedParameter(astVariable, arg); @override @@ -1524,7 +1522,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin Expression? get initializer => astVariable.initializer; @override - // Coverage-ignore(suite): Not run. void set initializer(Expression? value) { astVariable.initializer = value; } @@ -1658,12 +1655,11 @@ mixin DelegatingVariableMixin on InternalVariableMixin } @override - // Coverage-ignore(suite): Not run. - VariableDeclaration? get variableInitialization => + VariableInitialization? get variableInitialization => astVariable.variableInitialization; @override - void set variableInitialization(VariableDeclaration? value) { + void set variableInitialization(VariableInitialization? value) { astVariable.variableInitialization = value; } @@ -1735,13 +1731,13 @@ mixin DelegatingVariableMixin on InternalVariableMixin @override // Coverage-ignore(suite): Not run. - R accept(StatementVisitor v) { + R accept(VariableVisitor v) { return astVariable.accept(v); } @override // Coverage-ignore(suite): Not run. - R accept1(StatementVisitor1 v, A arg) { + R accept1(VariableVisitor1 v, A arg) { return astVariable.accept1(v, arg); } @@ -5835,7 +5831,9 @@ sealed class _VariableForInElement extends _BaseForInElement { }) { return new ForInEncoding( preLoopError: error, - bodyPrologue: _variableForSideEffect, + bodyPrologue: _variableForSideEffect != null + ? extern.createVariableStatement(_variableForSideEffect!) + : null, ); } } @@ -5858,7 +5856,7 @@ class VariableInitializationForInElement extends _VariableForInElement { // Coverage-ignore(suite): Not run. void toTextInternal(AstPrinter printer) { printer.writeVariableInitialization( - variableInitialization, + variableInitialization.variable, includeInitializer: false, isImplicitlyTyped: (variableInitialization.variable is InternalVariable) && @@ -5881,36 +5879,36 @@ class VariableInitializationForInElement extends _VariableForInElement { /// For-in element for a single declared variable. class SingleVariableDeclarationForInElement extends _VariableForInElement { /// The declared variable. - final VariableDeclaration variableDeclaration; + final LegacyVariableStatement variableStatement; SingleVariableDeclarationForInElement({ - required this.variableDeclaration, + required this.variableStatement, required super.error, }); @override - VariableDeclaration get _variableDeclaration => variableDeclaration; + VariableDeclaration get _variableDeclaration => variableStatement.variable; @override // Coverage-ignore(suite): Not run. void toTextInternal(AstPrinter printer) { printer.writeVariableInitialization( - variableDeclaration, + variableStatement.variable, includeInitializer: false, isImplicitlyTyped: - variableDeclaration.variable is InternalVariable && - (variableDeclaration.variable as InternalVariable).isImplicitlyTyped, + variableStatement.variable is InternalVariable && + (variableStatement.variable as InternalVariable).isImplicitlyTyped, ); } @override DartType _computeElementTypeContext(InferenceVisitorBase visitor) { - if (variableDeclaration case InternalVariable variable) { + if (variableStatement.variable case InternalVariable variable) { if (variable.isImplicitlyTyped) { return const UnknownType(); } } - return variableDeclaration.type; + return variableStatement.variable.type; } } @@ -5918,7 +5916,7 @@ class SingleVariableDeclarationForInElement extends _VariableForInElement { /// `for (var a, b in [])`. This is an error case. class MultiVariableDeclarationForInElement extends _BaseForInElement { /// The declared variables. - final List variableDeclarations; + final List variableDeclarations; /// The error that should be emitted prior to the for-in statement. final InvalidExpression error; @@ -5932,20 +5930,21 @@ class MultiVariableDeclarationForInElement extends _BaseForInElement { // Coverage-ignore(suite): Not run. void toTextInternal(AstPrinter printer) { for (int i = 0; i < variableDeclarations.length; i++) { - VariableDeclaration variableDeclaration = variableDeclarations[i]; + VariableStatement variableDeclaration = variableDeclarations[i]; if (i == 0) { printer.writeVariableInitialization( - variableDeclaration, + variableDeclaration.variable, includeModifiersAndType: true, includeInitializer: false, isImplicitlyTyped: - variableDeclaration is InternalVariable && - (variableDeclaration as InternalVariable).isImplicitlyTyped, + variableDeclaration.variable is InternalVariable && + (variableDeclaration.variable as InternalVariable) + .isImplicitlyTyped, ); } else { printer.write(', '); printer.writeVariableInitialization( - variableDeclaration, + variableDeclaration.variable, includeModifiersAndType: false, includeInitializer: false, ); diff --git a/pkg/front_end/lib/src/kernel/internal_ast_helper.dart b/pkg/front_end/lib/src/kernel/internal_ast_helper.dart index 21c79b0f36d..f27b961e5ed 100644 --- a/pkg/front_end/lib/src/kernel/internal_ast_helper.dart +++ b/pkg/front_end/lib/src/kernel/internal_ast_helper.dart @@ -302,7 +302,7 @@ Statement createExpressionStatement( ForElement createForElement( int fileOffset, - List variables, + List variables, Expression? condition, List updates, Expression body, @@ -363,7 +363,7 @@ ForInStatement createForInStatement( ForMapEntry createForMapEntry( int fileOffset, - List variables, + List variables, Expression? condition, List updates, MapLiteralEntry body, @@ -375,7 +375,7 @@ ForMapEntry createForMapEntry( /// Return a representation of a for statement. Statement createForStatement( int fileOffset, - List? variables, + List? variables, Expression? condition, List updaters, Statement body, @@ -810,7 +810,7 @@ PatternForElement createPatternForElement( int fileOffset, { required PatternVariableDeclaration patternVariableDeclaration, required List intermediateVariables, - required List variables, + required List variables, required Expression? condition, required List updates, required Expression body, @@ -829,7 +829,7 @@ PatternForMapEntry createPatternForMapEntry( int fileOffset, { required PatternVariableDeclaration patternVariableDeclaration, required List intermediateVariables, - required List variableInitializations, + required List variableInitializations, required Expression? condition, required List updates, required MapLiteralEntry body, @@ -1240,6 +1240,10 @@ InternalVariableSet createVariableSet( ..fileOffset = fileOffset; } +VariableStatement createVariableStatement(VariableDeclaration variable) { + return new VariableStatement(variable)..fileOffset = variable.fileOffset; +} + /// Return a representation of a while statement at the given [fileOffset] /// consisting of the given [condition] and [body]. Statement createWhileStatement( @@ -1291,13 +1295,13 @@ bool isThisExpression(Object node) => bool isVariablesDeclaration(Object? node) => node is _VariablesDeclaration; _VariablesDeclaration variablesDeclaration( - List declarations, + List declarations, Uri uri, ) { return new _VariablesDeclaration(declarations, uri); } -List variablesDeclarationExtractDeclarations( +List variablesDeclarationExtractDeclarations( Object? variablesDeclaration, ) { return (variablesDeclaration as _VariablesDeclaration).declarations; @@ -1306,9 +1310,13 @@ List variablesDeclarationExtractDeclarations( Statement wrapVariables(Statement statement) { if (statement is _VariablesDeclaration) { return new Block( - new List.of(statement.declarations, growable: true), + new List.generate( + statement.declarations.length, + (int index) => statement.declarations[index], + growable: true, + ), )..fileOffset = statement.fileOffset; - } else if (statement is VariableDeclaration) { + } else if (statement is VariableStatement) { return new Block([statement])..fileOffset = statement.fileOffset; } else { return statement; @@ -1316,7 +1324,7 @@ Statement wrapVariables(Statement statement) { } class _VariablesDeclaration extends AuxiliaryStatement { - final List declarations; + final List declarations; final Uri uri; _VariablesDeclaration(this.declarations, this.uri) { @@ -1348,7 +1356,7 @@ class _VariablesDeclaration extends AuxiliaryStatement { printer.write(', '); } printer.writeVariableInitialization( - declarations[index], + declarations[index].variable, includeModifiersAndType: index == 0, ); } diff --git a/pkg/front_end/lib/src/kernel/late_lowering.dart b/pkg/front_end/lib/src/kernel/late_lowering.dart index 6d6c5b4d0ce..8346c854b74 100644 --- a/pkg/front_end/lib/src/kernel/late_lowering.dart +++ b/pkg/front_end/lib/src/kernel/late_lowering.dart @@ -158,7 +158,7 @@ Statement createGetterWithInitializerWithRecheck( new Not(createIsSetRead()..fileOffset = fileOffset) ..fileOffset = fileOffset, new Block([ - temp, + new VariableStatement(temp)..fileOffset = temp.fileOffset, new IfStatement( createIsSetRead()..fileOffset = fileOffset, new ExpressionStatement(exception)..fileOffset = fileOffset, diff --git a/pkg/front_end/lib/src/testing/id_extractor.dart b/pkg/front_end/lib/src/testing/id_extractor.dart index 6ea2b2eb229..44e8719f482 100644 --- a/pkg/front_end/lib/src/testing/id_extractor.dart +++ b/pkg/front_end/lib/src/testing/id_extractor.dart @@ -334,7 +334,7 @@ abstract class DataExtractor extends VisitorDefault } @override - void visitVariableDeclaration(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { if (node.name != null && node.parent is! FunctionDeclaration) { // Skip synthetic variables and function declaration variables. computeForNode( diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/type_inference/inference_visitor.dart index 37be2a76f85..962b50defbc 100644 --- a/pkg/front_end/lib/src/type_inference/inference_visitor.dart +++ b/pkg/front_end/lib/src/type_inference/inference_visitor.dart @@ -3441,9 +3441,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase scopeProviderInfoKind: ScopeProviderInfoKind.Loop, ); } - List? variables; + List? variables; for (int index = 0; index < node.variables.length; index++) { - VariableDeclaration variable = node.variables[index]; + VariableStatement variableStatement = node.variables[index]; + VariableDeclaration variable = variableStatement.variable; if (variable.name == null) { if (variable.initializer != null) { ExpressionInferenceResult result = inferExpression( @@ -3455,24 +3456,26 @@ class InferenceVisitorImpl extends InferenceVisitorBase variable.type = result.inferredType; } } else { - StatementInferenceResult variableResult = inferStatement(variable); + StatementInferenceResult variableResult = inferStatement( + variableStatement, + ); if (variableResult.hasChanged) { // Coverage-ignore-block(suite): Not run. if (variables == null) { - variables = []; + variables = []; variables.addAll(node.variables.sublist(0, index)); } if (variableResult.statementCount == 1) { - variables.add(variableResult.statement as VariableDeclaration); + variables.add(variableResult.statement as VariableStatement); } else { for (Statement variable in variableResult.statements) { - variables.add(variable as VariableDeclaration); + variables.add(variable as VariableStatement); } } } // Coverage-ignore(suite): Not run. else if (variables != null) { - variables.add(variable); + variables.add(variableStatement); } } } @@ -4368,7 +4371,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase ).expression..parent = intermediateVariable; intermediateVariable.type = type; - element.variableInitializations[i].type = type; + element.variableInitializations[i].variable.type = type; } return _inferForElementBase( @@ -4400,13 +4403,15 @@ class InferenceVisitorImpl extends InferenceVisitorBase Map inferredConditionTypes, ) { // TODO(johnniwinther): Use _visitStatements instead. - List? variables; + List? variables; for ( int index = 0; index < element.variableInitializations.length; index++ ) { - VariableDeclaration variable = element.variableInitializations[index]; + VariableStatement variableStatement = + element.variableInitializations[index]; + VariableDeclaration variable = variableStatement.variable; if (variable.name == null) { if (variable.initializer != null) { ExpressionInferenceResult initializerResult = inferExpression( @@ -4419,24 +4424,26 @@ class InferenceVisitorImpl extends InferenceVisitorBase variable.type = initializerResult.inferredType; } } else { - StatementInferenceResult variableResult = inferStatement(variable); + StatementInferenceResult variableResult = inferStatement( + variableStatement, + ); if (variableResult.hasChanged) { // Coverage-ignore-block(suite): Not run. if (variables == null) { - variables = []; + variables = []; variables.addAll(element.variableInitializations.sublist(0, index)); } if (variableResult.statementCount == 1) { - variables.add(variableResult.statement as VariableDeclaration); + variables.add(variableResult.statement as VariableStatement); } else { for (Statement variable in variableResult.statements) { - variables.add(variable as VariableDeclaration); + variables.add(variable as VariableStatement); } } } // Coverage-ignore(suite): Not run. else if (variables != null) { - variables.add(variable); + variables.add(variableStatement); } } } @@ -4999,7 +5006,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase )..fileOffset = node.fileOffset, receiverType, ); - body = [result]; + body = [extern.createVariableStatement(result)]; // Add the elements up to the first non-expression. for (int j = 0; j < index; ++j) { _addExpressionElement( @@ -5024,7 +5031,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); } } - body ??= [result]; + body ??= [extern.createVariableStatement(result)]; // Translate the elements starting with the first non-expression. for (; index < elements.length; ++index) { _translateElement( @@ -5317,7 +5324,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase // Coverage-ignore(suite): Not run. ?.registerAlias(element, loop); body.add(element.patternVariableDeclaration); - body.addAll(element.intermediateVariables); + for (VariableDeclaration intermediateVariable + in element.intermediateVariables) { + body.add(extern.createVariableStatement(intermediateVariable)); + } body.add(loop); } @@ -5394,7 +5404,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase value, typeSchemaEnvironment.iterableType(elementType, Nullability.nullable), ); - body.add(temp); + body.add(extern.createVariableStatement(temp)); value = _createNullCheckedVariableGet(temp); } @@ -5428,7 +5438,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase Nullability.nullable, ), ); - body.add(temp); + body.add(extern.createVariableStatement(temp)); value = _createNullCheckedVariableGet(temp); } @@ -5445,7 +5455,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase elementType, ); Statement loopBody = _createBlock([ - castedVar, + extern.createVariableStatement(castedVar), _createExpressionStatement( _createAdd( // Don't make a mess of jumping around (and make scope building @@ -5505,7 +5515,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase Nullability.nullable, ); VariableDeclaration temp = _createVariable(value, nullableElementType); - body.add(temp); + body.add(extern.createVariableStatement(temp)); Statement statement = _createIf( temp.fileOffset, @@ -5622,14 +5632,14 @@ class InferenceVisitorImpl extends InferenceVisitorBase _createMapLiteral(node.fileOffset, node.keyType, node.valueType, []), receiverType, ); - body = [result]; + body = [extern.createVariableStatement(result)]; // Add all the entries up to the first control-flow entry. for (int j = 0; j < index; ++j) { _addNormalEntry(node.entries[j], receiverType, result, body); } } - body ??= [result]; + body ??= [extern.createVariableStatement(result)]; // Translate the elements starting with the first non-expression. for (; index < node.entries.length; ++index) { @@ -5919,7 +5929,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase // Coverage-ignore(suite): Not run. ?.registerAlias(entry, loop); body.add(entry.patternVariableDeclaration); - body.addAll(entry.intermediateVariables); + for (VariableDeclaration intermediateVariable + in entry.intermediateVariables) { + body.add(extern.createVariableStatement(intermediateVariable)); + } body.add(loop); } @@ -6007,7 +6020,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase Nullability.nullable, ), ); - body.add(temp); + body.add(extern.createVariableStatement(temp)); value = _createNullCheckedVariableGet(temp); } @@ -6041,7 +6054,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase Nullability.nullable, ), ); - body.add(temp); + body.add(extern.createVariableStatement(temp)); value = _createNullCheckedVariableGet(temp); } @@ -6079,8 +6092,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase valueType, ); Statement loopBody = _createBlock([ - keyVar, - valueVar, + extern.createVariableStatement(keyVar), + extern.createVariableStatement(valueVar), _createExpressionStatement( _createIndexSet( entry.expression.fileOffset, @@ -6169,8 +6182,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); addedEntryStatementParent ??= ifValueNotNullStatement; - desugaredStatement = _createBlock([valueTemp, ifValueNotNullStatement]) - ..fileOffset = entry.fileOffset; + desugaredStatement = _createBlock([ + extern.createVariableStatement(valueTemp), + ifValueNotNullStatement, + ])..fileOffset = entry.fileOffset; } if (entry.isKeyNullAware) { @@ -6190,8 +6205,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); addedEntryStatementParent ??= ifKeyNotNullStatement; - desugaredStatement = _createBlock([keyTemp, ifKeyNotNullStatement]) - ..fileOffset = entry.fileOffset; + desugaredStatement = _createBlock([ + extern.createVariableStatement(keyTemp), + ifKeyNotNullStatement, + ])..fileOffset = entry.fileOffset; } else if (entry.isValueNullAware) { assert(!entry.isKeyNullAware); // The key is non null-aware, but the value is null-aware. In this case, @@ -6222,7 +6239,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase VariableDeclaration keyTemp = _createVariable(keyExpression, keyType); keyExpression = _createVariableGet(keyTemp); - desugaredStatement.statements.insert(0, keyTemp); + desugaredStatement.statements.insert( + 0, + extern.createVariableStatement(keyTemp), + ); keyTemp.parent = desugaredStatement; } @@ -6877,7 +6897,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase ForStatement _createForStatement( int fileOffset, - List variables, + List variables, Expression? condition, List updates, Statement body, @@ -7497,7 +7517,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase ).expression..parent = intermediateVariable; intermediateVariable.type = type; - entry.variables[i].type = type; + entry.variables[i].variable.type = type; } return _inferForMapEntryBase( @@ -7553,9 +7573,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase _MapLiteralEntryOffsets offsets, ) { // TODO(johnniwinther): Use _visitStatements instead. - List? variables; + List? variables; for (int index = 0; index < entry.variables.length; index++) { - VariableDeclaration variable = entry.variables[index]; + VariableStatement variableStatement = entry.variables[index]; + VariableDeclaration variable = variableStatement.variable; if (variable.name == null) { if (variable.initializer != null) { ExpressionInferenceResult result = inferExpression( @@ -7567,24 +7588,26 @@ class InferenceVisitorImpl extends InferenceVisitorBase variable.type = result.inferredType; } } else { - StatementInferenceResult variableResult = inferStatement(variable); + StatementInferenceResult variableResult = inferStatement( + variableStatement, + ); if (variableResult.hasChanged) { // Coverage-ignore-block(suite): Not run. if (variables == null) { - variables = []; + variables = []; variables.addAll(entry.variables.sublist(0, index)); } if (variableResult.statementCount == 1) { - variables.add(variableResult.statement as VariableDeclaration); + variables.add(variableResult.statement as VariableStatement); } else { for (Statement variable in variableResult.statements) { - variables.add(variable as VariableDeclaration); + variables.add(variable as VariableStatement); } } } // Coverage-ignore(suite): Not run. else if (variables != null) { - variables.add(variable); + variables.add(variableStatement); } } } @@ -12533,7 +12556,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); // Now create a list of all statements needed. - List statements = [setVar]; + List statements = [extern.createVariableStatement(setVar)]; for (int i = 0; i < node.expressions.length; i++) { Expression entry = node.expressions[i]; DartType functionType = Substitution.fromInterfaceType( @@ -13402,6 +13425,29 @@ class InferenceVisitorImpl extends InferenceVisitorBase } @override + StatementInferenceResult visitLegacyVariableStatement( + LegacyVariableStatement node, + ) { + InternalVariable nodeVariable = node.variable as InternalVariable; + StatementInferenceResult statementInferenceResult = + _inferInternalExpressionVariableDeclaration( + node.variable, + nodeVariable, + variableStatement: node, + ); + node.variable = nodeVariable.astVariable; + if (isClosureContextLoweringEnabled) { + // Coverage-ignore-block(suite): Not run. + _contextAllocationStrategy.handleDeclarationOfVariable( + node.variable, + captureKind: _captureKindForVariable(node.variable), + ); + } + return statementInferenceResult; + } + + @override + // Coverage-ignore(suite): Not run. StatementInferenceResult visitVariableDeclaration( covariant VariableDeclarationImpl node, ) { @@ -16760,7 +16806,11 @@ class InferenceVisitorImpl extends InferenceVisitorBase ) { InternalVariable nodeVariable = node.variable as InternalVariable; StatementInferenceResult statementInferenceResult = - _inferInternalExpressionVariableDeclaration(node, nodeVariable); + _inferInternalExpressionVariableDeclaration( + node.variable, + nodeVariable, + variableStatement: node, + ); node.variable = nodeVariable.astVariable; if (isClosureContextLoweringEnabled) { _contextAllocationStrategy.handleDeclarationOfVariable( @@ -16773,8 +16823,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase StatementInferenceResult _inferInternalExpressionVariableDeclaration( VariableDeclaration node, - InternalVariable nodeVariable, - ) { + InternalVariable nodeVariable, { + VariableStatement? variableStatement, + }) { DartType declaredType = nodeVariable.isImplicitlyTyped ? const UnknownType() : node.type; @@ -16785,7 +16836,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase // for loops, const variables, and late variables. This logic turns them // into `ExpressionStatement`s or `EmptyStatement`s so the backends don't // need to allocate space for them. - if (node.isWildcard && !node.isConst && node.parent is! ForStatement) { + if (node.isWildcard && + !node.isConst && + node.parent?.parent is! ForStatement) { if (node.initializer case var initializer? when !node.isLate) { return new StatementInferenceResult.single( createExpressionStatement( @@ -16871,7 +16924,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase int fileOffset = node.fileOffset; List result = []; - result.add(node); + result.add( + variableStatement ?? // Coverage-ignore(suite): Not run. + extern.createVariableStatement(node), + ); late_lowering.IsSetEncoding isSetEncoding = late_lowering .computeIsSetEncoding( @@ -16886,7 +16942,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase type: coreTypes.boolRawType(Nullability.nonNullable), isLowered: true, )..fileOffset = fileOffset; - result.add(isSetVariable); + result.add(extern.createVariableStatement(isSetVariable)); } Expression createVariableRead({bool needsPromotion = false}) { diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart b/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart index d188701240f..add668f9f18 100644 --- a/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart +++ b/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart @@ -4990,11 +4990,11 @@ abstract class InferenceVisitorBase implements InferenceVisitor { if (value is! VariableGet) return false; if (expression.body.statements.isEmpty) return false; Statement first = expression.body.statements.first; - if (first is! VariableDeclaration) return false; - Expression? initializer = first.initializer; + if (first is! VariableStatement) return false; + Expression? initializer = first.variable.initializer; if (initializer is! StaticInvocation) return false; if (initializer.target != engine.setFactory) return false; - return value.variable == first; + return value.variable == first.variable; } /// Determines if the given [expression]'s type is precisely known at compile diff --git a/pkg/front_end/lib/src/type_inference/matching_cache.dart b/pkg/front_end/lib/src/type_inference/matching_cache.dart index 0aec636f303..01d3a8a071a 100644 --- a/pkg/front_end/lib/src/type_inference/matching_cache.dart +++ b/pkg/front_end/lib/src/type_inference/matching_cache.dart @@ -49,7 +49,7 @@ class MatchingCache { bool _isClosed = false; /// The declarations need for the cached expressions. - List _declarations = []; + List _declarations = []; /// Map for the known cached keys and their corresponding expressions. Map _cacheKeyMap = {}; @@ -166,7 +166,7 @@ class MatchingCache { /// Registers that the variable or local function [declaration] is need for /// the cached expressions. - void registerDeclaration(Statement declaration) { + void registerDeclaration(VariableDeclaration declaration) { assert(!_isClosed); _declarations.add(declaration); } @@ -176,7 +176,7 @@ class MatchingCache { /// /// Once called, the matching cache is closed and no new cacheable expressions /// can be created. - Iterable get declarations { + Iterable get declarations { _isClosed = true; return _declarations; } diff --git a/pkg/front_end/test/incremental_suite.dart b/pkg/front_end/test/incremental_suite.dart index 630ac96db17..b737162e728 100644 --- a/pkg/front_end/test/incremental_suite.dart +++ b/pkg/front_end/test/incremental_suite.dart @@ -2210,10 +2210,10 @@ class Strategy extends EquivalenceStrategy { } @override - bool checkVariableStatement_binaryOffsetNoTag( + bool checkLegacyVariable_binaryOffsetNoTag( EquivalenceVisitor visitor, - VariableDeclaration node, - VariableDeclaration other, + LegacyVariable node, + LegacyVariable other, ) { return true; } diff --git a/pkg/front_end/test/predicates/predicate_test.dart b/pkg/front_end/test/predicates/predicate_test.dart index 8e40f68ab2c..e45e47438ba 100644 --- a/pkg/front_end/test/predicates/predicate_test.dart +++ b/pkg/front_end/test/predicates/predicate_test.dart @@ -215,7 +215,7 @@ class PredicateDataExtractor extends CfeDataExtractor { } @override - void visitVariableDeclaration(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { Object? identity; String? name; String? tag; @@ -257,7 +257,7 @@ class PredicateDataExtractor extends CfeDataExtractor { features[Tags.name] = name; } } - super.visitVariableDeclaration(node); + super.defaultVariableDeclaration(node); } @override diff --git a/pkg/front_end/test/static_types/type_arguments_test.dart b/pkg/front_end/test/static_types/type_arguments_test.dart index 8fc3bd834f4..dcd21e9e48a 100644 --- a/pkg/front_end/test/static_types/type_arguments_test.dart +++ b/pkg/front_end/test/static_types/type_arguments_test.dart @@ -65,12 +65,10 @@ class TypeArgumentsVisitor extends VerifyingAnalysis { 'AssertStatement', uri: astUri, ); - InterfaceType variableDeclarationType = interface.createInterfaceType( - 'VariableDeclaration', + InterfaceType variableStatementType = interface.createInterfaceType( + 'VariableStatement', uri: astUri, ); - InterfaceType variableInitializationType = interface - .createInterfaceType('VariableDeclaration', uri: astUri); DartType typeArgument = receiver.arguments.types.single; if (interface.isSubtypeOf(typeArgument, expressionType) && typeArgument != expressionType) { @@ -93,28 +91,15 @@ class TypeArgumentsVisitor extends VerifyingAnalysis { } } else if (interface.isSubtypeOf( typeArgument, - variableDeclarationType, + variableStatementType, )) { // [VariableDeclaration] is used as an exclusive member of, for // instance, `FunctionNode.positionalParameters`. - if (typeArgument != variableDeclarationType) { + if (typeArgument != variableStatementType) { registerError( node, "map().toList() with type argument " - "${typeArgument} instead of ${variableDeclarationType}", - ); - } - } else if (interface.isSubtypeOf( - typeArgument, - variableInitializationType, - )) { - // [VariableInitialization] is used as an exclusive member of, for - // instance, `ForStatement.variableInitializations`. - if (typeArgument != variableInitializationType) { - registerError( - node, - "map().toList() with type argument " - "${typeArgument} instead of ${variableInitializationType}", + "${typeArgument} instead of ${variableStatementType}", ); } } else if (typeArgument != statementType) { diff --git a/pkg/front_end/test/testing/suite.dart b/pkg/front_end/test/testing/suite.dart index e13de588e28..17ec5d37510 100644 --- a/pkg/front_end/test/testing/suite.dart +++ b/pkg/front_end/test/testing/suite.dart @@ -80,8 +80,8 @@ import 'package:kernel/ast.dart' TreeNode, Typedef, UnevaluatedConstant, - VariableDeclaration, - Version; + Version, + LegacyVariable; import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter; import 'package:kernel/class_hierarchy.dart' show ClassHierarchy; import 'package:kernel/core_types.dart' show CoreTypes; @@ -1713,10 +1713,10 @@ class Strategy extends EquivalenceStrategy { } @override - bool checkVariableStatement_binaryOffsetNoTag( + bool checkLegacyVariable_binaryOffsetNoTag( EquivalenceVisitor visitor, - VariableDeclaration node, - VariableDeclaration other, + LegacyVariable node, + LegacyVariable other, ) { return true; } diff --git a/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart b/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart index 8cb4f904236..a1524db2abe 100644 --- a/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart +++ b/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart @@ -46,6 +46,29 @@ void testStatement( ); } +void testVariableDeclaration( + VariableDeclaration node, + String normal, { + String? verbose, + String? limited, +}) { + Expect.stringEquals( + normal, + node.toText(normalStrategy), + "Unexpected normal strategy text for ${node.runtimeType}", + ); + Expect.stringEquals( + verbose ?? normal, + node.toText(verboseStrategy), + "Unexpected verbose strategy text for ${node.runtimeType}", + ); + Expect.stringEquals( + limited ?? normal, + node.toText(limitedStrategy), + "Unexpected limited strategy text for ${node.runtimeType}", + ); +} + void testExpression( Expression node, String normal, { @@ -201,16 +224,20 @@ void main() { void _testVariableDeclarations() { testStatement( forest.variablesDeclaration([ - new VariableDeclaration('a'), - new VariableDeclaration('b'), + new VariableStatement(new VariableDeclaration('a')), + new VariableStatement(new VariableDeclaration('b')), ], dummyUri), ''' dynamic a, b;''', ); testStatement( forest.variablesDeclaration([ - new VariableDeclaration('a', type: const VoidType()), - new VariableDeclaration('b', initializer: new NullLiteral()), + new VariableStatement( + new VariableDeclaration('a', type: const VoidType()), + ), + new VariableStatement( + new VariableDeclaration('b', initializer: new NullLiteral()), + ), ], dummyUri), ''' void a, b = null;''', @@ -348,7 +375,9 @@ void _testInternalForInStatement() { testStatement( new InternalForInStatement( new SingleVariableDeclarationForInElement( - variableDeclaration: new VariableDeclarationImpl('e', fileOffset: -1), + variableStatement: new LegacyVariableStatement( + new VariableDeclarationImpl('e', fileOffset: -1), + ), error: null, ), new NullLiteral(), @@ -364,10 +393,12 @@ for (var e in null) {}''', testStatement( new InternalForInStatement( new SingleVariableDeclarationForInElement( - variableDeclaration: new VariableDeclarationImpl( - 'e', - type: const VoidType(), - fileOffset: -1, + variableStatement: new LegacyVariableStatement( + new VariableDeclarationImpl( + 'e', + type: const VoidType(), + fileOffset: -1, + ), ), error: null, ), @@ -497,8 +528,12 @@ for (null in null) {}''', new InternalForInStatement( new MultiVariableDeclarationForInElement( variableDeclarations: [ - new VariableDeclarationImpl('a', fileOffset: -1), - new VariableDeclarationImpl('b', fileOffset: -1), + new VariableStatement( + new VariableDeclarationImpl('a', fileOffset: -1), + ), + new VariableStatement( + new VariableDeclarationImpl('b', fileOffset: -1), + ), ], error: new InvalidExpression('error'), ), @@ -516,12 +551,16 @@ for (var a, b in null) {}''', new InternalForInStatement( new MultiVariableDeclarationForInElement( variableDeclarations: [ - new VariableDeclarationImpl( - 'a', - type: const VoidType(), - fileOffset: -1, + new VariableStatement( + new VariableDeclarationImpl( + 'a', + type: const VoidType(), + fileOffset: -1, + ), + ), + new VariableStatement( + new VariableDeclarationImpl('b', fileOffset: -1), ), - new VariableDeclarationImpl('b', fileOffset: -1), ], error: new InvalidExpression('error'), ), @@ -1395,21 +1434,21 @@ return 0;'''); } void _testVariableDeclarationImpl() { - testStatement( + testVariableDeclaration( new VariableDeclarationImpl('foo', fileOffset: TreeNode.noOffset), ''' -dynamic foo;''', +dynamic foo''', ); - testStatement( + testVariableDeclaration( new VariableDeclarationImpl( 'foo', initializer: new IntLiteral(0), fileOffset: TreeNode.noOffset, ), ''' -dynamic foo = 0;''', +dynamic foo = 0''', ); - testStatement( + testVariableDeclaration( new VariableDeclarationImpl( 'foo', type: const VoidType(), @@ -1419,9 +1458,9 @@ dynamic foo = 0;''', fileOffset: TreeNode.noOffset, ), ''' -required final void foo;''', +required final void foo''', ); - testStatement( + testVariableDeclaration( new VariableDeclarationImpl( 'foo', type: const VoidType(), @@ -1430,9 +1469,9 @@ required final void foo;''', fileOffset: TreeNode.noOffset, ), ''' -late void foo = 0;''', +late void foo = 0''', ); - testStatement( + testVariableDeclaration( new VariableDeclarationImpl( 'foo', type: const VoidType(), @@ -1444,9 +1483,9 @@ late void foo = 0;''', fileOffset: TreeNode.noOffset, ), ''' -late void foo = 0;''', +late void foo = 0''', ); - testStatement( + testVariableDeclaration( new VariableDeclarationImpl( 'foo', type: const VoidType(), @@ -1459,7 +1498,7 @@ late void foo = 0;''', ) ..lateType = const DynamicType(), ''' -late dynamic foo = 0;''', +late dynamic foo = 0''', ); } diff --git a/pkg/front_end/testcases/closure_context_lowering/synthetic_variables.dart.strong.expect b/pkg/front_end/testcases/closure_context_lowering/synthetic_variables.dart.strong.expect index 2d4352ed503..0eedf765112 100644 --- a/pkg/front_end/testcases/closure_context_lowering/synthetic_variables.dart.strong.expect +++ b/pkg/front_end/testcases/closure_context_lowering/synthetic_variables.dart.strong.expect @@ -14,7 +14,7 @@ static method test(positional-parameter list) → dynamic/* scope=[ s := ""; for /* scope=[ #ctx3: not-captured VariableContext([ - SyntheticVariable + synthetic-variable #t1; ]), ] */ (synthetic-variable #t1 in list) { s = #t1; diff --git a/pkg/front_end/testcases/closure_context_lowering/synthetic_variables.dart.strong.modular.expect b/pkg/front_end/testcases/closure_context_lowering/synthetic_variables.dart.strong.modular.expect index 2d4352ed503..0eedf765112 100644 --- a/pkg/front_end/testcases/closure_context_lowering/synthetic_variables.dart.strong.modular.expect +++ b/pkg/front_end/testcases/closure_context_lowering/synthetic_variables.dart.strong.modular.expect @@ -14,7 +14,7 @@ static method test(positional-parameter list) → dynamic/* scope=[ s := ""; for /* scope=[ #ctx3: not-captured VariableContext([ - SyntheticVariable + synthetic-variable #t1; ]), ] */ (synthetic-variable #t1 in list) { s = #t1; diff --git a/pkg/front_end/testcases/modular.status b/pkg/front_end/testcases/modular.status index 37bbc147126..7a635f042c7 100644 --- a/pkg/front_end/testcases/modular.status +++ b/pkg/front_end/testcases/modular.status @@ -30,7 +30,7 @@ closure_context_lowering/foo45: Crash closure_context_lowering/foo48: Crash closure_context_lowering/assert_captured_variables: Crash closure_context_lowering/late_variable_initializers: Crash -closure_context_lowering/catch_variables: Crash +closure_context_lowering/catch_variables: ExpectationFileMismatchSerialized closure_context_lowering/synthetic_variables: Crash closure_context_lowering/assert_captured_variables: ExpectationFileMismatchSerialized closure_context_lowering/constructor_initializers: ExpectationFileMismatchSerialized diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status index bba943fdade..18e12cddf25 100644 --- a/pkg/front_end/testcases/strong.status +++ b/pkg/front_end/testcases/strong.status @@ -267,9 +267,8 @@ closure_context_lowering/loop_depth_strategy: Crash closure_context_lowering/foo42: Crash closure_context_lowering/foo45: Crash closure_context_lowering/foo48: Crash -closure_context_lowering/assert_captured_variables: Crash closure_context_lowering/late_variable_initializers: Crash -closure_context_lowering/catch_variables: Crash +closure_context_lowering/catch_variables: ExpectationFileMismatchSerialized closure_context_lowering/synthetic_variables: Crash closure_context_lowering/assert_captured_variables: ExpectationFileMismatchSerialized closure_context_lowering/constructor_initializers: ExpectationFileMismatchSerialized diff --git a/pkg/front_end/tool/ast_model.dart b/pkg/front_end/tool/ast_model.dart index a3d0a0e8ac5..664f7598893 100644 --- a/pkg/front_end/tool/ast_model.dart +++ b/pkg/front_end/tool/ast_model.dart @@ -32,7 +32,7 @@ Uri computePackageConfig(Uri repoDir) => /// defining its identity. const Map _declarativeClassesNames = const { // TODO(johnniwinther): This should be [VariableDeclaration]. - 'VariableStatement': 'name', + 'LegacyVariable': 'name', 'TypeParameter': 'name', 'StructuralParameter': 'name', 'LabeledStatement': null, @@ -151,7 +151,7 @@ const Map> _fieldRuleMap = { 'SyntheticVariable': { 'variableInitialization': FieldRule(isDeclaration: false), }, - 'VariableStatement': {'_name': FieldRule(name: 'name')}, + 'LegacyVariable': {'_name': FieldRule(name: 'name')}, 'AssignedVariablePattern': {'variable': FieldRule(isDeclaration: false)}, 'InvalidPattern': {'declaredVariables': FieldRule(isDeclaration: true)}, 'OrPattern': {'orPatternJointVariables': FieldRule(isDeclaration: false)}, diff --git a/pkg/front_end/tool/unreachable_if_finder.dart b/pkg/front_end/tool/unreachable_if_finder.dart index f7b0a4db103..94cf0e64db3 100644 --- a/pkg/front_end/tool/unreachable_if_finder.dart +++ b/pkg/front_end/tool/unreachable_if_finder.dart @@ -128,9 +128,9 @@ class EffectivelyFinal extends RecursiveVisitor { EffectivelyFinal._(); @override - void visitVariableDeclaration(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { unwritten.add(node); - super.visitVariableDeclaration(node); + super.defaultVariableDeclaration(node); } @override diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart index 04c4be82744..61637e5bca1 100644 --- a/pkg/kernel/lib/binary/ast_from_binary.dart +++ b/pkg/kernel/lib/binary/ast_from_binary.dart @@ -3726,7 +3726,7 @@ class BinaryBuilder { // 9.62% (6.92% - 12.64%). case Tag.VariableDeclaration: - return _readVariableDeclaration(); + return _readVariableStatement(); // 9.28% (6.69% - 11.18%). case Tag.EmptyStatement: @@ -3826,7 +3826,7 @@ class BinaryBuilder { Statement _readForStatement() { int variableStackHeight = variableStack.length; int offset = readOffset(); - List variables = readAndPushVariableDeclarationList(); + List variables = readAndPushVariableStatementList(); Expression? condition = readExpressionOption(); List updates = readExpressionList(); Statement body = readStatement(); @@ -3931,7 +3931,12 @@ class BinaryBuilder { )..fileOffset = offset; } - Statement _readVariableDeclaration() { + VariableStatement _readVariableStatement() { + VariableDeclaration variable = _readVariableDeclaration(); + return new VariableStatement(variable)..fileOffset = variable.fileOffset; + } + + VariableDeclaration _readVariableDeclaration() { VariableDeclaration variable = readVariableDeclaration(); variableStack.add(variable); // Will be popped by the enclosing scope. return variable; @@ -4427,6 +4432,16 @@ class BinaryBuilder { return new NamedExpression(readStringReference(), readExpression()); } + List readAndPushVariableStatementList() { + List list = readAndPushVariableDeclarationList(); + return new List.generate( + list.length, + (int index) => + new VariableStatement(list[index]) + ..fileOffset = list[index].fileOffset, + ); + } + List readAndPushVariableDeclarationList() { int length = readUInt30(); if (!useGrowableLists && length == 0) { diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart index c94bd1f1bd0..6385f2343d6 100644 --- a/pkg/kernel/lib/binary/ast_to_binary.dart +++ b/pkg/kernel/lib/binary/ast_to_binary.dart @@ -20,6 +20,7 @@ class BinaryPrinter TreeVisitorExperimentExclusionMixin, DartTypeVisitorExperimentExclusionMixin, StatementVisitorExperimentExclusionMixin, + VariableVisitorExperimentExclusionMixin, ExpressionVisitorExperimentExclusionMixin implements Visitor, BinarySink { final VariableIndexer Function() _newVariableIndexer; @@ -2358,7 +2359,7 @@ class BinaryPrinter variableIndexer.pushScope(); writeByte(Tag.ForStatement); writeOffset(node.fileOffset); - writeVariableDeclarationList(node.variables); + writeVariableStatementList(node.variables); writeOptionalNode(node.condition); writeNodeList(node.updates); writeNode(node.body); @@ -2480,6 +2481,10 @@ class BinaryPrinter writeVariableDeclaration(node); } + void writeVariableStatement(VariableStatement node) { + writeVariableDeclaration(node.variable); + } + void writeVariableDeclaration(VariableDeclaration node) { if (_metadataSubsections != null) { _writeNodeMetadata(node); @@ -2497,6 +2502,10 @@ class BinaryPrinter (_variableIndexer ??= _newVariableIndexer()).declare(node); } + void writeVariableStatementList(List nodes) { + writeList(nodes, writeVariableStatement); + } + void writeVariableDeclarationList(List nodes) { writeList(nodes, writeVariableDeclaration); } diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart index 3e5ea9af643..907db1a5743 100644 --- a/pkg/kernel/lib/clone.dart +++ b/pkg/kernel/lib/clone.dart @@ -607,7 +607,7 @@ class CloneVisitorNotMembers @override TreeNode visitForStatement(ForStatement node) { - List variables = node.variables.map(clone).toList(); + List variables = node.variables.map(clone).toList(); return new ForStatement( variables, cloneOptional(node.condition), @@ -792,10 +792,16 @@ class CloneVisitorNotMembers } @override - TreeNode visitVariableStatement(VariableStatement node) { + TreeNode visitLegacyVariableStatement(VariableStatement node) { + return new LegacyVariableStatement(clone(node.variable)) + ..fileOffset = _cloneFileOffset(node.fileOffset); + } + + @override + TreeNode visitLegacyVariable(LegacyVariable node) { return setVariableClone( node, - new VariableStatement( + new LegacyVariable( node.name, initializer: cloneOptional(node.initializer), type: visitType(node.type), @@ -821,8 +827,7 @@ class CloneVisitorNotMembers ..flags = node.flags ..annotations = cloneAnnotations && !node.annotations.isEmpty ? node.annotations.map(clone).toList() - : const [] - ..fileEqualsOffset = _cloneFileOffset(node.fileEqualsOffset); + : const []; } @override diff --git a/pkg/kernel/lib/src/ast/components.dart b/pkg/kernel/lib/src/ast/components.dart index 8086702d6fd..49557bb614a 100644 --- a/pkg/kernel/lib/src/ast/components.dart +++ b/pkg/kernel/lib/src/ast/components.dart @@ -368,6 +368,8 @@ abstract class MetadataRepository { static bool isSupported(Node node) { return !(node is MapLiteralEntry || node is Catch || - (node is Block && node.parent is BlockExpression)); + (node is Block && node.parent is BlockExpression) || + // TODO(johnniwinther): Support + node is LegacyVariableStatement); } } diff --git a/pkg/kernel/lib/src/ast/dummies.dart b/pkg/kernel/lib/src/ast/dummies.dart index b0cb53efa20..a1eb579e935 100644 --- a/pkg/kernel/lib/src/ast/dummies.dart +++ b/pkg/kernel/lib/src/ast/dummies.dart @@ -472,6 +472,15 @@ final List emptyListOfMapPatternEntry = List.filled( growable: false, ); +/// Non-nullable [VariableStatement] dummy value. +/// +/// This is used as the removal sentinel in [RemovingTransformer] and can be +/// used for instance as a dummy initial value for the `List.filled` +/// constructor. +final VariableStatement dummyVariableStatement = new VariableStatement( + dummyVariableDeclaration, +); + /// Non-nullable [VariableDeclaration] dummy value. /// /// This is used as the removal sentinel in [RemovingTransformer] and can be diff --git a/pkg/kernel/lib/src/ast/statements.dart b/pkg/kernel/lib/src/ast/statements.dart index 8c62e39040a..e12626cc220 100644 --- a/pkg/kernel/lib/src/ast/statements.dart +++ b/pkg/kernel/lib/src/ast/statements.dart @@ -539,10 +539,10 @@ class DoStatement extends Statement implements LoopStatement { class ForStatement extends Statement implements LoopStatement, ScopeProvider { // May be empty, but not null. - final List variables; + final List variables; // TODO(61572): Remove this. - List get variableInitializations => variables; + List get variableInitializations => variables; Expression? condition; // May be null. final List updates; // May be empty, but not null. @@ -589,7 +589,7 @@ class ForStatement extends Statement implements LoopStatement, ScopeProvider { @override void transformOrRemoveChildren(RemovingTransformer v) { - v.transformVariableDeclarationList(variables, this); + v.transformStatementList(variables, this); if (condition != null) { condition = v.transformOrRemoveExpression(condition!); condition?.parent = this; @@ -612,7 +612,7 @@ class ForStatement extends Statement implements LoopStatement, ScopeProvider { printer.write(', '); } printer.writeVariableInitialization( - variables[index], + variables[index].variable, includeModifiersAndType: index == 0, ); } @@ -1459,6 +1459,7 @@ class YieldStatement extends Statement { } } +// TODO(johnniwinther): Move this to `variables.dart`. /// Declaration of a local variable. /// /// This may occur as a statement, but is also used in several non-statement @@ -1467,8 +1468,8 @@ class YieldStatement extends Statement { /// When this occurs as a statement, it must be a direct child of a [Block]. // // DESIGN TODO: Should we remove the 'final' modifier from variables? -class VariableStatement extends Statement - implements Annotatable, VariableDeclaration { +class LegacyVariable extends TreeNode + implements VariableDeclaration, Annotatable { /// Offset of the equals sign in the source file it comes from. /// /// Valid values are from 0 and up, or -1 ([TreeNode.noOffset]) @@ -1511,7 +1512,7 @@ class VariableStatement extends Statement @override Expression? initializer; // May be null. - VariableStatement( + LegacyVariable( this._name, { this.initializer, this.type = const DynamicType(), @@ -1553,7 +1554,7 @@ class VariableStatement extends Statement } /// Creates a synthetic variable with the given expression as initializer. - VariableStatement.forValue( + LegacyVariable.forValue( this.initializer, { bool isFinal = true, bool isConst = false, @@ -1648,7 +1649,7 @@ class VariableStatement extends Statement @override bool get isErroneouslyInitialized => flags & FlagErroneouslyInitialized != 0; - /// If this [LegacyVariableDeclaration] is a parameter of a method, indicates + /// If this [LegacyVariable] is a parameter of a method, indicates /// whether the method implementation needs to contain a runtime type check to /// deal with generic covariance. /// @@ -1827,11 +1828,11 @@ class VariableStatement extends Statement } @override - R accept(StatementVisitor v) => v.visitVariableStatement(this); + R accept(VariableVisitor v) => v.visitLegacyVariable(this); @override - R accept1(StatementVisitor1 v, A arg) => - v.visitVariableStatement(this, arg); + R accept1(VariableVisitor1 v, A arg) => + v.visitLegacyVariable(this, arg); @override void visitChildren(Visitor v) { @@ -1889,13 +1890,13 @@ class VariableStatement extends Statement } @override - VariableDeclaration? get variableInitialization { + VariableInitialization? get variableInitialization { throw new UnsupportedError("${this.runtimeType}.variableInitialization"); } @override - void set variableInitialization(VariableDeclaration? value) { - throw new UnsupportedError("${this.runtimeType}.variableInitialization="); + void set variableInitialization(VariableInitialization? value) { + throw new UnsupportedError("${this.runtimeType}.variableInitialization"); } @override @@ -1962,6 +1963,73 @@ class VariableStatement extends Statement bool get hasIsWildcard => true; } +/// Declaration of a local variable. +abstract class VariableStatement extends Statement { + /// The declared variable. + abstract final VariableDeclaration variable; + + /// The declared initializer, if any. + abstract Expression? initializer; + + factory VariableStatement(VariableDeclaration variable) = + LegacyVariableStatement; +} + +/// Declaration of a local variable. +class LegacyVariableStatement extends Statement implements VariableStatement { + /// The declared variable. + @override + VariableDeclaration variable; + + LegacyVariableStatement(this.variable) { + variable.parent = this; + } + + @override + Expression? get initializer => variable.initializer; + + @override + void set initializer(Expression? value) { + variable.initializer = value; + } + + @override + R accept(StatementVisitor v) => v.visitLegacyVariableStatement(this); + + @override + R accept1(StatementVisitor1 v, A arg) => + v.visitLegacyVariableStatement(this, arg); + + @override + void visitChildren(Visitor v) { + variable.accept(v); + } + + @override + void transformChildren(Transformer v) { + variable = v.transform(variable)..parent = this; + } + + @override + void transformOrRemoveChildren(RemovingTransformer v) { + variable = v.transformOrRemove(variable, cannotRemoveSentinel)! + ..parent = this; + } + + /// Returns a possibly synthesized name for this variable, consistent with + /// the names used across all [toString] calls. + @override + String toString() { + return "VariableStatement(${toStringInternal()})"; + } + + @override + void toTextInternal(AstPrinter printer) { + printer.writeVariableInitialization(variable); + printer.write(';'); + } +} + /// Declaration a local function. /// /// The body of the function may use [variable] as its self-reference. @@ -2025,7 +2093,8 @@ class FunctionDeclaration extends Statement implements LocalFunction { } } -class VariableInitialization extends Statement implements VariableDeclaration { +class VariableInitialization extends Statement + implements VariableStatement, ContextConsumer { @override VariableDeclaration variable; @@ -2050,125 +2119,24 @@ class VariableInitialization extends Statement implements VariableDeclaration { static const int FlagHasDeclaredInitializer = 1 << 0; static const int FlagErroneouslyInitialized = 1 << 1; - @override int flags = 0; - @override bool get hasDeclaredInitializer => flags & FlagHasDeclaredInitializer != 0; - @override void set hasDeclaredInitializer(bool value) { flags = value ? (flags | FlagHasDeclaredInitializer) : (flags & ~FlagHasDeclaredInitializer); } - @override bool get isErroneouslyInitialized => flags & FlagErroneouslyInitialized != 0; - @override void set isErroneouslyInitialized(bool value) { flags = value ? (flags | FlagErroneouslyInitialized) : (flags & ~FlagErroneouslyInitialized); } - @override - bool get isConst => variable.isConst; - - @override - void set isConst(bool value) { - variable.isConst = value; - } - - @override - bool get isCovariantByClass => variable.isCovariantByClass; - - @override - void set isCovariantByClass(bool value) { - variable.isCovariantByClass = value; - } - - @override - bool get isCovariantByDeclaration => variable.isCovariantByDeclaration; - - @override - void set isCovariantByDeclaration(bool value) { - variable.isCovariantByDeclaration = value; - } - - @override - bool get isFinal => variable.isFinal; - - @override - void set isFinal(bool value) { - variable.isFinal = value; - } - - @override - bool get isHoisted => variable.isHoisted; - - @override - void set isHoisted(bool value) { - variable.isHoisted = value; - } - - @override - bool get isInitializingFormal => variable.isInitializingFormal; - - @override - void set isInitializingFormal(bool value) { - variable.isInitializingFormal = value; - } - - @override - bool get isLate => variable.isLate; - - @override - void set isLate(bool value) { - variable.isLate = value; - } - - @override - bool get isLowered => variable.isLowered; - - @override - void set isLowered(bool value) { - variable.isLowered = value; - } - - @override - bool get isRequired => variable.isRequired; - - @override - void set isRequired(bool value) { - variable.isRequired = value; - } - - @override - bool get isSuperInitializingFormal => variable.isSuperInitializingFormal; - - @override - void set isSuperInitializingFormal(bool value) { - variable.isSuperInitializingFormal = value; - } - - @override - bool get isSynthesized => variable.isSynthesized; - - @override - void set isSynthesized(bool value) { - variable.isSynthesized = value; - } - - @override - bool get isWildcard => variable.isWildcard; - - @override - void set isWildcard(bool value) { - variable.isWildcard = value; - } - @override R accept(StatementVisitor v) => v.visitVariableInitialization(this); @@ -2178,8 +2146,7 @@ class VariableInitialization extends Statement implements VariableDeclaration { @override void transformChildren(Transformer v) { - // Note that [variable] is not owned by [VariableInitialization], so it's - // not visited. + variable = v.transform(variable)..parent = this; v.transformList(annotations, this); if (initializer != null) { initializer = v.transform(initializer!); @@ -2189,8 +2156,8 @@ class VariableInitialization extends Statement implements VariableDeclaration { @override void transformOrRemoveChildren(RemovingTransformer v) { - // Note that [variable] is not owned by [VariableInitialization], so it's - // not visited. + variable = v.transformOrRemove(variable, cannotRemoveSentinel)! + ..parent = this; v.transformExpressionList(annotations, this); if (initializer != null) { initializer = v.transformOrRemoveExpression(initializer!); @@ -2200,8 +2167,7 @@ class VariableInitialization extends Statement implements VariableDeclaration { @override void visitChildren(Visitor v) { - // Note that [variable] is not owned by [VariableInitialization], so it's - // not visited. + variable.accept(v); visitList(annotations, v); initializer?.accept(v); } @@ -2221,32 +2187,8 @@ class VariableInitialization extends Statement implements VariableDeclaration { printer.write(';'); } - @override List annotations = const []; - @override - int binaryOffsetNoTag = TreeNode.noOffset; - - @override - int fileEqualsOffset = TreeNode.noOffset; - - @override - String? get name => variable.cosmeticName; - - @override - void set name(String? value) { - variable.cosmeticName = value; - } - - @override - DartType get type => variable.type; - - @override - void set type(DartType value) { - variable.type = value; - } - - @override void addAnnotation(Expression node) { if (annotations.isEmpty) { annotations = []; @@ -2254,142 +2196,7 @@ class VariableInitialization extends Statement implements VariableDeclaration { annotations.add(node..parent = this); } - @override void clearAnnotations() { annotations = const []; } - - @override - bool get isAssignable => variable.isAssignable; - - @override - String? get cosmeticName => variable.cosmeticName; - - @override - void set cosmeticName(String? value) { - variable.cosmeticName = value; - } - - @override - VariableDeclaration? get variableInitialization => this; - - @override - void set variableInitialization(VariableDeclaration? value) { - throw new UnsupportedError("${this.runtimeType}"); - } - - @override - VariableDeclaration get asVariableDeclaration => variable; - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - VariableContext get context { - throw UnsupportedError("${runtimeType}.context"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - void set context(VariableContext value) { - throw UnsupportedError("${runtimeType}.context="); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasHasDeclaredInitializer { - throw UnsupportedError("${runtimeType}.hasHasDeclaredInitializer"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsConst { - throw new UnsupportedError("${runtimeType}.hasIsConst"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsCovariantByClass { - throw new UnsupportedError("${runtimeType}.hasIsCovariantByClass"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsCovariantByDeclaration { - throw new UnsupportedError("${runtimeType}.hasIsCovariantByDeclaration"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsErroneouslyInitialized { - throw new UnsupportedError("${runtimeType}.hasIsErroneouslyInitialized"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsFinal { - throw new UnsupportedError("${runtimeType}.hasIsFinal"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsHoisted { - throw new UnsupportedError("${runtimeType}.hasIsHoisted"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsInitializingFormal { - throw new UnsupportedError("${runtimeType}.hasIsInitializingFormal"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsLate { - throw new UnsupportedError("${runtimeType}.hasIsLate"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsLowered { - throw new UnsupportedError("${runtimeType}.hasIsLowered"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsRequired { - throw new UnsupportedError("${runtimeType}.hasIsRequired"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsSuperInitializingFormal { - throw new UnsupportedError("${runtimeType}.hasIsSuperInitializingFormal"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsSynthesized { - throw new UnsupportedError("${runtimeType}.hasIsSynthesized"); - } - - @override - // TODO(62620): Remove the method when the [VariableInitialization] stops - // implementing [VariableDeclaration]. - bool get hasIsWildcard { - throw new UnsupportedError("${runtimeType}.hasIsWildcard"); - } } diff --git a/pkg/kernel/lib/src/ast/variables.dart b/pkg/kernel/lib/src/ast/variables.dart index b2368c32f5f..382e3de9586 100644 --- a/pkg/kernel/lib/src/ast/variables.dart +++ b/pkg/kernel/lib/src/ast/variables.dart @@ -28,7 +28,7 @@ sealed class VariableBase extends TreeNode implements Annotatable { abstract interface class IVariable implements TreeNode { abstract DartType type; abstract String? cosmeticName; - abstract VariableDeclaration? variableInitialization; + abstract VariableInitialization? variableInitialization; abstract Expression? initializer; abstract VariableContext context; abstract bool isFinal; @@ -74,14 +74,14 @@ abstract interface class IVariable implements TreeNode { /// The root of the sealed hierarchy of non-type variables. sealed class VariableDeclaration extends VariableBase - implements IVariable, Statement, ContextConsumer { + implements IVariable, ContextConsumer { /// Static type of the variable. @override abstract DartType type; /// Initialization node for the variable, if available. @override - abstract VariableDeclaration? variableInitialization; + abstract VariableInitialization? variableInitialization; /// Derived from [variableInitialization], if available. @override @@ -136,7 +136,7 @@ sealed class VariableDeclaration extends VariableBase bool isHoisted, bool hasDeclaredInitializer, bool isWildcard, - }) = VariableStatement; + }) = LegacyVariable; factory VariableDeclaration.forValue( Expression? initializer, { @@ -148,7 +148,7 @@ sealed class VariableDeclaration extends VariableBase bool isRequired, bool isLowered, DartType type, - }) = VariableStatement.forValue; + }) = LegacyVariable.forValue; VariableDeclaration.empty(); @@ -188,6 +188,12 @@ sealed class VariableDeclaration extends VariableBase VariableDeclaration get asVariableDeclaration => this; abstract String? name; + + @override + R accept(VariableVisitor visitor); + + @override + R accept1(VariableVisitor1 visitor, A arg); } /// Local variables. They aren't Statements. A [LocalVariable] is "declared" in @@ -202,7 +208,7 @@ class LocalVariable extends VariableDeclaration { DartType type; @override - VariableDeclaration? variableInitialization; + VariableInitialization? variableInitialization; @override List annotations = const []; @@ -319,9 +325,8 @@ class LocalVariable extends VariableDeclaration { } @override - bool get hasDeclaredInitializer { - throw new UnsupportedError("${this.runtimeType}"); - } + bool get hasDeclaredInitializer => + variableInitialization!.hasDeclaredInitializer; @override void set hasDeclaredInitializer(bool value) { @@ -377,10 +382,10 @@ class LocalVariable extends VariableDeclaration { } @override - R accept(StatementVisitor v) => v.visitLocalVariable(this); + R accept(VariableVisitor v) => v.visitLocalVariable(this); @override - R accept1(StatementVisitor1 v, A arg) => + R accept1(VariableVisitor1 v, A arg) => v.visitLocalVariable(this, arg); @override @@ -538,12 +543,12 @@ class CatchVariable extends VariableDeclaration { } @override - VariableDeclaration? get variableInitialization { + VariableInitialization? get variableInitialization { throw new UnsupportedError("${this.runtimeType}.variableInitialization"); } @override - void set variableInitialization(VariableDeclaration? value) { + void set variableInitialization(VariableInitialization? value) { throw new UnsupportedError("${this.runtimeType}.variableInitialization="); } @@ -693,10 +698,10 @@ class CatchVariable extends VariableDeclaration { bool get isAssignable => false; @override - R accept(StatementVisitor v) => v.visitCatchVariable(this); + R accept(VariableVisitor v) => v.visitCatchVariable(this); @override - R accept1(StatementVisitor1 v, A arg) => + R accept1(VariableVisitor1 v, A arg) => v.visitCatchVariable(this, arg); @override @@ -719,9 +724,7 @@ class CatchVariable extends VariableDeclaration { } @override - Expression? get initializer { - throw new UnsupportedError("${this.runtimeType}.initializer"); - } + Expression? get initializer => null; @override void set initializer(Expression? value) { @@ -842,10 +845,10 @@ sealed class FunctionParameter extends VariableDeclaration { /// Function parameters don't have initializers, only default values. @override - VariableDeclaration? get variableInitialization => null; + VariableInitialization? get variableInitialization => null; @override - void set variableInitialization(VariableDeclaration? value) {} + void set variableInitialization(VariableInitialization? value) {} @override Expression? get initializer => defaultValue; @@ -1063,10 +1066,10 @@ class PositionalParameter extends FunctionParameter { } @override - R accept(StatementVisitor v) => v.visitPositionalParameter(this); + R accept(VariableVisitor v) => v.visitPositionalParameter(this); @override - R accept1(StatementVisitor1 v, A arg) => + R accept1(VariableVisitor1 v, A arg) => v.visitPositionalParameter(this, arg); @override @@ -1210,10 +1213,10 @@ class NamedParameter extends FunctionParameter { } @override - R accept(StatementVisitor v) => v.visitNamedParameter(this); + R accept(VariableVisitor v) => v.visitNamedParameter(this); @override - R accept1(StatementVisitor1 v, A arg) => + R accept1(VariableVisitor1 v, A arg) => v.visitNamedParameter(this, arg); @override @@ -1304,10 +1307,10 @@ class ThisVariable extends VariableDeclaration { void set cosmeticName(String? value) {} @override - VariableDeclaration? get variableInitialization => null; + VariableInitialization? get variableInitialization => null; @override - void set variableInitialization(VariableDeclaration? value) {} + void set variableInitialization(VariableInitialization? value) {} @override DartType type; @@ -1465,10 +1468,10 @@ class ThisVariable extends VariableDeclaration { } @override - R accept(StatementVisitor v) => v.visitThisVariable(this); + R accept(VariableVisitor v) => v.visitThisVariable(this); @override - R accept1(StatementVisitor1 v, A arg) => + R accept1(VariableVisitor1 v, A arg) => v.visitThisVariable(this, arg); @override @@ -1588,7 +1591,7 @@ class SyntheticVariable extends VariableDeclaration { DartType type; @override - VariableDeclaration? variableInitialization; + VariableInitialization? variableInitialization; // TODO(cstefantsova): Consider a throwing implementation instead. @override @@ -1741,10 +1744,10 @@ class SyntheticVariable extends VariableDeclaration { } @override - R accept(StatementVisitor v) => v.visitSyntheticVariable(this); + R accept(VariableVisitor v) => v.visitSyntheticVariable(this); @override - R accept1(StatementVisitor1 v, A arg) => + R accept1(VariableVisitor1 v, A arg) => v.visitSyntheticVariable(this, arg); @override diff --git a/pkg/kernel/lib/src/coverage.dart b/pkg/kernel/lib/src/coverage.dart index 32dfd84b190..c4998baf39d 100644 --- a/pkg/kernel/lib/src/coverage.dart +++ b/pkg/kernel/lib/src/coverage.dart @@ -956,8 +956,8 @@ class CoverageVisitor implements Visitor { } @override - void visitVariableStatement(VariableStatement node) { - visited.add(StatementKind.VariableStatement); + void visitLegacyVariableStatement(LegacyVariableStatement node) { + visited.add(StatementKind.LegacyVariableStatement); node.visitChildren(this); } @@ -985,6 +985,12 @@ class CoverageVisitor implements Visitor { node.visitChildren(this); } + @override + void visitLegacyVariable(LegacyVariable node) { + visited.add(NodeKind.LegacyVariable); + node.visitChildren(this); + } + @override void visitLocalVariable(LocalVariable node) { visited.add(VariableDeclarationKind.LocalVariable); @@ -1324,6 +1330,7 @@ enum NodeKind { Extension, ExtensionTypeDeclaration, FunctionNode, + LegacyVariable, Library, LibraryDependency, LibraryPart, @@ -1462,6 +1469,7 @@ enum StatementKind { IfCaseStatement, IfStatement, LabeledStatement, + LegacyVariableStatement, PatternSwitchStatement, PatternVariableDeclaration, ReturnStatement, @@ -1469,7 +1477,6 @@ enum StatementKind { TryCatch, TryFinally, VariableInitialization, - VariableStatement, WhileStatement, YieldStatement, } diff --git a/pkg/kernel/lib/src/equivalence.dart b/pkg/kernel/lib/src/equivalence.dart index 2b5249cd814..6ecaafd410e 100644 --- a/pkg/kernel/lib/src/equivalence.dart +++ b/pkg/kernel/lib/src/equivalence.dart @@ -836,8 +836,8 @@ class EquivalenceVisitor implements Visitor1 { } @override - bool visitVariableStatement(VariableStatement node, Node other) { - return strategy.checkVariableStatement(this, node, other); + bool visitLegacyVariableStatement(LegacyVariableStatement node, Node other) { + return strategy.checkLegacyVariableStatement(this, node, other); } @override @@ -860,6 +860,11 @@ class EquivalenceVisitor implements Visitor1 { return strategy.checkCatch(this, node, other); } + @override + bool visitLegacyVariable(LegacyVariable node, Node other) { + return strategy.checkLegacyVariable(this, node, other); + } + @override bool visitLocalVariable(LocalVariable node, Node other) { return strategy.checkLocalVariable(this, node, other); @@ -1306,8 +1311,8 @@ class EquivalenceVisitor implements Visitor1 { if (a is LabeledStatement) { return b is LabeledStatement; } - if (a is VariableStatement) { - return b is VariableStatement && a.name == b.name; + if (a is LegacyVariable) { + return b is LegacyVariable && a.name == b.name; } if (a is StructuralParameter) { return b is StructuralParameter && a.name == b.name; @@ -5904,41 +5909,20 @@ class EquivalenceStrategy { return result; } - bool checkVariableStatement( + bool checkLegacyVariableStatement( EquivalenceVisitor visitor, - VariableStatement? node, + LegacyVariableStatement? node, Object? other, ) { if (identical(node, other)) return true; - if (node is! VariableStatement) return false; - if (other is! VariableStatement) return false; - if (!visitor.checkDeclarations(node, other, '')) { - return false; - } + if (node is! LegacyVariableStatement) return false; + if (other is! LegacyVariableStatement) return false; visitor.pushNodeState(node, other); bool result = true; - if (!checkVariableStatement_fileEqualsOffset(visitor, node, other)) { + if (!checkLegacyVariableStatement_variable(visitor, node, other)) { result = visitor.resultOnInequivalence; } - if (!checkVariableStatement_annotations(visitor, node, other)) { - result = visitor.resultOnInequivalence; - } - if (!checkVariableStatement_name(visitor, node, other)) { - result = visitor.resultOnInequivalence; - } - if (!checkVariableStatement_flags(visitor, node, other)) { - result = visitor.resultOnInequivalence; - } - if (!checkVariableStatement_type(visitor, node, other)) { - result = visitor.resultOnInequivalence; - } - if (!checkVariableStatement_binaryOffsetNoTag(visitor, node, other)) { - result = visitor.resultOnInequivalence; - } - if (!checkVariableStatement_initializer(visitor, node, other)) { - result = visitor.resultOnInequivalence; - } - if (!checkVariableStatement_fileOffset(visitor, node, other)) { + if (!checkLegacyVariableStatement_fileOffset(visitor, node, other)) { result = visitor.resultOnInequivalence; } visitor.popState(); @@ -5993,12 +5977,6 @@ class EquivalenceStrategy { if (!checkVariableInitialization_annotations(visitor, node, other)) { result = visitor.resultOnInequivalence; } - if (!checkVariableInitialization_binaryOffsetNoTag(visitor, node, other)) { - result = visitor.resultOnInequivalence; - } - if (!checkVariableInitialization_fileEqualsOffset(visitor, node, other)) { - result = visitor.resultOnInequivalence; - } if (!checkVariableInitialization_fileOffset(visitor, node, other)) { result = visitor.resultOnInequivalence; } @@ -6057,6 +6035,47 @@ class EquivalenceStrategy { return result; } + bool checkLegacyVariable( + EquivalenceVisitor visitor, + LegacyVariable? node, + Object? other, + ) { + if (identical(node, other)) return true; + if (node is! LegacyVariable) return false; + if (other is! LegacyVariable) return false; + if (!visitor.checkDeclarations(node, other, '')) { + return false; + } + visitor.pushNodeState(node, other); + bool result = true; + if (!checkLegacyVariable_fileEqualsOffset(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkLegacyVariable_annotations(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkLegacyVariable_name(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkLegacyVariable_flags(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkLegacyVariable_type(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkLegacyVariable_binaryOffsetNoTag(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkLegacyVariable_initializer(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkLegacyVariable_fileOffset(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + visitor.popState(); + return result; + } + bool checkLocalVariable( EquivalenceVisitor visitor, LocalVariable? node, @@ -13259,83 +13278,18 @@ class EquivalenceStrategy { return checkStatement_fileOffset(visitor, node, other); } - bool checkVariableStatement_fileEqualsOffset( + bool checkLegacyVariableStatement_variable( EquivalenceVisitor visitor, - VariableStatement node, - VariableStatement other, + LegacyVariableStatement node, + LegacyVariableStatement other, ) { - return visitor.checkValues( - node.fileEqualsOffset, - other.fileEqualsOffset, - 'fileEqualsOffset', - ); + return visitor.checkNodes(node.variable, other.variable, 'variable'); } - bool checkVariableStatement_annotations( + bool checkLegacyVariableStatement_fileOffset( EquivalenceVisitor visitor, - VariableStatement node, - VariableStatement other, - ) { - return visitor.checkLists( - node.annotations, - other.annotations, - visitor.checkNodes, - 'annotations', - ); - } - - bool checkVariableStatement_name( - EquivalenceVisitor visitor, - VariableStatement node, - VariableStatement other, - ) { - return visitor.checkValues(node.name, other.name, 'name'); - } - - bool checkVariableStatement_flags( - EquivalenceVisitor visitor, - VariableStatement node, - VariableStatement other, - ) { - return visitor.checkValues(node.flags, other.flags, 'flags'); - } - - bool checkVariableStatement_type( - EquivalenceVisitor visitor, - VariableStatement node, - VariableStatement other, - ) { - return visitor.checkNodes(node.type, other.type, 'type'); - } - - bool checkVariableStatement_binaryOffsetNoTag( - EquivalenceVisitor visitor, - VariableStatement node, - VariableStatement other, - ) { - return visitor.checkValues( - node.binaryOffsetNoTag, - other.binaryOffsetNoTag, - 'binaryOffsetNoTag', - ); - } - - bool checkVariableStatement_initializer( - EquivalenceVisitor visitor, - VariableStatement node, - VariableStatement other, - ) { - return visitor.checkNodes( - node.initializer, - other.initializer, - 'initializer', - ); - } - - bool checkVariableStatement_fileOffset( - EquivalenceVisitor visitor, - VariableStatement node, - VariableStatement other, + LegacyVariableStatement node, + LegacyVariableStatement other, ) { return checkStatement_fileOffset(visitor, node, other); } @@ -13420,30 +13374,6 @@ class EquivalenceStrategy { ); } - bool checkVariableInitialization_binaryOffsetNoTag( - EquivalenceVisitor visitor, - VariableInitialization node, - VariableInitialization other, - ) { - return visitor.checkValues( - node.binaryOffsetNoTag, - other.binaryOffsetNoTag, - 'binaryOffsetNoTag', - ); - } - - bool checkVariableInitialization_fileEqualsOffset( - EquivalenceVisitor visitor, - VariableInitialization node, - VariableInitialization other, - ) { - return visitor.checkValues( - node.fileEqualsOffset, - other.fileEqualsOffset, - 'fileEqualsOffset', - ); - } - bool checkVariableInitialization_fileOffset( EquivalenceVisitor visitor, VariableInitialization node, @@ -13517,6 +13447,87 @@ class EquivalenceStrategy { return checkTreeNode_fileOffset(visitor, node, other); } + bool checkLegacyVariable_fileEqualsOffset( + EquivalenceVisitor visitor, + LegacyVariable node, + LegacyVariable other, + ) { + return visitor.checkValues( + node.fileEqualsOffset, + other.fileEqualsOffset, + 'fileEqualsOffset', + ); + } + + bool checkLegacyVariable_annotations( + EquivalenceVisitor visitor, + LegacyVariable node, + LegacyVariable other, + ) { + return visitor.checkLists( + node.annotations, + other.annotations, + visitor.checkNodes, + 'annotations', + ); + } + + bool checkLegacyVariable_name( + EquivalenceVisitor visitor, + LegacyVariable node, + LegacyVariable other, + ) { + return visitor.checkValues(node.name, other.name, 'name'); + } + + bool checkLegacyVariable_flags( + EquivalenceVisitor visitor, + LegacyVariable node, + LegacyVariable other, + ) { + return visitor.checkValues(node.flags, other.flags, 'flags'); + } + + bool checkLegacyVariable_type( + EquivalenceVisitor visitor, + LegacyVariable node, + LegacyVariable other, + ) { + return visitor.checkNodes(node.type, other.type, 'type'); + } + + bool checkLegacyVariable_binaryOffsetNoTag( + EquivalenceVisitor visitor, + LegacyVariable node, + LegacyVariable other, + ) { + return visitor.checkValues( + node.binaryOffsetNoTag, + other.binaryOffsetNoTag, + 'binaryOffsetNoTag', + ); + } + + bool checkLegacyVariable_initializer( + EquivalenceVisitor visitor, + LegacyVariable node, + LegacyVariable other, + ) { + return visitor.checkNodes( + node.initializer, + other.initializer, + 'initializer', + ); + } + + bool checkLegacyVariable_fileOffset( + EquivalenceVisitor visitor, + LegacyVariable node, + LegacyVariable other, + ) { + return checkTreeNode_fileOffset(visitor, node, other); + } + bool checkLocalVariable_cosmeticName( EquivalenceVisitor visitor, LocalVariable node, diff --git a/pkg/kernel/lib/src/node_creator.dart b/pkg/kernel/lib/src/node_creator.dart index 4eb2fc1f8ab..ebca61bb722 100644 --- a/pkg/kernel/lib/src/node_creator.dart +++ b/pkg/kernel/lib/src/node_creator.dart @@ -135,7 +135,8 @@ class NodeCreator { } _neededLabeledStatements.clear(); statement = Block([ - ..._neededVariableDeclarations, + for (VariableDeclaration neededVariable in _neededVariableDeclarations) + VariableStatement(neededVariable), ..._neededFunctionDeclarations, statement, ]); @@ -385,6 +386,7 @@ class NodeCreator { case NodeKind.PatternSwitchCase: case NodeKind.SwitchExpressionCase: case NodeKind.TypeVariable: + case NodeKind.LegacyVariable: throw new UnimplementedError('Expected in body node $kind.'); case NodeKind.Class: _needLibrary().addClass(node as Class); @@ -919,11 +921,8 @@ class NodeCreator { return IsExpression(_createExpression(), _createDartType()) ..fileOffset = _needFileOffset(); case ExpressionKind.Let: - return Let( - _createStatementFromKind(StatementKind.VariableStatement) - as VariableDeclaration, - _createExpression(), - )..fileOffset = _needFileOffset(); + return Let(_createVariableDeclaration(), _createExpression()) + ..fileOffset = _needFileOffset(); case ExpressionKind.ListConcatenation: return _createOneOf(_pendingExpressions, kind, index, [ () => @@ -1474,13 +1473,16 @@ class NodeCreator { ForStatement([], null, [], _createStatement()) ..fileOffset = _needFileOffset(), () => ForStatement( - [_createVariableDeclaration()], + [VariableStatement(_createVariableDeclaration())], _createExpression(), [_createExpression()], _createStatement(), )..fileOffset = _needFileOffset(), () => ForStatement( - [_createVariableDeclaration(), _createVariableDeclaration()], + [ + VariableStatement(_createVariableDeclaration()), + VariableStatement(_createVariableDeclaration()), + ], _createExpression(), [_createExpression(), _createExpression()], _createStatement(), @@ -1539,15 +1541,19 @@ class NodeCreator { case StatementKind.TryFinally: return TryFinally(_createStatement(), _createStatement()) ..fileOffset = _needFileOffset(); - case StatementKind.VariableStatement: + case StatementKind.LegacyVariableStatement: return _createOneOf(_pendingStatements, kind, index, [ - () => VariableDeclaration('foo')..fileOffset = _needFileOffset(), - () => - VariableDeclaration('foo', initializer: _createExpression()) - ..fileOffset = _needFileOffset(), - () => - VariableDeclaration('foo', type: _createDartType()) - ..fileOffset = _needFileOffset(), + () => VariableStatement( + VariableDeclaration('foo')..fileOffset = _needFileOffset(), + )..fileOffset = _needFileOffset(), + () => VariableStatement( + VariableDeclaration('foo', initializer: _createExpression()) + ..fileOffset = _needFileOffset(), + )..fileOffset = _needFileOffset(), + () => VariableStatement( + VariableDeclaration('foo', type: _createDartType()) + ..fileOffset = _needFileOffset(), + )..fileOffset = _needFileOffset(), ]); case StatementKind.WhileStatement: return WhileStatement(_createExpression(), _createStatement()) @@ -1608,8 +1614,7 @@ class NodeCreator { /// If there are any pending [VariableDeclaration] nodes, one of these is /// created. VariableDeclaration _createVariableDeclaration() { - return _createStatementFromKind(StatementKind.VariableStatement) - as VariableDeclaration; + return VariableDeclaration('foo'); } /// Creates a [DartType] node. @@ -2128,6 +2133,17 @@ class NodeCreator { _createNodeFromKind(NodeKind.PatternGuard) as PatternGuard, _createExpression(), )..fileOffset = _needFileOffset(); + case NodeKind.LegacyVariable: + return _createOneOf(_pendingNodes, kind, index, [ + () => VariableDeclaration('foo')..fileOffset = _needFileOffset(), + + () => + VariableDeclaration('foo', initializer: _createExpression()) + ..fileOffset = _needFileOffset(), + () => + VariableDeclaration('foo', type: _createDartType()) + ..fileOffset = _needFileOffset(), + ]); case NodeKind.TypeVariable: throw new UnimplementedError("Unimplemented support for kind $kind."); } diff --git a/pkg/kernel/lib/src/printer.dart b/pkg/kernel/lib/src/printer.dart index cf7298deea4..04fb2b70998 100644 --- a/pkg/kernel/lib/src/printer.dart +++ b/pkg/kernel/lib/src/printer.dart @@ -260,8 +260,7 @@ class AstPrinter { return _variableNames[node] ??= '#${_variableNames.length}'; case CatchVariable(catchVariableName: var name): return name; - case VariableStatement(:var name): - case VariableInitialization(:var name): + case LegacyVariable(:var name): if (name != null) { return name; } diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart index 1734f524fbc..44b3d6c25b9 100644 --- a/pkg/kernel/lib/text/ast_to_text.dart +++ b/pkg/kernel/lib/text/ast_to_text.dart @@ -1248,9 +1248,16 @@ class Printer extends VisitorDefault with VisitorVoidMixin { endLine(';'); } + @override + void visitSyntheticVariable(SyntheticVariable node) { + writeIndentation(); + writeExpressionVariable(node); + endLine(';'); + } + void writeExpressionVariable(VariableDeclaration node) { // TODO(cstefantsova): Printer of the new variables is broken. - if (node is VariableStatement && node is! FunctionParameter) { + if (node is LegacyVariable && node is! FunctionParameter) { writeVariableDeclaration(node); } else { if (showOffsets) writeWord("[${node.fileOffset}]"); @@ -1267,7 +1274,7 @@ class Printer extends VisitorDefault with VisitorVoidMixin { writeWord('this-variable'); case SyntheticVariable(): writeWord('synthetic-variable'); - case VariableStatement(): + case LegacyVariable(): writeWord('variable-declaration'); case CatchVariable(): writeWord('catch-variable'); @@ -2580,7 +2587,7 @@ class Printer extends VisitorDefault with VisitorVoidMixin { ensureSpace(); } writeSymbol('('); - writeList(node.variables, writeVariableInitialization); + writeList(node.variables, writeVariableStatement); writeComma(';'); Expression? condition = node.condition; if (condition != null) { @@ -2604,7 +2611,7 @@ class Printer extends VisitorDefault with VisitorVoidMixin { ensureSpace(); } writeSymbol('('); - if (node.variable case VariableStatement variable) { + if (node.variable case LegacyVariable variable) { writeVariableDeclaration(variable, useVarKeyword: true); } else { writeExpressionVariable(node.variable); @@ -2751,16 +2758,16 @@ class Printer extends VisitorDefault with VisitorVoidMixin { } @override - void visitVariableDeclaration(VariableDeclaration node) { + void visitLegacyVariableStatement(LegacyVariableStatement node) { writeIndentation(); - writeVariableDeclaration(node, useVarKeyword: true); + writeVariableStatement(node); endLine(';'); } @override void visitVariableInitialization(VariableInitialization node) { writeIndentation(); - writeVariableInitialization(node); + writeVariableStatement(node); _writeContexts(node); endLine(';'); } @@ -2786,7 +2793,7 @@ class Printer extends VisitorDefault with VisitorVoidMixin { case PositionalParameter(): case NamedParameter(): writeExpressionVariable(node); - case VariableStatement(): + case LegacyVariable(): if (showOffsets) writeWord("[${node.fileOffset}]"); if (showMetadata) writeMetadata(node); writeAnnotationList(node.annotations, separateLines: false); @@ -2835,41 +2842,43 @@ class Printer extends VisitorDefault with VisitorVoidMixin { writeSpaced('='); writeExpression(initializer); } - case VariableInitialization(): - writeVariableInitialization(node); } } - void writeVariableInitialization(VariableDeclaration node) { + void writeVariableStatement(VariableStatement node) { + VariableDeclaration variable = node.variable; if (node is VariableInitialization) { if (showOffsets) writeWord("[${node.fileOffset}]"); if (showMetadata) writeMetadata(node); writeAnnotationList(node.annotations, separateLines: false); writeModifier(node.isErroneouslyInitialized, 'erroneously-initialized'); bool hasImplicitInitializer = - node.initializer is NullLiteral || - (node.initializer is ConstantExpression && - (node.initializer as ConstantExpression).constant + variable.initializer is NullLiteral || + (variable.initializer is ConstantExpression && + (variable.initializer as ConstantExpression).constant is NullConstant); - if ((node.initializer == null || hasImplicitInitializer) && - node.hasDeclaredInitializer) { - writeModifier(node.hasDeclaredInitializer, 'has-declared-initializer'); - } else if (node.initializer != null && - !hasImplicitInitializer && - !node.hasDeclaredInitializer) { + if ((variable.initializer == null || hasImplicitInitializer) && + variable.hasDeclaredInitializer) { writeModifier( - node.hasDeclaredInitializer, + variable.hasDeclaredInitializer, + 'has-declared-initializer', + ); + } else if (variable.initializer != null && + !hasImplicitInitializer && + !variable.hasDeclaredInitializer) { + writeModifier( + variable.hasDeclaredInitializer, 'has-no-declared-initializer', ); } - writeWord(getVariableName(node.variable)); - Expression? initializer = node.initializer; + writeWord(getVariableName(variable.variable)); + Expression? initializer = variable.initializer; if (initializer != null) { writeSpaced(':='); writeExpression(initializer); } } else { - writeVariableDeclaration(node); + writeVariableDeclaration(variable); } } diff --git a/pkg/kernel/lib/text/debug_printer.dart b/pkg/kernel/lib/text/debug_printer.dart index c3b66ff4135..c234028ecf5 100644 --- a/pkg/kernel/lib/text/debug_printer.dart +++ b/pkg/kernel/lib/text/debug_printer.dart @@ -85,7 +85,7 @@ class DebugPrinter extends VisitorDefault } @override - void visitVariableDeclaration(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { openNode(node, '${node.runtimeType}', { 'name': '${node.name ?? '--unnamed--'}', 'isFinal': '${node.isFinal}', diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart index 0bfd15822d9..8ac6b0336be 100644 --- a/pkg/kernel/lib/type_checker.dart +++ b/pkg/kernel/lib/type_checker.dart @@ -1183,7 +1183,7 @@ class TypeCheckingVisitor @override void visitForStatement(ForStatement node) { - node.variables.forEach(_handleVariableInitialization); + node.variables.forEach(_handleVariableStatement); if (node.condition != null) { node.condition = checkExpressionAndAssignability( node.condition!, @@ -1257,15 +1257,6 @@ class TypeCheckingVisitor @override void visitVariableDeclaration(VariableDeclaration node) { - _handleVariableInitialization(node); - } - - @override - void visitVariableInitialization(VariableInitialization node) { - _handleVariableInitialization(node); - } - - void _handleVariableInitialization(VariableDeclaration node) { if (node.initializer != null) { node.initializer = checkExpressionAndAssignability( node.initializer!, @@ -1274,6 +1265,25 @@ class TypeCheckingVisitor } } + @override + void visitLegacyVariableStatement(LegacyVariableStatement node) { + _handleVariableStatement(node); + } + + @override + void visitVariableInitialization(VariableInitialization node) { + _handleVariableStatement(node); + } + + void _handleVariableStatement(VariableStatement node) { + if (node.initializer != null) { + node.initializer = checkExpressionAndAssignability( + node.initializer!, + node.variable.type, + ); + } + } + @override void visitWhileStatement(WhileStatement node) { node.condition = checkExpressionAndAssignability( diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart index 307c3f36f37..8572cb936b4 100644 --- a/pkg/kernel/lib/verifier.dart +++ b/pkg/kernel/lib/verifier.dart @@ -270,7 +270,7 @@ class VerifyingVisitor extends RecursiveResultVisitor { // TODO(cstefantsova): Remove this method when the new variable model is // supported. bool _isNewModelVariable(TreeNode node) { - return node is VariableDeclaration && node is! VariableStatement || + return node is VariableDeclaration && node is! LegacyVariable || node is FunctionParameter; } @@ -1137,37 +1137,36 @@ class VerifyingVisitor extends RecursiveResultVisitor { } @override - void visitVariableDeclaration(VariableDeclaration node) { - return _verifyVariableInitialization(node); + void visitLegacyVariableStatement(LegacyVariableStatement node) { + _verifyVariableStatement(node); + super.visitLegacyVariableStatement(node); } @override - void visitVariableInitialization(VariableDeclaration node) { - return _verifyVariableInitialization(node); + void visitVariableInitialization(VariableInitialization node) { + _verifyVariableStatement(node); + super.visitVariableInitialization(node); } - void _verifyVariableInitialization(VariableDeclaration node) { - enterTreeNode(node); + void _verifyVariableStatement(VariableStatement node) { TreeNode? parent = node.parent; - if (parent is! Block && - !(parent is Catch && parent.body != node) && - !(parent is FunctionNode && parent.body != node) && - parent is! FunctionDeclaration && - !(parent is ForStatement && parent.body != node) && - !(parent is ForInStatement && parent.body != node) && - parent is! Let && - parent is! LocalInitializer && - parent is! Typedef) { + if (parent is! Block && !(parent is ForStatement && parent.body != node)) { problem( node, - "VariableDeclaration must be a direct child of a Block, " + "VariableStatement must be a direct child of a Block or ForStatement, " "not ${parent.runtimeType}.", ); } - TreeNode? oldParent = enterParent(node); - _visitAnnotations(node.annotations); - node.initializer?.accept(this); - exitParent(oldParent); + } + + @override + void defaultVariableDeclaration(VariableDeclaration node) { + return _verifyVariableDeclaration(node); + } + + void _verifyVariableDeclaration(VariableDeclaration node) { + enterTreeNode(node); + visitChildren(node); declareVariable(node.variable); if (afterConst && node.isConst && constantLocalsShouldBeRemoved) { Expression? initializer = node.initializer; diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart index 6b6cf2647c1..2705e852772 100644 --- a/pkg/kernel/lib/visitor.dart +++ b/pkg/kernel/lib/visitor.dart @@ -502,36 +502,54 @@ abstract class StatementVisitor { const StatementVisitor(); R visitAuxiliaryStatement(AuxiliaryStatement node); + R visitExpressionStatement(ExpressionStatement node); + R visitBlock(Block node); + R visitAssertBlock(AssertBlock node); + R visitEmptyStatement(EmptyStatement node); + R visitAssertStatement(AssertStatement node); + R visitLabeledStatement(LabeledStatement node); + R visitVariableInitialization(VariableInitialization node); + R visitBreakStatement(BreakStatement node); + R visitWhileStatement(WhileStatement node); + R visitDoStatement(DoStatement node); + R visitForStatement(ForStatement node); + R visitForInStatement(ForInStatement node); + R visitSwitchStatement(SwitchStatement node); + R visitPatternSwitchStatement(PatternSwitchStatement node); + R visitContinueSwitchStatement(ContinueSwitchStatement node); + R visitIfStatement(IfStatement node); + R visitIfCaseStatement(IfCaseStatement node); + R visitReturnStatement(ReturnStatement node); + R visitTryCatch(TryCatch node); + R visitTryFinally(TryFinally node); + R visitYieldStatement(YieldStatement node); + R visitPatternVariableDeclaration(PatternVariableDeclaration node); + R visitFunctionDeclaration(FunctionDeclaration node); - R visitVariableStatement(VariableStatement node); - R visitPositionalParameter(PositionalParameter node); - R visitNamedParameter(NamedParameter node); - R visitLocalVariable(LocalVariable node); - R visitCatchVariable(CatchVariable node); - R visitThisVariable(ThisVariable node); - R visitSyntheticVariable(SyntheticVariable node); + + R visitLegacyVariableStatement(LegacyVariableStatement node); } /// Helper mixin for [StatementVisitor] that implements visit methods by @@ -587,8 +605,6 @@ mixin StatementVisitorDefaultMixin implements StatementVisitor { R visitTryFinally(TryFinally node) => defaultStatement(node); @override R visitYieldStatement(YieldStatement node) => defaultStatement(node); - R visitVariableDeclaration(VariableDeclaration node) => - defaultStatement(node); @override R visitPatternVariableDeclaration(PatternVariableDeclaration node) => defaultStatement(node); @@ -596,21 +612,45 @@ mixin StatementVisitorDefaultMixin implements StatementVisitor { R visitFunctionDeclaration(FunctionDeclaration node) => defaultStatement(node); @override - R visitVariableStatement(VariableStatement node) => - visitVariableDeclaration(node); + R visitLegacyVariableStatement(LegacyVariableStatement node) => + defaultStatement(node); +} + +abstract class VariableVisitor { + const VariableVisitor(); + + R visitLegacyVariable(LegacyVariable node); + R visitPositionalParameter(PositionalParameter node); + R visitNamedParameter(NamedParameter node); + R visitLocalVariable(LocalVariable node); + R visitCatchVariable(CatchVariable node); + R visitThisVariable(ThisVariable node); + R visitSyntheticVariable(SyntheticVariable node); +} + +/// Helper mixin for [VariableVisitor] that implements visit methods by +/// delegating to the [visitVariableDeclaration] method. +mixin VariableVisitorDefaultMixin implements VariableVisitor { + R defaultVariableDeclaration(VariableDeclaration node); + + @override + R visitLegacyVariable(LegacyVariable node) => + defaultVariableDeclaration(node); @override R visitPositionalParameter(PositionalParameter node) => - defaultStatement(node); + defaultVariableDeclaration(node); @override - R visitNamedParameter(NamedParameter node) => defaultStatement(node); + R visitNamedParameter(NamedParameter node) => + defaultVariableDeclaration(node); @override - R visitLocalVariable(LocalVariable node) => defaultStatement(node); + R visitLocalVariable(LocalVariable node) => defaultVariableDeclaration(node); @override - R visitCatchVariable(CatchVariable node) => defaultStatement(node); + R visitCatchVariable(CatchVariable node) => defaultVariableDeclaration(node); @override - R visitThisVariable(ThisVariable node) => defaultStatement(node); + R visitThisVariable(ThisVariable node) => defaultVariableDeclaration(node); @override - R visitSyntheticVariable(SyntheticVariable node) => defaultStatement(node); + R visitSyntheticVariable(SyntheticVariable node) => + defaultVariableDeclaration(node); } abstract class MemberVisitor { @@ -737,6 +777,7 @@ abstract class TreeVisitor ExpressionVisitor, PatternVisitor, StatementVisitor, + VariableVisitor, MemberVisitor, InitializerVisitor { const TreeVisitor(); @@ -832,6 +873,7 @@ abstract class TreeVisitorDefault with ExpressionVisitorDefaultMixin, StatementVisitorDefaultMixin, + VariableVisitorDefaultMixin, PatternVisitorDefaultMixin, InitializerVisitorDefaultMixin, MemberVisitorDefaultMixin, @@ -846,6 +888,9 @@ abstract class TreeVisitorDefault @override R defaultStatement(Statement node) => defaultTreeNode(node); @override + R defaultVariableDeclaration(VariableDeclaration node) => + defaultTreeNode(node); + @override R defaultInitializer(Initializer node) => defaultTreeNode(node); @override R defaultMember(Member node) => defaultTreeNode(node); @@ -856,6 +901,7 @@ abstract class TreeVisitor1 ExpressionVisitor1, PatternVisitor1, StatementVisitor1, + VariableVisitor1, MemberVisitor1, InitializerVisitor1 { const TreeVisitor1(); @@ -960,6 +1006,7 @@ abstract class TreeVisitor1Default ExpressionVisitor1DefaultMixin, PatternVisitor1DefaultMixin, StatementVisitor1DefaultMixin, + VariableVisitor1DefaultMixin, InitializerVisitor1DefaultMixin, MemberVisitor1DefaultMixin implements TreeVisitor1 { @@ -972,6 +1019,9 @@ abstract class TreeVisitor1Default @override R defaultStatement(Statement node, A arg) => defaultTreeNode(node, arg); @override + R defaultVariableDeclaration(VariableDeclaration node, A arg) => + defaultTreeNode(node, arg); + @override R defaultInitializer(Initializer node, A arg) => defaultTreeNode(node, arg); @override R defaultMember(Member node, A arg) => defaultTreeNode(node, arg); @@ -2822,13 +2872,7 @@ abstract class StatementVisitor1 { R visitYieldStatement(YieldStatement node, A arg); R visitPatternVariableDeclaration(PatternVariableDeclaration node, A arg); R visitFunctionDeclaration(FunctionDeclaration node, A arg); - R visitVariableStatement(VariableStatement node, A arg); - R visitPositionalParameter(PositionalParameter node, A arg); - R visitNamedParameter(NamedParameter node, A arg); - R visitLocalVariable(LocalVariable node, A arg); - R visitCatchVariable(CatchVariable node, A arg); - R visitThisVariable(ThisVariable node, A arg); - R visitSyntheticVariable(SyntheticVariable node, A arg); + R visitLegacyVariableStatement(LegacyVariableStatement node, A arg); } /// Helper mixin for [StatementVisitor1] that implements visit methods by @@ -2895,8 +2939,6 @@ mixin StatementVisitor1DefaultMixin implements StatementVisitor1 { @override R visitYieldStatement(YieldStatement node, A arg) => defaultStatement(node, arg); - R visitVariableDeclaration(VariableDeclaration node, A arg) => - defaultStatement(node, arg); @override R visitPatternVariableDeclaration(PatternVariableDeclaration node, A arg) => defaultStatement(node, arg); @@ -2904,25 +2946,48 @@ mixin StatementVisitor1DefaultMixin implements StatementVisitor1 { R visitFunctionDeclaration(FunctionDeclaration node, A arg) => defaultStatement(node, arg); @override - R visitVariableStatement(VariableStatement node, A arg) => - visitVariableDeclaration(node, arg); + R visitLegacyVariableStatement(LegacyVariableStatement node, A arg) => + defaultStatement(node, arg); +} + +abstract class VariableVisitor1 { + const VariableVisitor1(); + + R visitLegacyVariable(LegacyVariable node, A arg); + R visitPositionalParameter(PositionalParameter node, A arg); + R visitNamedParameter(NamedParameter node, A arg); + R visitLocalVariable(LocalVariable node, A arg); + R visitCatchVariable(CatchVariable node, A arg); + R visitThisVariable(ThisVariable node, A arg); + R visitSyntheticVariable(SyntheticVariable node, A arg); +} + +/// Helper mixin for [VariableVisitor1] that implements visit methods by +/// delegating to the [visitVariableDeclaration] method. +mixin VariableVisitor1DefaultMixin implements VariableVisitor1 { + R defaultVariableDeclaration(VariableDeclaration node, A arg); + + @override + R visitLegacyVariable(LegacyVariable node, A arg) => + defaultVariableDeclaration(node, arg); @override R visitPositionalParameter(PositionalParameter node, A arg) => - defaultStatement(node, arg); + defaultVariableDeclaration(node, arg); @override R visitNamedParameter(NamedParameter node, A arg) => - defaultStatement(node, arg); + defaultVariableDeclaration(node, arg); @override R visitLocalVariable(LocalVariable node, A arg) => - defaultStatement(node, arg); + defaultVariableDeclaration(node, arg); @override R visitCatchVariable(CatchVariable node, A arg) => - defaultStatement(node, arg); + defaultVariableDeclaration(node, arg); @override - R visitThisVariable(ThisVariable node, A arg) => defaultStatement(node, arg); + R visitThisVariable(ThisVariable node, A arg) => + defaultVariableDeclaration(node, arg); @override R visitSyntheticVariable(SyntheticVariable node, A arg) => - defaultStatement(node, arg); + defaultVariableDeclaration(node, arg); } /// [DartTypeVisitorExperimentExclusionMixin] is intended to reduce the effects @@ -3178,9 +3243,31 @@ mixin StatementVisitorExperimentExclusionMixin R visitVariableDeclaration(VariableDeclaration node); @override - R visitVariableStatement(VariableStatement node) { - return visitVariableDeclaration(node); + R visitLegacyVariableStatement(LegacyVariableStatement node) { + return visitVariableDeclaration(node.variable); } +} + +/// [VariableVisitorExperimentExclusionMixin] is intended to reduce the effects +/// of CFE experiments on the backends. +/// +/// The mixin provides implementations of the visit methods for the experimental +/// nodes. The methods throw an exception signaling that the experimental nodes +/// aren't supported. +mixin VariableVisitorExperimentExclusionMixin implements VariableVisitor { + /// Since [VariableDeclaration] is abstract due to an experiment, it doesn't + /// have its own visit method in [VariableVisitor]. However, for the + /// transitional period the backends would rely on having + /// [visitVariableDeclaration] and on needing to override it. Since the + /// statement visitors in the backends should mix in + /// [VariableVisitorExperimentExclusionMixin], we can deliver the abstract + /// declaration of [visitVariableDeclaration] to them via the mixin. At the + /// same time, it allows us to redirect [visitVariableStatement] to the + /// overrides of [visitVariableDeclarations] the backends already have. + R visitVariableDeclaration(VariableDeclaration node); + + @override + R visitLegacyVariable(LegacyVariable node) => visitVariableDeclaration(node); @override R visitPositionalParameter(PositionalParameter node) { @@ -3242,40 +3329,8 @@ mixin StatementVisitor1ExperimentExclusionMixin R visitVariableDeclaration(VariableDeclaration node, A arg); @override - R visitVariableStatement(VariableStatement node, A arg) { - return visitVariableDeclaration(node, arg); - } - - @override - R visitPositionalParameter(PositionalParameter node, A arg) { - throw StateError( - "${runtimeType}.visitPositionalParameter isn't supported.", - ); - } - - @override - R visitNamedParameter(NamedParameter node, A arg) { - throw StateError("${runtimeType}.visitNamedParameter isn't supported."); - } - - @override - R visitLocalVariable(LocalVariable node, A arg) { - throw StateError("${runtimeType}.visitLocalVariable isn't supported."); - } - - @override - R visitCatchVariable(CatchVariable node, A arg) { - throw StateError("${runtimeType}.visitCatchVariable isn't supported."); - } - - @override - R visitThisVariable(ThisVariable node, A arg) { - throw StateError("${runtimeType}.visitThisVariable isn't supported."); - } - - @override - R visitSyntheticVariable(SyntheticVariable node, A arg) { - throw StateError("${runtimeType}.visitSyntheticVariable isn't supported."); + R visitLegacyVariableStatement(LegacyVariableStatement node, A arg) { + return visitVariableDeclaration(node.variable, arg); } } diff --git a/pkg/kernel/test/verify_test.dart b/pkg/kernel/test/verify_test.dart index 8f86518afa6..02647f4b131 100644 --- a/pkg/kernel/test/verify_test.dart +++ b/pkg/kernel/test/verify_test.dart @@ -48,7 +48,7 @@ void main() { VariableDeclaration variable = test.makeVariable(); test.addNode( Block([ - new Block([variable]), + new Block([new VariableStatement(variable)]), new ReturnStatement(new VariableGet(variable)), ]), ); @@ -75,7 +75,14 @@ void main() { 'Variable redeclared', (TestHarness test) { VariableDeclaration variable = test.makeVariable(); - test.addNode(Block([variable, variable])); + test.addNode( + Procedure( + new Name('bar'), + ProcedureKind.Method, + FunctionNode(null, positionalParameters: [variable, variable]), + fileUri: dummyUri, + )..fileOffset = dummyFileOffset, + ); return variable; }, (Node? node) => "${errorPrefix}Variable '$node' declared more than once.", diff --git a/pkg/vm/lib/modular/transformations/ffi/finalizable.dart b/pkg/vm/lib/modular/transformations/ffi/finalizable.dart index 882c173e300..88fd45dc3f8 100644 --- a/pkg/vm/lib/modular/transformations/ffi/finalizable.dart +++ b/pkg/vm/lib/modular/transformations/ffi/finalizable.dart @@ -78,8 +78,10 @@ mixin FinalizableTransformer on Transformer { final possiblyUninitialized = entry.key; final alwaysInitialized = entry.value; addPossiblyUninitializedTo!.statements.insert( - addPossiblyUninitializedTo.statements.indexOf(possiblyUninitialized), - alwaysInitialized, + addPossiblyUninitializedTo.statements.indexOf( + possiblyUninitialized.parent as VariableStatement, + ), + VariableStatement(alwaysInitialized), ); } assert(_currentScope == scope); @@ -269,8 +271,8 @@ mixin FinalizableTransformer on Transformer { } @override - TreeNode visitVariableDeclaration(VariableDeclaration node) { - node = super.visitVariableDeclaration(node) as VariableDeclaration; + TreeNode defaultVariableDeclaration(VariableDeclaration node) { + node = super.defaultVariableDeclaration(node) as VariableDeclaration; if (_currentScope == null) { // Global variable. return node; @@ -559,7 +561,10 @@ mixin FinalizableTransformer on Transformer { isSynthesized: true, ); return BlockExpression( - Block([resultVariable, ..._reachabilityFences(declarations)]), + Block([ + VariableStatement(resultVariable), + ..._reachabilityFences(declarations), + ]), VariableGet(resultVariable), ); } @@ -642,11 +647,11 @@ class FindCaptures extends RecursiveVisitor { } @override - void visitVariableDeclaration(VariableDeclaration node) { + void defaultVariableDeclaration(VariableDeclaration node) { if (_isFinalizable(node.type)) { _currentScope.addDeclaration(node); } - super.visitVariableDeclaration(node); + super.defaultVariableDeclaration(node); } @override @@ -740,6 +745,7 @@ ${parent?.toStringIndented(indentation: indentation + 2)} VariableDeclaration possiblyUninitialized, VariableDeclaration nullableValue, ) { + assert(possiblyUninitialized.parent is VariableStatement); _possiblyUninitializedDeclarations[possiblyUninitialized] = nullableValue; addDeclaration(possiblyUninitialized); } diff --git a/pkg/vm/lib/modular/transformations/ffi/native.dart b/pkg/vm/lib/modular/transformations/ffi/native.dart index 79a6f26e427..49c22d6be56 100644 --- a/pkg/vm/lib/modular/transformations/ffi/native.dart +++ b/pkg/vm/lib/modular/transformations/ffi/native.dart @@ -296,7 +296,7 @@ class FfiNativeTransformer extends FfiTransformer { ); pointerAddress = BlockExpression( Block([ - pointerAddressVar, + VariableStatement(pointerAddressVar), IfStatement( InstanceInvocation( InstanceAccessKind.Instance, @@ -363,7 +363,7 @@ class FfiNativeTransformer extends FfiTransformer { List dartParameters = dartFunctionType.positionalParameters; // Create lists of temporary variables for arguments potentially being // wrapped, and the (potentially) wrapped arguments to be passed. - final temporariesForArguments = []; + final temporariesForArguments = []; final callArguments = []; final fencedArguments = []; for (int i = 0; i < invocation.arguments.positional.length; i++) { @@ -374,7 +374,7 @@ class FfiNativeTransformer extends FfiTransformer { ); // Note: We also evaluate, and assign temporaries for, non-wrapped // arguments as we need to preserve the original evaluation order. - temporariesForArguments.add(temporary); + temporariesForArguments.add(VariableStatement(temporary)); callArguments.add( _getTemporary( temporary, @@ -419,7 +419,7 @@ class FfiNativeTransformer extends FfiTransformer { final resultBlock = BlockExpression( Block([ ...temporariesForArguments, - result, + VariableStatement(result), for (final argument in fencedArguments) ExpressionStatement( StaticInvocation( diff --git a/pkg/vm/lib/modular/transformations/ffi/use_sites.dart b/pkg/vm/lib/modular/transformations/ffi/use_sites.dart index 20651228e19..42a1d09214d 100644 --- a/pkg/vm/lib/modular/transformations/ffi/use_sites.dart +++ b/pkg/vm/lib/modular/transformations/ffi/use_sites.dart @@ -387,8 +387,8 @@ mixin _FfiUseSiteTransformer on FfiTransformer { return BlockExpression( Block([ - arrayVar, - indexVar, + VariableStatement(arrayVar), + VariableStatement(indexVar), ExpressionStatement( InstanceInvocation( InstanceAccessKind.Instance, @@ -916,7 +916,7 @@ mixin _FfiUseSiteTransformer on FfiTransformer { )..fileOffset = fileOffset; final result = BlockExpression( - Block([pointerVar, closure]), + Block([VariableStatement(pointerVar), closure]), VariableGet(closure.variable), ); @@ -1209,7 +1209,7 @@ mixin _FfiUseSiteTransformer on FfiTransformer { // expression result: _callback; return BlockExpression( - Block([nativeCallable, pointerSetter]), + Block([VariableStatement(nativeCallable), pointerSetter]), VariableGet(nativeCallable), ); } @@ -1507,7 +1507,7 @@ mixin _FfiUseSiteTransformer on FfiTransformer { )..fileOffset = node.fileOffset; return BlockExpression( - Block([sourceVar]), + Block([VariableStatement(sourceVar)]), referencedStruct.generateStore( sourceVar, dartType: node.arguments.types[0], @@ -1588,8 +1588,8 @@ mixin _FfiUseSiteTransformer on FfiTransformer { return BlockExpression( Block([ - arrayVar, - indexVar, + VariableStatement(arrayVar), + VariableStatement(indexVar), ExpressionStatement( InstanceInvocation( InstanceAccessKind.Instance, @@ -1858,8 +1858,8 @@ mixin _FfiUseSiteTransformer on FfiTransformer { )..fileOffset = node.fileOffset; final checkIndexAndLocalVars = [ - arrayVar, - indexVar, + VariableStatement(arrayVar), + VariableStatement(indexVar), ExpressionStatement( InstanceInvocation( InstanceAccessKind.Instance, @@ -1870,9 +1870,9 @@ mixin _FfiUseSiteTransformer on FfiTransformer { functionType: arrayCheckIndex.getterType as FunctionType, ), ), - singleElementSizeVar, - elementSizeVar, - offsetVar, + VariableStatement(singleElementSizeVar), + VariableStatement(elementSizeVar), + VariableStatement(offsetVar), ]; if (!setter) { @@ -1930,7 +1930,7 @@ mixin _FfiUseSiteTransformer on FfiTransformer { isSynthesized: true, )..fileOffset = node.fileOffset; return BlockExpression( - Block([...checkIndexAndLocalVars, valueVar]), + Block([...checkIndexAndLocalVars, VariableStatement(valueVar)]), StaticInvocation( memCopy, Arguments([ @@ -2440,7 +2440,7 @@ mixin _FfiUseSiteTransformer on FfiTransformer { isSynthesized: true, )..fileOffset = fileOffset; final newArgument = BlockExpression( - Block([valueVar]), + Block([VariableStatement(valueVar)]), ConstructorInvocation( compoundFromTypedDataBase, Arguments([ diff --git a/pkg/vm/lib/modular/transformations/for_in_lowering.dart b/pkg/vm/lib/modular/transformations/for_in_lowering.dart index 18f32dde866..8d67a25fef9 100644 --- a/pkg/vm/lib/modular/transformations/for_in_lowering.dart +++ b/pkg/vm/lib/modular/transformations/for_in_lowering.dart @@ -143,7 +143,11 @@ class ForInLowering { )..fileOffset = stmt.bodyOffset; valueVariable.initializer!.parent = valueVariable; - final whileBody = new Block([valueVariable, stmt.body]); + final whileBody = new Block([ + new VariableStatement(valueVariable) + ..fileOffset = valueVariable.fileOffset, + stmt.body, + ]); final tryBody = new WhileStatement(whileCondition, whileBody) ..fileOffset = stmt.fileOffset; @@ -182,8 +186,10 @@ class ForInLowering { final tryFinally = new TryFinally(tryBody, tryFinalizer); final block = new Block([ - streamVariable, - forIteratorVariable, + new VariableStatement(streamVariable) + ..fileOffset = streamVariable.fileOffset, + new VariableStatement(forIteratorVariable) + ..fileOffset = forIteratorVariable.fileOffset, tryFinally, ]); return block; @@ -269,17 +275,24 @@ class ForInLowering { initializer: syncForLoopVariableInitializer, ); - final Block body = Block([syncForLoopVariableInitialization, stmt.body]) - ..fileOffset = stmt.bodyOffset; + final Block body = Block([ + syncForLoopVariableInitialization + ..fileOffset = syncForLoopVariableInitialization.fileOffset, + stmt.body, + ])..fileOffset = stmt.bodyOffset; final forStatement = ForStatement([], condition, [], body) ..scope = stmt.scope ..fileOffset = stmt.fileOffset; - return Block([syncForIteratorVariableInitialization, forStatement]); + return Block([ + syncForIteratorVariableInitialization + ..fileOffset = syncForIteratorVariableInitialization.fileOffset, + forStatement, + ]); } - (VariableDeclaration, VariableDeclaration) + (VariableDeclaration, Statement) _createSyncForIteratorVariableAndInitialization({ required Expression initializer, required DartType type, @@ -302,11 +315,14 @@ class ForInLowering { type: type, isSynthesized: true, )..fileOffset = fileOffset; - return (variableAndInitialization, variableAndInitialization); + return ( + variableAndInitialization, + VariableStatement(variableAndInitialization)..fileOffset = fileOffset, + ); } } - VariableDeclaration _ensureSyncForLoopVariableInitialization({ + Statement _ensureSyncForLoopVariableInitialization({ required VariableDeclaration variable, required Expression initializer, }) { @@ -314,10 +330,11 @@ class ForInLowering { return VariableInitialization( variable: variable, initializer: initializer, - ); + )..fileOffset = variable.fileOffset; } else { initializer.parent = variable; - return variable..initializer = initializer; + variable..initializer = initializer; + return VariableStatement(variable)..fileOffset = variable.fileOffset; } } } diff --git a/pkg/vm/lib/modular/transformations/late_var_init_transformer.dart b/pkg/vm/lib/modular/transformations/late_var_init_transformer.dart index 7d788fd9fb8..bfb6a01aebe 100644 --- a/pkg/vm/lib/modular/transformations/late_var_init_transformer.dart +++ b/pkg/vm/lib/modular/transformations/late_var_init_transformer.dart @@ -9,16 +9,16 @@ class LateVarInitTransformer { const LateVarInitTransformer(); bool _shouldApplyTransform(Statement s) { - if (s is VariableDeclaration) { + if (s is VariableStatement) { // This transform only applies to late variables. - if (!s.isLate) return false; + if (!s.variable.isLate) return false; // Const variables are ignored. - if (s.isConst) return false; + if (s.variable.isConst) return false; // Variables with no initializer or a trivial initializer are ignored. - if (s.initializer == null) return false; - final Expression? init = s.initializer; + if (s.variable.initializer == null) return false; + final Expression? init = s.variable.initializer; if (init is StringLiteral) return false; if (init is BoolLiteral) return false; if (init is IntLiteral) return false; @@ -34,29 +34,29 @@ class LateVarInitTransformer { } List _transformVariableDeclaration( - VariableDeclaration node, + VariableStatement node, LocalFunctionIdGenerator localFunctionIdGenerator, ) { final fnNode = FunctionNode( - ReturnStatement(node.initializer), - returnType: node.type, + ReturnStatement(node.variable.initializer), + returnType: node.variable.type, ); final functionType = fnNode.computeThisFunctionType( Nullability.nonNullable, ); final fn = FunctionDeclaration( VariableDeclaration( - "#${node.name}#initializer", + "#${node.variable.name}#initializer", type: functionType, isSynthesized: true, ), fnNode, )..id = localFunctionIdGenerator.allocateId(); - node.initializer = LocalFunctionInvocation( + node.variable.initializer = LocalFunctionInvocation( fn.variable, Arguments([]), functionType: functionType, - )..parent = node; + )..parent = node.variable; return [fn, node]; } @@ -71,7 +71,7 @@ class LateVarInitTransformer { if (_shouldApplyTransform(s)) { newStatements.addAll( _transformVariableDeclaration( - s as VariableDeclaration, + s as VariableStatement, localFunctionIdGenerator, ), ); diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart index 1f8dcd70a4a..41845317172 100644 --- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart +++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart @@ -409,7 +409,7 @@ class _VariablesInfoCollector extends RecursiveVisitor { } @override - visitVariableDeclaration(VariableDeclaration node) { + defaultVariableDeclaration(VariableDeclaration node) { final int index = numVariables; varDeclarations.add(node); varIndex[node] = index; @@ -2600,7 +2600,7 @@ class SummaryCollector extends RecursiveResultVisitor { @override TypeExpr? visitForStatement(ForStatement node) { - node.variables.forEach(visitVariableDeclaration); + node.variables.forEach((v) => defaultVariableDeclaration(v.variable)); final List joins = _insertJoinsForModifiedVariables(node, false); final trueState = _cloneVariableValues(_variableValues); final falseState = _cloneVariableValues(_variableValues); @@ -2808,15 +2808,22 @@ class SummaryCollector extends RecursiveResultVisitor { } @override - TypeExpr? visitVariableDeclaration(VariableDeclaration node) { - node.annotations.forEach(_visitAnnotation); - final initializer = node.initializer; + TypeExpr? visitLegacyVariableStatement(LegacyVariableStatement node) { + defaultVariableDeclaration(node.variable); + return null; + } + + TypeExpr? defaultVariableDeclaration(VariableDeclaration node) { + final variable = node.variable; + variable.annotations.forEach(_visitAnnotation); + final initializer = variable.initializer; final TypeExpr initialValue = initializer == null - ? ((node.type.nullability == Nullability.nonNullable || node.isLate) + ? ((variable.type.nullability == Nullability.nonNullable || + variable.isLate) ? emptyType : _nullType) : _visit(initializer); - _declareVariable(node, initialValue); + _declareVariable(variable, initialValue); return null; } @@ -2886,7 +2893,7 @@ class SummaryCollector extends RecursiveResultVisitor { @override TypeExpr? visitLocalInitializer(LocalInitializer node) { - visitVariableDeclaration(node.variable); + defaultVariableDeclaration(node.variable); return null; } diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart index f57bf6fe7b5..0424f71ad0a 100644 --- a/pkg/vm/lib/transformations/type_flow/transformer.dart +++ b/pkg/vm/lib/transformations/type_flow/transformer.dart @@ -899,12 +899,12 @@ class AnnotateKernel extends RecursiveVisitor { } @override - visitVariableDeclaration(VariableDeclaration node) { + defaultVariableDeclaration(VariableDeclaration node) { final inferredType = _typeFlowAnalysis.capturedVariableType(node); if (inferredType != null) { _setInferredType(node, inferredType); } - super.visitVariableDeclaration(node); + super.defaultVariableDeclaration(node); } @override diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect index 53f1c940c57..7014027f5ab 100644 --- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect +++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect @@ -12,13 +12,13 @@ RESULT: t3 %this = _Parameter #0 [_T (#lib::C)+] %x = _Parameter #1 t2 = _Extract (%this[#lib::C/0]) -t3 = _TypeCheck (%x against t2) (for #lib::C.T% x;) +t3 = _TypeCheck (%x against t2) (for #lib::C.T% x) RESULT: t3 ------------ C.id2 ------------ %this = _Parameter #0 [_T (#lib::C)+] %x = _Parameter #1 t2 = _Extract (%this[#lib::C/0]) -t3 = _TypeCheck (%x against t2) (for #lib::C.T% x;) +t3 = _TypeCheck (%x against t2) (for #lib::C.T% x) RESULT: t3 ------------ D. ------------ %this = _Parameter #0 [_T (#lib::D)+] @@ -77,7 +77,7 @@ RESULT: _T {} %x = _Parameter #1 t2 = _Extract (%this[#lib::C2/0]) t3 = _CreateRuntimeType (dart.core::Comparable @ (t2)) -t4 = _TypeCheck (%x against t3) (for dart.core::Comparable<#lib::C2.T%> x;) +t4 = _TypeCheck (%x against t3) (for dart.core::Comparable<#lib::C2.T%> x) RESULT: t4 ------------ C2.id4 ------------ %this = _Parameter #0 [_T (#lib::C2)+] @@ -85,7 +85,7 @@ RESULT: t4 t2 = _Extract (%this[#lib::C2/0]) t3 = _CreateRuntimeType (#lib::I @ (t2)) t4 = _CreateRuntimeType (#lib::K @ (t3)) -t5 = _TypeCheck (%x against t4) (for #lib::K<#lib::I<#lib::C2.T%>> x;) +t5 = _TypeCheck (%x against t4) (for #lib::K<#lib::I<#lib::C2.T%>> x) RESULT: t5 ------------ main ------------ t0* = _Call direct [#lib::C.] (_T (#lib::C)) diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect index f15002efc11..eb3653813e3 100644 --- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect +++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect @@ -17,9 +17,9 @@ RESULT: _T {} %key = _Parameter #1 %value = _Parameter #2 t3 = _Extract (%this[#lib::_NotRealHashMap/0]) -t4 = _TypeCheck (%key against t3) (for #lib::_NotRealHashMap.K% key;) +t4 = _TypeCheck (%key against t3) (for #lib::_NotRealHashMap.K% key) t5 = _Extract (%this[#lib::_NotRealHashMap/1]) -t6 = _TypeCheck (%value against t5) (for #lib::_NotRealHashMap.V% value;) +t6 = _TypeCheck (%value against t5) (for #lib::_NotRealHashMap.V% value) RESULT: _T {}? ------------ InheritedElement. ------------ %this = _Parameter #0 [_T (#lib::InheritedElement)+]