[model] Mark erroneous constructors as such in the CFE
This allows to skip some apriori failing checks and avoid cascading
errors. Aditionally it instructs the verifier to not check the
erroneous constructors.
Change-Id: Ie96bbe84d02a96567b3deab65e15e0780a625d19
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/424820
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
diff --git a/pkg/front_end/lib/src/kernel/kernel_target.dart b/pkg/front_end/lib/src/kernel/kernel_target.dart
index d890f289..4c91ebf 100644
--- a/pkg/front_end/lib/src/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/kernel/kernel_target.dart
@@ -1433,18 +1433,23 @@
Initializer initializer = fieldBuilder.buildImplicitInitializer();
constructorBuilder.prependInitializer(initializer);
if (fieldBuilder.isFinal) {
- libraryBuilder.addProblem(
- templateFinalFieldNotInitializedByConstructor
- .withArguments(fieldBuilder.name),
- constructorBuilder.fileOffset,
- constructorBuilder.name.length,
- constructorBuilder.fileUri,
- context: [
- templateMissingImplementationCause
- .withArguments(fieldBuilder.name)
- .withLocation(fieldBuilder.fileUri,
- fieldBuilder.fileOffset, fieldBuilder.name.length)
- ]);
+ // Avoid cascading error if the constructor is known to be
+ // erroneous: such constructors don't initialize the final fields
+ // properly.
+ if (!constructorBuilder.invokeTarget.isErroneous) {
+ libraryBuilder.addProblem(
+ templateFinalFieldNotInitializedByConstructor
+ .withArguments(fieldBuilder.name),
+ constructorBuilder.fileOffset,
+ constructorBuilder.name.length,
+ constructorBuilder.fileUri,
+ context: [
+ templateMissingImplementationCause
+ .withArguments(fieldBuilder.name)
+ .withLocation(fieldBuilder.fileUri,
+ fieldBuilder.fileOffset, fieldBuilder.name.length)
+ ]);
+ }
} else if (fieldBuilder.fieldType is! InvalidType &&
!fieldBuilder.isLate &&
fieldBuilder.fieldType.isPotentiallyNonNullable) {
diff --git a/pkg/front_end/lib/src/source/source_constructor_builder.dart b/pkg/front_end/lib/src/source/source_constructor_builder.dart
index 7740b0f..d051fb5 100644
--- a/pkg/front_end/lib/src/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/source/source_constructor_builder.dart
@@ -368,6 +368,9 @@
message: message,
kind: UnresolvedKind.Constructor))
..parent = parent);
+ if (parent is Constructor) {
+ parent.isErroneous = true;
+ }
} else {
_initializers.add(initializer..parent = parent);
}
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.expect
index df359db..4bf8416 100644
--- a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.expect
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.expect
@@ -7,14 +7,6 @@
// const E2.named(int value) : this(value, value); // Error.
// ^
//
-// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:9: Error: Final field 'foo' is not initialized by this constructor.
-// Try to initialize the field using an initializing formal or a field initializer.
-// const E2.named(int value) : this(value, value); // Error.
-// ^^^^^
-// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:19:13: Context: 'foo' is defined here.
-// final int foo;
-// ^^^
-//
import self as self;
import "dart:core" as core;
@@ -46,7 +38,7 @@
const constructor •(core::int #index, core::String #name, core::int foo) → self::E2
: self::E2::foo = foo, super core::_Enum::•(#index, #name)
;
- const constructor named(core::int #index, core::String #name, core::int value) → self::E2
+ const erroneous constructor named(core::int #index, core::String #name, core::int value) → self::E2
: self::E2::foo = null, final dynamic #t1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
Try removing the extra positional arguments.
const E2.named(int value) : this(value, value); // Error.
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.modular.expect b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.modular.expect
index df359db..4bf8416 100644
--- a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.modular.expect
@@ -7,14 +7,6 @@
// const E2.named(int value) : this(value, value); // Error.
// ^
//
-// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:9: Error: Final field 'foo' is not initialized by this constructor.
-// Try to initialize the field using an initializing formal or a field initializer.
-// const E2.named(int value) : this(value, value); // Error.
-// ^^^^^
-// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:19:13: Context: 'foo' is defined here.
-// final int foo;
-// ^^^
-//
import self as self;
import "dart:core" as core;
@@ -46,7 +38,7 @@
const constructor •(core::int #index, core::String #name, core::int foo) → self::E2
: self::E2::foo = foo, super core::_Enum::•(#index, #name)
;
- const constructor named(core::int #index, core::String #name, core::int value) → self::E2
+ const erroneous constructor named(core::int #index, core::String #name, core::int value) → self::E2
: self::E2::foo = null, final dynamic #t1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
Try removing the extra positional arguments.
const E2.named(int value) : this(value, value); // Error.
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.outline.expect b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.outline.expect
index 00353042..e8e5bc5 100644
--- a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.outline.expect
@@ -32,7 +32,7 @@
const constructor •(core::int #index, core::String #name, core::int foo) → self::E2
: self::E2::foo = foo, super core::_Enum::•(#index, #name)
;
- const constructor named(core::int #index, core::String #name, core::int value) → self::E2
+ const erroneous constructor named(core::int #index, core::String #name, core::int value) → self::E2
: final dynamic #t1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
Try removing the extra positional arguments.
const E2.named(int value) : this(value, value); // Error.
diff --git a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.transformed.expect
index df359db..4bf8416 100644
--- a/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart.strong.transformed.expect
@@ -7,14 +7,6 @@
// const E2.named(int value) : this(value, value); // Error.
// ^
//
-// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:9: Error: Final field 'foo' is not initialized by this constructor.
-// Try to initialize the field using an initializing formal or a field initializer.
-// const E2.named(int value) : this(value, value); // Error.
-// ^^^^^
-// pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:19:13: Context: 'foo' is defined here.
-// final int foo;
-// ^^^
-//
import self as self;
import "dart:core" as core;
@@ -46,7 +38,7 @@
const constructor •(core::int #index, core::String #name, core::int foo) → self::E2
: self::E2::foo = foo, super core::_Enum::•(#index, #name)
;
- const constructor named(core::int #index, core::String #name, core::int value) → self::E2
+ const erroneous constructor named(core::int #index, core::String #name, core::int value) → self::E2
: self::E2::foo = null, final dynamic #t1 = invalid-expression "pkg/front_end/testcases/enhanced_enums/redirecting_initializers.dart:22:35: Error: Too many positional arguments: 3 allowed, but 4 found.
Try removing the extra positional arguments.
const E2.named(int value) : this(value, value); // Error.
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect
index ef4b510..3bf5b68 100644
--- a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect
@@ -11,7 +11,7 @@
import "dart:core" as core;
class C extends core::Object /*hasConstConstructor*/ {
- const constructor •() → self::C
+ const erroneous constructor •() → self::C
: final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Error: Too many positional arguments: 0 allowed, but 1 found.
Try removing the extra positional arguments.
const C() : this.x(1);
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.modular.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.modular.expect
index ef4b510..3bf5b68 100644
--- a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.modular.expect
@@ -11,7 +11,7 @@
import "dart:core" as core;
class C extends core::Object /*hasConstConstructor*/ {
- const constructor •() → self::C
+ const erroneous constructor •() → self::C
: final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Error: Too many positional arguments: 0 allowed, but 1 found.
Try removing the extra positional arguments.
const C() : this.x(1);
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.outline.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.outline.expect
index 79fa8bb..4735bab 100644
--- a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.outline.expect
+++ b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.outline.expect
@@ -11,7 +11,7 @@
import "dart:core" as core;
class C extends core::Object /*hasConstConstructor*/ {
- const constructor •() → self::C
+ const erroneous constructor •() → self::C
: final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Error: Too many positional arguments: 0 allowed, but 1 found.
Try removing the extra positional arguments.
const C() : this.x(1);
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect
index ef4b510..3bf5b68 100644
--- a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
import "dart:core" as core;
class C extends core::Object /*hasConstConstructor*/ {
- const constructor •() → self::C
+ const erroneous constructor •() → self::C
: final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/bad_constructor_redirection.dart:6:21: Error: Too many positional arguments: 0 allowed, but 1 found.
Try removing the extra positional arguments.
const C() : this.x(1);
diff --git a/pkg/kernel/lib/src/ast/members.dart b/pkg/kernel/lib/src/ast/members.dart
index 2f61c13..7ebeaf2 100644
--- a/pkg/kernel/lib/src/ast/members.dart
+++ b/pkg/kernel/lib/src/ast/members.dart
@@ -599,6 +599,7 @@
static const int FlagConst = 1 << 0; // Must match serialized bit positions.
static const int FlagExternal = 1 << 1;
static const int FlagSynthetic = 1 << 2;
+ static const int FlagErroneous = 1 << 3;
@override
bool get isConst => flags & FlagConst != 0;
@@ -606,6 +607,9 @@
@override
bool get isExternal => flags & FlagExternal != 0;
+ @override
+ bool get isErroneous => flags & FlagErroneous != 0;
+
/// True if this is a synthetic constructor inserted in a class that
/// does not otherwise declare any constructors.
bool get isSynthetic => flags & FlagSynthetic != 0;
@@ -622,6 +626,10 @@
flags = value ? (flags | FlagSynthetic) : (flags & ~FlagSynthetic);
}
+ void set isErroneous(bool value) {
+ flags = value ? (flags | FlagErroneous) : (flags & ~FlagErroneous);
+ }
+
@override
bool get isInstanceMember => false;
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 2116aa4..cb3c754 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1180,6 +1180,7 @@
writeModifier(node.isExternal, 'external');
writeModifier(node.isConst, 'const');
writeModifier(node.isSynthetic, 'synthetic');
+ writeModifier(node.isErroneous, 'erroneous');
writeWord('constructor');
List<String> features = <String>[];
if (node.enclosingClass.fileUri != node.fileUri) {