Emit a compile-time error on incorrect types of initializing formals

Fixes #32526.

Bug: http://dartbug.com/32526
Change-Id: I1e4738937ade7592f7fb1d16bf485ad4ccd077c2
Reviewed-on: https://dart-review.googlesource.com/46801
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 5f91fd5..4b6ff13 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -2814,6 +2814,59 @@
         r"""Try removing the initializer, or using a different kind of loop.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        DartType _type,
+        DartType
+            _type2)> templateInitializingFormalTypeMismatch = const Template<
+        Message Function(String name, DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The type of parameter '#name' (#type) is not a subtype of the corresponding field's type (#type2).""",
+    tipTemplate:
+        r"""Try changing the type of parameter '#name' to a subtype of #type2.""",
+    withArguments: _withArgumentsInitializingFormalTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, DartType _type, DartType _type2)>
+    codeInitializingFormalTypeMismatch =
+    const Code<Message Function(String name, DartType _type, DartType _type2)>(
+        "InitializingFormalTypeMismatch",
+        templateInitializingFormalTypeMismatch,
+        analyzerCode: "INVALID_PARAMETER_DECLARATION",
+        dart2jsCode: "*fatal*",
+        severity: Severity.errorLegacyWarning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInitializingFormalTypeMismatch(
+    String name, DartType _type, DartType _type2) {
+  NameSystem nameSystem = new NameSystem();
+  StringBuffer buffer = new StringBuffer();
+  new Printer(buffer, syntheticNames: nameSystem).writeNode(_type);
+  String type = '$buffer';
+
+  buffer = new StringBuffer();
+  new Printer(buffer, syntheticNames: nameSystem).writeNode(_type2);
+  String type2 = '$buffer';
+
+  return new Message(codeInitializingFormalTypeMismatch,
+      message:
+          """The type of parameter '$name' ($type) is not a subtype of the corresponding field's type ($type2).""",
+      tip: """Try changing the type of parameter '$name' to a subtype of $type2.""",
+      arguments: {'name': name, 'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInitializingFormalTypeMismatchField =
+    messageInitializingFormalTypeMismatchField;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInitializingFormalTypeMismatchField =
+    const MessageCode("InitializingFormalTypeMismatchField",
+        severity: Severity.context,
+        message: r"""The field that corresponds to the parameter.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(Uri uri_)> templateInputFileNotFound =
     const Template<Message Function(Uri uri_)>(
         messageTemplate: r"""Input file not found: #uri.""",
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index d50fdc3..c72e5ab 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -585,7 +585,8 @@
                   true,
                   formal.name,
                   formal.charOffset,
-                  toExpression(new VariableGet(formal.declaration)));
+                  toExpression(new VariableGet(formal.declaration)),
+                  formalType: formal.declaration.type);
             }
             member.addInitializer(initializer, _typeInferrer);
           }
@@ -3914,9 +3915,19 @@
     return initializer;
   }
 
+  /// Parameter [formalType] should only be passed in the special case of
+  /// building a field initializer as a desugaring of an initializing formal
+  /// parameter.  The spec says the following:
+  ///
+  /// "If an explicit type is attached to the initializing formal, that is its
+  /// static type.  Otherwise, the type of an initializing formal named _id_ is
+  /// _Tid_, where _Tid_ is the type of the instance variable named _id_ in the
+  /// immediately enclosing class.  It is a static warning if the static type of
+  /// _id_ is not a subtype of _Tid_."
   @override
   Initializer buildFieldInitializer(
-      bool isSynthetic, String name, int offset, Expression expression) {
+      bool isSynthetic, String name, int offset, Expression expression,
+      {DartType formalType}) {
     Declaration builder =
         classBuilder.scope.local[name] ?? classBuilder.origin.scope.local[name];
     if (builder is KernelFieldBuilder && builder.isInstanceMember) {
@@ -3950,6 +3961,21 @@
                 charOffset: offset)))),
             offset);
       } else {
+        if (library.loader.target.strongMode &&
+            formalType != null &&
+            !_typeInferrer.typeSchemaEnvironment
+                .isSubtypeOf(formalType, builder.field.type)) {
+          library.addProblem(
+              fasta.templateInitializingFormalTypeMismatch
+                  .withArguments(name, formalType, builder.field.type),
+              offset,
+              noLength,
+              uri,
+              context: [
+                fasta.messageInitializingFormalTypeMismatchField
+                    .withLocation(builder.fileUri, builder.charOffset, noLength)
+              ]);
+        }
         return new ShadowFieldInitializer(
             builder.field, toKernelExpression(expression))
           ..fileOffset = offset
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index 4d3404a..5351b10 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -80,7 +80,8 @@
   Initializer buildInvalidInitializer(Expression expression, [int offset]);
 
   Initializer buildFieldInitializer(
-      bool isSynthetic, String name, int offset, Expression expression);
+      bool isSynthetic, String name, int offset, Expression expression,
+      {DartType formalType});
 
   Initializer buildSuperInitializer(
       bool isSynthetic, Constructor constructor, Arguments arguments,
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 440aab5..04de09a 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -2207,3 +2207,19 @@
   template: "A for-in loop can't have more than one loop variable."
   severity: ERROR
   statement: "for (var x, y in []) {}"
+
+InitializingFormalTypeMismatch:
+  template: "The type of parameter '#name' (#type) is not a subtype of the corresponding field's type (#type2)."
+  tip: "Try changing the type of parameter '#name' to a subtype of #type2."
+  severity: ERROR_LEGACY_WARNING
+  analyzerCode: INVALID_PARAMETER_DECLARATION
+  dart2jsCode: "*fatal*"
+  script: >
+    class C {
+      int x;
+      C(num this.x);
+    }
+
+InitializingFormalTypeMismatchField:
+  template: "The field that corresponds to the parameter."
+  severity: CONTEXT
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index dfd4e39..94f990f 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -57,6 +57,7 @@
 Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t01: MissingCompileTimeError
 Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t02: MissingCompileTimeError
 Language/Classes/Constructors/Constant_Constructors/invalid_constant_initializer_t02: MissingCompileTimeError
+Language/Classes/Constructors/Generative_Constructors/static_type_t01: CompileTimeError
 Language/Classes/Instance_Methods/same_name_setter_t02: CompileTimeError # Issue 14736
 Language/Classes/Setters/name_t03: CompileTimeError
 Language/Classes/Setters/name_t04: CompileTimeError
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index fdfc105..c51bde4 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -1152,7 +1152,6 @@
 override_inheritance_generic_test/02: CompileTimeError
 override_inheritance_method_test/28: CompileTimeError
 override_inheritance_method_test/29: CompileTimeError
-parameter_initializer_test: CompileTimeError
 parser_quirks_test: CompileTimeError
 regress_22976_test/01: CompileTimeError
 regress_22976_test/02: CompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 9b6948a..5a9ca58 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -918,8 +918,6 @@
 compile_time_constant_k_test/03: MissingCompileTimeError
 compile_time_constant_o_test/01: MissingCompileTimeError
 compile_time_constant_o_test/02: MissingCompileTimeError
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
 compile_time_constant_static5_test/11: CompileTimeError
 compile_time_constant_static5_test/16: CompileTimeError
 compile_time_constant_static5_test/21: CompileTimeError
@@ -1047,8 +1045,6 @@
 identical_const_test/04: MissingCompileTimeError
 if_null_precedence_test/none: RuntimeError
 infinity_test: RuntimeError # non JS number semantics - Issue 4984
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 instance_creation_in_function_annotation_test: RuntimeError
 instantiate_tearoff_of_call_test: CompileTimeError
 int64_literal_test/01: RuntimeError
@@ -1458,8 +1454,6 @@
 compile_time_constant_k_test/03: MissingCompileTimeError
 compile_time_constant_o_test/01: MissingCompileTimeError
 compile_time_constant_o_test/02: MissingCompileTimeError
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
 compile_time_constant_static5_test/11: CompileTimeError
 compile_time_constant_static5_test/16: CompileTimeError
 compile_time_constant_static5_test/21: CompileTimeError
@@ -1581,8 +1575,6 @@
 identical_const_test/04: MissingCompileTimeError
 if_null_precedence_test/none: RuntimeError
 infinity_test: RuntimeError # non JS number semantics - Issue 4984
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 instance_creation_in_function_annotation_test: RuntimeError
 instantiate_tearoff_of_call_test: CompileTimeError
 int64_literal_test/01: RuntimeError
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 290e42a..671d1b0 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -141,7 +141,6 @@
 override_inheritance_generic_test/02: CompileTimeError
 override_inheritance_method_test/28: CompileTimeError
 override_inheritance_method_test/29: CompileTimeError
-parameter_initializer_test: CompileTimeError
 part_refers_to_core_library_test/01: Crash
 prefix_shadow_test/01: MissingCompileTimeError # Issue 33005
 regress_23089_test: MissingCompileTimeError
@@ -322,8 +321,6 @@
 compile_time_constant_k_test/03: MissingCompileTimeError
 compile_time_constant_o_test/01: MissingCompileTimeError
 compile_time_constant_o_test/02: MissingCompileTimeError
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
 compile_time_constant_static4_test/02: MissingCompileTimeError
 compile_time_constant_static4_test/03: MissingCompileTimeError
 compile_time_constant_static5_test/11: CompileTimeError # Issue 31537
@@ -415,8 +412,6 @@
 implicit_creation/implicit_const_not_default_values_test/e30: Pass
 implicit_creation/implicit_const_not_default_values_test/e6: Pass
 implicit_creation/implicit_const_not_default_values_test/e9: Pass
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 instantiate_tearoff_of_call_test: CompileTimeError
 issue18628_2_test/01: MissingCompileTimeError
 issue31596_override_test/07: MissingCompileTimeError
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index e923ac4..68d5a9a 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -699,8 +699,6 @@
 type_variable_bounds4_test/01: RuntimeError
 
 [ $compiler == dartk && $runtime == vm && !$checked && $strong ]
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
 conditional_rewrite_test: RuntimeError # Issue 31402 (Not)
 type_error_test: RuntimeError # Issue 31402 (Variable declaration)
 
@@ -772,8 +770,6 @@
 generic_tearoff_test: CompileTimeError
 generic_tearoff_test: RuntimeError
 if_null_evaluation_order_test: Pass
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 instantiate_tearoff_of_call_test: CompileTimeError
 issue18628_2_test/01: MissingCompileTimeError
 issue31596_super_test/01: CompileTimeError
@@ -984,8 +980,6 @@
 [ $compiler == dartkp && $runtime == dart_precompiled && !$checked && $strong ]
 assertion_initializer_const_error_test/01: MissingCompileTimeError
 assertion_initializer_const_function_error_test/01: MissingCompileTimeError
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
 conditional_rewrite_test: RuntimeError # Issue 31402 (Not)
 implicit_downcast_during_combiner_test: RuntimeError
 implicit_downcast_during_compound_assignment_test: RuntimeError
@@ -1115,8 +1109,6 @@
 implicit_downcast_during_while_statement_test: Pass # Correctly passes.
 implicit_downcast_during_yield_star_test: Pass # Correctly passes.
 implicit_downcast_during_yield_test: Pass # Correctly passes.
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 instance_creation_in_function_annotation_test: SkipByDesign
 instantiate_tearoff_of_call_test: CompileTimeError
 invocation_mirror2_test: SkipByDesign
@@ -1483,10 +1475,6 @@
 deopt_inlined_function_lazy_test: Skip
 
 [ $fasta && $strong ]
-compile_time_constant_static2_test/04: MissingCompileTimeError
-compile_time_constant_static3_test/04: MissingCompileTimeError
-initializing_formal_type_annotation_test/01: MissingCompileTimeError
-initializing_formal_type_annotation_test/02: MissingCompileTimeError
 issue18628_2_test/01: MissingCompileTimeError
 map_literal3_test/03: MissingCompileTimeError
 redirecting_factory_infinite_steps_test/01: MissingCompileTimeError
diff --git a/tests/language_2/parameter_initializer_test.dart b/tests/language_2/parameter_initializer_test.dart
index e1d5855..1696703 100644
--- a/tests/language_2/parameter_initializer_test.dart
+++ b/tests/language_2/parameter_initializer_test.dart
@@ -9,9 +9,6 @@
     var obj = new Foo.untyped(1);
     Expect.equals(1, obj.x);
 
-    obj = new Foo.supertype(9);
-    Expect.equals(9, obj.x);
-
     obj = new Foo.subtype(7);
     Expect.equals(7, obj.x);
 
@@ -40,7 +37,6 @@
   }
 
   Foo.untyped(this.x) {}
-  Foo.supertype(Object this.x) {}
   Foo.subtype(int this.x) {}
   Foo.optional([this.x = 5]) {}