From 8e2d140fa5c1ae50a2704c14c30f8c062430bb4e Mon Sep 17 00:00:00 2001 From: Johnni Winther Date: Thu, 11 Jun 2026 02:43:16 -0700 Subject: [PATCH] [cfe][InternalNodes] Implement InternalVariable directly This updates the InternalVariable hierarchy to be based on a sealed base class InternalVariable with no connection to IVariable. IVariable is removed and unused properties of InternalVariable are removed. TEST=existing Change-Id: Iacfbe9ab21d1c9aab043712099cd1ee6e4cee174 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/510825 Reviewed-by: Alexander Markov Reviewed-by: Nicholas Shahan Reviewed-by: Chloe Stefantsova Commit-Queue: Johnni Winther --- pkg/cfg/lib/front_end/ast_to_ir.dart | 9 +- pkg/cfg/lib/front_end/computed_scopes.dart | 2 +- pkg/compiler/lib/src/ir/scope_visitor.dart | 2 +- pkg/dart2bytecode/lib/bytecode_generator.dart | 8 +- pkg/dart2bytecode/lib/local_vars.dart | 4 +- .../lib/src/kernel/body_builder.dart | 16 +- .../lib/src/kernel/internal_ast.dart | 580 +++--------------- .../lib/src/kernel/internal_ast_helper.dart | 3 - .../lib/src/kernel/resolver_helpers.dart | 3 - .../src/type_inference/inference_visitor.dart | 8 +- .../inference_visitor_base.dart | 6 +- .../lib/src/type_inference/type_inferrer.dart | 2 +- ...internal_ast_text_representation_test.dart | 24 +- pkg/kernel/lib/src/ast/variables.dart | 165 +---- pkg/kernel/lib/src/printer.dart | 2 +- pkg/kernel/lib/text/ast_to_text.dart | 2 +- pkg/kernel/lib/verifier.dart | 2 +- .../type_flow/summary_collector.dart | 12 +- 18 files changed, 128 insertions(+), 722 deletions(-) diff --git a/pkg/cfg/lib/front_end/ast_to_ir.dart b/pkg/cfg/lib/front_end/ast_to_ir.dart index 9bcebd0d003..f3a78be4a21 100644 --- a/pkg/cfg/lib/front_end/ast_to_ir.dart +++ b/pkg/cfg/lib/front_end/ast_to_ir.dart @@ -920,11 +920,10 @@ class AstToIr extends ast.RecursiveVisitor { @override void defaultVariable(ast.Variable node) { - final variable = node.variable; if (node.isConst) return; if (node.isLate) { builder.addSentinelConstant(); - _writeVariable(variable); + _writeVariable(node); } else { final initializer = node.initializer; if (initializer != null) { @@ -933,11 +932,11 @@ class AstToIr extends ast.RecursiveVisitor { builder.pop(); return; } - _writeVariable(variable); + _writeVariable(node); } else if (node.type.nullability == ast.Nullability.nullable && - !_isCaptured(variable)) { + !_isCaptured(node)) { builder.addNullConstant(); - _writeVariable(variable); + _writeVariable(node); } } } diff --git a/pkg/cfg/lib/front_end/computed_scopes.dart b/pkg/cfg/lib/front_end/computed_scopes.dart index 941356c2145..697738577cd 100644 --- a/pkg/cfg/lib/front_end/computed_scopes.dart +++ b/pkg/cfg/lib/front_end/computed_scopes.dart @@ -310,7 +310,7 @@ class _ScopeBuilder extends ast.RecursiveVisitor { @override void defaultVariable(ast.Variable node) { - _declareVariable(node.variable); + _declareVariable(node); node.visitChildren(this); } diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart index 3558bb8b1fc..b2281639116 100644 --- a/pkg/compiler/lib/src/ir/scope_visitor.dart +++ b/pkg/compiler/lib/src/ir/scope_visitor.dart @@ -329,7 +329,7 @@ class ScopeModelBuilder extends ir.VisitorDefault @override EvaluationComplexity defaultVariable(ir.Variable node) { - _handleVariableDeclaration(node.variable, SimpleVariableUse.localType); + _handleVariableDeclaration(node, SimpleVariableUse.localType); return const EvaluationComplexity.lazy(); } diff --git a/pkg/dart2bytecode/lib/bytecode_generator.dart b/pkg/dart2bytecode/lib/bytecode_generator.dart index bef3a778a5b..b1f492889a2 100644 --- a/pkg/dart2bytecode/lib/bytecode_generator.dart +++ b/pkg/dart2bytecode/lib/bytecode_generator.dart @@ -4903,7 +4903,7 @@ class BytecodeGenerator extends RecursiveVisitor { void _handleVariableInitialization(Variable node) { if (!node.isConst) { - final bool isCaptured = locals.isCaptured(node.variable); + final bool isCaptured = locals.isCaptured(node); final initializer = node.initializer; final bool emitStore = !_skipVariableInitialization(node, isCaptured); int maxInitializerPosition = node.fileOffset; @@ -4919,7 +4919,7 @@ class BytecodeGenerator extends RecursiveVisitor { } asm.emitSourcePosition(); if (isCaptured) { - _genPushContextForVariable(node.variable); + _genPushContextForVariable(node); } if (node.isLate && !_isTrivialInitializer(initializer)) { asm.emitPushUninitializedSentinel(); @@ -4933,11 +4933,11 @@ class BytecodeGenerator extends RecursiveVisitor { } if (options.emitLocalVarInfo && !asm.isUnreachable && node.name != null) { - _declareLocalVariable(node.variable, maxInitializerPosition + 1); + _declareLocalVariable(node, maxInitializerPosition + 1); } if (emitStore) { - _genStoreVar(node.variable); + _genStoreVar(node); } } } diff --git a/pkg/dart2bytecode/lib/local_vars.dart b/pkg/dart2bytecode/lib/local_vars.dart index 785aae2b849..db159348029 100644 --- a/pkg/dart2bytecode/lib/local_vars.dart +++ b/pkg/dart2bytecode/lib/local_vars.dart @@ -514,7 +514,7 @@ class _ScopeBuilder extends RecursiveVisitor { @override void defaultVariable(Variable node) { - _declareVariable(node.variable); + _declareVariable(node); node.visitChildren(this); } @@ -1018,7 +1018,7 @@ class _Allocator extends RecursiveVisitor { @override void defaultVariable(Variable node) { - _allocateVariable(node.variable); + _allocateVariable(node); node.visitChildren(this); } diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart index 5df49bc3c15..97b4db1e38f 100644 --- a/pkg/front_end/lib/src/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/kernel/body_builder.dart @@ -3572,9 +3572,9 @@ class BodyBuilderImpl extends StackListenerImpl node as InternalVariableDeclaration; if (annotations != null) { for (int i = 0; i < annotations.length; i++) { - declaration.variable.addAnnotation(annotations[i]); + declaration.variable.astVariable.addAnnotation(annotations[i]); } - _registerSingleTargetAnnotations(declaration.variable); + _registerSingleTargetAnnotations(declaration.variable.astVariable); } // TODO(johnniwinther): Should [VariableStatement] use offset from // [endToken]? @@ -3597,10 +3597,10 @@ class BodyBuilderImpl extends StackListenerImpl if (annotations != null) { InternalVariableDeclaration first = variables.first; for (int i = 0; i < annotations.length; i++) { - first.variable.addAnnotation(annotations[i]); + first.variable.astVariable.addAnnotation(annotations[i]); } _registerMultiTargetAnnotations( - variables.map((v) => v.variable).toList(), + variables.map((v) => v.variable.astVariable).toList(), ); } push(intern.variablesDeclaration(variables, uri)); @@ -5533,14 +5533,14 @@ class BodyBuilderImpl extends StackListenerImpl ..parent = functionParameter; } if (annotations != null) { - functionParameter.clearAnnotations(); + functionParameter.astVariable.clearAnnotations(); for (Expression annotation in annotations) { - functionParameter.addAnnotation(annotation); + functionParameter.astVariable.addAnnotation(annotation); } // TODO(johnniwinther): This seems wrong. If we add the annotations, we // should infer them. if (functionNestingLevel == 0) { - _registerSingleTargetAnnotations(functionParameter); + _registerSingleTargetAnnotations(functionParameter.astVariable); } } } @@ -7885,7 +7885,7 @@ class BodyBuilderImpl extends StackListenerImpl InternalVariable variable = declaration.variable; if (annotations != null) { for (Expression annotation in annotations) { - variable.addAnnotation(annotation); + variable.astVariable.addAnnotation(annotation); } } declaration.hasImplicitReturnType = hasImplicitReturnType; diff --git a/pkg/front_end/lib/src/kernel/internal_ast.dart b/pkg/front_end/lib/src/kernel/internal_ast.dart index 4e6e4f8d455..cde99795675 100644 --- a/pkg/front_end/lib/src/kernel/internal_ast.dart +++ b/pkg/front_end/lib/src/kernel/internal_ast.dart @@ -1154,9 +1154,7 @@ class ReturnStatementImpl extends ReturnStatement { } /// Front end specific implementation of [Variable]. -class InternalLegacyVariable extends TreeNode - with InternalVariableMixin, DelegatingVariableMixin - implements LegacyVariable, InternalVariable { +class InternalLegacyVariable extends InternalVariable { @override final Variable astVariable; @@ -1177,25 +1175,23 @@ class InternalLegacyVariable extends TreeNode bool isStaticLate = false, bool isLateFinalWithoutInitializer = false, required int fileOffset, - int fileEqualsOffset = TreeNode.noOffset, }) : isLocalFunction = isLocalFunction { this.isStaticLate = isStaticLate; this.isLateFinalWithoutInitializer = isLateFinalWithoutInitializer; this.fileOffset = fileOffset; - this.fileEqualsOffset = fileEqualsOffset; } @override bool get isAssignable { if (isStaticLate) return true; - return super.isAssignable; + return astVariable.isAssignable; } @override // Coverage-ignore(suite): Not run. void toTextInternal(AstPrinter printer) { printer.writeVariableInitialization( - this, + astVariable, isLate: isLate || lateGetter != null, isImplicitlyTyped: isImplicitlyTyped, type: lateType ?? type, @@ -1208,9 +1204,7 @@ class InternalLegacyVariable extends TreeNode } } -class InternalLocalVariable extends TreeNode - with InternalVariableMixin, DelegatingVariableMixin - implements LocalVariable, InternalVariable { +class InternalLocalVariable extends InternalVariable { @override LocalVariable astVariable; @@ -1234,7 +1228,6 @@ class InternalLocalVariable extends TreeNode }) { this.fileOffset = fileOffset; this.isStaticLate = isStaticLate; - this.fileEqualsOffset = fileEqualsOffset; } @override @@ -1270,43 +1263,9 @@ class InternalLocalVariable extends TreeNode printer.write("[${modifiers.join(",")}]"); } } - - @override - int binaryOffsetNoTag = -1; - - @override - // Coverage-ignore(suite): Not run. - List? get capturedContexts => - variableDeclaration?.capturedContexts; - - @override - // Coverage-ignore(suite): Not run. - void set capturedContexts(List? value) { - variableDeclaration!.capturedContexts = value; - } - - @override - int fileEqualsOffset = TreeNode.noOffset; - - @override - // Coverage-ignore(suite): Not run. - Variable get variable => this; - - @override - void set variable(Variable variable) { - throw new UnsupportedError("${this.runtimeType}.variable="); - } - - @override - // Coverage-ignore(suite): Not run. - void clearAnnotations() { - annotations.clear(); - } } -class InternalLateVariable extends TreeNode - with InternalVariableMixin, DelegatingVariableMixin - implements LateVariable, InternalVariable { +class InternalLateVariable extends InternalVariable { @override LateVariable astVariable; @@ -1326,11 +1285,9 @@ class InternalLateVariable extends TreeNode this.isLocalFunction = false, bool isStaticLate = false, required int fileOffset, - int fileEqualsOffset = TreeNode.noOffset, }) { this.fileOffset = fileOffset; this.isStaticLate = isStaticLate; - this.fileEqualsOffset = fileEqualsOffset; } @override @@ -1366,43 +1323,9 @@ class InternalLateVariable extends TreeNode printer.write("[${modifiers.join(",")}]"); } } - - @override - int binaryOffsetNoTag = -1; - - @override - // Coverage-ignore(suite): Not run. - List? get capturedContexts => - variableDeclaration?.capturedContexts; - - @override - // Coverage-ignore(suite): Not run. - void set capturedContexts(List? value) { - variableDeclaration!.capturedContexts = value; - } - - @override - int fileEqualsOffset = TreeNode.noOffset; - - @override - // Coverage-ignore(suite): Not run. - Variable get variable => this; - - @override - void set variable(Variable variable) { - throw new UnsupportedError("${this.runtimeType}.variable="); - } - - @override - // Coverage-ignore(suite): Not run. - void clearAnnotations() { - annotations.clear(); - } } -class InternalPositionalParameter extends TreeNode - with InternalVariableMixin, DelegatingVariableMixin - implements PositionalParameter, InternalVariable { +class InternalPositionalParameter extends InternalVariable { @override PositionalParameter astVariable; @@ -1425,18 +1348,6 @@ class InternalPositionalParameter extends TreeNode this.fileOffset = fileOffset; } - @override - // TODO(62620): Conforming to [Variable] interface. Remove this. - List? get capturedContexts { - throw new UnsupportedError("${this.runtimeType}.capturedContexts"); - } - - @override - // TODO(62620): Conforming to [Variable] interface. Remove this. - void set capturedContexts(List? value) { - throw new UnsupportedError("${this.runtimeType}.capturedContexts="); - } - @override // Coverage-ignore(suite): Not run. R accept(VariableVisitor v) => v.visitPositionalParameter(astVariable); @@ -1465,51 +1376,24 @@ class InternalPositionalParameter extends TreeNode } } - @override // Coverage-ignore(suite): Not run. Expression? get defaultValue => astVariable.defaultValue; - @override // Coverage-ignore(suite): Not run. void set defaultValue(Expression? value) { astVariable.defaultValue = value; } - @override // Coverage-ignore(suite): Not run. bool get hasDeclaredDefaultValue => astVariable.hasDeclaredDefaultValue; - @override // Coverage-ignore(suite): Not run. void set hasDeclaredDefaultValue(bool value) { astVariable.hasDeclaredDefaultValue = value; } - - @override - // Coverage-ignore(suite): Not run. - void clearAnnotations() { - astVariable.clearAnnotations(); - } - - @override - int binaryOffsetNoTag = -1; - - @override - int fileEqualsOffset = TreeNode.noOffset; - - @override - // Coverage-ignore(suite): Not run. - Variable get variable => this; - - @override - void set variable(Variable value) { - throw new UnsupportedError("${this.runtimeType}"); - } } -class InternalNamedParameter extends TreeNode - with InternalVariableMixin, DelegatingVariableMixin - implements NamedParameter, InternalVariable { +class InternalNamedParameter extends InternalVariable { @override NamedParameter astVariable; @@ -1532,18 +1416,6 @@ class InternalNamedParameter extends TreeNode this.fileOffset = fileOffset; } - @override - // TODO(62620): Conforming to [Variable] interface. Remove this. - List? get capturedContexts { - throw new UnsupportedError("${this.runtimeType}.capturedContexts"); - } - - @override - // TODO(62620): Conforming to [Variable] interface. Remove this. - void set capturedContexts(List? value) { - throw new UnsupportedError("${this.runtimeType}.capturedContexts="); - } - @override // Coverage-ignore(suite): Not run. R accept(VariableVisitor v) => v.visitNamedParameter(astVariable); @@ -1572,70 +1444,22 @@ class InternalNamedParameter extends TreeNode } } - @override // Coverage-ignore(suite): Not run. Expression? get defaultValue => astVariable.defaultValue; - @override // Coverage-ignore(suite): Not run. void set defaultValue(Expression? value) { astVariable.defaultValue = value; } - @override // Coverage-ignore(suite): Not run. bool get hasDeclaredDefaultValue => astVariable.hasDeclaredDefaultValue; - @override - // Coverage-ignore(suite): Not run. - void set hasDeclaredDefaultValue(bool value) { - astVariable.hasDeclaredDefaultValue = value; - } - - @override - // Coverage-ignore(suite): Not run. - void clearAnnotations() { - astVariable.clearAnnotations(); - } - - @override - List get annotations => astVariable.annotations; - - @override - // Coverage-ignore(suite): Not run. - void addAnnotation(Expression node) { - astVariable.addAnnotation(node); - } - - @override // Coverage-ignore(suite): Not run. String get parameterName => astVariable.parameterName; - - @override - // Coverage-ignore(suite): Not run. - void set parameterName(String value) { - astVariable.parameterName = value; - } - - @override - int binaryOffsetNoTag = -1; - - @override - int fileEqualsOffset = TreeNode.noOffset; - - @override - // Coverage-ignore(suite): Not run. - Variable get variable => this; - - @override - void set variable(Variable value) { - throw new UnsupportedError("${this.runtimeType}"); - } } -class InternalCatchVariable extends TreeNode - with InternalVariableMixin, DelegatingVariableMixin - implements CatchVariable, InternalVariable { +class InternalCatchVariable extends InternalVariable { @override CatchVariable astVariable; @@ -1677,15 +1501,12 @@ class InternalCatchVariable extends TreeNode } } - @override // Coverage-ignore(suite): Not run. String get catchVariableName => astVariable.catchVariableName; } // Coverage-ignore(suite): Not run. -class InternalSyntheticVariable extends TreeNode - with InternalVariableMixin, DelegatingVariableMixin - implements SyntheticVariable, InternalVariable { +class InternalSyntheticVariable extends InternalVariable { @override SyntheticVariable astVariable; @@ -1727,9 +1548,68 @@ class InternalSyntheticVariable extends TreeNode } } -mixin DelegatingVariableMixin on InternalVariableMixin - implements InternalVariable { - @override +sealed class InternalVariable extends TreeNode with InternalTreeNode { + /// This is the output variable that the clients receive. + /// + /// Most of the calls to variable properties are delegated to [astVariable], + /// but some operations must be performed directly on [astVariable], as + /// follows: + /// + /// * passing [astVariable] into the flow analysis engine, + /// * using [astVariable] as a part of the generated AST, + /// * checking semantic properties of an AST node, such as [isExtensionThis] + /// in `lowering_predicates.dart`. + Variable get astVariable; + + bool get forSyntheticToken; + + /// Determine whether the given [InternalVariable] had an implicit + /// type. + bool get isImplicitlyTyped; + + /// Determines whether the given [InternalVariable] represents a + /// local function. + bool get isLocalFunction; + + /// Whether the variable is final with no initializer. + /// + /// Such variables behave similar to those declared with the `late` keyword, + /// except that the don't have lazy evaluation semantics, and it is statically + /// verified by the front end that they are always assigned before they are + /// used. + bool isStaticLate = false; + + /// The synthesized local getter function for a lowered late variable. + /// + /// This is set in `InferenceVisitor.visitVariableDeclaration` when late + /// lowering is enabled. + Variable? lateGetter; + + /// The synthesized local setter function for an assignable lowered late + /// variable. + /// + /// This is set in `InferenceVisitor.visitVariableDeclaration` when late + /// lowering is enabled. + Variable? lateSetter; + + /// Is `true` if this a lowered late final variable without an initializer. + /// + /// This is set in `InferenceVisitor.visitVariableDeclaration` when late + /// lowering is enabled. + bool isLateFinalWithoutInitializer = false; + + /// The original type (declared or inferred) of a lowered late variable. + /// + /// This is set in `InferenceVisitor.visitVariableDeclaration` when late + /// lowering is enabled. + DartType? lateType; + + /// The original name of a lowered late variable. + /// + /// This is set in `InferenceVisitor.visitVariableDeclaration` when late + /// lowering is enabled. + String? lateName; + String? get cosmeticName => astVariable.cosmeticName; @override @@ -1740,240 +1620,82 @@ mixin DelegatingVariableMixin on InternalVariableMixin astVariable.parent = value; } - @override - List get annotations => astVariable.annotations; - - @override - // Coverage-ignore(suite): Not run. - void set annotations(List value) { - astVariable.annotations = value; - } - - @override - void addAnnotation(Expression node) { - astVariable.addAnnotation(node); - } - - @override void set cosmeticName(String? value) { astVariable.cosmeticName = value; } - @override bool get hasDeclaredInitializer => astVariable.hasDeclaredInitializer; - @override void set hasDeclaredInitializer(bool value) { astVariable.hasDeclaredInitializer = value; } - @override Expression? get initializer => astVariable.initializer; - @override void set initializer(Expression? value) { astVariable.initializer = value; } - @override bool get isConst => astVariable.isConst; - @override void set isConst(bool value) { astVariable.isConst = value; } - @override - // Coverage-ignore(suite): Not run. - bool get isCovariantByClass => astVariable.isCovariantByClass; - - @override - // Coverage-ignore(suite): Not run. - void set isCovariantByClass(bool value) { - astVariable.isCovariantByClass = value; - } - - @override - // Coverage-ignore(suite): Not run. - bool get isCovariantByDeclaration => astVariable.isCovariantByDeclaration; - - @override - // Coverage-ignore(suite): Not run. - void set isCovariantByDeclaration(bool value) { - astVariable.isCovariantByDeclaration = value; - } - - @override bool get isErroneouslyInitialized => astVariable.isErroneouslyInitialized; - @override void set isErroneouslyInitialized(bool value) { astVariable.isErroneouslyInitialized = value; } - @override bool get isFinal => astVariable.isFinal; - @override void set isFinal(bool value) { astVariable.isFinal = value; } - @override - // Coverage-ignore(suite): Not run. - bool get isHoisted => astVariable.isHoisted; - - @override - // Coverage-ignore(suite): Not run. - void set isHoisted(bool value) { - astVariable.isHoisted = value; - } - - @override - // Coverage-ignore(suite): Not run. - bool get isInitializingFormal => astVariable.isInitializingFormal; - - @override - // Coverage-ignore(suite): Not run. - void set isInitializingFormal(bool value) { - astVariable.isInitializingFormal = value; - } - - @override bool get isLate => astVariable.isLate; - @override void set isLate(bool value) { astVariable.isLate = value; } - @override // Coverage-ignore(suite): Not run. bool get isLowered => astVariable.isLowered; - @override void set isLowered(bool value) { astVariable.isLowered = value; } - @override bool get isRequired => astVariable.isRequired; - @override // Coverage-ignore(suite): Not run. void set isRequired(bool value) { astVariable.isRequired = value; } - @override - // Coverage-ignore(suite): Not run. - bool get isSuperInitializingFormal => astVariable.isSuperInitializingFormal; - - @override - // Coverage-ignore(suite): Not run. - void set isSuperInitializingFormal(bool value) { - astVariable.isSuperInitializingFormal = value; - } - - @override bool get isSynthesized => astVariable.isSynthesized; - @override // Coverage-ignore(suite): Not run. void set isSynthesized(bool value) { astVariable.isSynthesized = value; } - @override bool get isWildcard => astVariable.isWildcard; - @override // Coverage-ignore(suite): Not run. void set isWildcard(bool value) { astVariable.isWildcard = value; } - @override DartType get type => astVariable.type; - @override void set type(DartType value) { astVariable.type = value; } - @override - // Coverage-ignore(suite): Not run. - VariableDeclaration? get variableDeclaration => - astVariable.variableDeclaration; - - @override - // Coverage-ignore(suite): Not run. - void set variableDeclaration(VariableDeclaration? value) { - astVariable.variableDeclaration = value; - } - - @override bool get isAssignable => astVariable.isAssignable; - @override - // Coverage-ignore(suite): Not run. - bool get hasIsFinal => astVariable.hasIsFinal; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsConst => astVariable.hasIsConst; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsLate => astVariable.hasIsLate; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsInitializingFormal => astVariable.hasIsInitializingFormal; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsSynthesized => astVariable.hasIsSynthesized; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsHoisted => astVariable.hasIsHoisted; - - @override - // Coverage-ignore(suite): Not run. - bool get hasHasDeclaredInitializer => astVariable.hasHasDeclaredInitializer; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsCovariantByClass => astVariable.hasIsCovariantByClass; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsRequired => astVariable.hasIsRequired; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsCovariantByDeclaration => - astVariable.hasIsCovariantByDeclaration; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsLowered => astVariable.hasIsLowered; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsWildcard => astVariable.hasIsWildcard; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsSuperInitializingFormal => - astVariable.hasIsSuperInitializingFormal; - - @override - // Coverage-ignore(suite): Not run. - bool get hasIsErroneouslyInitialized => - astVariable.hasIsErroneouslyInitialized; - @override int get fileOffset => astVariable.fileOffset; @@ -1982,14 +1704,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin astVariable.fileOffset = value; } - // Coverage-ignore(suite): Not run. - int get flags => astVariable.flags; - - // Coverage-ignore(suite): Not run. - void set flags(int value) { - astVariable.flags = value; - } - @override // Coverage-ignore(suite): Not run. R accept(VariableVisitor v) { @@ -2010,16 +1724,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin astVariable.cosmeticName = value; } - @override - // Coverage-ignore(suite): Not run. - VariableContext get context => astVariable.context; - - @override - // Coverage-ignore(suite): Not run. - void set context(VariableContext value) { - astVariable.context = value; - } - @override Component? get enclosingComponent { throw new UnsupportedError("${this.runtimeType}"); @@ -2081,144 +1785,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin void visitChildren(Visitor v) { throw new UnsupportedError("${this.runtimeType}"); } - - @override - // Coverage-ignore(suite): Not run. - int get binaryOffsetNoTag => astVariable.binaryOffsetNoTag; - - @override - // Coverage-ignore(suite): Not run. - void set binaryOffsetNoTag(int value) { - astVariable.binaryOffsetNoTag = value; - } - - @override - // Coverage-ignore(suite): Not run. - List? get capturedContexts => astVariable.capturedContexts; - - @override - // Coverage-ignore(suite): Not run. - void set capturedContexts(List? value) { - astVariable.capturedContexts = value; - } - - @override - // Coverage-ignore(suite): Not run. - int get fileEqualsOffset => astVariable.fileEqualsOffset; - - @override - void set fileEqualsOffset(int value) { - astVariable.fileEqualsOffset = value; - } - - @override - Variable get variable => astVariable.variable; - - @override - // Coverage-ignore(suite): Not run. - void set variable(Variable value) { - astVariable.variable = value; - } - - @override - void clearAnnotations() { - astVariable.clearAnnotations(); - } -} - -abstract interface class InternalVariable implements IVariable, Annotatable { - /// This is the output variable that the clients receive. - /// - /// Most of the calls to variable properties are delegated to [astVariable], - /// but some operations must be performed directly on [astVariable], as - /// follows: - /// - /// * passing [astVariable] into the flow analysis engine, - /// * using [astVariable] as a part of the generated AST, - /// * checking semantic properties of an AST node, such as [isExtensionThis] - /// in `lowering_predicates.dart`. - Variable get astVariable; - - bool get forSyntheticToken; - - /// Determine whether the given [InternalVariable] had an implicit - /// type. - bool get isImplicitlyTyped; - - /// Determines whether the given [InternalVariable] represents a - /// local function. - bool get isLocalFunction; - - /// Whether the variable is final with no initializer. - /// - /// Such variables behave similar to those declared with the `late` keyword, - /// except that the don't have lazy evaluation semantics, and it is statically - /// verified by the front end that they are always assigned before they are - /// used. - abstract bool isStaticLate; - - /// The synthesized local getter function for a lowered late variable. - /// - /// This is set in `InferenceVisitor.visitVariableDeclaration` when late - /// lowering is enabled. - abstract Variable? lateGetter; - - /// The synthesized local setter function for an assignable lowered late - /// variable. - /// - /// This is set in `InferenceVisitor.visitVariableDeclaration` when late - /// lowering is enabled. - abstract Variable? lateSetter; - - /// Is `true` if this a lowered late final variable without an initializer. - /// - /// This is set in `InferenceVisitor.visitVariableDeclaration` when late - /// lowering is enabled. - abstract bool isLateFinalWithoutInitializer; - - /// The original type (declared or inferred) of a lowered late variable. - /// - /// This is set in `InferenceVisitor.visitVariableDeclaration` when late - /// lowering is enabled. - abstract DartType? lateType; - - /// The original name of a lowered late variable. - /// - /// This is set in `InferenceVisitor.visitVariableDeclaration` when late - /// lowering is enabled. - abstract String? lateName; - - @override - abstract List annotations; -} - -mixin InternalVariableMixin on TreeNode implements InternalVariable { - @override - bool get forSyntheticToken; - - @override - bool get isImplicitlyTyped; - - @override - bool get isLocalFunction; - - @override - bool isStaticLate = false; - - @override - Variable? lateGetter; - - @override - Variable? lateSetter; - - @override - bool isLateFinalWithoutInitializer = false; - - @override - DartType? lateType; - - @override - String? lateName; } /// Front end specific implementation of [LoadLibrary]. @@ -8417,9 +7983,7 @@ class InternalLet extends InternalExpression { } } -class InternalThisVariable extends TreeNode - with InternalVariableMixin, DelegatingVariableMixin - implements ThisVariable, InternalVariable { +class InternalThisVariable extends InternalVariable { @override final ThisVariable astVariable; 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 9dbef53f6ea..e058ab7efc1 100644 --- a/pkg/front_end/lib/src/kernel/internal_ast_helper.dart +++ b/pkg/front_end/lib/src/kernel/internal_ast_helper.dart @@ -676,7 +676,6 @@ InternalVariable createLateVariable({ forSyntheticToken: forSyntheticToken, isImplicitlyTyped: isImplicitlyTyped, isStaticLate: isStaticLate, - fileEqualsOffset: fileEqualsOffset, fileOffset: fileOffset, ); } else { @@ -696,7 +695,6 @@ InternalVariable createLateVariable({ fileOffset: fileOffset, forSyntheticToken: forSyntheticToken, isStaticLate: isStaticLate, - fileEqualsOffset: fileEqualsOffset, isImplicitlyTyped: isImplicitlyTyped, ); } @@ -809,7 +807,6 @@ InternalVariable createLocalVariable({ forSyntheticToken: forSyntheticToken, isLocalFunction: isLocalFunction, isStaticLate: isStaticLate, - fileEqualsOffset: fileEqualsOffset, isImplicitlyTyped: isImplicitlyTyped, ); } diff --git a/pkg/front_end/lib/src/kernel/resolver_helpers.dart b/pkg/front_end/lib/src/kernel/resolver_helpers.dart index 1a7e88c4f3f..2f7b3b94493 100644 --- a/pkg/front_end/lib/src/kernel/resolver_helpers.dart +++ b/pkg/front_end/lib/src/kernel/resolver_helpers.dart @@ -127,9 +127,6 @@ class _ResolverContext { required SingleTargetAnnotations singleTarget, }) { Annotatable target = singleTarget.target; - if (target is InternalVariable) { - target = target.astVariable; - } _inferAnnotations( annotatable: target, indices: singleTarget.indicesOfAnnotationsToBeInferred, 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 444593b28d3..e7b1164ca27 100644 --- a/pkg/front_end/lib/src/type_inference/inference_visitor.dart +++ b/pkg/front_end/lib/src/type_inference/inference_visitor.dart @@ -3619,7 +3619,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase InternalVariable variable = node.variable; flowAnalysis.functionExpression_begin(node); _returnContexts.push(const StandardReturnContext()); - inferMetadata(this, variable); + inferMetadata(this, variable.astVariable); LocalFunctionResult localFunctionResult = _visitInternalFunctionNode( function, typeContext: null, @@ -17567,11 +17567,11 @@ class InferenceVisitorImpl extends InferenceVisitorBase Expression createVariableRead({bool needsPromotion = false}) { if (needsPromotion) { return new VariableGet( - internalVariable.variable, + internalVariable.astVariable, internalVariable.type, )..fileOffset = fileOffset; } else { - return new VariableGet(internalVariable.variable) + return new VariableGet(internalVariable.astVariable) ..fileOffset = fileOffset; } } @@ -17579,7 +17579,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase Expression createIsSetRead() => new VariableGet(isSetVariable!)..fileOffset = fileOffset; Expression createVariableWrite(Expression value) => - new VariableSet(internalVariable.variable, value); + new VariableSet(internalVariable.astVariable, value); Expression createIsSetWrite(Expression value) => new VariableSet(isSetVariable!, value); 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 28eb5cff72b..3ded1dbaed5 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 @@ -2306,7 +2306,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor { new SharedTypeView(parameter.type), initialized: true, ); - inferMetadata(visitor, parameter); + inferMetadata(visitor, parameter.astVariable); if (parameter.initializer != null) { ExpressionInferenceResult initializerResult = visitor.inferExpression( parameter.initializer!, @@ -2322,7 +2322,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor { new SharedTypeView(parameter.type), initialized: true, ); - inferMetadata(visitor, parameter); + inferMetadata(visitor, parameter.astVariable); if (parameter.initializer != null) { ExpressionInferenceResult initializerResult = visitor.inferExpression( parameter.initializer!, @@ -2423,7 +2423,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor { ); } - /// Infers the [annotations]. + /// Infers the annotations of [annotatable]. /// /// If [indices] is provided, only the annotations at the given indices are /// inferred. Otherwise all annotations are inferred. diff --git a/pkg/front_end/lib/src/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/type_inference/type_inferrer.dart index ef4a29e80e1..7aec451cc8c 100644 --- a/pkg/front_end/lib/src/type_inference/type_inferrer.dart +++ b/pkg/front_end/lib/src/type_inference/type_inferrer.dart @@ -85,7 +85,7 @@ abstract class TypeInferrer { required bool isConstructorWithoutBody, }); - /// Performs type inference on the given metadata [annotations]. + /// Performs type inference on the metadata annotations of the [annotatable]. /// /// If [indices] is provided, only the annotations at the given indices are /// inferred. Otherwise all annotations are inferred. 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 b162e8c7dad..23f2b7877e9 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 @@ -48,7 +48,7 @@ void testStatement( } void testVariableDeclaration( - Variable node, + InternalVariable node, String normal, { String? verbose, String? limited, @@ -1584,17 +1584,14 @@ late void foo = 0''', ); testVariableDeclaration( new InternalLegacyVariable( - astVariable: new LegacyVariable( - 'foo', - type: const VoidType(), - initializer: new IntLiteral(0), - ), - fileOffset: TreeNode.noOffset, - ) - ..lateGetter = new InternalLegacyVariable( - astVariable: new LegacyVariable('foo#getter'), - fileOffset: TreeNode.noOffset, + astVariable: new LegacyVariable( + 'foo', + type: const VoidType(), + initializer: new IntLiteral(0), ), + fileOffset: TreeNode.noOffset, + )..lateGetter = new LegacyVariable('foo#getter'), + ''' late void foo = 0''', ); @@ -1607,10 +1604,7 @@ late void foo = 0''', ), fileOffset: TreeNode.noOffset, ) - ..lateGetter = new InternalLegacyVariable( - astVariable: new LegacyVariable('foo#getter'), - fileOffset: TreeNode.noOffset, - ) + ..lateGetter = new LegacyVariable('foo#getter') ..lateType = const DynamicType(), ''' late dynamic foo = 0''', diff --git a/pkg/kernel/lib/src/ast/variables.dart b/pkg/kernel/lib/src/ast/variables.dart index f6c569ad326..6aa349c4b29 100644 --- a/pkg/kernel/lib/src/ast/variables.dart +++ b/pkg/kernel/lib/src/ast/variables.dart @@ -21,15 +21,20 @@ sealed class VariableBase extends TreeNode implements Annotatable { } } -/// This is a helper class to enable mixing a mixin into concrete -/// implementations of the sealed class [Variable]. It's not supposed -/// to be used as a type annotation, but purely for declaring the class -/// hierarchy. -abstract interface class IVariable implements TreeNode, Annotatable { +/// The root of the sealed hierarchy of non-type variables. +sealed class Variable extends VariableBase implements ContextConsumer { + /// Static type of the variable. abstract DartType type; - abstract String? cosmeticName; + + /// Declaration node for the variable, if available. abstract VariableDeclaration? variableDeclaration; + + /// Derived from [variableDeclaration], if available. abstract Expression? initializer; + + @override + abstract List annotations; + abstract bool isFinal; abstract bool isConst; abstract bool isLate; @@ -48,78 +53,9 @@ abstract interface class IVariable implements TreeNode, Annotatable { // The following is due to [VariableDeclaration] implementing // [VariableInitialization]. abstract int binaryOffsetNoTag; - abstract List? capturedContexts; abstract int fileEqualsOffset; - abstract Variable variable; void clearAnnotations(); - VariableContext? get context; - void set context(VariableContext value); - - bool get isAssignable; - bool get hasIsFinal; - bool get hasIsConst; - bool get hasIsLate; - bool get hasIsInitializingFormal; - bool get hasIsSynthesized; - bool get hasIsHoisted; - bool get hasHasDeclaredInitializer; - bool get hasIsCovariantByClass; - bool get hasIsRequired; - bool get hasIsCovariantByDeclaration; - bool get hasIsLowered; - bool get hasIsWildcard; - bool get hasIsSuperInitializingFormal; - bool get hasIsErroneouslyInitialized; -} - -/// The root of the sealed hierarchy of non-type variables. -sealed class Variable extends VariableBase - implements IVariable, ContextConsumer { - /// Static type of the variable. - @override - abstract DartType type; - - /// Declaration node for the variable, if available. - @override - abstract VariableDeclaration? variableDeclaration; - - /// Derived from [variableDeclaration], if available. - @override - abstract Expression? initializer; - - @override - abstract List annotations; - - @override - abstract bool isFinal; - @override - abstract bool isConst; - @override - abstract bool isLate; - @override - abstract bool isInitializingFormal; - @override - abstract bool isSynthesized; - @override - abstract bool isHoisted; - @override - abstract bool hasDeclaredInitializer; - @override - abstract bool isCovariantByClass; - @override - abstract bool isRequired; - @override - abstract bool isCovariantByDeclaration; - @override - abstract bool isLowered; - @override - abstract bool isWildcard; - @override - abstract bool isSuperInitializingFormal; - @override - abstract bool isErroneouslyInitialized; - factory( String? name, { Expression? initializer, @@ -153,36 +89,21 @@ sealed class Variable extends VariableBase new empty(); - @override bool get hasIsFinal; - @override bool get hasIsConst; - @override bool get hasIsLate; - @override bool get hasIsInitializingFormal; - @override bool get hasIsSynthesized; - @override bool get hasIsHoisted; - @override bool get hasHasDeclaredInitializer; - @override bool get hasIsCovariantByClass; - @override bool get hasIsRequired; - @override bool get hasIsCovariantByDeclaration; - @override bool get hasIsLowered; - @override bool get hasIsWildcard; - @override bool get hasIsSuperInitializingFormal; - @override bool get hasIsErroneouslyInitialized; - @override bool get isAssignable; abstract String? name; @@ -642,14 +563,6 @@ class LegacyVariable extends TreeNode implements Variable, Annotatable { throw new UnsupportedError("${this.runtimeType}.context="); } - @override - Variable get variable => this; - - @override - void set variable(Variable value) { - throw new UnsupportedError("${this.runtimeType}.variable="); - } - @override bool get hasHasDeclaredInitializer => true; @@ -989,14 +902,6 @@ class LocalVariable extends Variable { @override int fileEqualsOffset = TreeNode.noOffset; - @override - Variable get variable => this; - - @override - void set variable(Variable variable) { - throw new UnsupportedError("${this.runtimeType}.variable="); - } - @override void clearAnnotations() { annotations.clear(); @@ -1302,14 +1207,6 @@ class LateVariable extends Variable { @override int fileEqualsOffset = TreeNode.noOffset; - @override - Variable get variable => this; - - @override - void set variable(Variable variable) { - throw new UnsupportedError("${this.runtimeType}.variable="); - } - @override void clearAnnotations() { annotations.clear(); @@ -1618,14 +1515,6 @@ class CatchVariable extends Variable { @override int fileEqualsOffset = TreeNode.noOffset; - @override - Variable get variable => this; - - @override - void set variable(Variable variable) { - throw new UnsupportedError("${this.runtimeType}.variable="); - } - @override void clearAnnotations() { annotations.clear(); @@ -1976,14 +1865,6 @@ class PositionalParameter extends FunctionParameter { @override int fileEqualsOffset = TreeNode.noOffset; - - @override - Variable get variable => this; - - @override - void set variable(Variable value) { - throw new UnsupportedError("${this.runtimeType}"); - } } /// Named parameters. The [name] field is mandatory. @@ -2129,14 +2010,6 @@ class NamedParameter extends FunctionParameter { void set name(String? value) { parameterName = value!; } - - @override - Variable get variable => this; - - @override - void set variable(Variable value) { - throw new UnsupportedError("${this.runtimeType}"); - } } /// The variable storage for `this`. @@ -2409,14 +2282,6 @@ class ThisVariable extends Variable { @override int fileEqualsOffset = TreeNode.noOffset; - @override - Variable get variable => this; - - @override - void set variable(Variable variable) { - throw new UnsupportedError("${this.runtimeType}.variable="); - } - @override void clearAnnotations() { annotations.clear(); @@ -2702,14 +2567,6 @@ class SyntheticVariable extends Variable { @override int fileEqualsOffset = TreeNode.noOffset; - @override - Variable get variable => this; - - @override - void set variable(Variable variable) { - throw new UnsupportedError("${this.runtimeType}.variable="); - } - @override void clearAnnotations() { annotations.clear(); diff --git a/pkg/kernel/lib/src/printer.dart b/pkg/kernel/lib/src/printer.dart index 24231052e37..2073496c9be 100644 --- a/pkg/kernel/lib/src/printer.dart +++ b/pkg/kernel/lib/src/printer.dart @@ -573,7 +573,7 @@ class AstPrinter { _sb.write(' '); } } - _sb.write(getVariableName(node.variable)); + _sb.write(getVariableName(node)); if (includeInitializer && node.initializer != null && !node.isRequired) { _sb.write(' = '); writeExpression(node.initializer!); diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart index 2c77f743707..1ea0a415bf8 100644 --- a/pkg/kernel/lib/text/ast_to_text.dart +++ b/pkg/kernel/lib/text/ast_to_text.dart @@ -2867,7 +2867,7 @@ class Printer extends VisitorDefault with VisitorVoidMixin { 'has-no-declared-initializer', ); } - writeWord(getVariableName(variable.variable)); + writeWord(getVariableName(variable)); Expression? initializer = variable.initializer; if (initializer != null) { writeSpaced(':='); diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart index eb31800944c..58d0a85246e 100644 --- a/pkg/kernel/lib/verifier.dart +++ b/pkg/kernel/lib/verifier.dart @@ -1277,7 +1277,7 @@ class VerifyingVisitor extends RecursiveResultVisitor { void _verifyVariableDeclaration(Variable node) { enterTreeNode(node); visitChildren(node); - declareVariable(node.variable); + declareVariable(node); if (afterConst && node.isConst && constantLocalsShouldBeRemoved) { Expression? initializer = node.initializer; if (!(initializer is InvalidExpression || diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart index ad55e732e32..0bee383f03f 100644 --- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart +++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart @@ -2814,18 +2814,16 @@ class SummaryCollector extends RecursiveResultVisitor { } TypeExpr? defaultVariable(Variable node) { - final variable = node.variable; - variable.annotations.forEach(_visitAnnotation); - final initializer = variable.initializer; + node.annotations.forEach(_visitAnnotation); + final initializer = node.initializer; final savedCondition = _currentCondition; final TypeExpr initialValue = initializer == null - ? ((variable.type.nullability == Nullability.nonNullable || - variable.isLate) + ? ((node.type.nullability == Nullability.nonNullable || node.isLate) ? emptyType : _nullType) : _visit(initializer); - _declareVariable(variable, initialValue); - if (variable.isLate) { + _declareVariable(node, initialValue); + if (node.isLate) { // Restore condition as initializer of a late variable // is not evaluated immediately. _currentCondition = savedCondition;