[cfe] Disentangle type inference and default value copying in super-parameters

Part of https://github.com/dart-lang/sdk/issues/47525

Change-Id: Ia8f14aa5995f50719bc95d8b26c3bd5a40d6f967
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/229148
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
diff --git a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
index c880b78..dcaf732 100644
--- a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
@@ -357,45 +357,42 @@
       if (formal.isSuperInitializingFormal) {
         superInitializingFormalIndex++;
         bool hasImmediatelyDeclaredInitializer = formal.hasDeclaredInitializer;
-        if (formal.type == null) {
-          DartType? type;
 
-          if (formal.isPositional) {
-            if (superInitializingFormalIndex < superFormals.length) {
-              FormalParameterBuilder correspondingSuperFormal =
-                  superFormals[superInitializingFormalIndex];
-              formal.hasDeclaredInitializer =
-                  hasImmediatelyDeclaredInitializer ||
-                      correspondingSuperFormal.hasDeclaredInitializer;
-              if (!hasImmediatelyDeclaredInitializer) {
-                (positionalSuperParameters ??= <int>[]).add(formalIndex);
-              }
-              type = correspondingSuperFormal.variable!.type;
-            } else {
-              // TODO(cstefantsova): Report an error.
+        FormalParameterBuilder? correspondingSuperFormal;
+
+        if (formal.isPositional) {
+          if (superInitializingFormalIndex < superFormals.length) {
+            correspondingSuperFormal =
+                superFormals[superInitializingFormalIndex];
+            formal.hasDeclaredInitializer = hasImmediatelyDeclaredInitializer ||
+                correspondingSuperFormal.hasDeclaredInitializer;
+            if (!hasImmediatelyDeclaredInitializer) {
+              (positionalSuperParameters ??= <int>[]).add(formalIndex);
             }
           } else {
-            FormalParameterBuilder? correspondingSuperFormal;
-            for (FormalParameterBuilder superFormal in superFormals) {
-              if (superFormal.isNamed && superFormal.name == formal.name) {
-                correspondingSuperFormal = superFormal;
-                break;
-              }
-            }
-
-            if (correspondingSuperFormal != null) {
-              formal.hasDeclaredInitializer =
-                  hasImmediatelyDeclaredInitializer ||
-                      correspondingSuperFormal.hasDeclaredInitializer;
-              if (!hasImmediatelyDeclaredInitializer) {
-                (namedSuperParameters ??= <String>[]).add(formal.name);
-              }
-              type = correspondingSuperFormal.variable!.type;
-            } else {
-              // TODO(cstefantsova): Report an error.
+            // TODO(cstefantsova): Report an error.
+          }
+        } else {
+          for (FormalParameterBuilder superFormal in superFormals) {
+            if (superFormal.isNamed && superFormal.name == formal.name) {
+              correspondingSuperFormal = superFormal;
+              break;
             }
           }
 
+          if (correspondingSuperFormal != null) {
+            formal.hasDeclaredInitializer = hasImmediatelyDeclaredInitializer ||
+                correspondingSuperFormal.hasDeclaredInitializer;
+            if (!hasImmediatelyDeclaredInitializer) {
+              (namedSuperParameters ??= <String>[]).add(formal.name);
+            }
+          } else {
+            // TODO(cstefantsova): Report an error.
+          }
+        }
+
+        if (formal.type == null) {
+          DartType? type = correspondingSuperFormal?.variable?.type;
           if (substitution.isNotEmpty && type != null) {
             type = substitute(type, substitution);
           }
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart
new file mode 100644
index 0000000..f5b1bd9
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart
@@ -0,0 +1,16 @@
+// 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 S {
+  int s1;
+  int s2;
+  S([this.s1 = 1, this.s2 = 2]);
+}
+
+class C extends S {
+  int c1;
+  C(this.c1, [int super.s1, int x = 0, int super.s2]);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.transformed.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.textual_outline.expect
new file mode 100644
index 0000000..7acd1b7
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+class S {
+  int s1;
+  int s2;
+  S([this.s1 = 1, this.s2 = 2]);
+}
+class C extends S {
+  int c1;
+  C(this.c1, [int super.s1, int x = 0, int super.s2]);
+}
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.modular.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.modular.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.outline.expect
new file mode 100644
index 0000000..aae570e
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.outline.expect
@@ -0,0 +1,18 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = 1, core::int s2 = 2]) → self::S
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = 1, core::int x = 0, dynamic s2 = 2]) → self::C
+    : self::C::c1 = c1
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.transformed.expect
new file mode 100644
index 0000000..3bd8f09
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/super_parameters_with_types_and_default_values.dart.weak.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class S extends core::Object {
+  field core::int s1;
+  field core::int s2;
+  constructor •([core::int s1 = #C1, core::int s2 = #C2]) → self::S
+    : self::S::s1 = s1, self::S::s2 = s2, super core::Object::•()
+    ;
+}
+class C extends self::S {
+  field core::int c1;
+  constructor •(core::int c1, [dynamic s1 = #C1, core::int x = #C3, dynamic s2 = #C2]) → self::C
+    : self::C::c1 = c1, super self::S::•(s1, s2)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 86a420c..751ebe1 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -100,10 +100,10 @@
 general/issue43363: FormatterCrash
 general/issue45490: FormatterCrash
 general/issue45700.crash: FormatterCrash
-general/issue_46886: FormatterCrash
 general/issue47495: FormatterCrash
 general/issue47728_2: FormatterCrash
 general/issue47728_3: FormatterCrash
+general/issue_46886: FormatterCrash
 general/macro_class: FormatterCrash
 general/many_errors: FormatterCrash
 general/missing_prefix_name: FormatterCrash
@@ -219,6 +219,7 @@
 super_parameters/simple_inference: FormatterCrash
 super_parameters/simple_named_super_parameters: FormatterCrash
 super_parameters/simple_positional_super_parameters: FormatterCrash
+super_parameters/super_parameters_with_types_and_default_values: FormatterCrash
 super_parameters/synthesized_super_constructor_with_parameters: FormatterCrash
 super_parameters/type_alias_in_supertype: FormatterCrash
 super_parameters/typed_super_parameter: FormatterCrash