[cfe] Don't hoist arguments in const constructor calls

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

Change-Id: Id31a1b9b3a78caba29095e314309b9b8258ab632
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/245860
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index bb6d2ee..4ab6e5a 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -2364,7 +2364,8 @@
     if (libraryFeatures.namedArgumentsAnywhere.isEnabled &&
         arguments.argumentsOriginalOrder != null &&
         hoistedExpressions == null &&
-        !isTopLevel) {
+        !isTopLevel &&
+        !isConst) {
       hoistedExpressions = localHoistedExpressions = <VariableDeclaration>[];
     }
 
diff --git a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.outline.expect
index 336105f..0870c9a 100644
--- a/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/enhanced_enums/named_arguments_anywhere/redirecting_constructor.dart.weak.outline.expect
@@ -6,8 +6,8 @@
   static const field core::List<self::C> values = const <self::C>[self::C::a, self::C::b, self::C::c, self::C::d, self::C::e, self::C::f];
   final field core::String log;
   static const field self::C a = const self::C::•(0, "a", 1, 2, z: 3);
-  static const field self::C b = let final core::int #t1 = 1 in let final core::String #t2 = "b" in let final core::int #t3 = 3 in const self::C::•(#t1, #t2, 1, 2, z: #t3);
-  static const field self::C c = let final core::int #t4 = 2 in let final core::String #t5 = "c" in let final core::int #t6 = 1 in let final core::int #t7 = 3 in const self::C::•(#t4, #t5, #t6, 2, z: #t7);
+  static const field self::C b = const self::C::•(1, "b", 1, 2, z: 3);
+  static const field self::C c = const self::C::•(2, "c", 1, 2, z: 3);
   static const field self::C d = const self::C::named1(3, "d", 1, 2, 3);
   static const field self::C e = const self::C::named2(4, "e", 1, 2, 3);
   static const field self::C f = const self::C::named3(5, "f", 1, 2, 3);
@@ -18,10 +18,10 @@
     : this self::C::•(#index, #name, x, y, z: z)
     ;
   const constructor named2(core::int #index, core::String #name, core::int x, core::int y, core::int z) → self::C
-    : final core::int #t8 = #index, final core::String #t9 = #name, final core::int #t10 = x, final core::int #t11 = z, this self::C::•(#t8, #t9, #t10, y, z: #t11)
+    : final core::int #t1 = #index, final core::String #t2 = #name, final core::int #t3 = x, final core::int #t4 = z, this self::C::•(#t1, #t2, #t3, y, z: #t4)
     ;
   const constructor named3(core::int #index, core::String #name, core::int x, core::int y, core::int z) → self::C
-    : final core::int #t12 = #index, final core::String #t13 = #name, final core::int #t14 = z, this self::C::•(#t12, #t13, x, y, z: #t14)
+    : final core::int #t5 = #index, final core::String #t6 = #name, final core::int #t7 = z, this self::C::•(#t5, #t6, x, y, z: #t7)
     ;
   method toString() → core::String
     return "C.${this.{core::_Enum::_name}{core::String}}";
@@ -35,8 +35,8 @@
 Extra constant evaluation status:
 Evaluated: ListLiteral @ org-dartlang-testcase:///redirecting_constructor.dart:5:6 -> ListConstant(const <C*>[const C{C.log: "x=1, y=2, z=3", _Enum.index: 0, _Enum._name: "a"}, const C{C.log: "x=1, y=2, z=3", _Enum.index: 1, _Enum._name: "b"}, const C{C.log: "x=1, y=2, z=3", _Enum.index: 2, _Enum._name: "c"}, const C{C.log: "x=1, y=2, z=3", _Enum.index: 3, _Enum._name: "d"}, const C{C.log: "x=1, y=2, z=3", _Enum.index: 4, _Enum._name: "e"}, const C{C.log: "x=1, y=2, z=3", _Enum.index: 5, _Enum._name: "f"}])
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_constructor.dart:6:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 0, _Enum._name: "a"})
-Evaluated: Let @ org-dartlang-testcase:///redirecting_constructor.dart:7:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 1, _Enum._name: "b"})
-Evaluated: Let @ org-dartlang-testcase:///redirecting_constructor.dart:8:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 2, _Enum._name: "c"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_constructor.dart:7:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 1, _Enum._name: "b"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_constructor.dart:8:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 2, _Enum._name: "c"})
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_constructor.dart:9:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 3, _Enum._name: "d"})
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_constructor.dart:10:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 4, _Enum._name: "e"})
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///redirecting_constructor.dart:11:3 -> InstanceConstant(const C{C.log: "x=1, y=2, z=3", _Enum.index: 5, _Enum._name: "f"})
diff --git a/pkg/front_end/testcases/general/issue49087.dart b/pkg/front_end/testcases/general/issue49087.dart
new file mode 100644
index 0000000..0073bb9
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue49087.dart
@@ -0,0 +1,13 @@
+// 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.
+
+class A {
+  const A(int x, {String? y});
+  const factory A.redir(int x, {String? y}) = A;
+}
+
+test1() => const A(y: "foo", 0);
+test2() => const A.redir(y: "foo", 0);
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue49087.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue49087.dart.textual_outline.expect
new file mode 100644
index 0000000..b783d52
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue49087.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+class A {
+  const A(int x, {String? y});
+  const factory A.redir(int x, {String? y}) = A;
+}
+
+test1() => const A(y: "foo", 0);
+test2() => const A.redir(y: "foo", 0);
+main() {}
diff --git a/pkg/front_end/testcases/general/issue49087.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue49087.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2239f30
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue49087.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+class A {
+  const A(int x, {String? y});
+  const factory A.redir(int x, {String? y}) = A;
+}
+
+main() {}
+test1() => const A(y: "foo", 0);
+test2() => const A.redir(y: "foo", 0);
diff --git a/pkg/front_end/testcases/general/issue49087.dart.weak.expect b/pkg/front_end/testcases/general/issue49087.dart.weak.expect
new file mode 100644
index 0000000..0664156
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue49087.dart.weak.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  const constructor •(core::int x, {core::String? y = #C2}) → self::A
+    : super core::Object::•()
+    ;
+  static factory redir(core::int x, {core::String? y = #C2}) → self::A
+    return new self::A::•(x, y: y);
+}
+static method test1() → dynamic
+  return #C3;
+static method test2() → dynamic
+  return #C3;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::redir
+  #C2 = null
+  #C3 = self::A {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49087.dart:
+- A. (from org-dartlang-testcase:///issue49087.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/issue49087.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue49087.dart.weak.modular.expect
new file mode 100644
index 0000000..0664156
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue49087.dart.weak.modular.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  const constructor •(core::int x, {core::String? y = #C2}) → self::A
+    : super core::Object::•()
+    ;
+  static factory redir(core::int x, {core::String? y = #C2}) → self::A
+    return new self::A::•(x, y: y);
+}
+static method test1() → dynamic
+  return #C3;
+static method test2() → dynamic
+  return #C3;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::redir
+  #C2 = null
+  #C3 = self::A {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49087.dart:
+- A. (from org-dartlang-testcase:///issue49087.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/issue49087.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue49087.dart.weak.outline.expect
new file mode 100644
index 0000000..b574977
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue49087.dart.weak.outline.expect
@@ -0,0 +1,23 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir]/*isLegacy*/;
+  const constructor •(core::int x, {core::String? y = null}) → self::A
+    : super core::Object::•()
+    ;
+  static factory redir(core::int x, {core::String? y = null}) → self::A
+    return new self::A::•(x, y: y);
+}
+static method test1() → dynamic
+  ;
+static method test2() → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue49087.dart:5:7 -> ConstructorTearOffConstant(A.redir)
+Extra constant evaluation: evaluated: 5, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/issue49087.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue49087.dart.weak.transformed.expect
new file mode 100644
index 0000000..0664156
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue49087.dart.weak.transformed.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  const constructor •(core::int x, {core::String? y = #C2}) → self::A
+    : super core::Object::•()
+    ;
+  static factory redir(core::int x, {core::String? y = #C2}) → self::A
+    return new self::A::•(x, y: y);
+}
+static method test1() → dynamic
+  return #C3;
+static method test2() → dynamic
+  return #C3;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::redir
+  #C2 = null
+  #C3 = self::A {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49087.dart:
+- A. (from org-dartlang-testcase:///issue49087.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)