Generate an error if writing to a potentially-already-assigned final var.
Change-Id: Iee4dccbc2c11290cdf56b3a95259f6401a123620
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164246
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index 552baa0..7c00414 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -4039,6 +4039,32 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(
+ String
+ name)> templateFinalPossiblyAssignedError = const Template<
+ Message Function(String name)>(
+ messageTemplate:
+ r"""Final variable '#name' might already be assigned at this point.""",
+ withArguments: _withArgumentsFinalPossiblyAssignedError);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeFinalPossiblyAssignedError =
+ const Code<Message Function(String name)>(
+ "FinalPossiblyAssignedError", templateFinalPossiblyAssignedError,
+ analyzerCodes: <String>["ASSIGNMENT_TO_FINAL_LOCAL"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFinalPossiblyAssignedError(String name) {
+ if (name.isEmpty) throw 'No name provided';
+ name = demangleMixinApplicationName(name);
+ return new Message(codeFinalPossiblyAssignedError,
+ message:
+ """Final variable '${name}' might already be assigned at this point.""",
+ arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeForInLoopExactlyOneVariable =
messageForInLoopExactlyOneVariable;
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 878aad2..49becf5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -5630,8 +5630,10 @@
VariableSet node, DartType typeContext) {
VariableDeclarationImpl variable = node.variable;
bool isDefinitelyAssigned = false;
+ bool isDefinitelyUnassigned = false;
if (inferrer.isNonNullableByDefault) {
isDefinitelyAssigned = inferrer.flowAnalysis.isAssigned(variable);
+ isDefinitelyUnassigned = inferrer.flowAnalysis.isUnassigned(variable);
}
DartType declaredOrInferredType = variable.lateType ?? variable.type;
DartType promotedType;
@@ -5677,6 +5679,17 @@
node.fileOffset,
node.variable.name.length));
}
+ } else if (variable.isStaticLate) {
+ if (!isDefinitelyUnassigned) {
+ return new ExpressionInferenceResult(
+ resultType,
+ inferrer.helper.wrapInProblem(
+ resultExpression,
+ templateFinalPossiblyAssignedError
+ .withArguments(node.variable.name),
+ node.fileOffset,
+ node.variable.name.length));
+ }
}
}
}
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 2d71510..6138394 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -4230,6 +4230,17 @@
t = 0;
}
+FinalPossiblyAssignedError:
+ template: "Final variable '#name' might already be assigned at this point."
+ analyzerCode: ASSIGNMENT_TO_FINAL_LOCAL
+ configuration: nnbd-strong
+ script: |
+ method() {
+ final int i;
+ i = 0;
+ i = 0;
+ }
+
NonAgnosticConstant:
template: "Constant value is not strong/weak mode agnostic."