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]) {}