[cfe] Mutable lists and list add method in const functions.

Within constant evaluation, mutable lists can be created and altered with `add`.

Change-Id: I4ad86e3bea768844835dd732bff3ae135d6df8fb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/197280
Commit-Queue: Kallen Tu <kallentu@google.com>
Reviewed-by: Jake Macdonald <jakemac@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart b/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart
index a11857d..7a92c54 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart
@@ -88,8 +88,15 @@
 }
 
 class ListConstantBuilder extends _ListOrSetConstantBuilder<ListLiteral> {
+  /// If [true], builds a [MutableListConstant].
+  ///
+  /// [MutableListConstant]s can be modified during constant evaluation, but
+  /// still results in a normal constant list at runtime.
+  final bool isMutable;
+
   ListConstantBuilder(
-      Expression original, DartType elementType, ConstantEvaluator evaluator)
+      Expression original, DartType elementType, ConstantEvaluator evaluator,
+      {this.isMutable: false})
       : super(original, elementType, evaluator);
 
   @override
@@ -115,9 +122,13 @@
   Constant build() {
     if (parts.length == 1) {
       // Fully evaluated
+      if (isMutable) {
+        return new MutableListConstant(elementType, parts.single);
+      }
       return evaluator
           .lowerListConstant(new ListConstant(elementType, parts.single));
     }
+    // TODO(kallentu): Handle partially evaluated [isMutable] lists.
     List<Expression> lists = <Expression>[];
     for (Object part in parts) {
       if (part is List<Constant>) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index d200491..756de3c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -1337,11 +1337,12 @@
 
   @override
   Constant visitListLiteral(ListLiteral node) {
-    if (!node.isConst) {
+    if (!node.isConst && !enableConstFunctions) {
       return createInvalidExpressionConstant(node, "Non-constant list literal");
     }
-    final ListConstantBuilder builder =
-        new ListConstantBuilder(node, convertType(node.typeArgument), this);
+    final ListConstantBuilder builder = new ListConstantBuilder(
+        node, convertType(node.typeArgument), this,
+        isMutable: !node.isConst);
     // These expressions are at the same level, so one of them being
     // unevaluated doesn't mean a sibling is or has an unevaluated child.
     // We therefore reset it before each call, combine it and set it correctly
@@ -2259,6 +2260,12 @@
                     typeEnvironment.coreTypes.intNonNullableRawType,
                     other.getType(_staticTypeContext),
                     isNonNullableByDefault));
+          case 'add':
+            if (receiver is MutableListConstant) {
+              receiver.entries.add(other);
+              return receiver;
+            }
+            return new _AbortDueToThrowConstant(node, new UnsupportedError(op));
         }
       }
     } else if (receiver is MapConstant && enableConstFunctions) {
@@ -4041,6 +4048,15 @@
   BreakStatus(this.target);
 }
 
+/// Mutable lists used within the [ConstantEvaluator].
+class MutableListConstant extends ListConstant {
+  MutableListConstant(DartType typeArgument, List<Constant> entries)
+      : super(typeArgument, entries);
+
+  @override
+  String toString() => 'MutableListConstant(${toStringInternal()})';
+}
+
 /// An intermediate result that is used for invoking function nodes with their
 /// respective environment within the [ConstantEvaluator].
 class FunctionValue implements Constant {
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list.dart b/pkg/front_end/testcases/const_functions/const_functions_list.dart
index ee6c222..ffe641e 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list.dart
+++ b/pkg/front_end/testcases/const_functions/const_functions_list.dart
@@ -110,6 +110,19 @@
   return 1;
 }
 
+const mutableListVar = mutableList();
+List<int> mutableList() {
+  List<int> x = [1, 2];
+  return x;
+}
+
+const mutableListAddVar = mutableListAdd();
+List<int> mutableListAdd() {
+  List<int> x = [1, 2];
+  x.add(3);
+  return x;
+}
+
 void main() {
   Expect.equals(firstVar, 1);
   Expect.equals(firstCatchVar, 0);
@@ -124,4 +137,6 @@
   Expect.equals(typeVar, int);
   Expect.equals(getWithIndexVar, 1);
   Expect.equals(rangeErrorCatchVar, 0);
+  Expect.equals(mutableListVar, const [1, 2]);
+  Expect.equals(mutableListAddVar, const [1, 2, 3]);
 }
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list.dart.strong.expect b/pkg/front_end/testcases/const_functions/const_functions_list.dart.strong.expect
index 3a26c41..e6068a5 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list.dart.strong.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list.dart.strong.expect
@@ -19,12 +19,14 @@
 static const field core::Type typeVar = #C6;
 static const field core::int getWithIndexVar = #C1;
 static const field core::int rangeErrorCatchVar = #C2;
+static const field core::List<core::int> mutableListVar = #C7;
+static const field core::List<core::int> mutableListAddVar = #C9;
 static method firstFn() → core::int {
   return (#C7).{core::Iterable::first};
 }
 static method firstCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::first};
+    core::int v = (#C10).{core::Iterable::first};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -42,7 +44,7 @@
 }
 static method lastCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::last};
+    core::int v = (#C10).{core::Iterable::last};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -53,11 +55,11 @@
   return (#C7).{core::List::length};
 }
 static method singleFn() → core::int {
-  return (#C9).{core::Iterable::single};
+  return (#C11).{core::Iterable::single};
 }
 static method singleCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::single};
+    core::int v = (#C10).{core::Iterable::single};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -77,17 +79,26 @@
   return (#C7).{core::Object::runtimeType};
 }
 static method getWithIndexFn() → core::int {
-  return (#C9).{core::List::[]}(0);
+  return (#C11).{core::List::[]}(0);
 }
 static method rangeErrorCatchFn() → core::int {
   try {
-    core::int v = (#C9).{core::List::[]}(1);
+    core::int v = (#C11).{core::List::[]}(1);
   }
   on core::RangeError catch(no-exception-var) {
     return 0;
   }
   return 1;
 }
+static method mutableList() → core::List<core::int> {
+  core::List<core::int> x = <core::int>[1, 2];
+  return x;
+}
+static method mutableListAdd() → core::List<core::int> {
+  core::List<core::int> x = <core::int>[1, 2];
+  x.{core::List::add}(3);
+  return x;
+}
 static method main() → void {
   exp::Expect::equals(#C1, 1);
   exp::Expect::equals(#C2, 0);
@@ -102,6 +113,8 @@
   exp::Expect::equals(#C6, #C6);
   exp::Expect::equals(#C1, 1);
   exp::Expect::equals(#C2, 0);
+  exp::Expect::equals(#C7, #C7);
+  exp::Expect::equals(#C9, #C9);
 }
 
 constants  {
@@ -112,6 +125,8 @@
   #C5 = 2
   #C6 = TypeLiteralConstant(core::int)
   #C7 = <core::int>[#C1, #C5]
-  #C8 = <core::int>[]
-  #C9 = <core::int>[#C1]
+  #C8 = 3
+  #C9 = <core::int>[#C1, #C5, #C8]
+  #C10 = <core::int>[]
+  #C11 = <core::int>[#C1]
 }
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list.dart.strong.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_list.dart.strong.transformed.expect
index 3a26c41..4091f3e 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list.dart.strong.transformed.expect
@@ -19,12 +19,14 @@
 static const field core::Type typeVar = #C6;
 static const field core::int getWithIndexVar = #C1;
 static const field core::int rangeErrorCatchVar = #C2;
+static const field core::List<core::int> mutableListVar = #C7;
+static const field core::List<core::int> mutableListAddVar = #C9;
 static method firstFn() → core::int {
   return (#C7).{core::Iterable::first};
 }
 static method firstCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::first};
+    core::int v = (#C10).{core::Iterable::first};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -42,7 +44,7 @@
 }
 static method lastCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::last};
+    core::int v = (#C10).{core::Iterable::last};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -53,11 +55,11 @@
   return (#C7).{core::List::length};
 }
 static method singleFn() → core::int {
-  return (#C9).{core::Iterable::single};
+  return (#C11).{core::Iterable::single};
 }
 static method singleCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::single};
+    core::int v = (#C10).{core::Iterable::single};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -77,17 +79,26 @@
   return (#C7).{core::Object::runtimeType};
 }
 static method getWithIndexFn() → core::int {
-  return (#C9).{core::List::[]}(0);
+  return (#C11).{core::List::[]}(0);
 }
 static method rangeErrorCatchFn() → core::int {
   try {
-    core::int v = (#C9).{core::List::[]}(1);
+    core::int v = (#C11).{core::List::[]}(1);
   }
   on core::RangeError catch(no-exception-var) {
     return 0;
   }
   return 1;
 }
+static method mutableList() → core::List<core::int> {
+  core::List<core::int> x = core::_GrowableList::_literal2<core::int>(1, 2);
+  return x;
+}
+static method mutableListAdd() → core::List<core::int> {
+  core::List<core::int> x = core::_GrowableList::_literal2<core::int>(1, 2);
+  x.{core::List::add}(3);
+  return x;
+}
 static method main() → void {
   exp::Expect::equals(#C1, 1);
   exp::Expect::equals(#C2, 0);
@@ -102,6 +113,8 @@
   exp::Expect::equals(#C6, #C6);
   exp::Expect::equals(#C1, 1);
   exp::Expect::equals(#C2, 0);
+  exp::Expect::equals(#C7, #C7);
+  exp::Expect::equals(#C9, #C9);
 }
 
 constants  {
@@ -112,6 +125,8 @@
   #C5 = 2
   #C6 = TypeLiteralConstant(core::int)
   #C7 = <core::int>[#C1, #C5]
-  #C8 = <core::int>[]
-  #C9 = <core::int>[#C1]
+  #C8 = 3
+  #C9 = <core::int>[#C1, #C5, #C8]
+  #C10 = <core::int>[]
+  #C11 = <core::int>[#C1]
 }
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list.dart.textual_outline.expect b/pkg/front_end/testcases/const_functions/const_functions_list.dart.textual_outline.expect
index 0e77dc5..3d19d8a 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list.dart.textual_outline.expect
@@ -27,4 +27,8 @@
 int getWithIndexFn() {}
 const rangeErrorCatchVar = rangeErrorCatchFn();
 int rangeErrorCatchFn() {}
+const mutableListVar = mutableList();
+List<int> mutableList() {}
+const mutableListAddVar = mutableListAdd();
+List<int> mutableListAdd() {}
 void main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/const_functions/const_functions_list.dart.textual_outline_modelled.expect
index d57d3a1..e39fc73 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list.dart.textual_outline_modelled.expect
@@ -1,5 +1,7 @@
 import "package:expect/expect.dart";
 
+List<int> mutableList() {}
+List<int> mutableListAdd() {}
 Type typeFn() {}
 bool isEmptyFn() {}
 bool isNotEmptyFn() {}
@@ -11,6 +13,8 @@
 const lastCatchVar = lastCatchFn();
 const lastVar = lastFn();
 const lengthVar = lengthFn();
+const mutableListAddVar = mutableListAdd();
+const mutableListVar = mutableList();
 const rangeErrorCatchVar = rangeErrorCatchFn();
 const singleCatchVar = singleCatchFn();
 const singleCatchVar2 = singleCatchFn2();
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.expect b/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.expect
index e3fdeb2..f3366b9 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.expect
@@ -19,12 +19,14 @@
 static const field core::Type typeVar = #C6;
 static const field core::int getWithIndexVar = #C1;
 static const field core::int rangeErrorCatchVar = #C2;
+static const field core::List<core::int> mutableListVar = #C7;
+static const field core::List<core::int> mutableListAddVar = #C9;
 static method firstFn() → core::int {
   return (#C7).{core::Iterable::first};
 }
 static method firstCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::first};
+    core::int v = (#C10).{core::Iterable::first};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -42,7 +44,7 @@
 }
 static method lastCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::last};
+    core::int v = (#C10).{core::Iterable::last};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -53,11 +55,11 @@
   return (#C7).{core::List::length};
 }
 static method singleFn() → core::int {
-  return (#C9).{core::Iterable::single};
+  return (#C11).{core::Iterable::single};
 }
 static method singleCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::single};
+    core::int v = (#C10).{core::Iterable::single};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -77,17 +79,26 @@
   return (#C7).{core::Object::runtimeType};
 }
 static method getWithIndexFn() → core::int {
-  return (#C9).{core::List::[]}(0);
+  return (#C11).{core::List::[]}(0);
 }
 static method rangeErrorCatchFn() → core::int {
   try {
-    core::int v = (#C9).{core::List::[]}(1);
+    core::int v = (#C11).{core::List::[]}(1);
   }
   on core::RangeError catch(no-exception-var) {
     return 0;
   }
   return 1;
 }
+static method mutableList() → core::List<core::int> {
+  core::List<core::int> x = <core::int>[1, 2];
+  return x;
+}
+static method mutableListAdd() → core::List<core::int> {
+  core::List<core::int> x = <core::int>[1, 2];
+  x.{core::List::add}(3);
+  return x;
+}
 static method main() → void {
   exp::Expect::equals(#C1, 1);
   exp::Expect::equals(#C2, 0);
@@ -102,6 +113,8 @@
   exp::Expect::equals(#C6, #C6);
   exp::Expect::equals(#C1, 1);
   exp::Expect::equals(#C2, 0);
+  exp::Expect::equals(#C7, #C7);
+  exp::Expect::equals(#C9, #C9);
 }
 
 constants  {
@@ -112,6 +125,8 @@
   #C5 = 2
   #C6 = TypeLiteralConstant(core::int*)
   #C7 = <core::int*>[#C1, #C5]
-  #C8 = <core::int*>[]
-  #C9 = <core::int*>[#C1]
+  #C8 = 3
+  #C9 = <core::int*>[#C1, #C5, #C8]
+  #C10 = <core::int*>[]
+  #C11 = <core::int*>[#C1]
 }
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.outline.expect b/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.outline.expect
index 70812a7..72ee4b8 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.outline.expect
@@ -18,6 +18,8 @@
 static const field core::Type typeVar = self::typeFn();
 static const field core::int getWithIndexVar = self::getWithIndexFn();
 static const field core::int rangeErrorCatchVar = self::rangeErrorCatchFn();
+static const field core::List<core::int> mutableListVar = self::mutableList();
+static const field core::List<core::int> mutableListAddVar = self::mutableListAdd();
 static method firstFn() → core::int
   ;
 static method firstCatchFn() → core::int
@@ -44,10 +46,14 @@
   ;
 static method rangeErrorCatchFn() → core::int
   ;
+static method mutableList() → core::List<core::int>
+  ;
+static method mutableListAdd() → core::List<core::int>
+  ;
 static method main() → void
   ;
 
 
 Extra constant evaluation status:
 Evaluated: TypeLiteral @ org-dartlang-testcase:///const_functions_list.dart:89:21 -> TypeLiteralConstant(int*)
-Extra constant evaluation: evaluated: 14, effectively constant: 1
+Extra constant evaluation: evaluated: 16, effectively constant: 1
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.transformed.expect
index e3fdeb2..2722eb3 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list.dart.weak.transformed.expect
@@ -19,12 +19,14 @@
 static const field core::Type typeVar = #C6;
 static const field core::int getWithIndexVar = #C1;
 static const field core::int rangeErrorCatchVar = #C2;
+static const field core::List<core::int> mutableListVar = #C7;
+static const field core::List<core::int> mutableListAddVar = #C9;
 static method firstFn() → core::int {
   return (#C7).{core::Iterable::first};
 }
 static method firstCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::first};
+    core::int v = (#C10).{core::Iterable::first};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -42,7 +44,7 @@
 }
 static method lastCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::last};
+    core::int v = (#C10).{core::Iterable::last};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -53,11 +55,11 @@
   return (#C7).{core::List::length};
 }
 static method singleFn() → core::int {
-  return (#C9).{core::Iterable::single};
+  return (#C11).{core::Iterable::single};
 }
 static method singleCatchFn() → core::int {
   try {
-    core::int v = (#C8).{core::Iterable::single};
+    core::int v = (#C10).{core::Iterable::single};
   }
   on core::StateError catch(no-exception-var) {
     return 0;
@@ -77,17 +79,26 @@
   return (#C7).{core::Object::runtimeType};
 }
 static method getWithIndexFn() → core::int {
-  return (#C9).{core::List::[]}(0);
+  return (#C11).{core::List::[]}(0);
 }
 static method rangeErrorCatchFn() → core::int {
   try {
-    core::int v = (#C9).{core::List::[]}(1);
+    core::int v = (#C11).{core::List::[]}(1);
   }
   on core::RangeError catch(no-exception-var) {
     return 0;
   }
   return 1;
 }
+static method mutableList() → core::List<core::int> {
+  core::List<core::int> x = core::_GrowableList::_literal2<core::int>(1, 2);
+  return x;
+}
+static method mutableListAdd() → core::List<core::int> {
+  core::List<core::int> x = core::_GrowableList::_literal2<core::int>(1, 2);
+  x.{core::List::add}(3);
+  return x;
+}
 static method main() → void {
   exp::Expect::equals(#C1, 1);
   exp::Expect::equals(#C2, 0);
@@ -102,6 +113,8 @@
   exp::Expect::equals(#C6, #C6);
   exp::Expect::equals(#C1, 1);
   exp::Expect::equals(#C2, 0);
+  exp::Expect::equals(#C7, #C7);
+  exp::Expect::equals(#C9, #C9);
 }
 
 constants  {
@@ -112,6 +125,8 @@
   #C5 = 2
   #C6 = TypeLiteralConstant(core::int*)
   #C7 = <core::int*>[#C1, #C5]
-  #C8 = <core::int*>[]
-  #C9 = <core::int*>[#C1]
+  #C8 = 3
+  #C9 = <core::int*>[#C1, #C5, #C8]
+  #C10 = <core::int*>[]
+  #C11 = <core::int*>[#C1]
 }
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart
index 7112539..ec90637 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart
+++ b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart
@@ -54,4 +54,11 @@
   return x[0.1];
 }
 
+const constListAddException = constListAddExceptionFn();
+List<int> constListAddExceptionFn() {
+  const List<int> x = [1, 2];
+  x.add(3);
+  return x;
+}
+
 void main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.strong.expect b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.strong.expect
index c0f7a01..d9798b9 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.strong.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.strong.expect
@@ -54,6 +54,13 @@
 //   return x[-1];
 //           ^
 //
+// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:57:31: Error: Constant evaluation error:
+// const constListAddException = constListAddExceptionFn();
+//                               ^
+// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:60:5: Context: Unhandled core exception: Unsupported operation: add
+//   x.add(3);
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -73,6 +80,7 @@
 static const field core::int getWithIndexException3 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_list_error.dart:54:12: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
   return x[0.1];
            ^";
+static const field core::List<core::int> constListAddException = invalid-expression "Unhandled core exception: Unsupported operation: add";
 static method firstExceptionFn() → core::int {
   return (#C1).{core::Iterable::first};
 }
@@ -103,6 +111,10 @@
   return x[0.1];
            ^" in 0.1 as{TypeError,ForNonNullableByDefault} core::int);
 }
+static method constListAddExceptionFn() → core::List<core::int> {
+  (#C4).{core::List::add}(3);
+  return #C4;
+}
 static method main() → void {}
 
 constants  {
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.strong.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.strong.transformed.expect
index e279288..fb04009 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.strong.transformed.expect
@@ -54,6 +54,13 @@
 //   return x[-1];
 //           ^
 //
+// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:57:31: Error: Constant evaluation error:
+// const constListAddException = constListAddExceptionFn();
+//                               ^
+// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:60:5: Context: Unhandled core exception: Unsupported operation: add
+//   x.add(3);
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -73,6 +80,7 @@
 static const field core::int getWithIndexException3 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_list_error.dart:54:12: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
   return x[0.1];
            ^";
+static const field core::List<core::int> constListAddException = invalid-expression "Unhandled core exception: Unsupported operation: add";
 static method firstExceptionFn() → core::int {
   return (#C1).{core::Iterable::first};
 }
@@ -103,6 +111,10 @@
   return x[0.1];
            ^" in 0.1 as{TypeError,ForNonNullableByDefault} core::int);
 }
+static method constListAddExceptionFn() → core::List<core::int> {
+  (#C4).{core::List::add}(3);
+  return #C4;
+}
 static method main() → void {}
 
 constants  {
@@ -115,4 +127,4 @@
 
 Extra constant evaluation status:
 Evaluated: MethodInvocation @ org-dartlang-testcase:///const_functions_list_error.dart:48:12 -> IntConstant(-1)
-Extra constant evaluation: evaluated: 10, effectively constant: 1
+Extra constant evaluation: evaluated: 11, effectively constant: 1
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.textual_outline.expect b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.textual_outline.expect
index 0305a22..15cf9bd 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.textual_outline.expect
@@ -16,4 +16,6 @@
 int getWithIndexExceptionFn2() {}
 const getWithIndexException3 = getWithIndexExceptionFn3();
 int getWithIndexExceptionFn3() {}
+const constListAddException = constListAddExceptionFn();
+List<int> constListAddExceptionFn() {}
 void main() {}
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.textual_outline_modelled.expect
index 6ad769d..26100eb9 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.textual_outline_modelled.expect
@@ -1,5 +1,7 @@
 import "package:expect/expect.dart";
 
+List<int> constListAddExceptionFn() {}
+const constListAddException = constListAddExceptionFn();
 const firstException = firstExceptionFn();
 const getWithIndexException = getWithIndexExceptionFn();
 const getWithIndexException2 = getWithIndexExceptionFn2();
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.expect b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.expect
index f063521..d918e0a 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.expect
@@ -54,6 +54,13 @@
 //   return x[-1];
 //           ^
 //
+// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:57:31: Error: Constant evaluation error:
+// const constListAddException = constListAddExceptionFn();
+//                               ^
+// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:60:5: Context: Unhandled core exception: Unsupported operation: add
+//   x.add(3);
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -73,6 +80,7 @@
 static const field core::int getWithIndexException3 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_list_error.dart:54:12: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
   return x[0.1];
            ^";
+static const field core::List<core::int> constListAddException = invalid-expression "Unhandled core exception: Unsupported operation: add";
 static method firstExceptionFn() → core::int {
   return (#C1).{core::Iterable::first};
 }
@@ -103,6 +111,10 @@
   return x[0.1];
            ^" in 0.1 as{TypeError,ForNonNullableByDefault} core::int);
 }
+static method constListAddExceptionFn() → core::List<core::int> {
+  (#C4).{core::List::add}(3);
+  return #C4;
+}
 static method main() → void {}
 
 constants  {
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.outline.expect b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.outline.expect
index 85d4fbd..1125fba 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.outline.expect
@@ -12,6 +12,7 @@
 static const field core::int getWithIndexException = self::getWithIndexExceptionFn();
 static const field core::int getWithIndexException2 = self::getWithIndexExceptionFn2();
 static const field core::int getWithIndexException3 = self::getWithIndexExceptionFn3();
+static const field core::List<core::int> constListAddException = self::constListAddExceptionFn();
 static method firstExceptionFn() → core::int
   ;
 static method lastExceptionFn() → core::int
@@ -28,5 +29,7 @@
   ;
 static method getWithIndexExceptionFn3() → core::int
   ;
+static method constListAddExceptionFn() → core::List<core::int>
+  ;
 static method main() → void
   ;
diff --git a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.transformed.expect b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.transformed.expect
index 83813a5..e2984c7 100644
--- a/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/const_functions/const_functions_list_error.dart.weak.transformed.expect
@@ -54,6 +54,13 @@
 //   return x[-1];
 //           ^
 //
+// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:57:31: Error: Constant evaluation error:
+// const constListAddException = constListAddExceptionFn();
+//                               ^
+// pkg/front_end/testcases/const_functions/const_functions_list_error.dart:60:5: Context: Unhandled core exception: Unsupported operation: add
+//   x.add(3);
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -73,6 +80,7 @@
 static const field core::int getWithIndexException3 = invalid-expression "pkg/front_end/testcases/const_functions/const_functions_list_error.dart:54:12: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
   return x[0.1];
            ^";
+static const field core::List<core::int> constListAddException = invalid-expression "Unhandled core exception: Unsupported operation: add";
 static method firstExceptionFn() → core::int {
   return (#C1).{core::Iterable::first};
 }
@@ -103,6 +111,10 @@
   return x[0.1];
            ^" in 0.1 as{TypeError,ForNonNullableByDefault} core::int);
 }
+static method constListAddExceptionFn() → core::List<core::int> {
+  (#C4).{core::List::add}(3);
+  return #C4;
+}
 static method main() → void {}
 
 constants  {
@@ -115,4 +127,4 @@
 
 Extra constant evaluation status:
 Evaluated: MethodInvocation @ org-dartlang-testcase:///const_functions_list_error.dart:48:12 -> IntConstant(-1)
-Extra constant evaluation: evaluated: 10, effectively constant: 1
+Extra constant evaluation: evaluated: 11, effectively constant: 1
diff --git a/tests/language/const_functions/const_functions_list_error_test.dart b/tests/language/const_functions/const_functions_list_error_test.dart
index 45e6f96..cbde9f7 100644
--- a/tests/language/const_functions/const_functions_list_error_test.dart
+++ b/tests/language/const_functions/const_functions_list_error_test.dart
@@ -83,3 +83,13 @@
   // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
   // [cfe] A value of type 'double' can't be assigned to a variable of type 'int'.
 }
+
+const constListAddException = constListAddExceptionFn();
+//                            ^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+List<int> constListAddExceptionFn() {
+  const List<int> x = [1, 2];
+  x.add(3);
+  return x;
+}
diff --git a/tests/language/const_functions/const_functions_list_test.dart b/tests/language/const_functions/const_functions_list_test.dart
index 31746a5..deb8b0f 100644
--- a/tests/language/const_functions/const_functions_list_test.dart
+++ b/tests/language/const_functions/const_functions_list_test.dart
@@ -158,6 +158,23 @@
   return 1;
 }
 
+const mutableListVar = mutableList();
+//                     ^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+List<int> mutableList() {
+  List<int> x = [1, 2];
+  return x;
+}
+
+const mutableListAddVar = mutableListAdd();
+//                        ^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+List<int> mutableListAdd() {
+  List<int> x = [1, 2];
+  x.add(3);
+  return x;
+}
+
 void main() {
   Expect.equals(firstVar, 1);
   Expect.equals(firstCatchVar, 0);
@@ -173,4 +190,6 @@
   Expect.equals(typeVar, int);
   Expect.equals(getWithIndexVar, 1);
   Expect.equals(rangeErrorCatchVar, 0);
+  Expect.equals(mutableListVar, const [1, 2]);
+  Expect.equals(mutableListAddVar, const [1, 2, 3]);
 }