[kernel][Contexts] Move initializer from VariableInitialization to Variable

This is a step back towards the end goal of separating Variable its initializer. This is done in order to normalize the encoding between the old and the new variable model, such that the split can be perform in both the old and new model simultaneously.

TEST=existing

Change-Id: I3ad6595613c06812d95dff3cabbca6eb05dc1c98
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/505000
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
Johnni Winther
2026-05-21 01:51:10 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent a1fec21b8a
commit d18803c5be
10 changed files with 141 additions and 149 deletions
+5 -3
View File
@@ -349,12 +349,14 @@ class _AwaitTransformer extends Transformer {
VariableStatement decl = stmt.variables[i];
temps.add(Variable(null, type: decl.variable.type, isSynthesized: true));
loopBody.add(decl);
if (decl.initializer != null) {
if (decl.variable.initializer != null) {
initializers.addAll(initEffects[i]);
initializers.add(
ExpressionStatement(VariableSet(decl.variable, decl.initializer!)),
ExpressionStatement(
VariableSet(decl.variable, decl.variable.initializer!),
),
);
decl.initializer = null;
decl.variable.initializer = null;
}
updates.add(
ExpressionStatement(
@@ -3405,6 +3405,7 @@ class BodyBuilderImpl extends StackListenerImpl
isLate: isLate,
isWildcard: isWildcard,
fileOffset: identifier.nameOffset,
initializer: initializer,
),
forSyntheticToken: identifier.token.isSynthetic,
isImplicitlyTyped: currentLocalVariableType == null,
@@ -3412,7 +3413,7 @@ class BodyBuilderImpl extends StackListenerImpl
);
variableInitialization = intern.createVariableInitialization(
variable: internalVariable.asVariableDeclaration,
initializer: initializer,
hasDeclaredInitializer: initializer != null,
fileOffset: offsetForToken(equalsToken),
);
@@ -8354,7 +8355,7 @@ class BodyBuilderImpl extends StackListenerImpl
if (lvalue is VariableInitialization) {
// Variable initializers are not supported. An error has already been
// reported by the parser.
lvalue.initializer = null;
lvalue.variable.initializer = null;
lvalue.hasDeclaredInitializer = false;
// Late for-in variables are not supported. An error has already been
// reported by the parser.
@@ -606,6 +606,7 @@ LocalVariable createLocalVariable({
bool isLate = false,
bool isWildcard = false,
required int fileOffset,
Expression? initializer,
}) {
return new LocalVariable(
cosmeticName: cosmeticName,
@@ -614,6 +615,7 @@ LocalVariable createLocalVariable({
isConst: isConst,
isLate: isLate,
isWildcard: isWildcard,
initializer: initializer,
)..fileOffset = fileOffset;
}
@@ -1212,13 +1214,11 @@ InternalVariableGet createVariableGet(
VariableInitialization createVariableInitialization({
required Variable variable,
required Expression? initializer,
required bool hasDeclaredInitializer,
required int fileOffset,
}) {
return new VariableInitialization(
variable: variable,
initializer: initializer,
hasDeclaredInitializer: hasDeclaredInitializer,
)..fileOffset = fileOffset;
}
+4 -8
View File
@@ -755,6 +755,7 @@ class CloneVisitorNotMembers
new LocalVariable(
cosmeticName: node.cosmeticName,
type: visitOptionalType(node.type),
initializer: cloneOptional(node.initializer),
)
..flags = node.flags
..annotations = _cloneAnnotations(node)
@@ -769,6 +770,7 @@ class CloneVisitorNotMembers
SyntheticVariable(
cosmeticName: node.cosmeticName,
type: visitType(node.type),
initializer: cloneOptional(node.initializer),
)
..flags = node.flags
..annotations = _cloneAnnotations(node)
@@ -816,14 +818,8 @@ class CloneVisitorNotMembers
@override
TreeNode visitVariableInitialization(VariableInitialization node) {
return new VariableInitialization(
variable: clone(node.variable),
initializer: cloneOptional(node.initializer),
)
..flags = node.flags
..annotations = cloneAnnotations && !node.annotations.isEmpty
? node.annotations.map(clone).toList()
: const <Expression>[];
return new VariableInitialization(variable: clone(node.variable))
..flags = node.flags;
}
@override
+1 -41
View File
@@ -1464,9 +1464,6 @@ abstract class VariableStatement extends Statement {
/// The declared variable.
abstract final Variable variable;
/// The declared initializer, if any.
abstract Expression? initializer;
factory VariableStatement(Variable variable) = LegacyVariableStatement;
}
@@ -1480,14 +1477,6 @@ class LegacyVariableStatement extends Statement implements VariableStatement {
variable.parent = this;
}
@override
Expression? get initializer => variable.initializer;
@override
void set initializer(Expression? value) {
variable.initializer = value;
}
@override
R accept<R>(StatementVisitor<R> v) => v.visitLegacyVariableStatement(this);
@@ -1593,9 +1582,6 @@ class VariableInitialization extends Statement
@override
Variable variable;
@override
Expression? initializer;
/// Contexts of the variables captured by the late variable initializer.
///
/// If [variable] isn't `late`, [capturedContexts] should be `null`.
@@ -1604,7 +1590,6 @@ class VariableInitialization extends Statement
VariableInitialization({
required this.variable,
required this.initializer,
bool hasDeclaredInitializer = false,
}) {
variable.variableInitialization = this;
@@ -1642,29 +1627,17 @@ class VariableInitialization extends Statement
@override
void transformChildren(Transformer v) {
variable = v.transform(variable)..parent = this;
v.transformList(annotations, this);
if (initializer != null) {
initializer = v.transform(initializer!);
initializer?.parent = this;
}
}
@override
void transformOrRemoveChildren(RemovingTransformer v) {
variable = v.transformOrRemove(variable, cannotRemoveSentinel)!
..parent = this;
v.transformExpressionList(annotations, this);
if (initializer != null) {
initializer = v.transformOrRemoveExpression(initializer!);
initializer?.parent = this;
}
}
@override
void visitChildren(Visitor v) {
variable.accept(v);
visitList(annotations, v);
initializer?.accept(v);
}
@override
@@ -1675,23 +1648,10 @@ class VariableInitialization extends Statement
@override
void toTextInternal(AstPrinter printer) {
printer.write(printer.getVariableName(variable));
if (initializer case var initializer?) {
if (variable.initializer case var initializer?) {
printer.write(' := ');
printer.writeExpression(initializer);
}
printer.write(';');
}
List<Expression> annotations = const <Expression>[];
void addAnnotation(Expression node) {
if (annotations.isEmpty) {
annotations = <Expression>[];
}
annotations.add(node..parent = this);
}
void clearAnnotations() {
annotations = const <Expression>[];
}
}
+88 -49
View File
@@ -27,7 +27,7 @@ sealed class VariableBase extends TreeNode implements Annotatable {
/// 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 {
abstract interface class IVariable implements TreeNode, Annotatable {
abstract DartType type;
abstract String? cosmeticName;
abstract VariableInitialization? variableInitialization;
@@ -723,6 +723,10 @@ class LocalVariable extends Variable {
VariableContext? _context;
@override
// TODO(johnniwinther): Remove this.
Expression? initializer;
LocalVariable({
this.cosmeticName,
required DartType? type,
@@ -730,12 +734,14 @@ class LocalVariable extends Variable {
bool isConst = false,
bool isLate = false,
bool isWildcard = false,
this.initializer,
}) : type = type ?? const DynamicType(),
super.empty() {
this.isFinal = isFinal;
this.isConst = isConst;
this.isLate = isLate;
this.isWildcard = isWildcard;
this.initializer?.parent = this;
}
@override
@@ -897,7 +903,7 @@ class LocalVariable extends Variable {
bool get isAssignable {
if (isConst) return false;
if (isFinal) {
if (isLate) return variableInitialization?.initializer == null;
if (isLate) return initializer == null;
return false;
}
return true;
@@ -911,13 +917,28 @@ class LocalVariable extends Variable {
v.visitLocalVariable(this, arg);
@override
void transformChildren(Transformer v) {}
void transformChildren(Transformer v) {
v.transformList(annotations, this);
if (initializer != null) {
initializer = v.transform(initializer!);
initializer?.parent = this;
}
}
@override
void transformOrRemoveChildren(RemovingTransformer v) {}
void transformOrRemoveChildren(RemovingTransformer v) {
v.transformExpressionList(annotations, this);
if (initializer != null) {
initializer = v.transformOrRemoveExpression(initializer!);
initializer?.parent = this;
}
}
@override
void visitChildren(Visitor v) {}
void visitChildren(Visitor v) {
visitList(annotations, v);
initializer?.accept(v);
}
@override
String toString() {
@@ -929,20 +950,6 @@ class LocalVariable extends Variable {
printer.writeExpressionVariable(this);
}
@override
Expression? get initializer => variableInitialization?.initializer;
@override
void set initializer(Expression? value) {
if (value != null && variableInitialization == null) {
throw new StateError(
"Attempt to assign initializer to variable "
"without an initialization node.",
);
}
variableInitialization!.initializer = value;
}
@override
String? get name => cosmeticName;
@@ -1241,13 +1248,19 @@ class CatchVariable extends Variable {
v.visitCatchVariable(this, arg);
@override
void transformChildren(Transformer v) {}
void transformChildren(Transformer v) {
v.transformList(annotations, this);
}
@override
void transformOrRemoveChildren(RemovingTransformer v) {}
void transformOrRemoveChildren(RemovingTransformer v) {
v.transformExpressionList(annotations, this);
}
@override
void visitChildren(Visitor v) {}
void visitChildren(Visitor v) {
visitList(annotations, v);
}
@override
String toString() {
@@ -1623,13 +1636,19 @@ class PositionalParameter extends FunctionParameter {
v.visitPositionalParameter(this, arg);
@override
void transformChildren(Transformer v) {}
void transformChildren(Transformer v) {
v.transformList(annotations, this);
}
@override
void transformOrRemoveChildren(RemovingTransformer v) {}
void transformOrRemoveChildren(RemovingTransformer v) {
v.transformExpressionList(annotations, this);
}
@override
void visitChildren(Visitor v) {}
void visitChildren(Visitor v) {
visitList(annotations, v);
}
@override
String toString() {
@@ -1784,13 +1803,19 @@ class NamedParameter extends FunctionParameter {
v.visitNamedParameter(this, arg);
@override
void transformChildren(Transformer v) {}
void transformChildren(Transformer v) {
v.transformList(annotations, this);
}
@override
void transformOrRemoveChildren(RemovingTransformer v) {}
void transformOrRemoveChildren(RemovingTransformer v) {
v.transformExpressionList(annotations, this);
}
@override
void visitChildren(Visitor v) {}
void visitChildren(Visitor v) {
visitList(annotations, v);
}
@override
String toString() {
@@ -2053,13 +2078,19 @@ class ThisVariable extends Variable {
v.visitThisVariable(this, arg);
@override
void transformChildren(Transformer v) {}
void transformChildren(Transformer v) {
v.transformList(annotations, this);
}
@override
void transformOrRemoveChildren(RemovingTransformer v) {}
void transformOrRemoveChildren(RemovingTransformer v) {
v.transformExpressionList(annotations, this);
}
@override
void visitChildren(Visitor v) {}
void visitChildren(Visitor v) {
visitList(annotations, v);
}
@override
String toString() {
@@ -2177,7 +2208,14 @@ class SyntheticVariable extends Variable {
VariableContext? _context;
SyntheticVariable({this.cosmeticName, required this.type}) : super.empty();
@override
// TODO(johnniwinther): Remove this.
Expression? initializer;
SyntheticVariable({this.cosmeticName, required this.type, this.initializer})
: super.empty() {
this.initializer?.parent = this;
}
@override
VariableContext? get context {
@@ -2343,13 +2381,28 @@ class SyntheticVariable extends Variable {
v.visitSyntheticVariable(this, arg);
@override
void transformChildren(Transformer v) {}
void transformChildren(Transformer v) {
v.transformList(annotations, this);
if (initializer != null) {
initializer = v.transform(initializer!);
initializer?.parent = this;
}
}
@override
void transformOrRemoveChildren(RemovingTransformer v) {}
void transformOrRemoveChildren(RemovingTransformer v) {
v.transformExpressionList(annotations, this);
if (initializer != null) {
initializer = v.transformOrRemoveExpression(initializer!);
initializer?.parent = this;
}
}
@override
void visitChildren(Visitor v) {}
void visitChildren(Visitor v) {
visitList(annotations, v);
initializer?.accept(v);
}
@override
String toString() {
@@ -2359,20 +2412,6 @@ class SyntheticVariable extends Variable {
@override
bool get isAssignable => !isConst && !isFinal;
@override
Expression? get initializer => variableInitialization?.initializer;
@override
void set initializer(Expression? value) {
if (value != null && variableInitialization == null) {
throw new StateError(
"Attempt to assign initializer to variable "
"without an initialization node.",
);
}
variableInitialization!.initializer = value;
}
@override
String? get name => cosmeticName;
+30 -31
View File
@@ -5965,18 +5965,12 @@ class EquivalenceStrategy {
if (!checkVariableInitialization_variable(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkVariableInitialization_initializer(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkVariableInitialization_capturedContexts(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkVariableInitialization_flags(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkVariableInitialization_annotations(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkVariableInitialization_fileOffset(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
@@ -6127,6 +6121,9 @@ class EquivalenceStrategy {
if (!checkLocalVariable_context(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkLocalVariable_initializer(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkLocalVariable_binaryOffsetNoTag(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
@@ -6323,6 +6320,9 @@ class EquivalenceStrategy {
if (!checkSyntheticVariable_context(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkSyntheticVariable_initializer(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkSyntheticVariable_binaryOffsetNoTag(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
@@ -13326,18 +13326,6 @@ class EquivalenceStrategy {
return visitor.checkNodes(node.variable, other.variable, 'variable');
}
bool checkVariableInitialization_initializer(
EquivalenceVisitor visitor,
VariableInitialization node,
VariableInitialization other,
) {
return visitor.checkNodes(
node.initializer,
other.initializer,
'initializer',
);
}
bool checkVariableInitialization_capturedContexts(
EquivalenceVisitor visitor,
VariableInitialization node,
@@ -13361,19 +13349,6 @@ class EquivalenceStrategy {
return visitor.checkValues(node.flags, other.flags, 'flags');
}
bool checkVariableInitialization_annotations(
EquivalenceVisitor visitor,
VariableInitialization node,
VariableInitialization other,
) {
return visitor.checkLists(
node.annotations,
other.annotations,
visitor.checkNodes,
'annotations',
);
}
bool checkVariableInitialization_fileOffset(
EquivalenceVisitor visitor,
VariableInitialization node,
@@ -13644,6 +13619,18 @@ class EquivalenceStrategy {
return checkVariableContext(visitor, node.context, other.context);
}
bool checkLocalVariable_initializer(
EquivalenceVisitor visitor,
LocalVariable node,
LocalVariable other,
) {
return visitor.checkNodes(
node.initializer,
other.initializer,
'initializer',
);
}
bool checkLocalVariable_binaryOffsetNoTag(
EquivalenceVisitor visitor,
LocalVariable node,
@@ -14114,6 +14101,18 @@ class EquivalenceStrategy {
return checkVariableContext(visitor, node.context, other.context);
}
bool checkSyntheticVariable_initializer(
EquivalenceVisitor visitor,
SyntheticVariable node,
SyntheticVariable other,
) {
return visitor.checkNodes(
node.initializer,
other.initializer,
'initializer',
);
}
bool checkSyntheticVariable_binaryOffsetNoTag(
EquivalenceVisitor visitor,
SyntheticVariable node,
-1
View File
@@ -2846,7 +2846,6 @@ class Printer extends VisitorDefault<void> with VisitorVoidMixin {
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 =
variable.initializer is NullLiteral ||
+3 -3
View File
@@ -1276,9 +1276,9 @@ class TypeCheckingVisitor
}
void _handleVariableStatement(VariableStatement node) {
if (node.initializer != null) {
node.initializer = checkExpressionAndAssignability(
node.initializer!,
if (node.variable.initializer != null) {
node.variable.initializer = checkExpressionAndAssignability(
node.variable.initializer!,
node.variable.type,
);
}
@@ -301,11 +301,9 @@ class ForInLowering {
final variable = SyntheticVariable(
cosmeticName: ForInVariables.syncForIterator,
type: type,
);
final initialization = VariableInitialization(
variable: variable,
initializer: initializer,
);
final initialization = VariableInitialization(variable: variable);
return (variable, initialization);
} else {
final variableAndInitialization = Variable(
@@ -325,14 +323,12 @@ class ForInLowering {
required Variable variable,
required Expression initializer,
}) {
initializer.parent = variable;
variable..initializer = initializer;
if (isClosureContextLoweringEnabled) {
return VariableInitialization(
variable: variable,
initializer: initializer,
)..fileOffset = variable.fileOffset;
return VariableInitialization(variable: variable)
..fileOffset = variable.fileOffset;
} else {
initializer.parent = variable;
variable..initializer = initializer;
return VariableStatement(variable)..fileOffset = variable.fileOffset;
}
}