[cfe] Ensure abstract methods have sync marker
This ensures that abstract methods have sync markers even when they
are erroneously marked with a sync*, async or async* marker. This
ensures that these are verifiable.
Change-Id: I6d5bed9305129c47306ad9fd0e248683a6577800
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/307804
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
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 a8aa068..4f785bd 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -1245,7 +1245,7 @@
if (_context.isConstructor) {
finishConstructor(asyncModifier, body,
superParametersAsArguments: superParametersAsArguments);
- } else {
+ } else if (body != null) {
_context.setAsyncModifier(asyncModifier);
}
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 48e3a8b..6707ef7 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -1961,6 +1961,10 @@
}
TypeBuilder? returnType = pop() as TypeBuilder?;
bool isAbstract = bodyKind == MethodBody.Abstract;
+ if (isAbstract) {
+ // An error has been reported if this wasn't already sync.
+ asyncModifier = AsyncMarker.Sync;
+ }
if (getOrSet != null && optional("set", getOrSet)) {
if (formals == null || formals.length != 1) {
// This isn't abstract as we'll add an error-recovery node in
diff --git a/pkg/front_end/testcases/general/abstract_async.dart b/pkg/front_end/testcases/general/abstract_async.dart
new file mode 100644
index 0000000..472f484
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_async.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2023, 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.
+
+abstract class Class {
+ void abstractSyncStar() sync*;
+ void abstractAsync() async;
+ void abstractAsyncStar() async*;
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/abstract_async.dart.strong.expect b/pkg/front_end/testcases/general/abstract_async.dart.strong.expect
new file mode 100644
index 0000000..e0e76e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_async.dart.strong.expect
@@ -0,0 +1,50 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsyncStar() async*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsyncStar() async*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:8: Error: Functions marked 'sync*' can't have return type 'void'.
+// void abstractSyncStar() sync*;
+// ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:8: Error: Functions marked 'async*' can't have return type 'void'.
+// void abstractAsyncStar() async*;
+// ^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Class extends core::Object {
+ synthetic constructor •() → self::Class
+ : super core::Object::•()
+ ;
+ abstract method abstractSyncStar() → void;
+ abstract method abstractAsync() → void;
+ abstract method abstractAsyncStar() → void;
+}
diff --git a/pkg/front_end/testcases/general/abstract_async.dart.strong.transformed.expect b/pkg/front_end/testcases/general/abstract_async.dart.strong.transformed.expect
new file mode 100644
index 0000000..e0e76e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_async.dart.strong.transformed.expect
@@ -0,0 +1,50 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsyncStar() async*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsyncStar() async*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:8: Error: Functions marked 'sync*' can't have return type 'void'.
+// void abstractSyncStar() sync*;
+// ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:8: Error: Functions marked 'async*' can't have return type 'void'.
+// void abstractAsyncStar() async*;
+// ^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Class extends core::Object {
+ synthetic constructor •() → self::Class
+ : super core::Object::•()
+ ;
+ abstract method abstractSyncStar() → void;
+ abstract method abstractAsync() → void;
+ abstract method abstractAsyncStar() → void;
+}
diff --git a/pkg/front_end/testcases/general/abstract_async.dart.textual_outline.expect b/pkg/front_end/testcases/general/abstract_async.dart.textual_outline.expect
new file mode 100644
index 0000000..4dd0374
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_async.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+abstract class Class {
+ void abstractSyncStar() sync*;
+ void abstractAsync() async;
+ void abstractAsyncStar() async*;
+}
diff --git a/pkg/front_end/testcases/general/abstract_async.dart.weak.expect b/pkg/front_end/testcases/general/abstract_async.dart.weak.expect
new file mode 100644
index 0000000..e0e76e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_async.dart.weak.expect
@@ -0,0 +1,50 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsyncStar() async*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsyncStar() async*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:8: Error: Functions marked 'sync*' can't have return type 'void'.
+// void abstractSyncStar() sync*;
+// ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:8: Error: Functions marked 'async*' can't have return type 'void'.
+// void abstractAsyncStar() async*;
+// ^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Class extends core::Object {
+ synthetic constructor •() → self::Class
+ : super core::Object::•()
+ ;
+ abstract method abstractSyncStar() → void;
+ abstract method abstractAsync() → void;
+ abstract method abstractAsyncStar() → void;
+}
diff --git a/pkg/front_end/testcases/general/abstract_async.dart.weak.modular.expect b/pkg/front_end/testcases/general/abstract_async.dart.weak.modular.expect
new file mode 100644
index 0000000..e0e76e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_async.dart.weak.modular.expect
@@ -0,0 +1,50 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsyncStar() async*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsyncStar() async*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:8: Error: Functions marked 'sync*' can't have return type 'void'.
+// void abstractSyncStar() sync*;
+// ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:8: Error: Functions marked 'async*' can't have return type 'void'.
+// void abstractAsyncStar() async*;
+// ^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Class extends core::Object {
+ synthetic constructor •() → self::Class
+ : super core::Object::•()
+ ;
+ abstract method abstractSyncStar() → void;
+ abstract method abstractAsync() → void;
+ abstract method abstractAsyncStar() → void;
+}
diff --git a/pkg/front_end/testcases/general/abstract_async.dart.weak.outline.expect b/pkg/front_end/testcases/general/abstract_async.dart.weak.outline.expect
new file mode 100644
index 0000000..c2be419
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_async.dart.weak.outline.expect
@@ -0,0 +1,41 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsyncStar() async*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsyncStar() async*;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Class extends core::Object {
+ synthetic constructor •() → self::Class
+ ;
+ abstract method abstractSyncStar() → void;
+ abstract method abstractAsync() → void;
+ abstract method abstractAsyncStar() → void;
+}
diff --git a/pkg/front_end/testcases/general/abstract_async.dart.weak.transformed.expect b/pkg/front_end/testcases/general/abstract_async.dart.weak.transformed.expect
new file mode 100644
index 0000000..e0e76e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/abstract_async.dart.weak.transformed.expect
@@ -0,0 +1,50 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:32: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractSyncStar() sync*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:7:29: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsync() async;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Abstract methods can't use 'async', 'async*', or 'sync*'.
+// void abstractAsyncStar() async*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:34: Error: Expected a function body or '=>'.
+// Try adding {}.
+// void abstractAsyncStar() async*;
+// ^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:6:8: Error: Functions marked 'sync*' can't have return type 'void'.
+// void abstractSyncStar() sync*;
+// ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/abstract_async.dart:8:8: Error: Functions marked 'async*' can't have return type 'void'.
+// void abstractAsyncStar() async*;
+// ^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Class extends core::Object {
+ synthetic constructor •() → self::Class
+ : super core::Object::•()
+ ;
+ abstract method abstractSyncStar() → void;
+ abstract method abstractAsync() → void;
+ abstract method abstractAsyncStar() → void;
+}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 6b1ca37..77f5ac8 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -52,6 +52,7 @@
extensions/issue38600: FormatterCrash
extensions/issue38712: FormatterCrash
extensions/issue38745: FormatterCrash
+general/abstract_async: FormatterCrash
general/annotation_eof: FormatterCrash
general/bad_setter_abstract: FormatterCrash
general/bug31124: FormatterCrash