[Kernel] Signal errors on static fields in constant contexts

Fasta allows some non-const static field access in constant contexts
which leads to the constant evaluator trying to evaluate them.  Signal
an error instead of crashing.  This will double-report errors for the
cases that Fasta already catches, and we should fix that
double-reporting.

Fix unbounded recursion in printing unevaluated constants (writeNode
called visitUnevaluatedConstant which called defaultConstant which
called writeNode...).

Fix a spurious trailing comma in printing of instance constants.

Change-Id: Idff3169a3a56432ad67c27ff9c267ef355c4c1dc
Reviewed-on: https://dart-review.googlesource.com/c/89514
Commit-Queue: Kevin Millikin <kmillikin@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
index b26535f..5d76a5f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
@@ -15,8 +15,8 @@
         Library,
         ListConstant,
         MapConstant,
+        Member,
         NullConstant,
-        Procedure,
         StaticInvocation,
         StringConstant,
         TreeNode;
@@ -102,7 +102,7 @@
 
   @override
   void invalidStaticInvocation(
-      List<TreeNode> context, TreeNode node, Procedure target) {
+      List<TreeNode> context, TreeNode node, Member target) {
     addProblem(
         node,
         templateConstEvalInvalidStaticInvocation
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 328e40a..8899c8a 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1910,9 +1910,14 @@
       sb.write('>');
     }
     sb.write(' {');
+    bool first = true;
     node.fieldValues.forEach((Reference fieldRef, Constant constant) {
       final String name = syntheticNames.nameConstant(constant);
-      sb.write('${fieldRef.asField.name}: $name, ');
+      if (!first) {
+        first = false;
+        sb.write(', ');
+      }
+      sb.write('${fieldRef.asField.name}: $name');
     });
     sb.write('}');
     endLine(sb.toString());
@@ -1936,6 +1941,13 @@
     endLine('  $name = String.fromEnvironment(${node.name}, ${defaultValue})');
   }
 
+  visitUnevaluatedConstant(UnevaluatedConstant node) {
+    final String name = syntheticNames.nameConstant(node);
+    write('  $name = ');
+    writeExpression(node.expression);
+    endLine();
+  }
+
   defaultNode(Node node) {
     write('<${node.runtimeType}>');
   }
diff --git a/pkg/kernel/lib/transformations/constants.dart b/pkg/kernel/lib/transformations/constants.dart
index 5e96821..73f62ca 100644
--- a/pkg/kernel/lib/transformations/constants.dart
+++ b/pkg/kernel/lib/transformations/constants.dart
@@ -1107,10 +1107,14 @@
   visitStaticGet(StaticGet node) {
     return withNewEnvironment(() {
       final Member target = node.target;
-      if (target is Field && target.isConst) {
-        return runInsideContext(target, () {
-          return _evaluateSubexpression(target.initializer);
-        });
+      if (target is Field) {
+        if (target.isConst) {
+          return runInsideContext(target, () {
+            return _evaluateSubexpression(target.initializer);
+          });
+        }
+        errorReporter.invalidStaticInvocation(contextChain, node, target);
+        throw new _AbortCurrentEvaluation();
       } else if (target is Procedure) {
         if (target.kind == ProcedureKind.Method) {
           return canonicalize(new TearOffConstant(target));
@@ -1500,7 +1504,7 @@
   void invalidMethodInvocation(
       List<TreeNode> context, TreeNode node, Constant receiver, String op);
   void invalidStaticInvocation(
-      List<TreeNode> context, TreeNode node, Procedure target);
+      List<TreeNode> context, TreeNode node, Member target);
   void invalidStringInterpolationOperand(
       List<TreeNode> context, TreeNode node, Constant constant);
   void invalidSymbolName(
@@ -1567,7 +1571,7 @@
 
   @override
   void invalidStaticInvocation(
-      List<TreeNode> context, TreeNode node, Procedure target) {
+      List<TreeNode> context, TreeNode node, Member target) {
     report(
         context, 'Cannot invoke "$target" inside a constant expression', node);
   }
diff --git a/pkg/vm/lib/constants_error_reporter.dart b/pkg/vm/lib/constants_error_reporter.dart
index cadbc0e..def7f4c 100644
--- a/pkg/vm/lib/constants_error_reporter.dart
+++ b/pkg/vm/lib/constants_error_reporter.dart
@@ -12,7 +12,7 @@
 import 'package:front_end/src/api_unstable/vm.dart' as codes;
 
 import 'package:kernel/ast.dart'
-    show Constant, DartType, IntConstant, Procedure, TreeNode;
+    show Constant, DartType, IntConstant, Member, TreeNode;
 import 'package:kernel/transformations/constants.dart' as constants;
 import 'package:kernel/type_environment.dart' show TypeEnvironment;
 
@@ -69,7 +69,7 @@
 
   @override
   void invalidStaticInvocation(
-      List<TreeNode> context, TreeNode node, Procedure target) {
+      List<TreeNode> context, TreeNode node, Member target) {
     final message = codes.templateConstEvalInvalidStaticInvocation
         .withArguments(target.name.toString());
     reportIt(context, message, node);
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index 96999e6..f98b2af 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -56,10 +56,7 @@
 [ $compiler == fasta ]
 Language/Statements/For/syntax_t13: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
 Language/Statements/For/syntax_t20: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
-LanguageFeatures/Constant_update2018/CastOperator_A03_t02/01: Crash
 LanguageFeatures/Constant_update2018/CastOperator_A04_t02: Crash
-LanguageFeatures/Constant_update2018/EqualityOperator_A01_t03: Crash
-LanguageFeatures/Constant_update2018/EqualityOperator_A01_t04: Crash
 LanguageFeatures/Constant_update2018/NewOperators_A01_t01: Crash
 LanguageFeatures/Constant_update2018/NewOperators_A01_t02: Crash
 LanguageFeatures/Constant_update2018/NewOperators_A02_t01: CompileTimeError
@@ -82,8 +79,6 @@
 LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t02: Crash
 LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t01: Crash
 LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t02: Crash
-LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t03/01: Crash
-LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t04/01: Crash
 LanguageFeatures/Set-literals/constant_set_literals_A02_t01: Pass # CompileTimeError on $fasta
 LanguageFeatures/Set-literals/constant_set_literals_A02_t02/01: MissingCompileTimeError # Issue 35608
 LanguageFeatures/Set-literals/constant_set_literals_A02_t02/02: MissingCompileTimeError # Issue 35608
@@ -848,13 +843,7 @@
 LanguageFeatures/Constant_update2018/CastOperator_A01_t01: DartkCrash
 LanguageFeatures/Constant_update2018/CastOperator_A02_t01: DartkCrash
 LanguageFeatures/Constant_update2018/CastOperator_A02_t02: DartkCrash
-LanguageFeatures/Constant_update2018/CastOperator_A03_t01/02: Pass
-LanguageFeatures/Constant_update2018/CastOperator_A03_t01/03: Pass
-LanguageFeatures/Constant_update2018/CastOperator_A03_t02/01: DartkCrash
-LanguageFeatures/Constant_update2018/CastOperator_A04_t01: Pass
 LanguageFeatures/Constant_update2018/CastOperator_A04_t02: DartkCrash
-LanguageFeatures/Constant_update2018/EqualityOperator_A01_t03: DartkCrash
-LanguageFeatures/Constant_update2018/EqualityOperator_A01_t04: DartkCrash
 LanguageFeatures/Constant_update2018/NewOperators_A01_t01: DartkCrash
 LanguageFeatures/Constant_update2018/NewOperators_A01_t02: DartkCrash
 LanguageFeatures/Constant_update2018/NewOperators_A02_t01: Fail
@@ -878,8 +867,6 @@
 LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t02: DartkCrash
 LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t01: Pass
 LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t02: Pass
-LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t03/01: DartkCrash
-LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t04/01: DartkCrash
 LanguageFeatures/Constant_update2018/TypeTestOperator_A04_t01: Pass
 LanguageFeatures/Constant_update2018/TypeTestOperator_A04_t02: Pass
 LanguageFeatures/Set-literals/constant_set_literals_A02_t01: Pass