[vm] Improve async performance by taking advantage of static types of returned values

In general any async function can return X or Future<X>. Though the
future implementation has to do different things depending on which case
we're in. It does so by using a `<obj> is Future<T>` test. This test is very
expensive if many different classes flow into `<obj>`.

Though most functions do not return `Future` objects from async
functions. We can determine that statically by looking if any returned
expression could be a future. If not, we can bypass the `is Future<T>`
test entirely.

Issue https://github.com/dart-lang/sdk/issues/48226
Issue https://github.com/dart-lang/sdk/issues/48235

TEST=pkg/front_end/testcases/general/async_function_returns_future_or.dart

Change-Id: If655bdbdddc214dd7b12be9905b3c788252547d0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/230662
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index e90cf3d..90ad778 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -2570,6 +2570,8 @@
 
 _completeOnAsyncReturn(_future, value, async_jump_var) {}
 
+_completeWithNoFutureOnAsyncReturn(_future, value, async_jump_var) {}
+
 _completeOnAsyncError(_future, e, st, async_jump_var) {}
 
 class _AsyncStarStreamController {
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect
index adcb97b..aaa0017 100644
--- a/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect
@@ -28,7 +28,7 @@
 static method Extension|asyncMethod(lowered final core::int* #this) → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -37,7 +37,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect
index 4e5d4b5..cda03dd 100644
--- a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect
@@ -17,7 +17,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -38,7 +38,7 @@
         self::expect(87, let final core::Object* #t11 = CheckLibraryIsLoaded(prefix) in def::Extension|staticProperty = 87);
         self::expect(87, let final core::Object* #t12 = CheckLibraryIsLoaded(prefix) in def::Extension|staticMethod());
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect
index 299f5f6..52535cd 100644
--- a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -29,7 +29,7 @@
         self::expect(87, let final core::Object* #t7 = CheckLibraryIsLoaded(prefix) in def::topLevelProperty);
         self::expect(87, let final core::Object* #t8 = CheckLibraryIsLoaded(prefix) in def::topLevelMethod());
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
index 295921a..4b96489 100644
--- a/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
@@ -10,7 +10,7 @@
 static method asyncString() → asy::Future<core::String*>* /* originally async */ {
   final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
   core::bool* :is_sync = false;
-  FutureOr<core::String*>* :return_value;
+  core::String? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -22,7 +22,7 @@
         :return_value = "foo";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -181,7 +181,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -194,7 +194,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::asyncString(), :async_op_then, :async_op_error, :async_op) in null;
         core::String* str = _in::unsafeCast<core::String*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart b/pkg/front_end/testcases/general/async_function_returns_future_or.dart
new file mode 100644
index 0000000..8a4d911
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart
@@ -0,0 +1,37 @@
+// 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.
+
+import 'dart:async';
+
+main() async {
+  await returnsString();
+  await returnsFutureOrString();
+  await returnsAwaitFutureOrString();
+  await returnsFutureString();
+  await returnsAwaitFutureString();
+  await returnsObject();
+  await returnsFutureOrObject();
+  await returnsAwaitFutureOrObject();
+  await returnsFutureObject();
+  await returnsAwaitFutureObject();
+}
+
+Future<String> returnsString() async => 'a';
+Future<String> returnsFutureOrString() async => getFutureOr<String>('a');
+Future<String> returnsAwaitFutureOrString() async =>
+    await getFutureOr<String>('a');
+Future<String> returnsFutureString() async => getFuture<String>('a');
+FutureOr<String> returnsAwaitFutureString() async =>
+    await getFuture<String>('a');
+
+Future<Object> returnsObject() async => Object();
+Future<Object> returnsFutureOrObject() async => getFutureOr<Object>(Object());
+Future<Object> returnsAwaitFutureOrObject() async =>
+    await getFutureOr<Object>(Object());
+Future<Object> returnsFutureObject() async => getFuture<Object>(Object());
+FutureOr<Object> returnsAwaitFutureObject() async =>
+    await getFuture<Object>(Object());
+
+FutureOr<T> getFutureOr<T>(T v) async => v;
+Future<T> getFuture<T>(T v) async => v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline.expect
new file mode 100644
index 0000000..94a1eca
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+import 'dart:async';
+
+main() async {}
+Future<String> returnsString() async => 'a';
+Future<String> returnsFutureOrString() async => getFutureOr<String>('a');
+Future<String> returnsAwaitFutureOrString() async =>
+    await getFutureOr<String>('a');
+Future<String> returnsFutureString() async => getFuture<String>('a');
+FutureOr<String> returnsAwaitFutureString() async =>
+    await getFuture<String>('a');
+Future<Object> returnsObject() async => Object();
+Future<Object> returnsFutureOrObject() async => getFutureOr<Object>(Object());
+Future<Object> returnsAwaitFutureOrObject() async =>
+    await getFutureOr<Object>(Object());
+Future<Object> returnsFutureObject() async => getFuture<Object>(Object());
+FutureOr<Object> returnsAwaitFutureObject() async =>
+    await getFuture<Object>(Object());
+FutureOr<T> getFutureOr<T>(T v) async => v;
+Future<T> getFuture<T>(T v) async => v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..41cf593
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+import 'dart:async';
+
+Future<Object> returnsAwaitFutureOrObject() async =>
+    await getFutureOr<Object>(Object());
+Future<Object> returnsFutureObject() async => getFuture<Object>(Object());
+Future<Object> returnsFutureOrObject() async => getFutureOr<Object>(Object());
+Future<Object> returnsObject() async => Object();
+Future<String> returnsAwaitFutureOrString() async =>
+    await getFutureOr<String>('a');
+Future<String> returnsFutureOrString() async => getFutureOr<String>('a');
+Future<String> returnsFutureString() async => getFuture<String>('a');
+Future<String> returnsString() async => 'a';
+Future<T> getFuture<T>(T v) async => v;
+FutureOr<Object> returnsAwaitFutureObject() async =>
+    await getFuture<Object>(Object());
+FutureOr<String> returnsAwaitFutureString() async =>
+    await getFuture<String>('a');
+FutureOr<T> getFutureOr<T>(T v) async => v;
+main() async {}
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.expect
new file mode 100644
index 0000000..6f8e4d4
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.expect
@@ -0,0 +1,43 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method main() → dynamic async {
+  await self::returnsString();
+  await self::returnsFutureOrString();
+  await self::returnsAwaitFutureOrString();
+  await self::returnsFutureString();
+  await self::returnsAwaitFutureString();
+  await self::returnsObject();
+  await self::returnsFutureOrObject();
+  await self::returnsAwaitFutureOrObject();
+  await self::returnsFutureObject();
+  await self::returnsAwaitFutureObject();
+}
+static method returnsString() → asy::Future<core::String> async 
+  return "a";
+static method returnsFutureOrString() → asy::Future<core::String> async 
+  return self::getFutureOr<core::String>("a");
+static method returnsAwaitFutureOrString() → asy::Future<core::String> async 
+  return await self::getFutureOr<core::String>("a");
+static method returnsFutureString() → asy::Future<core::String> async 
+  return self::getFuture<core::String>("a");
+static method returnsAwaitFutureString() → FutureOr<core::String> async 
+  return await self::getFuture<core::String>("a");
+static method returnsObject() → asy::Future<core::Object> async 
+  return new core::Object::•();
+static method returnsFutureOrObject() → asy::Future<core::Object> async 
+  return self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> async 
+  return await self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsFutureObject() → asy::Future<core::Object> async 
+  return self::getFuture<core::Object>(new core::Object::•());
+static method returnsAwaitFutureObject() → FutureOr<core::Object> async 
+  return await self::getFuture<core::Object>(new core::Object::•());
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> async 
+  return v;
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> async 
+  return v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.modular.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.modular.expect
new file mode 100644
index 0000000..6f8e4d4
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.modular.expect
@@ -0,0 +1,43 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method main() → dynamic async {
+  await self::returnsString();
+  await self::returnsFutureOrString();
+  await self::returnsAwaitFutureOrString();
+  await self::returnsFutureString();
+  await self::returnsAwaitFutureString();
+  await self::returnsObject();
+  await self::returnsFutureOrObject();
+  await self::returnsAwaitFutureOrObject();
+  await self::returnsFutureObject();
+  await self::returnsAwaitFutureObject();
+}
+static method returnsString() → asy::Future<core::String> async 
+  return "a";
+static method returnsFutureOrString() → asy::Future<core::String> async 
+  return self::getFutureOr<core::String>("a");
+static method returnsAwaitFutureOrString() → asy::Future<core::String> async 
+  return await self::getFutureOr<core::String>("a");
+static method returnsFutureString() → asy::Future<core::String> async 
+  return self::getFuture<core::String>("a");
+static method returnsAwaitFutureString() → FutureOr<core::String> async 
+  return await self::getFuture<core::String>("a");
+static method returnsObject() → asy::Future<core::Object> async 
+  return new core::Object::•();
+static method returnsFutureOrObject() → asy::Future<core::Object> async 
+  return self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> async 
+  return await self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsFutureObject() → asy::Future<core::Object> async 
+  return self::getFuture<core::Object>(new core::Object::•());
+static method returnsAwaitFutureObject() → FutureOr<core::Object> async 
+  return await self::getFuture<core::Object>(new core::Object::•());
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> async 
+  return v;
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> async 
+  return v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.outline.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.outline.expect
new file mode 100644
index 0000000..98b26fc
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method main() → dynamic async 
+  ;
+static method returnsString() → asy::Future<core::String> async 
+  ;
+static method returnsFutureOrString() → asy::Future<core::String> async 
+  ;
+static method returnsAwaitFutureOrString() → asy::Future<core::String> async 
+  ;
+static method returnsFutureString() → asy::Future<core::String> async 
+  ;
+static method returnsAwaitFutureString() → FutureOr<core::String> async 
+  ;
+static method returnsObject() → asy::Future<core::Object> async 
+  ;
+static method returnsFutureOrObject() → asy::Future<core::Object> async 
+  ;
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> async 
+  ;
+static method returnsFutureObject() → asy::Future<core::Object> async 
+  ;
+static method returnsAwaitFutureObject() → FutureOr<core::Object> async 
+  ;
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> async 
+  ;
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> async 
+  ;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.transformed.expect
new file mode 100644
index 0000000..3100e06
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.transformed.expect
@@ -0,0 +1,386 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+static method main() → dynamic /* originally async */ {
+  final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
+  core::bool* :is_sync = false;
+  dynamic :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        [yield] let dynamic #t1 = asy::_awaitHelper(self::returnsString(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::String>(:result);
+        [yield] let dynamic #t2 = asy::_awaitHelper(self::returnsFutureOrString(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::String>(:result);
+        [yield] let dynamic #t3 = asy::_awaitHelper(self::returnsAwaitFutureOrString(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::String>(:result);
+        [yield] let dynamic #t4 = asy::_awaitHelper(self::returnsFutureString(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::String>(:result);
+        [yield] let dynamic #t5 = asy::_awaitHelper(self::returnsAwaitFutureString(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::String>(:result);
+        [yield] let dynamic #t6 = asy::_awaitHelper(self::returnsObject(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::Object>(:result);
+        [yield] let dynamic #t7 = asy::_awaitHelper(self::returnsFutureOrObject(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::Object>(:result);
+        [yield] let dynamic #t8 = asy::_awaitHelper(self::returnsAwaitFutureOrObject(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::Object>(:result);
+        [yield] let dynamic #t9 = asy::_awaitHelper(self::returnsFutureObject(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::Object>(:result);
+        [yield] let dynamic #t10 = asy::_awaitHelper(self::returnsAwaitFutureObject(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::Object>(:result);
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsString() → asy::Future<core::String> /* originally async */ {
+  final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+  core::bool* :is_sync = false;
+  core::String? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        :return_value = "a";
+        break #L2;
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsFutureOrString() → asy::Future<core::String> /* originally async */ {
+  final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+  core::bool* :is_sync = false;
+  FutureOr<core::String>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        :return_value = self::getFutureOr<core::String>("a");
+        break #L3;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsAwaitFutureOrString() → asy::Future<core::String> /* originally async */ {
+  final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+  core::bool* :is_sync = false;
+  core::String? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L4:
+      {
+        [yield] let dynamic #t11 = asy::_awaitHelper(self::getFutureOr<core::String>("a"), :async_op_then, :async_op_error, :async_op) in null;
+        :return_value = _in::unsafeCast<core::String>(:result);
+        break #L4;
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsFutureString() → asy::Future<core::String> /* originally async */ {
+  final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+  core::bool* :is_sync = false;
+  FutureOr<core::String>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L5:
+      {
+        :return_value = self::getFuture<core::String>("a");
+        break #L5;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsAwaitFutureString() → FutureOr<core::String> /* originally async */ {
+  final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+  core::bool* :is_sync = false;
+  core::String? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L6:
+      {
+        [yield] let dynamic #t12 = asy::_awaitHelper(self::getFuture<core::String>("a"), :async_op_then, :async_op_error, :async_op) in null;
+        :return_value = _in::unsafeCast<core::String>(:result);
+        break #L6;
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsObject() → asy::Future<core::Object> /* originally async */ {
+  final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+  core::bool* :is_sync = false;
+  FutureOr<core::Object>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L7:
+      {
+        :return_value = new core::Object::•();
+        break #L7;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsFutureOrObject() → asy::Future<core::Object> /* originally async */ {
+  final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+  core::bool* :is_sync = false;
+  FutureOr<core::Object>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L8:
+      {
+        :return_value = self::getFutureOr<core::Object>(new core::Object::•());
+        break #L8;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> /* originally async */ {
+  final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+  core::bool* :is_sync = false;
+  FutureOr<core::Object>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L9:
+      {
+        [yield] let dynamic #t13 = asy::_awaitHelper(self::getFutureOr<core::Object>(new core::Object::•()), :async_op_then, :async_op_error, :async_op) in null;
+        :return_value = _in::unsafeCast<core::Object>(:result);
+        break #L9;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsFutureObject() → asy::Future<core::Object> /* originally async */ {
+  final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+  core::bool* :is_sync = false;
+  FutureOr<core::Object>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L10:
+      {
+        :return_value = self::getFuture<core::Object>(new core::Object::•());
+        break #L10;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsAwaitFutureObject() → FutureOr<core::Object> /* originally async */ {
+  final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+  core::bool* :is_sync = false;
+  FutureOr<core::Object>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L11:
+      {
+        [yield] let dynamic #t14 = asy::_awaitHelper(self::getFuture<core::Object>(new core::Object::•()), :async_op_then, :async_op_error, :async_op) in null;
+        :return_value = _in::unsafeCast<core::Object>(:result);
+        break #L11;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> /* originally async */ {
+  final asy::_Future<self::getFutureOr::T%> :async_future = new asy::_Future::•<self::getFutureOr::T%>();
+  core::bool* :is_sync = false;
+  FutureOr<self::getFutureOr::T%>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L12:
+      {
+        :return_value = v;
+        break #L12;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> /* originally async */ {
+  final asy::_Future<self::getFuture::T%> :async_future = new asy::_Future::•<self::getFuture::T%>();
+  core::bool* :is_sync = false;
+  FutureOr<self::getFuture::T%>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L13:
+      {
+        :return_value = v;
+        break #L13;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
diff --git a/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect
index c05a8b5..7e77550 100644
--- a/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect
@@ -13,7 +13,7 @@
 static method foo() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -24,7 +24,7 @@
       {
         invalid-type x;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
index 758329d..ef502e2 100644
--- a/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
@@ -30,7 +30,7 @@
 static method main() → void /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -62,7 +62,7 @@
           throw "Expected '${expected}' but got '${actual}'";
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/await.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await.dart.weak.transformed.expect
index 6107389..7fd936b 100644
--- a/pkg/front_end/testcases/general/await.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -20,7 +20,7 @@
         [yield] let dynamic #t1 = asy::_awaitHelper("Hello, World!", :async_op_then, :async_op_error, :async_op) in null;
         core::print(_in::unsafeCast<core::String*>(:result));
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
index 087766ec..22900f0 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
@@ -59,7 +59,7 @@
 static method staticMembers() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -100,7 +100,7 @@
         core::num* e = _in::unsafeCast<core::int*>(:async_temporary_5).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
         self::expect(5, e);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -115,7 +115,7 @@
 static method topLevelMembers() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -151,7 +151,7 @@
         core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
         self::expect(5, e);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -166,7 +166,7 @@
 static method instanceMembers() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -203,7 +203,7 @@
         core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
         self::expect(5, e);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -218,7 +218,7 @@
 static method others() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -255,7 +255,7 @@
         core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
         self::expect(2, e);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -270,7 +270,7 @@
 static method conditionals() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -327,7 +327,7 @@
         on dynamic catch(final dynamic e) {
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -342,7 +342,7 @@
 static method asserts() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -400,7 +400,7 @@
           }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -415,7 +415,7 @@
 static method controlFlow() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -681,7 +681,7 @@
           }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -758,7 +758,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -785,7 +785,7 @@
           :result;
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect
index 0372529..3dce525 100644
--- a/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect
@@ -13,7 +13,7 @@
   method m() → asy::Future<core::List<core::int*>*>* /* originally async */ {
     final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
     core::bool* :is_sync = false;
-    FutureOr<core::List<core::int*>*>* :return_value;
+    core::List<core::int*>? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -29,7 +29,7 @@
           :return_value = block {} =>#t1;
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -44,7 +44,7 @@
   method _m() → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -56,7 +56,7 @@
           :return_value = 42;
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -82,7 +82,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -95,7 +95,7 @@
         [yield] let dynamic #t3 = asy::_awaitHelper(new self::C::•().{self::C::m}(){() →* asy::Future<core::List<core::int*>*>*}, :async_op_then, :async_op_error, :async_op) in null;
         self::expect(42, _in::unsafeCast<core::List<core::int*>*>(:result).{core::Iterable::first}{core::int*});
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect b/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect
index 3d71e92..1345153 100644
--- a/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
 static method returnsString() → FutureOr<core::String*>* /* originally async */ {
   final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
   core::bool* :is_sync = false;
-  FutureOr<core::String*>* :return_value;
+  core::String? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -24,7 +24,7 @@
         :return_value = "oh no";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect b/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
index 85541c5..8f45939 100644
--- a/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
@@ -43,7 +43,7 @@
 static method f1() → asy::Future<core::List<core::Object*>*>* /* originally async */ {
   final asy::_Future<core::List<core::Object*>*>* :async_future = new asy::_Future::•<core::List<core::Object*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::List<core::Object*>*>* :return_value;
+  core::List<core::Object*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -55,7 +55,7 @@
         :return_value = core::_GrowableList::_literal1<core::Object*>(1);
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -72,7 +72,7 @@
 static method f3() → asy::Future<core::Object*>* /* originally async */ {
   final asy::_Future<core::Object*>* :async_future = new asy::_Future::•<core::Object*>();
   core::bool* :is_sync = false;
-  FutureOr<core::Object*>* :return_value;
+  core::Object? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -84,7 +84,7 @@
         :return_value = 3;
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -99,7 +99,7 @@
 static method foo() → asy::Future<self::X*>* /* originally async */ {
   final asy::_Future<self::X*>* :async_future = new asy::_Future::•<self::X*>();
   core::bool* :is_sync = false;
-  FutureOr<self::X*>* :return_value;
+  self::X? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -120,7 +120,7 @@
         :return_value = new self::X::•(_in::unsafeCast<self::Y*>(:async_temporary_0), _in::unsafeCast<core::Object*>(:result));
         break #L3;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -135,7 +135,7 @@
 static method main() → asy::Future<void>* /* originally async */ {
   final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>* :return_value;
+  void :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -148,7 +148,7 @@
         [yield] let dynamic #t4 = asy::_awaitHelper(self::foo(), :async_op_then, :async_op_error, :async_op) in null;
         core::print(_in::unsafeCast<self::X*>(:result));
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect b/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect
index 0a550d4..5c69330 100644
--- a/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect
@@ -10,7 +10,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -24,7 +24,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(LoadLibrary(lib), :async_op_then, :async_op_error, :async_op) in null;
         def::m(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect
index 59854bd..e74ebe2 100644
--- a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect
@@ -1946,7 +1946,7 @@
 static method testForElementErrors(core::Map<core::int*, core::int*>* map, core::List<core::int*>* list) → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -2481,7 +2481,7 @@
           #t293.{core::Map::[]=}{Invariant}("baz", null){(core::String*, core::int*) →* void};
         } =>#t293;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect
index d223493..cd22de9 100644
--- a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect
@@ -19,7 +19,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -60,7 +60,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect b/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect
index cae05ae..946e531 100644
--- a/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect
@@ -116,7 +116,7 @@
   method test(covariant-by-class asy::Future<self::Response<core::String*>*>* fetch) → asy::Future<core::String*>* /* originally async */ {
     final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
     core::bool* :is_sync = false;
-    FutureOr<core::String*>* :return_value;
+    core::String? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -146,7 +146,7 @@
           :return_value = result;
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -185,7 +185,7 @@
   method test(covariant-by-class asy::Future<self::PagingResponse<core::String*>*>* fetch) → asy::Future<core::String*>* /* originally async */ {
     final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
     core::bool* :is_sync = false;
-    FutureOr<core::String*>* :return_value;
+    core::String? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -215,7 +215,7 @@
           :return_value = result;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect b/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect
index d6d5aa0..f0fb90b 100644
--- a/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect
@@ -45,7 +45,7 @@
 static method returnClass() → self::Class* /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -57,7 +57,7 @@
         :return_value = new self::Class::•();
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -72,7 +72,7 @@
 static method returnFutureClass() → asy::Future<self::Class*>* /* originally async */ {
   final asy::_Future<self::Class*>* :async_future = new asy::_Future::•<self::Class*>();
   core::bool* :is_sync = false;
-  FutureOr<self::Class*>* :return_value;
+  self::Class? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -84,7 +84,7 @@
         :return_value = new self::Class::•();
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -99,7 +99,7 @@
 static method returnFutureOrClass() → FutureOr<self::Class*>* /* originally async */ {
   final asy::_Future<self::Class*>* :async_future = new asy::_Future::•<self::Class*>();
   core::bool* :is_sync = false;
-  FutureOr<self::Class*>* :return_value;
+  self::Class? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -111,7 +111,7 @@
         :return_value = new self::Class::•();
         break #L3;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -369,7 +369,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -404,7 +404,7 @@
         [yield] let dynamic #t12 = asy::_awaitHelper(self::returnFutureOrClassFromFutureOrClass(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<self::Class*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect
index b9327a2..ae34a36 100644
--- a/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect
@@ -27,7 +27,7 @@
   function f2() → invalid-type /* originally async */ {
     final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -36,7 +36,7 @@
       try {
         #L1:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect
index ba98fca..be46445 100644
--- a/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect
@@ -17,7 +17,7 @@
 static method test(self::A<core::String> a) → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
         final core::String? x = _in::unsafeCast<core::String?>(:result);
         self::bar(x);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect b/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect
index e545ab0..983f3d4 100644
--- a/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
   method _foo() → void /* originally async */ {
     final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -25,7 +25,7 @@
           _in::unsafeCast<Null>(:result);
           core::print("hello");
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect b/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
index 3d879b8..3c53c2b 100644
--- a/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
   method foo(dynamic x) → asy::Future<void>* /* originally async */ {
     final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
     core::bool* :is_sync = false;
-    FutureOr<void>* :return_value;
+    void :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -20,7 +20,7 @@
       try {
         #L1:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -50,7 +50,7 @@
   method bar(dynamic x) → asy::Future<void>* /* originally async */ {
     final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
     core::bool* :is_sync = false;
-    FutureOr<void>* :return_value;
+    void :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
       try {
         #L2:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -85,7 +85,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -105,7 +105,7 @@
         :return_value = core::_GrowableList::_literal2<asy::Future<void>*>(_in::unsafeCast<asy::Future<void>*>(:async_temporary_1), _in::unsafeCast<self::B*>(:async_temporary_0).{self::B::bar}(_in::unsafeCast<Null>(:result)){(dynamic) →* asy::Future<void>*});
         break #L3;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect b/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect
index f6ea477..99d4140 100644
--- a/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect
@@ -37,7 +37,7 @@
 static method returnFutureDynamic() → asy::Future<dynamic>* /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -49,7 +49,7 @@
         :return_value = new self::Class::•();
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -64,7 +64,7 @@
 static method returnFutureClass() → asy::Future<self::Class*>* /* originally async */ {
   final asy::_Future<self::Class*>* :async_future = new asy::_Future::•<self::Class*>();
   core::bool* :is_sync = false;
-  FutureOr<self::Class*>* :return_value;
+  self::Class? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -76,7 +76,7 @@
         :return_value = new self::Class::•();
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -169,7 +169,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -206,7 +206,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect
index e955e1e..1bb3512 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect
@@ -4,7 +4,7 @@
   static method whatever() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -19,7 +19,7 @@
           :return_value = "hello";
           break #L1;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -56,7 +56,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -70,7 +70,7 @@
           :result;
           dart.core::print(#C2);
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect
index 4f65073..6a2982c 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect
@@ -4,7 +4,7 @@
   static method whatever() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -19,7 +19,7 @@
           :return_value = "hello";
           break #L1;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -56,7 +56,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -71,7 +71,7 @@
           dart.core::print(#C2);
           dart.core::print("Done");
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect
index 5d54f1b..9d83b08 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect
@@ -22,7 +22,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -36,7 +36,7 @@
           :result;
           dart.core::print(#C2);
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -51,7 +51,7 @@
   static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -66,7 +66,7 @@
           :return_value = "hello";
           break #L2;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect
index d857553..d0bec69 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect
@@ -22,7 +22,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -36,7 +36,7 @@
           :result;
           dart.core::print(#C2);
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -51,7 +51,7 @@
   static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -66,7 +66,7 @@
           :return_value = "hello!!!";
           break #L2;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect
index 8da36e7..d9b9b9f 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect
@@ -22,7 +22,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -37,7 +37,7 @@
           dart.core::print(#C2);
           dart.core::print("Done!");
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -52,7 +52,7 @@
   static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -67,7 +67,7 @@
           :return_value = "hello!!!";
           break #L2;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect
index 919ede4..7072277 100644
--- a/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect
@@ -29,7 +29,7 @@
 static method test() → void /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
         function test0() → asy::Future<core::int*>* /* originally async */ {
           final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
           core::bool* :is_sync = false;
-          FutureOr<core::int*>* :return_value;
+          core::int? :return_value;
           (dynamic) →* dynamic :async_op_then;
           (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
           core::int* :await_jump_var = 0;
@@ -64,7 +64,7 @@
                 :return_value = x0;
                 break #L2;
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -340,7 +340,7 @@
         [yield] let dynamic #t10 = asy::_awaitHelper(x9, :async_op_then, :async_op_error, :async_op) in null;
         core::int* y9 = _in::unsafeCast<core::int*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect
index 02f5546..d131af3 100644
--- a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 static field () →* asy::Future<core::int*>* f = () → asy::Future<core::int*>* /* originally async */ {
   final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
   core::bool* :is_sync = false;
-  FutureOr<core::int*>* :return_value;
+  core::int? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -18,7 +18,7 @@
         :return_value = 0;
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect
index 946c0ba..33452c2 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
   () →* asy::Future<core::num*>* f = () → asy::Future<core::num*>* /* originally async */ {
     final asy::_Future<core::num*>* :async_future = new asy::_Future::•<core::num*>();
     core::bool* :is_sync = false;
-    FutureOr<core::num*>* :return_value;
+    core::num? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -29,7 +29,7 @@
             break #L1;
           }
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect
index 2f681c5..1ca076e 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -51,7 +51,7 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(f(){() →* asy::Future<Null>*}, :async_op_then, :async_op_error, :async_op) in null;
         core::String* s = _in::unsafeCast<Null>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect
index fbf4bc7..0b66184 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -57,7 +57,7 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(f(){() →* asy::Stream<Null>*}.{asy::Stream::first}{asy::Future<Null>*}, :async_op_then, :async_op_error, :async_op) in null;
         core::String* s = _in::unsafeCast<Null>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect
index 0b4c6aa..ef028bb 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
 static method main() → asy::Future<dynamic>* /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -25,7 +25,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(d as{TypeError,ForDynamic} core::int*)), :async_op_then, :async_op_error, :async_op) in null;
         core::List<core::int*>* l1 = _in::unsafeCast<core::List<core::int*>*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect
index acaf1c5..f7624fe 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect
@@ -62,7 +62,7 @@
 static method f() → asy::Future<dynamic>* /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -226,7 +226,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -241,7 +241,7 @@
 static method main() → asy::Future<dynamic>* /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -318,7 +318,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect
index e4fd3e1..b47ff66 100644
--- a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -83,7 +83,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect
index ab96b76..6786a24 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   asy::Future<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   asy::Future<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect
index bffba5ef..2f74e115 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   asy::Future<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   asy::Future<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect
index 37463d1..7decc2d 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   self::MyFuture<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   self::MyFuture<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect
index 90f1db4..6bc3b03 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   self::MyFuture<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   self::MyFuture<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect
index 39baeba..4971cd6 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   asy::Future<core::int*>* t3 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   asy::Future<core::int*>* t4 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect
index 6a2855eb..7cffed8 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   asy::Future<core::int*>* t3 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   asy::Future<core::int*>* t4 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
index 204dbee..be1084c 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
index 608046f..4327ac5 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
index e32c9fb..477a406 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
index 02b3b6b..0211604 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
index e0176fc..6759525 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
index 9fb5822..877ea634 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
index bf8be62..2716550 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -60,7 +60,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect
index 3145f91..955a495 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect
@@ -47,7 +47,7 @@
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::List<core::int*>*>* :return_value;
+  core::List<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
         :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect
index 0bdd40c..9c426f7 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::List<core::int*>*>* :return_value;
+  core::List<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -50,7 +50,7 @@
         :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect
index 925b980..09a8df9 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect
@@ -47,7 +47,7 @@
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::List<core::int*>*>* :return_value;
+  core::List<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
         :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect
index e0915b4..35a7372 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::List<core::int*>*>* :return_value;
+  core::List<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -50,7 +50,7 @@
         :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect
index ced25c9..e617289 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect
@@ -24,7 +24,7 @@
 static method foo() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -39,7 +39,7 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::wait<core::List<self::A*>*>(core::_GrowableList::_literal2<asy::Future<core::List<self::A*>*>*>(f1, f2)), :async_op_then, :async_op_error, :async_op) in null;
         core::List<core::List<self::A*>*>* merged = _in::unsafeCast<core::List<core::List<self::A*>*>>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect
index ebe5e12..241a603 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -25,7 +25,7 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(self::id<FutureOr<core::String*>*>(f), :async_op_then, :async_op_error, :async_op) in null;
         core::String* s = _in::unsafeCast<core::String*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect
index edb2427..3e7e7b1 100644
--- a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect
@@ -34,7 +34,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -54,7 +54,7 @@
         core::List<self::A*>* list = result;
         list = result2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect
index 3715d17..9c545575 100644
--- a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
   function f1() → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -21,7 +21,7 @@
           :return_value = 42;
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -39,7 +39,7 @@
   function f3() → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -51,7 +51,7 @@
           :return_value = 42;
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect
index fef5b28..8eee676 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect
@@ -58,7 +58,7 @@
   method foo(covariant-by-class self::Bar::T* t) → dynamic /* originally async */ {
     final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -97,7 +97,7 @@
               }
           }
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -127,7 +127,7 @@
   method foo(covariant-by-class self::Baz::S* t) → dynamic /* originally async */ {
     final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -167,7 +167,7 @@
               }
           }
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -244,7 +244,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -440,7 +440,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect
index aa020dd..dfc471b 100644
--- a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect
@@ -30,7 +30,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -122,7 +122,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect
index 2ad99fc..356e2de 100644
--- a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect
@@ -46,7 +46,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -201,7 +201,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
index 079f495..5b963bf 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
@@ -139,7 +139,7 @@
 static method hest() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -178,7 +178,7 @@
         :return_value = "hest";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -193,7 +193,7 @@
 static method fisk() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -250,7 +250,7 @@
         function #f#set(core::Function f#param) → dynamic
           return #f = f#param;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
index c43553e..c376454 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
@@ -159,7 +159,7 @@
 static method hest() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -198,7 +198,7 @@
         :return_value = "hest";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -213,7 +213,7 @@
 static method fisk() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -294,7 +294,7 @@
           return #f = f#param;
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
index 4d55755..64a9400 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
@@ -76,7 +76,7 @@
   method test(covariant-by-class asy::Future<self::Response<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
     final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
     core::bool* :is_sync = false;
-    FutureOr<core::String>? :return_value;
+    core::String? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -106,7 +106,7 @@
           :return_value = result;
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -135,7 +135,7 @@
   method test(covariant-by-class asy::Future<self::PagingResponse<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
     final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
     core::bool* :is_sync = false;
-    FutureOr<core::String>? :return_value;
+    core::String? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
           :return_value = result;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
index 4d55755..64a9400 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
@@ -76,7 +76,7 @@
   method test(covariant-by-class asy::Future<self::Response<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
     final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
     core::bool* :is_sync = false;
-    FutureOr<core::String>? :return_value;
+    core::String? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -106,7 +106,7 @@
           :return_value = result;
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -135,7 +135,7 @@
   method test(covariant-by-class asy::Future<self::PagingResponse<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
     final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
     core::bool* :is_sync = false;
-    FutureOr<core::String>? :return_value;
+    core::String? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
           :return_value = result;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect
index 3864109..1ecce4a 100644
--- a/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -31,7 +31,7 @@
   List y = await l(); // should be a List?
            ^" in let core::List<dynamic>? #t2 = _in::unsafeCast<core::List<dynamic>?>(:result) in #t2 == null ?{core::List<dynamic>} #t2 as{TypeError,ForNonNullableByDefault} core::List<dynamic> : #t2{core::List<dynamic>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect
index 18ac50d..1a6d93f 100644
--- a/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect
@@ -15,7 +15,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -31,7 +31,7 @@
   List y = await l(); // should be a List?
            ^" in _in::unsafeCast<core::List<dynamic>?>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
index 9eb092b..ec795d3 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -20,7 +20,7 @@
         core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2 == null ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
         core::print(i);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
index 9eb092b..ec795d3 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -20,7 +20,7 @@
         core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2 == null ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
         core::print(i);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
index e3bb148..d45e990 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
@@ -85,7 +85,7 @@
   (core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
     core::bool* :is_sync = false;
-    FutureOr<Never>? :return_value;
+    Never? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -96,7 +96,7 @@
         {
           throw v;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -165,7 +165,7 @@
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
     core::bool* :is_sync = false;
-    FutureOr<Never>? :return_value;
+    Never? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -176,7 +176,7 @@
         {
           self::throwing();
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -219,7 +219,7 @@
 static method errors() → void /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -407,7 +407,7 @@
           return :async_future;
         };
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
index dbb0ff6..90dabf3 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
@@ -86,7 +86,7 @@
   (core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
     core::bool* :is_sync = false;
-    FutureOr<Never>? :return_value;
+    Never? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -97,7 +97,7 @@
         {
           throw v;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -166,7 +166,7 @@
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
     core::bool* :is_sync = false;
-    FutureOr<Never>? :return_value;
+    Never? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -177,7 +177,7 @@
         {
           let final Never #t5 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -220,7 +220,7 @@
 static method errors() → void /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -408,7 +408,7 @@
           return :async_future;
         };
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
index a53d4d3..ed3a3ca 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
@@ -63,7 +63,7 @@
 static method getFutureBool() → asy::Future<core::bool> /* originally async */ {
   final asy::_Future<core::bool> :async_future = new asy::_Future::•<core::bool>();
   core::bool* :is_sync = false;
-  FutureOr<core::bool>? :return_value;
+  core::bool? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -75,7 +75,7 @@
         :return_value = true;
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -186,7 +186,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -390,7 +390,7 @@
           return :async_future;
         })(){() → asy::Future<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
index a53d4d3..ed3a3ca 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
@@ -63,7 +63,7 @@
 static method getFutureBool() → asy::Future<core::bool> /* originally async */ {
   final asy::_Future<core::bool> :async_future = new asy::_Future::•<core::bool>();
   core::bool* :is_sync = false;
-  FutureOr<core::bool>? :return_value;
+  core::bool? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -75,7 +75,7 @@
         :return_value = true;
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -186,7 +186,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -390,7 +390,7 @@
           return :async_future;
         })(){() → asy::Future<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect
index f1dad02..8b27a53 100644
--- a/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect
@@ -145,7 +145,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -284,7 +284,7 @@
           return new core::_SyncIterable::•<core::bool>(:sync_op_gen);
         })(){() → core::Iterable<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect
index f1dad02..8b27a53 100644
--- a/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect
@@ -145,7 +145,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -284,7 +284,7 @@
           return new core::_SyncIterable::•<core::bool>(:sync_op_gen);
         })(){() → core::Iterable<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
index afdc269..995ecac 100644
--- a/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
@@ -225,7 +225,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -460,7 +460,7 @@
           return :controller_stream;
         })(){() → asy::Stream<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
index afdc269..995ecac 100644
--- a/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
@@ -225,7 +225,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -460,7 +460,7 @@
           return :controller_stream;
         })(){() → asy::Stream<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect
index 50a282e..ec6e4be 100644
--- a/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect
@@ -18,7 +18,7 @@
 static method returnFutureOfVoid() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -43,7 +43,7 @@
 static method returnVoidAsync() → void /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -52,7 +52,7 @@
     try {
       #L2:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -67,7 +67,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -82,7 +82,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::returnVoidAsync(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -97,7 +97,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -110,7 +110,7 @@
         [yield] let dynamic #t3 = asy::_awaitHelper(self::returnFutureOfVoid(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect
index 50a282e..ec6e4be 100644
--- a/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect
@@ -18,7 +18,7 @@
 static method returnFutureOfVoid() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -43,7 +43,7 @@
 static method returnVoidAsync() → void /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -52,7 +52,7 @@
     try {
       #L2:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -67,7 +67,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -82,7 +82,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::returnVoidAsync(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -97,7 +97,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -110,7 +110,7 @@
         [yield] let dynamic #t3 = asy::_awaitHelper(self::returnFutureOfVoid(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
index 5a264b1..b845eb9 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
@@ -37,7 +37,7 @@
   <S extends FutureOr<core::num>>(S, FutureOr<core::num>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num>>(S s, FutureOr<core::num>t) → asy::Future<core::num> /* originally async */ {
     final asy::_Future<core::num> :async_future = new asy::_Future::•<core::num>();
     core::bool* :is_sync = false;
-    FutureOr<core::num>? :return_value;
+    core::num? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -51,7 +51,7 @@
           :return_value = _in::unsafeCast<core::num>(:result).{core::num::+}(1){(core::num) → core::num};
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
index 5a264b1..b845eb9 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
@@ -37,7 +37,7 @@
   <S extends FutureOr<core::num>>(S, FutureOr<core::num>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num>>(S s, FutureOr<core::num>t) → asy::Future<core::num> /* originally async */ {
     final asy::_Future<core::num> :async_future = new asy::_Future::•<core::num>();
     core::bool* :is_sync = false;
-    FutureOr<core::num>? :return_value;
+    core::num? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -51,7 +51,7 @@
           :return_value = _in::unsafeCast<core::num>(:result).{core::num::+}(1){(core::num) → core::num};
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
index b810299..fe3f074 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
@@ -40,7 +40,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -85,7 +85,7 @@
           return :async_future;
         })(){() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>>} as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
index b810299..fe3f074 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
@@ -40,7 +40,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -85,7 +85,7 @@
           return :async_future;
         })(){() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>>} as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
index 22760fa..ce05381 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -23,7 +23,7 @@
         (dynamic _) → asy::Future<core::int?> /* originally async */ {
           final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
           core::bool* :is_sync = false;
-          FutureOr<core::int?>? :return_value;
+          core::int? :return_value;
           (dynamic) → dynamic :async_op_then;
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
@@ -37,7 +37,7 @@
                   break #L2;
                 }
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -50,7 +50,7 @@
           return :async_future;
         };
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
index 22760fa..ce05381 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -23,7 +23,7 @@
         (dynamic _) → asy::Future<core::int?> /* originally async */ {
           final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
           core::bool* :is_sync = false;
-          FutureOr<core::int?>? :return_value;
+          core::int? :return_value;
           (dynamic) → dynamic :async_op_then;
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
@@ -37,7 +37,7 @@
                   break #L2;
                 }
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -50,7 +50,7 @@
           return :async_future;
         };
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect
index 122e031..83b083c 100644
--- a/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -32,7 +32,7 @@
           self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
         } =>#t2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect
index 122e031..83b083c 100644
--- a/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect
@@ -15,7 +15,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -32,7 +32,7 @@
           self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
         } =>#t2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
index 2885cb8..5d5407b 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
@@ -126,7 +126,7 @@
 static method hest() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
         :return_value = "hest";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -180,7 +180,7 @@
 static method fisk() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -231,7 +231,7 @@
           };
         late core::Function f = #f#initializer(){() → core::Function};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
index 2885cb8..5d5407b 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
@@ -126,7 +126,7 @@
 static method hest() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
         :return_value = "hest";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -180,7 +180,7 @@
 static method fisk() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -231,7 +231,7 @@
           };
         late core::Function f = #f#initializer(){() → core::Function};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
index 2a9f5d7..765a694 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
 static method allYield() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::allYield2(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -42,7 +42,7 @@
 static method allYield2() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
         [yield] let dynamic #t4 = asy::_awaitHelper(self::allYield3(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -72,7 +72,7 @@
 static method allYield3() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -86,7 +86,7 @@
         _in::unsafeCast<core::int>(:result);
         self::throwSync();
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -114,7 +114,7 @@
         asy::runZonedGuarded<asy::Future<Null>>(() → asy::Future<Null> /* originally async */ {
           final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
           core::bool* :is_sync = false;
-          FutureOr<Null>? :return_value;
+          Null :return_value;
           (dynamic) → dynamic :async_op_then;
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
@@ -128,7 +128,7 @@
                 _in::unsafeCast<void>(:result);
                 completer.{asy::Completer::complete}(null){([FutureOr<void>?]) → void};
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
index 2a9f5d7..765a694 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
 static method allYield() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::allYield2(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -42,7 +42,7 @@
 static method allYield2() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
         [yield] let dynamic #t4 = asy::_awaitHelper(self::allYield3(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -72,7 +72,7 @@
 static method allYield3() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -86,7 +86,7 @@
         _in::unsafeCast<core::int>(:result);
         self::throwSync();
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -114,7 +114,7 @@
         asy::runZonedGuarded<asy::Future<Null>>(() → asy::Future<Null> /* originally async */ {
           final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
           core::bool* :is_sync = false;
-          FutureOr<Null>? :return_value;
+          Null :return_value;
           (dynamic) → dynamic :async_op_then;
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
@@ -128,7 +128,7 @@
                 _in::unsafeCast<void>(:result);
                 completer.{asy::Completer::complete}(null){([FutureOr<void>?]) → void};
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
index d7034897..3686411 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
@@ -94,7 +94,7 @@
 static method returnAsync1() → asy::Future<dynamic> /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -103,7 +103,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -118,7 +118,7 @@
 static method returnAsync2() → FutureOr<dynamic> /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -127,7 +127,7 @@
     try {
       #L2:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -171,7 +171,7 @@
 static method returnAsync4() → FutureOr<core::int?> /* originally async */ {
   final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
   core::bool* :is_sync = false;
-  FutureOr<core::int?>? :return_value;
+  core::int? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -180,7 +180,7 @@
     try {
       #L4:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -195,7 +195,7 @@
 static method returnAsync5() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -204,7 +204,7 @@
     try {
       #L5:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -246,7 +246,7 @@
 static method returnAsync7() → asy::Future<core::int?> /* originally async */ {
   final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
   core::bool* :is_sync = false;
-  FutureOr<core::int?>? :return_value;
+  core::int? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -255,7 +255,7 @@
     try {
       #L7:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -362,7 +362,7 @@
   function returnAsync1() → asy::Future<dynamic> /* originally async */ {
     final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -371,7 +371,7 @@
       try {
         #L13:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -386,7 +386,7 @@
   function returnAsync2() → FutureOr<dynamic> /* originally async */ {
     final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -395,7 +395,7 @@
       try {
         #L14:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -439,7 +439,7 @@
   function returnAsync4() → FutureOr<core::int?> /* originally async */ {
     final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
     core::bool* :is_sync = false;
-    FutureOr<core::int?>? :return_value;
+    core::int? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -448,7 +448,7 @@
       try {
         #L16:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -463,7 +463,7 @@
   function returnAsync5() → asy::Future<Null> /* originally async */ {
     final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
     core::bool* :is_sync = false;
-    FutureOr<Null>? :return_value;
+    Null :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -472,7 +472,7 @@
       try {
         #L17:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -514,7 +514,7 @@
   function returnAsync7() → asy::Future<core::int?> /* originally async */ {
     final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
     core::bool* :is_sync = false;
-    FutureOr<core::int?>? :return_value;
+    core::int? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -523,7 +523,7 @@
       try {
         #L19:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
index 7f20e82..081a23c 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
@@ -95,7 +95,7 @@
 static method returnAsync1() → asy::Future<dynamic> /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -104,7 +104,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -119,7 +119,7 @@
 static method returnAsync2() → FutureOr<dynamic> /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -128,7 +128,7 @@
     try {
       #L2:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -172,7 +172,7 @@
 static method returnAsync4() → FutureOr<core::int?> /* originally async */ {
   final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
   core::bool* :is_sync = false;
-  FutureOr<core::int?>? :return_value;
+  core::int? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -181,7 +181,7 @@
     try {
       #L4:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -196,7 +196,7 @@
 static method returnAsync5() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -205,7 +205,7 @@
     try {
       #L5:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -247,7 +247,7 @@
 static method returnAsync7() → asy::Future<core::int?> /* originally async */ {
   final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
   core::bool* :is_sync = false;
-  FutureOr<core::int?>? :return_value;
+  core::int? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -256,7 +256,7 @@
     try {
       #L7:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -366,7 +366,7 @@
   function returnAsync1() → asy::Future<dynamic> /* originally async */ {
     final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -375,7 +375,7 @@
       try {
         #L14:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -390,7 +390,7 @@
   function returnAsync2() → FutureOr<dynamic> /* originally async */ {
     final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -399,7 +399,7 @@
       try {
         #L15:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -443,7 +443,7 @@
   function returnAsync4() → FutureOr<core::int?> /* originally async */ {
     final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
     core::bool* :is_sync = false;
-    FutureOr<core::int?>? :return_value;
+    core::int? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -452,7 +452,7 @@
       try {
         #L17:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -467,7 +467,7 @@
   function returnAsync5() → asy::Future<Null> /* originally async */ {
     final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
     core::bool* :is_sync = false;
-    FutureOr<Null>? :return_value;
+    Null :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -476,7 +476,7 @@
       try {
         #L18:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -518,7 +518,7 @@
   function returnAsync7() → asy::Future<core::int?> /* originally async */ {
     final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
     core::bool* :is_sync = false;
-    FutureOr<core::int?>? :return_value;
+    core::int? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -527,7 +527,7 @@
       try {
         #L20:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect
index 96460c4..160716b 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
 static method returnFutureOfVoid() → asy::Future<void>* /* originally async */ {
   final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>* :return_value;
+  void :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -16,7 +16,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -32,7 +32,7 @@
 static method returnVoidAsync() → void /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -41,7 +41,7 @@
     try {
       #L2:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -56,7 +56,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -73,7 +73,7 @@
         [yield] let dynamic #t3 = asy::_awaitHelper(self::returnVoidAsync(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
index dcba0f6..1f53e96 100644
--- a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
@@ -10,7 +10,7 @@
   return (typ::Request* r) → asy::Future<typ::Response*>* /* originally async */ {
     final asy::_Future<typ::Response*>* :async_future = new asy::_Future::•<typ::Response*>();
     core::bool* :is_sync = false;
-    FutureOr<typ::Response*>* :return_value;
+    typ::Response? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -22,7 +22,7 @@
           :return_value = new typ::Response::•();
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect
index d3211c4..b4b664d 100644
--- a/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect
@@ -116,7 +116,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -132,7 +132,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::f3(), :async_op_then, :async_op_error, :async_op) in null;
         core::print(_in::unsafeCast<invalid-type>(:result));
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect
index 8e89457..63a99de 100644
--- a/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect
@@ -22,7 +22,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -38,7 +38,7 @@
         function f_async() → core::int* /* originally async */ {
           final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
           core::bool* :is_sync = false;
-          FutureOr<dynamic>* :return_value;
+          dynamic :return_value;
           (dynamic) →* dynamic :async_op_then;
           (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
           core::int* :await_jump_var = 0;
@@ -50,7 +50,7 @@
                 :return_value = 42;
                 break #L2;
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -147,7 +147,7 @@
           }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect
index ee407a3..9262980 100644
--- a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
         [yield] let dynamic #t13 = asy::_awaitHelper(self::lhmfun2(), :async_op_then, :async_op_error, :async_op) in null;
         col::LinkedHashMap<core::int*, core::bool*>* flhm2 = _in::unsafeCast<col::LinkedHashMap<core::int*, core::bool*>*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
 static method mapfun() → asy::Future<core::Map<core::int*, core::bool*>*>* /* originally async */ {
   final asy::_Future<core::Map<core::int*, core::bool*>*>* :async_future = new asy::_Future::•<core::Map<core::int*, core::bool*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::Map<core::int*, core::bool*>*>* :return_value;
+  core::Map<core::int*, core::bool*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
         :return_value = <core::int*, core::bool*>{};
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -150,7 +150,7 @@
 static method setfun() → asy::Future<core::Set<core::int*>*>* /* originally async */ {
   final asy::_Future<core::Set<core::int*>*>* :async_future = new asy::_Future::•<core::Set<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::Set<core::int*>*>* :return_value;
+  core::Set<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -164,7 +164,7 @@
         } =>#t14;
         break #L3;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -179,7 +179,7 @@
 static method iterablefun() → asy::Future<core::Iterable<core::int*>*>* /* originally async */ {
   final asy::_Future<core::Iterable<core::int*>*>* :async_future = new asy::_Future::•<core::Iterable<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::Iterable<core::int*>*>* :return_value;
+  core::Iterable<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -193,7 +193,7 @@
         } =>#t15;
         break #L4;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index feaa794..4dc523e 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -164,6 +164,9 @@
   late final Procedure completeOnAsyncReturn =
       index.getTopLevelProcedure('dart:async', '_completeOnAsyncReturn');
 
+  late final Procedure completeWithNoFutureOnAsyncReturn = index
+      .getTopLevelProcedure('dart:async', '_completeWithNoFutureOnAsyncReturn');
+
   late final Procedure completeOnAsyncError =
       index.getTopLevelProcedure('dart:async', '_completeOnAsyncError');
 
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index ad89d1f..c0375c2 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -1347,6 +1347,18 @@
   VariableDeclaration? asyncFutureVariable;
   VariableDeclaration? isSyncVariable;
 
+  // In general an async functions such as
+  //
+  //     Future<X> foo() async { return <expr>; }
+  //
+  // can return as `<expr>` either X or Future<X>, i.e. it can return
+  // FutureOr<X>
+  //
+  // If we know it doesn't return any object of type `Future`, we can optimize
+  // the future completion process by avoiding some expensive `is Future<T>`
+  // type checks on the returned value.
+  late bool canReturnFuture;
+
   AsyncFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction,
       StatefulStaticTypeContext staticTypeContext)
       : super(helper, enclosingFunction, staticTypeContext);
@@ -1385,13 +1397,22 @@
         type: helper.coreTypes.boolLegacyRawType);
     statements.add(isSyncVariable!);
 
-    // asy::FutureOr<dynamic>* :return_value;
+    // asy::FutureOr<T>* :return_value;
     returnVariable = VariableDeclaration(ContinuationVariables.returnValue,
         type: returnType);
     statements.add(returnVariable!);
 
+    canReturnFuture = false;
+
     setupAsyncContinuations(statements);
 
+    // If we could prove the function doesn't return a `Future` we change the
+    // type of `:return_value`.
+    if (!canReturnFuture) {
+      returnVariable!.type =
+          valueType.withDeclaredNullability(Nullability.nullable);
+    }
+
     // :async_op();
     final startStatement = ExpressionStatement(LocalFunctionInvocation(
         nestedClosureVariable, Arguments([]),
@@ -1439,7 +1460,9 @@
     return Block(<Statement>[
       body,
       ExpressionStatement(StaticInvocation(
-          helper.completeOnAsyncReturn,
+          canReturnFuture
+              ? helper.completeOnAsyncReturn
+              : helper.completeWithNoFutureOnAsyncReturn,
           Arguments([
             VariableGet(asyncFutureVariable!),
             VariableGet(returnVariable!),
@@ -1452,14 +1475,47 @@
   @override
   TreeNode visitReturnStatement(
       ReturnStatement node, TreeNode? removalSentinel) {
-    var expr = node.expression == null
-        ? new NullLiteral()
+    final expression = node.expression;
+    if (expression != null && !canReturnFuture) {
+      final returnedType = staticTypeContext.getExpressionType(expression);
+      canReturnFuture = _canHoldFutureObject(returnedType);
+    }
+
+    final transformedExpression = node.expression == null
+        ? NullLiteral()
         : expressionRewriter!.rewrite(node.expression!, statements);
-    statements.add(new ExpressionStatement(
-        new VariableSet(returnVariable!, expr)..fileOffset = node.fileOffset));
-    statements.add(new BreakStatement(labeledBody!));
+    statements.add(ExpressionStatement(
+        VariableSet(returnVariable!, transformedExpression)
+          ..fileOffset = node.fileOffset));
+    statements.add(BreakStatement(labeledBody!));
     return removalSentinel ?? EmptyStatement();
   }
+
+  bool _canHoldFutureObject(DartType type) {
+    // Any supertype or subtype of `FutureOr` may hold a `Future` object.
+    final env = staticTypeContext.typeEnvironment;
+
+    if (type is TypeParameterType) {
+      type = type.parameter.defaultType;
+    }
+
+    if (type is FutureOrType) return true;
+
+    // Any supertype of Future (which includes Future/Object/dynamic) can hold
+    // Future objects.
+    if (env.isSubtypeOf(
+        helper.futureType, type, SubtypeCheckMode.ignoringNullabilities)) {
+      return true;
+    }
+
+    // Any subtype of Future (which includes Future/_Future and any user-defined
+    // implementations) can hold Future objects.
+    if (env.isSubtypeOf(
+        type, helper.futureType, SubtypeCheckMode.ignoringNullabilities)) {
+      return true;
+    }
+    return false;
+  }
 }
 
 class HelperNodes {
@@ -1476,6 +1532,7 @@
   final Procedure asyncThenWrapper;
   final Procedure awaitHelper;
   final Procedure completeOnAsyncReturn;
+  final Procedure completeWithNoFutureOnAsyncReturn;
   final Procedure completeOnAsyncError;
   final Library coreLibrary;
   final CoreTypes coreTypes;
@@ -1496,6 +1553,7 @@
   final Member syncIteratorYieldEachIterable;
   final Class boolClass;
   final Procedure unsafeCast;
+  final DartType futureType;
 
   bool productMode;
 
@@ -1513,6 +1571,7 @@
       this.asyncThenWrapper,
       this.awaitHelper,
       this.completeOnAsyncReturn,
+      this.completeWithNoFutureOnAsyncReturn,
       this.completeOnAsyncError,
       this.coreLibrary,
       this.coreTypes,
@@ -1533,7 +1592,9 @@
       this.syncIteratorYieldEachIterable,
       this.boolClass,
       this.productMode,
-      this.unsafeCast);
+      this.unsafeCast)
+      : futureType = InterfaceType(
+            futureClass, Nullability.nonNullable, [DynamicType()]);
 
   factory HelperNodes.fromCoreTypes(CoreTypes coreTypes, bool productMode) {
     return new HelperNodes._(
@@ -1550,6 +1611,7 @@
         coreTypes.asyncThenWrapperHelperProcedure,
         coreTypes.awaitHelperProcedure,
         coreTypes.completeOnAsyncReturn,
+        coreTypes.completeWithNoFutureOnAsyncReturn,
         coreTypes.completeOnAsyncError,
         coreTypes.coreLibrary,
         coreTypes,
diff --git a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
index 328e71f..e063504 100644
--- a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
+++ b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
@@ -48,7 +48,7 @@
   static method j() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
     dart.core::int :await_jump_var = 0;
@@ -59,7 +59,7 @@
         {
           dart.core::print("J");
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
@@ -79,7 +79,7 @@
   static method h() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
     dart.core::int :await_jump_var = 0;
@@ -90,7 +90,7 @@
         {
           dart.core::print("H");
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
@@ -147,7 +147,7 @@
   static method g() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
     dart.core::int :await_jump_var = 0;
@@ -158,7 +158,7 @@
         {
           dart.core::print("G");
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
@@ -395,7 +395,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
     dart.core::int :await_jump_var = 0;
@@ -410,7 +410,7 @@
           [yield] let dynamic #t14 = dart.async::_awaitHelper(b::b(), :async_op_then, :async_op_error, :async_op) in null;
           :result;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
index fc5a260..0f8f453 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
@@ -45,7 +45,7 @@
 static method baz() → asy::Future<dynamic> /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
         :return_value = new self::B::•();
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -72,7 +72,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -88,7 +88,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper([@vm.direct-call.metadata=#lib::A.bar??] [@vm.inferred-type.metadata=dart.async::_Future<dynamic> (receiver not int)] :async_temporary_0{dynamic}.bar(:result), :async_op_then, :async_op_error, :async_op) in null;
         :result;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
index 5fa848c..950e802 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
@@ -22,6 +22,6 @@
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3397,getterSelectorId:3398]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3399,getterSelectorId:3400]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
     return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
index 0b8da96..5ccaefa 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
@@ -51,6 +51,6 @@
   synthetic constructor •() → self::ConstClass
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3401,getterSelectorId:3402]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3403,getterSelectorId:3404]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
     return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
 }
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index cb64707..0e97fbb 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -888,7 +888,9 @@
   ASSERT(!function_.IsNull());
   auto isolate_group = IsolateGroup::Current();
   if (function_.ptr() ==
-      isolate_group->object_store()->complete_on_async_return()) {
+          isolate_group->object_store()->complete_on_async_return() ||
+      function_.ptr() == isolate_group->object_store()
+                             ->complete_with_no_future_on_async_return()) {
     // We are completing an async function's completer.
     return true;
   }
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 8ce45e3..81c5977 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -210,6 +210,15 @@
   return result.ptr();
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+static void DisableDebuggingAndInlining(const Function& function) {
+  if (FLAG_async_debugger) {
+    function.set_is_debuggable(false);
+    function.set_is_inlinable(false);
+  }
+}
+#endif  // DART_PRECOMPILED_RUNTIME
+
 void ObjectStore::InitKnownObjects() {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
@@ -251,11 +260,16 @@
                                      function_name, 0, 3, Object::null_array());
   ASSERT(!function.IsNull());
   set_complete_on_async_return(function);
-  if (FLAG_async_debugger) {
-    // Disable debugging and inlining the _CompleteOnAsyncReturn function.
-    function.set_is_debuggable(false);
-    function.set_is_inlinable(false);
-  }
+  DisableDebuggingAndInlining(function);
+
+  function_name =
+      async_lib.PrivateName(Symbols::_CompleteWithNoFutureOnAsyncReturn());
+  ASSERT(!function_name.IsNull());
+  function = Resolver::ResolveStatic(async_lib, Object::null_string(),
+                                     function_name, 0, 3, Object::null_array());
+  ASSERT(!function.IsNull());
+  set_complete_with_no_future_on_async_return(function);
+  DisableDebuggingAndInlining(function);
 
   function_name = async_lib.PrivateName(Symbols::_CompleteOnAsyncError());
   ASSERT(!function_name.IsNull());
@@ -263,11 +277,7 @@
                                      function_name, 0, 4, Object::null_array());
   ASSERT(!function.IsNull());
   set_complete_on_async_error(function);
-  if (FLAG_async_debugger) {
-    // Disable debugging and inlining the _CompleteOnAsyncError function.
-    function.set_is_debuggable(false);
-    function.set_is_inlinable(false);
-  }
+  DisableDebuggingAndInlining(function);
 
   cls =
       async_lib.LookupClassAllowPrivate(Symbols::_AsyncStarStreamController());
@@ -283,8 +293,7 @@
       if (function.IsNull()) {
         break;
       }
-      function.set_is_debuggable(false);
-      function.set_is_inlinable(false);
+      DisableDebuggingAndInlining(function);
     }
   }
 
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 3d77c61..896c01b 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -159,6 +159,7 @@
   RW(Function, simple_instance_of_false_function)                              \
   RW(Function, async_star_move_next_helper)                                    \
   RW(Function, complete_on_async_return)                                       \
+  RW(Function, complete_with_no_future_on_async_return)                        \
   RW(Function, complete_on_async_error)                                        \
   RW(Class, async_star_stream_controller)                                      \
   ARW_RELAXED(Smi, future_timeout_future_index)                                \
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 5c8db08..6c9758a 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -288,6 +288,7 @@
   V(_CombinatorMirror, "_CombinatorMirror")                                    \
   V(_CompileTimeError, "_CompileTimeError")                                    \
   V(_CompleteOnAsyncReturn, "_completeOnAsyncReturn")                          \
+  V(_CompleteWithNoFutureOnAsyncReturn, "_completeWithNoFutureOnAsyncReturn")  \
   V(_ControllerSubscription, "_ControllerSubscription")                        \
   V(_CompleteOnAsyncError, "_completeOnAsyncError")                            \
   V(_DeletedEnumPrefix, "Deleted enum value from ")                            \
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index 4c5aa63..ee371e7 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -264,6 +264,19 @@
 }
 
 @pragma("vm:entry-point", "call")
+void _completeWithNoFutureOnAsyncReturn(
+    _Future _future, Object? value, bool is_sync) {
+  // The first awaited expression is invoked sync. so complete is async. to
+  // allow then and error handlers to be attached.
+  // async_jump_var=0 is prior to first await, =1 is first await.
+  if (!is_sync) {
+    _future._asyncCompleteUncheckedNoFuture(value);
+  } else {
+    _future._completeWithValue(value);
+  }
+}
+
+@pragma("vm:entry-point", "call")
 void _completeOnAsyncError(
     _Future _future, Object e, StackTrace st, bool is_sync) {
   if (!is_sync) {
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 52026a3..1b7176e 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -618,6 +618,17 @@
     _asyncCompleteWithValue(unsafeCast<T>(typedValue));
   }
 
+  /// Internal helper function used to implement `async` functions.
+  ///
+  /// Like [_asyncCompleteUnchecked], but avoids a `is Future<T>` check due to
+  /// having a static guarantee on the callsite that the [value] cannot be a
+  /// [Future].
+  /// Should be used judiciously.
+  void _asyncCompleteUncheckedNoFuture(/*T*/ dynamic value) {
+    assert((value as T) == value);
+    _asyncCompleteWithValue(unsafeCast<T>(value));
+  }
+
   void _asyncCompleteWithValue(T value) {
     _setPendingComplete();
     _zone.scheduleMicrotask(() {