[VM] Report an error when accessing constructor parameters inside a constructor invocation

Closes https://github.com/dart-lang/sdk/issues/33604

Change-Id: I84034499de43ea300b278f2f922bc73c565e8bcc
Reviewed-on: https://dart-review.googlesource.com/61934
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 49496f9..17e0074 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -1091,6 +1091,32 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
+        String
+            string)> templateConstEvalNonConstantVariableGet = const Template<
+        Message Function(String string)>(
+    messageTemplate:
+        r"""The variable '#string' is not a constant, only constant expressions are allowed.""",
+    withArguments: _withArgumentsConstEvalNonConstantVariableGet);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string)>
+    codeConstEvalNonConstantVariableGet =
+    const Code<Message Function(String string)>(
+        "ConstEvalNonConstantVariableGet",
+        templateConstEvalNonConstantVariableGet,
+        analyzerCode: "NON_CONSTANT_VALUE_IN_INITIALIZER");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalNonConstantVariableGet(String string) {
+  return new Message(codeConstEvalNonConstantVariableGet,
+      message:
+          """The variable '${string}' is not a constant, only constant expressions are allowed.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
         String string,
         String
             string2)> templateConstEvalZeroDivisor = const Template<
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 44d3ab7..c811a73 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -84,6 +84,8 @@
 ConstEvalNegativeShift/example: Fail
 ConstEvalNonConstantLiteral/dart2jsCode: Fail
 ConstEvalNonConstantLiteral/example: Fail
+ConstEvalNonConstantVariableGet/dart2jsCode: Fail
+ConstEvalNonConstantVariableGet/example: Fail
 ConstEvalZeroDivisor/example: Fail
 ConstFieldWithoutInitializer/example: Fail
 ConstructorNotFound/analyzerCode: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 637cba2..e51c39a 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -131,6 +131,10 @@
   template: "This assertion failed with message: #string"
   analyzerCode: CONST_EVAL_THROWS_EXCEPTION
 
+ConstEvalNonConstantVariableGet:
+  template: "The variable '#string' is not a constant, only constant expressions are allowed."
+  analyzerCode: NON_CONSTANT_VALUE_IN_INITIALIZER
+
 NonAsciiIdentifier:
   template: "The non-ASCII character '#character' (#unicode) can't be used in identifiers, only in strings and comments."
   tip: "Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)."
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index da72794..4eb3bbf 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -5200,7 +5200,7 @@
 
   PrimitiveConstant(this.value);
 
-  String toString() => '${this.runtimeType}($value)';
+  String toString() => '$value';
 
   int get hashCode => value.hashCode;
 
diff --git a/pkg/kernel/lib/transformations/constants.dart b/pkg/kernel/lib/transformations/constants.dart
index 4e62d58..212d6e8 100644
--- a/pkg/kernel/lib/transformations/constants.dart
+++ b/pkg/kernel/lib/transformations/constants.dart
@@ -413,6 +413,14 @@
     }
   }
 
+  Constant runInsideContextIfNoContext(TreeNode node, Constant fun()) {
+    if (contextChain.isEmpty) {
+      return runInsideContext(node, fun);
+    } else {
+      return fun();
+    }
+  }
+
   pushContext(TreeNode contextNode) {
     contextChain.add(contextNode);
   }
@@ -533,11 +541,13 @@
 
     // Start building a new instance.
     return withNewInstanceBuilder(klass, typeArguments, () {
-      // "Run" the constructor (and any super constructor calls), which will
-      // initialize the fields of the new instance.
-      handleConstructorInvocation(
-          constructor, typeArguments, positionals, named);
-      return canonicalize(instanceBuilder.buildInstance());
+      return runInsideContextIfNoContext(node, () {
+        // "Run" the constructor (and any super constructor calls), which will
+        // initialize the fields of the new instance.
+        handleConstructorInvocation(
+            constructor, typeArguments, positionals, named);
+        return canonicalize(instanceBuilder.buildInstance());
+      });
     });
   }
 
@@ -907,7 +917,12 @@
       throw new Exception('The front-end should ensure we do not encounter a '
           'variable get of a non-const variable.');
     }
-    return env.lookupVariable(node.variable);
+    final Constant constant = env.lookupVariable(node.variable);
+    if (constant == null) {
+      errorReporter.nonConstantVariableGet(contextChain, node, variable.name);
+      throw const _AbortCurrentEvaluation();
+    }
+    return constant;
   }
 
   visitStaticGet(StaticGet node) {
@@ -1224,9 +1239,7 @@
   }
 
   Constant lookupVariable(VariableDeclaration variable) {
-    final Constant value = _variables[variable];
-    assert(value != null);
-    return value;
+    return _variables[variable];
   }
 
   DartType subsituteType(DartType type) {
@@ -1272,6 +1285,8 @@
   nonConstLiteral(List<TreeNode> context, TreeNode node, String klass);
   duplicateKey(List<TreeNode> context, TreeNode node, Constant key);
   failedAssertion(List<TreeNode> context, TreeNode node, String message);
+  nonConstantVariableGet(
+      List<TreeNode> context, TreeNode node, String variableName);
 }
 
 abstract class ErrorReporterBase implements ErrorReporter {
@@ -1374,6 +1389,15 @@
         'The assertion condition evaluated to "false" with message "$message"',
         node);
   }
+
+  nonConstantVariableGet(
+      List<TreeNode> context, TreeNode node, String variableName) {
+    report(
+        context,
+        'The variable "$variableName" cannot be used inside a constant '
+        'expression.',
+        node);
+  }
 }
 
 class _SimpleErrorReporter extends ErrorReporterBase {
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 162890e..b5ff2d5 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -312,6 +312,13 @@
     reportIt(context, message, node);
   }
 
+  nonConstantVariableGet(
+      List<TreeNode> context, TreeNode node, String variableName) {
+    final message = codes.templateConstEvalNonConstantVariableGet
+        .withArguments(variableName);
+    reportIt(context, message, node);
+  }
+
   reportIt(List<TreeNode> context, codes.Message message, TreeNode node) {
     final Uri uri = getFileUri(node);
     final int fileOffset = getFileOffset(node);
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index f059115..ca5cfe8 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -168,7 +168,6 @@
 [ $compiler == dartkp ]
 class_cycle_test/02: MissingCompileTimeError
 class_cycle_test/03: MissingCompileTimeError
-const_constructor_nonconst_param_test/01: DartkCrash # Issue 33604
 covariant_subtyping_test: RuntimeError
 duplicate_implements_test/01: MissingCompileTimeError
 duplicate_implements_test/02: MissingCompileTimeError