Version 2.17.0-178.0.dev

Merge commit '6231245e8053ea15120fe8b4fd66cf3966e78eb2' into 'dev'
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index 2795e48..f50a56d 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -27,6 +27,7 @@
 const greater = GreaterOperation();
 const identity = IdentityOperation();
 const ifNull = IfNullOperation();
+const index = _IndexOperation();
 const lessEqual = LessEqualOperation();
 const less = LessOperation();
 const modulo = ModuloOperation();
@@ -990,6 +991,38 @@
   }
 }
 
+class _IndexOperation implements BinaryOperation {
+  @override
+  final String name = '[]';
+
+  const _IndexOperation();
+
+  @override
+  ConstantValue fold(ConstantValue left, ConstantValue right) {
+    if (left is ListConstantValue) {
+      if (right is IntConstantValue) {
+        List<ConstantValue> entries = left.entries;
+        if (right.isUInt32()) {
+          int index = right.intValue.toInt();
+          if (index >= 0 && index < entries.length) {
+            return entries[index];
+          }
+        }
+      }
+    }
+    if (left is MapConstantValue) {
+      ConstantValue value = left.lookup(right);
+      if (value != null) return value;
+      return const NullConstantValue();
+    }
+
+    return null;
+  }
+
+  @override
+  apply(left, right) => throw UnsupportedError('punned indexing');
+}
+
 class UnfoldedUnaryOperation implements UnaryOperation {
   @override
   final String name;
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index ab80914..f514f5f 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -275,6 +275,11 @@
   const IndexSpecializer();
 
   @override
+  constant_system.BinaryOperation operation() {
+    return constant_system.index;
+  }
+
+  @override
   HInstruction tryConvertToBuiltin(
       HInvokeDynamic instruction,
       HGraph graph,
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index d7433a0..5e178c2 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -1493,15 +1493,15 @@
 
   @override
   HInstruction visitIndex(HIndex node) {
-    if (node.receiver.isConstantList() && node.index.isConstantInteger()) {
-      HConstant instruction = node.receiver;
-      ListConstantValue list = instruction.constant;
-      List<ConstantValue> entries = list.entries;
-      HConstant indexInstruction = node.index;
-      IntConstantValue indexConstant = indexInstruction.constant;
-      int index = indexConstant.intValue.toInt();
-      if (index >= 0 && index < entries.length) {
-        return _graph.addConstant(entries[index], _closedWorld);
+    HInstruction receiver = node.receiver;
+    if (receiver is HConstant) {
+      HInstruction index = node.index;
+      if (index is HConstant) {
+        ConstantValue foldedValue =
+            constant_system.index.fold(receiver.constant, index.constant);
+        if (foldedValue != null) {
+          return _graph.addConstant(foldedValue, _closedWorld);
+        }
       }
     }
     return node;
diff --git a/pkg/compiler/test/codegen/data/indexer_constant_folding.dart b/pkg/compiler/test/codegen/data/indexer_constant_folding.dart
new file mode 100644
index 0000000..da77d1e
--- /dev/null
+++ b/pkg/compiler/test/codegen/data/indexer_constant_folding.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const kList = ['first', 'second'];
+const kMap = {0: 'zero', 1: 'one', 2: "two"};
+
+@pragma('dart2js:noInline')
+/*member: list1:function() {
+  return "second";
+}*/
+list1() {
+  return kList[1]; // Constant folds to `"second"`.
+}
+
+@pragma('dart2js:noInline')
+/*member: list2:function() {
+  return A.ioore(B.List_first_second, 10);
+  return B.List_first_second[10];
+}*/
+list2() {
+  return kList[10]; // Does not constant-fold.
+}
+
+@pragma('dart2js:noInline')
+/*member: map1:function() {
+  return "one";
+}*/
+map1() {
+  return kMap[1]; // Constant folds to `"one"`.
+}
+
+@pragma('dart2js:noInline')
+/*member: map2:function() {
+  return null;
+}*/
+map2() {
+  return kMap[10]; // Constant folds to `null`.
+}
+
+/*member: main:ignore*/
+main() {
+  list1();
+  list2();
+  map1();
+  map2();
+}
diff --git a/tools/VERSION b/tools/VERSION
index 669b922..22204ac 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 177
+PRERELEASE 178
 PRERELEASE_PATCH 0
\ No newline at end of file