Version 2.12.0-255.0.dev

Merge commit 'aa03d4a8e0899ba9e3fd92cd425a3d9ce009fd63' into 'dev'
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index 8d9c2bb..e276893 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -16,14 +16,13 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AnalysisNotificationHighlightsTest);
-    defineReflectiveTests(HighlightsWithControlFlowCollectionsTest);
-    defineReflectiveTests(HighlightsWithNullSafetyTest);
     defineReflectiveTests(HighlightTypeTest);
   });
 }
 
 @reflectiveTest
-class AnalysisNotificationHighlightsTest extends HighlightsTestSupport {
+class AnalysisNotificationHighlightsTest extends HighlightsTestSupport
+    with WithNullSafetyServerAnalysisMixin {
   Future<void> test_ANNOTATION_hasArguments() async {
     addTestFile('''
 class AAA {
@@ -99,6 +98,42 @@
     assertHasRegion(HighlightRegionType.BUILT_IN, 'await for');
   }
 
+  Future<void> test_BUILT_IN_awaitForIn_list() async {
+    addTestFile('''
+f(a) async {
+  return [await for(var b in a) b];
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.BUILT_IN, 'await');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+  }
+
+  Future<void> test_BUILT_IN_awaitForIn_map() async {
+    addTestFile('''
+f(a) async {
+  return {await for(var b in a) b : 0};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.BUILT_IN, 'await');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+  }
+
+  Future<void> test_BUILT_IN_awaitForIn_set() async {
+    addTestFile('''
+f(a) async {
+  return {await for(var b in a) b};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.BUILT_IN, 'await');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+  }
+
   Future<void> test_BUILT_IN_deferred() async {
     addTestFile('''
 import 'dart:math' deferred as math;
@@ -704,6 +739,93 @@
     assertHasRegion(HighlightRegionType.KEYWORD, 'with A;');
   }
 
+  Future<void> test_KEYWORD_const_list() async {
+    addTestFile('''
+var v = const [];
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+  }
+
+  Future<void> test_KEYWORD_const_map() async {
+    addTestFile('''
+var v = const {0 : 1};
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+  }
+
+  Future<void> test_KEYWORD_const_set() async {
+    addTestFile('''
+var v = const {0};
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+  }
+
+  Future<void> test_KEYWORD_if_list() async {
+    addTestFile('''
+f(a, b) {
+  return [if (a < b) 'a'];
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+  }
+
+  Future<void> test_KEYWORD_if_map() async {
+    addTestFile('''
+f(a, b) {
+  return {if (a < b) 'a' : 1};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+  }
+
+  Future<void> test_KEYWORD_if_set() async {
+    addTestFile('''
+f(a, b) {
+  return {if (a < b) 'a'};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+  }
+
+  Future<void> test_KEYWORD_ifElse_list() async {
+    addTestFile('''
+f(a, b) {
+  return [if (a < b) 'a' else 'b'];
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+  }
+
+  Future<void> test_KEYWORD_ifElse_map() async {
+    addTestFile('''
+f(a, b) {
+  return {if (a < b) 'a' : 1 else 'b' : 2};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+  }
+
+  Future<void> test_KEYWORD_ifElse_set() async {
+    addTestFile('''
+f(a, b) {
+  return {if (a < b) 'a' else 'b'};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+  }
+
   Future<void> test_KEYWORD_ifElse_statement() async {
     addTestFile('''
 f(a, b) {
@@ -715,6 +837,16 @@
     assertHasRegion(HighlightRegionType.KEYWORD, 'else');
   }
 
+  Future<void> test_KEYWORD_late() async {
+    addTestFile('''
+class C {
+  late int x;
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'late');
+  }
+
   Future<void> test_KEYWORD_mixin() async {
     addTestFile('''
 mixin M {}
@@ -723,6 +855,14 @@
     assertHasRegion(HighlightRegionType.BUILT_IN, 'mixin');
   }
 
+  Future<void> test_KEYWORD_required() async {
+    addTestFile('''
+void f({required int x}) {}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'required');
+  }
+
   Future<void> test_KEYWORD_void() async {
     addTestFile('''
 void main() {
@@ -1154,179 +1294,6 @@
 }
 
 @reflectiveTest
-class HighlightsWithControlFlowCollectionsTest extends HighlightsTestSupport {
-  @failingTest
-  Future<void> test_KEYWORD_awaitForIn_list() async {
-    addTestFile('''
-f(a) async {
-  return [await for(var b in a) b];
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'await');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
-  }
-
-  @failingTest
-  Future<void> test_KEYWORD_awaitForIn_map() async {
-    addTestFile('''
-f(a) async {
-  return {await for(var b in a) b : 0};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'await');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
-  }
-
-  @failingTest
-  Future<void> test_KEYWORD_awaitForIn_set() async {
-    addTestFile('''
-f(a) async {
-  return {await for(var b in a) b};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'await');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
-  }
-
-  Future<void> test_KEYWORD_const_list() async {
-    addTestFile('''
-var v = const [];
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
-  }
-
-  Future<void> test_KEYWORD_const_map() async {
-    addTestFile('''
-var v = const {0 : 1};
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
-  }
-
-  Future<void> test_KEYWORD_const_set() async {
-    addTestFile('''
-var v = const {0};
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
-  }
-
-  Future<void> test_KEYWORD_if_list() async {
-    addTestFile('''
-f(a, b) {
-  return [if (a < b) 'a'];
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-  }
-
-  Future<void> test_KEYWORD_if_map() async {
-    addTestFile('''
-f(a, b) {
-  return {if (a < b) 'a' : 1};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-  }
-
-  Future<void> test_KEYWORD_if_set() async {
-    addTestFile('''
-f(a, b) {
-  return {if (a < b) 'a'};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-  }
-
-  Future<void> test_KEYWORD_ifElse_list() async {
-    addTestFile('''
-f(a, b) {
-  return [if (a < b) 'a' else 'b'];
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
-  }
-
-  Future<void> test_KEYWORD_ifElse_map() async {
-    addTestFile('''
-f(a, b) {
-  return {if (a < b) 'a' : 1 else 'b' : 2};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
-  }
-
-  Future<void> test_KEYWORD_ifElse_set() async {
-    addTestFile('''
-f(a, b) {
-  return {if (a < b) 'a' else 'b'};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
-  }
-
-  Future<void> test_LITERAL_LIST() async {
-    addTestFile('var V = <int>[1, 2, 3];');
-    await prepareHighlights();
-    assertHasStringRegion(HighlightRegionType.LITERAL_LIST, '<int>[1, 2, 3]');
-  }
-
-  Future<void> test_LITERAL_MAP() async {
-    addTestFile("var V = const <int, String>{1: 'a', 2: 'b', 3: 'c'};");
-    await prepareHighlights();
-    assertHasStringRegion(HighlightRegionType.LITERAL_MAP,
-        "const <int, String>{1: 'a', 2: 'b', 3: 'c'}");
-  }
-}
-
-@reflectiveTest
-class HighlightsWithNullSafetyTest extends HighlightsTestSupport {
-  @override
-  void createProject({Map<String, String> packageRoots}) {
-    addAnalysisOptionsFile('''
-analyzer:
-  enable-experiment:
-    - non-nullable
-''');
-    super.createProject(packageRoots: packageRoots);
-  }
-
-  Future<void> test_KEYWORD_late() async {
-    addTestFile('''
-class C {
-  late int x;
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'late');
-  }
-
-  Future<void> test_KEYWORD_required() async {
-    addTestFile('''
-void f({required int x}) {}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'required');
-  }
-}
-
-@reflectiveTest
 class HighlightTypeTest {
   void test_constructor() {
     expect(HighlightRegionType.CLASS,
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index dd5d637..adb4cc3 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -227,3 +227,15 @@
     return serverChannel.sendRequest(request, throwOnError: throwOnError);
   }
 }
+
+mixin WithNullSafetyServerAnalysisMixin on AbstractAnalysisTest {
+  @override
+  void createProject({Map<String, String> packageRoots}) {
+    addAnalysisOptionsFile('''
+analyzer:
+  enable-experiment:
+    - non-nullable
+''');
+    super.createProject(packageRoots: packageRoots);
+  }
+}
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index fe2afbf..a8e8b53 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -4,6 +4,7 @@
 * Widened the dependency on package:crypto to include version 3.0.0.
 * Deprecated `CompilationUnitElement.functionTypeAliases`.
   Use `CompilationUnitElement.typeAliases` instead.
+* Added `AnalysisContext.sdkRoot`.
 
 ## 0.41.1
 * Updated `PackageBuildWorkspace` that supports `package:build` to stop
diff --git a/pkg/analyzer/lib/dart/analysis/analysis_context.dart b/pkg/analyzer/lib/dart/analysis/analysis_context.dart
index 37035e4..97ff59c 100644
--- a/pkg/analyzer/lib/dart/analysis/analysis_context.dart
+++ b/pkg/analyzer/lib/dart/analysis/analysis_context.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/analysis/context_root.dart';
 import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 
@@ -27,6 +28,10 @@
   /// Return the currently active analysis session.
   AnalysisSession get currentSession;
 
+  /// The root directory of the SDK against which files of this context are
+  /// analyzed, or `null` if the SDK is not directory based.
+  Folder get sdkRoot;
+
   /// Return the workspace for containing the context root.
   Workspace get workspace;
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart b/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart
index 1d90610..13ebb84 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver;
+import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptions;
 import 'package:analyzer/src/workspace/workspace.dart';
 
@@ -42,6 +43,15 @@
   AnalysisSession get currentSession => driver.currentSession;
 
   @override
+  Folder get sdkRoot {
+    var sdk = driver.sourceFactory.dartSdk;
+    if (sdk is FolderBasedDartSdk) {
+      return sdk.directory;
+    }
+    return null;
+  }
+
+  @override
   Workspace get workspace {
     return _workspace ??= _buildWorkspace();
   }
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 9ac4dc9..146592c 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1153,6 +1153,7 @@
 
   /// A list containing all of the function type aliases contained in this
   /// compilation unit.
+  @Deprecated('Use typeAliases instead')
   List<FunctionTypeAliasElement> _functionTypeAliases;
 
   /// A list containing all of the type aliases contained in this compilation
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
index 6d65356..a6e5194 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
@@ -61,7 +61,7 @@
       node.staticType = type;
       identifier.staticType = type;
       return;
-    } else if (element is FunctionTypeAliasElement) {
+    } else if (element is TypeAliasElement) {
       if (node.parent is TypeName) {
         // no type
       } else {
diff --git a/pkg/analyzer/lib/src/error/assignment_verifier.dart b/pkg/analyzer/lib/src/error/assignment_verifier.dart
index 54f0b21..b3f762b 100644
--- a/pkg/analyzer/lib/src/error/assignment_verifier.dart
+++ b/pkg/analyzer/lib/src/error/assignment_verifier.dart
@@ -59,7 +59,7 @@
 
     if (recovery is ClassElement ||
         recovery is DynamicElementImpl ||
-        recovery is FunctionTypeAliasElement ||
+        recovery is TypeAliasElement ||
         recovery is TypeParameterElement) {
       _errorReporter.reportErrorForNode(
         CompileTimeErrorCode.ASSIGNMENT_TO_TYPE,
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 99b2de4..8d51b49 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -10365,7 +10365,7 @@
   // }
   // ```
   static const CompileTimeErrorCode RETURN_WITHOUT_VALUE = CompileTimeErrorCode(
-      'RETURN_WITHOUT_VALUE', "The  return value is missing after 'return'.",
+      'RETURN_WITHOUT_VALUE', "The return value is missing after 'return'.",
       hasPublishedDocs: true);
 
   static const CompileTimeErrorCode SET_ELEMENT_FROM_DEFERRED_LIBRARY =
diff --git a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
index 03496ce..57c322d 100644
--- a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
+++ b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
@@ -343,8 +343,6 @@
         _visitFieldElement(element);
       } else if (element is FunctionElement) {
         _visitFunctionElement(element);
-      } else if (element is FunctionTypeAliasElement) {
-        _visitFunctionTypeAliasElement(element);
       } else if (element is LocalVariableElement) {
         _visitLocalVariableElement(element);
       } else if (element is MethodElement) {
@@ -353,6 +351,8 @@
         _visitPropertyAccessorElement(element);
       } else if (element is TopLevelVariableElement) {
         _visitTopLevelVariableElement(element);
+      } else if (element is TypeAliasElement) {
+        _visitTypeAliasElement(element);
       }
     }
   }
@@ -580,13 +580,6 @@
     }
   }
 
-  void _visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
-    if (!_isUsedElement(element)) {
-      _reportErrorForElement(
-          HintCode.UNUSED_ELEMENT, element, [element.displayName]);
-    }
-  }
-
   void _visitLocalVariableElement(LocalVariableElement element) {
     if (!_isUsedElement(element) && !_isNamedUnderscore(element)) {
       HintCode errorCode;
@@ -621,6 +614,13 @@
           HintCode.UNUSED_ELEMENT, element, [element.displayName]);
     }
   }
+
+  void _visitTypeAliasElement(TypeAliasElement element) {
+    if (!_isUsedElement(element)) {
+      _reportErrorForElement(
+          HintCode.UNUSED_ELEMENT, element, [element.displayName]);
+    }
+  }
 }
 
 /// A container with sets of used [Element]s.
diff --git a/pkg/analyzer/lib/src/summary2/default_types_builder.dart b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
index 68cc053..2dcb918 100644
--- a/pkg/analyzer/lib/src/summary2/default_types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
@@ -257,7 +257,7 @@
 
           if (declaration is ClassElement) {
             recurseParameters(declaration.typeParameters);
-          } else if (declaration is FunctionTypeAliasElement) {
+          } else if (declaration is TypeAliasElement) {
             recurseParameters(declaration.typeParameters);
           }
           visited.remove(startType.element);
diff --git a/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart b/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
index a54fa1a..8df9d1c 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
@@ -88,4 +88,14 @@
     expect(context.driver.sourceFactory.dartSdk.mapDartUri('dart:core'),
         sdk.mapDartUri('dart:core'));
   }
+
+  test_createContext_sdkRoot() {
+    MockSdk(resourceProvider: resourceProvider);
+    DriverBasedAnalysisContext context = contextBuilder.createContext(
+        contextRoot: contextRoot,
+        sdkPath: resourceProvider.convertPath(sdkRoot));
+    expect(context.analysisOptions, isNotNull);
+    expect(context.contextRoot, contextRoot);
+    expect(context.sdkRoot.path, sdkRoot);
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 0dd6b71..25d5b03 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -7823,7 +7823,7 @@
     await resolveTestFile();
 
     FunctionTypeAlias alias = findNode.functionTypeAlias('F<T>');
-    FunctionTypeAliasElement aliasElement = alias.declaredElement;
+    TypeAliasElement aliasElement = alias.declaredElement;
 
     FieldDeclaration fDeclaration = findNode.fieldDeclaration('F<int> f');
 
@@ -7915,7 +7915,7 @@
     CompilationUnit unit = result.unit;
 
     FunctionTypeAlias fNode = unit.declarations[1];
-    FunctionTypeAliasElement fElement = fNode.declaredElement;
+    TypeAliasElement fElement = fNode.declaredElement;
 
     var statements = _getMainStatements(result);
 
diff --git a/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart b/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
index 37f0d93..c3d86dd 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
@@ -167,6 +167,38 @@
     );
   }
 
+  test_read_typedef_functionType() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+typedef A = void Function();
+''');
+
+    await assertNoErrorsInCode('''
+import 'a.dart' as p;
+
+void f() {
+  p.A;
+}
+''');
+
+    var importFind = findElement.importFind('package:test/a.dart');
+    var A = importFind.typeAlias('A');
+
+    var prefixed = findNode.prefixed('p.A');
+    assertPrefixedIdentifier(
+      prefixed,
+      element: A,
+      type: 'Type',
+    );
+
+    assertImportPrefix(prefixed.prefix, importFind.prefix);
+
+    assertSimpleIdentifier(
+      prefixed.identifier,
+      element: A,
+      type: 'Type',
+    );
+  }
+
   test_readWrite_assignment() async {
     await assertNoErrorsInCode('''
 class A {
@@ -288,6 +320,38 @@
       type: 'int',
     );
   }
+
+  test_read_typedef_interfaceType() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+typedef A = List<int>;
+''');
+
+    await assertNoErrorsInCode('''
+import 'a.dart' as p;
+
+void f() {
+  p.A;
+}
+''');
+
+    var importFind = findElement.importFind('package:test/a.dart');
+    var A = importFind.typeAlias('A');
+
+    var prefixed = findNode.prefixed('p.A');
+    assertPrefixedIdentifier(
+      prefixed,
+      element: A,
+      type: 'Type',
+    );
+
+    assertImportPrefix(prefixed.prefix, importFind.prefix);
+
+    assertSimpleIdentifier(
+      prefixed.identifier,
+      element: A,
+      type: 'Type',
+    );
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
index cdba72f..a8133c3 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
@@ -14,7 +14,8 @@
 }
 
 @reflectiveTest
-class AssignmentToTypeTest extends PubPackageResolutionTest {
+class AssignmentToTypeTest extends PubPackageResolutionTest
+    with WithNonFunctionTypeAliasesMixin {
   test_class() async {
     await assertErrorsInCode('''
 class C {}
@@ -47,7 +48,7 @@
     ]);
   }
 
-  test_typedef() async {
+  test_typedef_functionType() async {
     await assertErrorsInCode('''
 typedef void F();
 main() {
@@ -58,6 +59,18 @@
     ]);
   }
 
+  test_typedef_interfaceType() async {
+    await assertErrorsInCode('''
+typedef F = List<int>;
+
+void f() {
+  F = null;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 37, 1),
+    ]);
+  }
+
   test_typeParameter() async {
     await assertErrorsInCode('''
 class C<T> {
diff --git a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
index 95cf0b8..08e380a 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
@@ -11,6 +11,7 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(UnusedElementTest);
     defineReflectiveTests(UnusedElementWithNullSafetyTest);
+    defineReflectiveTests(UnusedElementWithNonFunctionTypeAliasesTest);
   });
 }
 
@@ -1526,6 +1527,94 @@
       error(HintCode.UNUSED_ELEMENT, 34, 2),
     ]);
   }
+
+  test_typeAlias_functionType_isUsed_isExpression() async {
+    await assertNoErrorsInCode(r'''
+typedef _F = void Function();
+main(f) {
+  if (f is _F) {
+    print('F');
+  }
+}
+''');
+  }
+
+  test_typeAlias_functionType_isUsed_reference() async {
+    await assertNoErrorsInCode(r'''
+typedef _F = void Function();
+main(_F f) {
+}
+''');
+  }
+
+  test_typeAlias_functionType_isUsed_typeArgument() async {
+    await assertNoErrorsInCode(r'''
+typedef _F = void Function();
+main() {
+  var v = new List<_F>();
+  print(v);
+}
+''');
+  }
+
+  test_typeAlias_functionType_isUsed_variableDeclaration() async {
+    await assertNoErrorsInCode(r'''
+typedef _F = void Function();
+class A {
+  _F f;
+}
+''');
+  }
+
+  test_typeAlias_functionType_notUsed_noReference() async {
+    await assertErrorsInCode(r'''
+typedef _F = void Function();
+main() {
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 8, 2),
+    ]);
+  }
+}
+
+@reflectiveTest
+class UnusedElementWithNonFunctionTypeAliasesTest
+    extends PubPackageResolutionTest with WithNonFunctionTypeAliasesMixin {
+  test_typeAlias_interfaceType_isUsed_typeName_isExpression() async {
+    await assertNoErrorsInCode(r'''
+typedef _A = List<int>;
+
+void f(a) {
+  a is _A;
+}
+''');
+  }
+
+  test_typeAlias_interfaceType_isUsed_typeName_parameter() async {
+    await assertNoErrorsInCode(r'''
+typedef _A = List<int>;
+
+void f(_A a) {}
+''');
+  }
+
+  test_typeAlias_interfaceType_isUsed_typeName_typeArgument() async {
+    await assertNoErrorsInCode(r'''
+typedef _A = List<int>;
+
+void f() {
+  Map<_A, int>();
+}
+''');
+  }
+
+  test_typeAlias_interfaceType_notUsed() async {
+    await assertErrorsInCode(r'''
+typedef _A = List<int>;
+''', [
+      error(HintCode.UNUSED_ELEMENT, 8, 2),
+    ]);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index b439e4f..d690b6c 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1314,7 +1314,7 @@
 ''');
   }
 
-  test_class_notSimplyBounded_complex_by_cycle() async {
+  test_class_notSimplyBounded_complex_by_cycle_class() async {
     var library = await checkLibrary('''
 class C<T extends D> {}
 class D<T extends C> {}
@@ -1327,6 +1327,29 @@
 ''');
   }
 
+  test_class_notSimplyBounded_complex_by_cycle_typedef_functionType() async {
+    var library = await checkLibrary('''
+typedef C<T extends D> = void Function();
+typedef D<T extends C> = void Function();
+''');
+    checkElementText(library, r'''
+notSimplyBounded typedef C<T extends dynamic Function()> = void Function();
+notSimplyBounded typedef D<T extends dynamic Function()> = void Function();
+''');
+  }
+
+  test_class_notSimplyBounded_complex_by_cycle_typedef_interfaceType() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary('''
+typedef C<T extends D> = List<T>;
+typedef D<T extends C> = List<T>;
+''');
+    checkElementText(library, r'''
+notSimplyBounded typedef C<T extends dynamic> = List<T>;
+notSimplyBounded typedef D<T extends dynamic> = List<T>;
+''');
+  }
+
   test_class_notSimplyBounded_complex_by_reference_to_cycle() async {
     var library = await checkLibrary('''
 class C<T extends D> {}
diff --git a/pkg/analyzer/test/util/element_type_matchers.dart b/pkg/analyzer/test/util/element_type_matchers.dart
index 1ace6dd..f286b3f 100644
--- a/pkg/analyzer/test/util/element_type_matchers.dart
+++ b/pkg/analyzer/test/util/element_type_matchers.dart
@@ -24,8 +24,6 @@
 
 const isFunctionElement = TypeMatcher<FunctionElement>();
 
-const isFunctionTypeAliasElement = TypeMatcher<FunctionTypeAliasElement>();
-
 const isFunctionTypedElement = TypeMatcher<FunctionTypedElement>();
 
 const isGenericFunctionTypeElement = TypeMatcher<GenericFunctionTypeElement>();
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 1fe281f..340a5a4 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -8878,7 +8878,7 @@
 
 ### return_without_value
 
-_The  return value is missing after 'return'._
+_The return value is missing after 'return'._
 
 #### Description
 
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index bf9f4a7..c01275b 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -96,6 +96,7 @@
   static const String useNewSourceInfo = '--use-new-source-info';
   static const String useOldRti = '--use-old-rti';
   static const String verbose = '--verbose';
+  static const String verbosity = '--verbosity';
   static const String progress = '--show-internal-progress';
   static const String version = '--version';
   static const String reportMetrics = '--report-metrics';
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index c528dfb..b1d2000 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -545,6 +545,7 @@
     new OptionHandler(Flags.testMode, passThrough),
     new OptionHandler('${Flags.dumpSsa}=.+', passThrough),
     new OptionHandler('${Flags.cfeInvocationModes}=.+', passThrough),
+    new OptionHandler('${Flags.verbosity}=.+', passThrough),
 
     // Experimental features.
     // We don't provide documentation for these yet.
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index a44d5c5..99a37c5 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -138,8 +138,13 @@
         bool verbose = false;
         Target target = Dart2jsTarget(targetName, TargetFlags());
         fe.FileSystem fileSystem = CompilerFileSystem(_compilerInput);
+        fe.Verbosity verbosity = _options.verbosity;
         fe.DiagnosticMessageHandler onDiagnostic =
-            (e) => reportFrontEndMessage(_reporter, e);
+            (fe.DiagnosticMessage message) {
+          if (fe.Verbosity.shouldPrint(verbosity, message)) {
+            reportFrontEndMessage(_reporter, message);
+          }
+        };
         fe.CompilerOptions options = fe.CompilerOptions()
           ..target = target
           ..librariesSpecificationUri = _options.librariesSpecificationUri
@@ -147,7 +152,8 @@
           ..explicitExperimentalFlags = _options.explicitExperimentalFlags
           ..verbose = verbose
           ..fileSystem = fileSystem
-          ..onDiagnostic = onDiagnostic;
+          ..onDiagnostic = onDiagnostic
+          ..verbosity = verbosity;
         bool isLegacy =
             await fe.uriUsesLegacyLanguageVersion(resolvedUri, options);
         inferNullSafetyMode(_options.enableNonNullable && !isLegacy);
@@ -171,8 +177,8 @@
             nnbdMode: _options.useLegacySubtyping
                 ? fe.NnbdMode.Weak
                 : fe.NnbdMode.Strong,
-            invocationModes:
-                fe.InvocationMode.parseArguments(_options.cfeInvocationModes));
+            invocationModes: _options.cfeInvocationModes,
+            verbosity: verbosity);
         component = await fe.compile(initializedCompilerState, verbose,
             fileSystem, onDiagnostic, resolvedUri);
         if (component == null) return null;
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 2e6ffe7..ddb6dd0 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -433,7 +433,10 @@
   /// See `InvocationMode` in
   /// `pkg/front_end/lib/src/api_prototype/compiler_options.dart` for all
   /// possible options.
-  String cfeInvocationModes = '';
+  Set<fe.InvocationMode> cfeInvocationModes = {};
+
+  /// Verbosity level used for filtering messages during compilation.
+  fe.Verbosity verbosity = fe.Verbosity.all;
 
   // -------------------------------------------------
   // Options for deprecated features
@@ -547,8 +550,13 @@
       .._noSoundNullSafety = _hasOption(options, Flags.noSoundNullSafety)
       .._mergeFragmentsThreshold =
           _extractIntOption(options, '${Flags.mergeFragmentsThreshold}=')
-      ..cfeInvocationModes =
-          _extractStringOption(options, '${Flags.cfeInvocationModes}=', '');
+      ..cfeInvocationModes = fe.InvocationMode.parseArguments(
+          _extractStringOption(options, '${Flags.cfeInvocationModes}=', ''),
+          onError: onError)
+      ..verbosity = fe.Verbosity.parseArgument(
+          _extractStringOption(
+              options, '${Flags.verbosity}=', fe.Verbosity.defaultValue),
+          onError: onError);
   }
 
   void validate() {
diff --git a/pkg/dart2native/bin/dart2native.dart b/pkg/dart2native/bin/dart2native.dart
index 6df0953..7f407416 100644
--- a/pkg/dart2native/bin/dart2native.dart
+++ b/pkg/dart2native/bin/dart2native.dart
@@ -7,6 +7,8 @@
 
 import 'package:args/args.dart';
 import 'package:dart2native/generate.dart';
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+    show Verbosity;
 
 void printUsage(final ArgParser parser) {
   print('''
@@ -65,7 +67,16 @@
 Comma separated list of experimental features.
 ''')
     ..addFlag('verbose',
-        abbr: 'v', negatable: false, help: 'Show verbose output.');
+        abbr: 'v', negatable: false, help: 'Show verbose output.')
+    ..addOption(
+      'verbosity',
+      defaultsTo: Verbosity.defaultValue,
+      help: '''
+Sets the verbosity level used for filtering messages during compilation.
+''',
+      allowed: Verbosity.allowedValues,
+      allowedHelp: Verbosity.allowedValuesHelp,
+    );
 
   ArgResults parsedArgs;
   try {
@@ -106,6 +117,7 @@
         enableExperiment: parsedArgs['enable-experiment'],
         enableAsserts: parsedArgs['enable-asserts'],
         verbose: parsedArgs['verbose'],
+        verbosity: parsedArgs['verbosity'],
         extraOptions: parsedArgs['extra-gen-snapshot-options']);
   } catch (e) {
     stderr.writeln('Failed to generate native files:');
diff --git a/pkg/dart2native/lib/generate.dart b/pkg/dart2native/lib/generate.dart
index 3579ec8..6bc3abd 100644
--- a/pkg/dart2native/lib/generate.dart
+++ b/pkg/dart2native/lib/generate.dart
@@ -27,6 +27,7 @@
   String enableExperiment = '',
   bool enableAsserts = false,
   bool verbose = false,
+  String verbosity = 'all',
   List<String> extraOptions = const [],
 }) async {
   final Directory tempDir = Directory.systemTemp.createTempSync();
@@ -58,7 +59,10 @@
     final kernelResult = await generateAotKernel(Platform.executable, genKernel,
         productPlatformDill, sourcePath, kernelFile, packages, defines,
         enableExperiment: enableExperiment,
-        extraGenKernelOptions: ['--invocation-modes=compile']);
+        extraGenKernelOptions: [
+          '--invocation-modes=compile',
+          '--verbosity=$verbosity'
+        ]);
     if (kernelResult.exitCode != 0) {
       // We pipe both stdout and stderr to stderr because the CFE doesn't print
       // errors to stderr. This unfortunately does emit info-only output in
diff --git a/pkg/dart2native/pubspec.yaml b/pkg/dart2native/pubspec.yaml
index 85a9eac..4c274e7 100644
--- a/pkg/dart2native/pubspec.yaml
+++ b/pkg/dart2native/pubspec.yaml
@@ -12,5 +12,7 @@
 dependencies:
    args: ^1.4.0
    path: any
+   front_end:
+     path: ../front_end
 
 dev_dependencies:
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index 29c5b3e..f3f6e63 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -7,6 +7,8 @@
 
 import 'package:dart2native/generate.dart';
 import 'package:path/path.dart' as path;
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+    show Verbosity;
 
 import '../core.dart';
 import '../experiments.dart';
@@ -19,8 +21,17 @@
   final String flag;
   final String help;
   final String abbr;
+  final String defaultsTo;
+  final List<String> allowed;
+  final Map<String, String> allowedHelp;
 
-  Option({this.flag, this.help, this.abbr});
+  Option(
+      {this.flag,
+      this.help,
+      this.abbr,
+      this.defaultsTo,
+      this.allowed,
+      this.allowedHelp});
 }
 
 final Map<String, Option> commonOptions = {
@@ -32,6 +43,15 @@
 This can be an absolute or relative path.
 ''',
   ),
+  'verbosity': Option(
+    flag: 'verbosity',
+    help: '''
+Sets the verbosity level of the compilation.
+''',
+    defaultsTo: Verbosity.defaultValue,
+    allowed: Verbosity.allowedValues,
+    allowedHelp: Verbosity.allowedValuesHelp,
+  ),
 };
 
 bool checkFile(String sourcePath) {
@@ -53,6 +73,15 @@
         commonOptions['outputFile'].flag,
         help: commonOptions['outputFile'].help,
         abbr: commonOptions['outputFile'].abbr,
+        defaultsTo: commonOptions['outputFile'].defaultsTo,
+      )
+      ..addOption(
+        commonOptions['verbosity'].flag,
+        help: commonOptions['verbosity'].help,
+        abbr: commonOptions['verbosity'].abbr,
+        defaultsTo: commonOptions['verbosity'].defaultsTo,
+        allowed: commonOptions['verbosity'].allowed,
+        allowedHelp: commonOptions['verbosity'].allowedHelp,
       )
       ..addFlag(
         'minified',
@@ -196,6 +225,14 @@
         help: commonOptions['outputFile'].help,
         abbr: commonOptions['outputFile'].abbr,
       )
+      ..addOption(
+        commonOptions['verbosity'].flag,
+        help: commonOptions['verbosity'].help,
+        abbr: commonOptions['verbosity'].abbr,
+        defaultsTo: commonOptions['verbosity'].defaultsTo,
+        allowed: commonOptions['verbosity'].allowed,
+        allowedHelp: commonOptions['verbosity'].allowedHelp,
+      )
       ..addMultiOption('define', abbr: 'D', valueHelp: 'key=value', help: '''
 Define an environment declaration. To specify multiple declarations, use multiple options or use commas to separate key-value pairs.
 For example: dart compile $commandName -Da=1,b=2 main.dart''')
@@ -246,6 +283,7 @@
         enableExperiment: argResults.enabledExperiments.join(','),
         debugFile: argResults['save-debugging-info'],
         verbose: verbose,
+        verbosity: argResults['verbosity'],
       );
       return 0;
     } catch (e) {
diff --git a/pkg/dartdev/pubspec.yaml b/pkg/dartdev/pubspec.yaml
index a8fef55..9beb550 100644
--- a/pkg/dartdev/pubspec.yaml
+++ b/pkg/dartdev/pubspec.yaml
@@ -17,6 +17,8 @@
   dart2native:
     path: ../dart2native
   dart_style: any
+  front_end:
+    path: ../front_end
   intl: any
   meta:
     path: ../meta
diff --git a/pkg/dartdev/test/commands/compile_test.dart b/pkg/dartdev/test/commands/compile_test.dart
index 8f2e8b8..5aaf14c 100644
--- a/pkg/dartdev/test/commands/compile_test.dart
+++ b/pkg/dartdev/test/commands/compile_test.dart
@@ -310,6 +310,30 @@
         reason: 'File not found: $outFile');
   });
 
+  test('Compile exe without info', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'exe',
+        '--verbosity=warning',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
   test('Compile JS with sound null safety', () {
     final p = project(mainSrc: '''void main() {}''');
     final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
@@ -357,6 +381,30 @@
         reason: 'File not found: $outFile');
   });
 
+  test('Compile JS without info', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myjs'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'js',
+        '--verbosity=warning',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
   test('Compile AOT snapshot with sound null safety', () {
     final p = project(mainSrc: '''void main() {}''');
     final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
@@ -404,6 +452,30 @@
         reason: 'File not found: $outFile');
   });
 
+  test('Compile AOT snapshot without info', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myaot'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'aot-snapshot',
+        '--verbosity=warning',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
   test('Compile kernel with sound null safety', () {
     final p = project(mainSrc: '''void main() {}''');
     final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 5e0b86b..5e7960f 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -7,7 +7,8 @@
 library front_end.compiler_options;
 
 import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
-    show DiagnosticMessageHandler;
+    show DiagnosticMessage, DiagnosticMessageHandler;
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
 import 'package:kernel/ast.dart' show Version;
 
@@ -265,6 +266,9 @@
   /// compilation mode when the modes includes [InvocationMode.compile].
   Set<InvocationMode> invocationModes = {};
 
+  /// Verbosity level used for filtering emitted messages.
+  Verbosity verbosity = Verbosity.all;
+
   bool isExperimentEnabledByDefault(ExperimentalFlag flag) {
     return flags.isExperimentEnabled(flag,
         defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting);
@@ -455,13 +459,25 @@
 
   /// Returns the set of information modes from a comma-separated list of
   /// invocation mode names.
-  static Set<InvocationMode> parseArguments(String arg) {
+  ///
+  /// If a name isn't recognized and [onError] is provided, [onError] is called
+  /// with an error messages and an empty set of invocation modes is returned.
+  ///
+  /// If a name isn't recognized and [onError] isn't provided, an error is
+  /// thrown.
+  static Set<InvocationMode> parseArguments(String arg,
+      {void Function(String) onError}) {
     Set<InvocationMode> result = {};
     for (String name in arg.split(',')) {
       if (name.isNotEmpty) {
         InvocationMode mode = fromName(name);
         if (mode == null) {
-          throw new UnsupportedError("Unknown invocation mode '$name'.");
+          String message = "Unknown invocation mode '$name'.";
+          if (onError != null) {
+            onError(message);
+          } else {
+            throw new UnsupportedError(message);
+          }
         } else {
           result.add(mode);
         }
@@ -482,3 +498,109 @@
 
   static const List<InvocationMode> values = const [compile];
 }
+
+/// Verbosity level used for filtering messages during compilation.
+class Verbosity {
+  /// Only error messages are emitted.
+  static const Verbosity error =
+      const Verbosity('error', 'Show only error messages');
+
+  /// Error and warning messages are emitted.
+  static const Verbosity warning =
+      const Verbosity('warning', 'Show only error and warning messages');
+
+  /// Error, warning, and info messages are emitted.
+  static const Verbosity info =
+      const Verbosity('info', 'Show error, warning, and info messages');
+
+  /// All messages are emitted.
+  static const Verbosity all = const Verbosity('all', 'Show all messages');
+
+  static const List<Verbosity> values = const [error, warning, info, all];
+
+  /// Returns the names of all options.
+  static List<String> get allowedValues =>
+      [for (Verbosity value in values) value.name];
+
+  /// Returns a map from option name to option help messages.
+  static Map<String, String> get allowedValuesHelp =>
+      {for (Verbosity value in values) value.name: value.help};
+
+  /// Returns the verbosity corresponding to the given [name].
+  ///
+  /// If [name] isn't recognized and [onError] is provided, [onError] is called
+  /// with an error messages and [defaultValue] is returned.
+  ///
+  /// If [name] isn't recognized and [onError] isn't provided, an error is
+  /// thrown.
+  static Verbosity parseArgument(String name,
+      {void Function(String) onError, Verbosity defaultValue: Verbosity.all}) {
+    for (Verbosity verbosity in values) {
+      if (name == verbosity.name) {
+        return verbosity;
+      }
+    }
+    String message = "Unknown verbosity '$name'.";
+    if (onError != null) {
+      onError(message);
+      return defaultValue;
+    }
+    throw new UnsupportedError(message);
+  }
+
+  static bool shouldPrint(Verbosity verbosity, DiagnosticMessage message) {
+    Severity severity = message.severity;
+    switch (verbosity) {
+      case Verbosity.error:
+        switch (severity) {
+          case Severity.internalProblem:
+          case Severity.error:
+            return true;
+          case Severity.warning:
+          case Severity.info:
+          case Severity.context:
+          case Severity.ignored:
+            return false;
+        }
+        break;
+      case Verbosity.warning:
+        switch (severity) {
+          case Severity.internalProblem:
+          case Severity.error:
+          case Severity.warning:
+            return true;
+          case Severity.info:
+          case Severity.context:
+          case Severity.ignored:
+            return false;
+        }
+        break;
+      case Verbosity.info:
+        switch (severity) {
+          case Severity.internalProblem:
+          case Severity.error:
+          case Severity.warning:
+          case Severity.info:
+            return true;
+          case Severity.context:
+          case Severity.ignored:
+            return false;
+        }
+        break;
+      case Verbosity.all:
+        return true;
+    }
+    throw new UnsupportedError(
+        "Unsupported verbosity $verbosity and severity $severity.");
+  }
+
+  static const String defaultValue = 'all';
+
+  final String name;
+  final String help;
+
+  const Verbosity(this.name, this.help);
+
+  @override
+  String toString() => 'Verbosity($name)';
+}
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index 358c006..c9fbb930 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -21,7 +21,7 @@
 import 'package:kernel/target/targets.dart' show Target;
 
 import '../api_prototype/compiler_options.dart'
-    show CompilerOptions, InvocationMode;
+    show CompilerOptions, InvocationMode, Verbosity;
 
 import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
 
@@ -103,6 +103,7 @@
     show
         CompilerOptions,
         InvocationMode,
+        Verbosity,
         parseExperimentalFlags,
         parseExperimentalArguments;
 
@@ -146,7 +147,8 @@
     {Map<ExperimentalFlag, bool> explicitExperimentalFlags,
     bool verify: false,
     NnbdMode nnbdMode,
-    Set<InvocationMode> invocationModes: const <InvocationMode>{}}) {
+    Set<InvocationMode> invocationModes: const <InvocationMode>{},
+    Verbosity verbosity: Verbosity.all}) {
   additionalDills.sort((a, b) => a.toString().compareTo(b.toString()));
 
   // We don't check `target` because it doesn't support '==' and each
@@ -160,7 +162,8 @@
           explicitExperimentalFlags) &&
       oldState.options.verify == verify &&
       oldState.options.nnbdMode == nnbdMode &&
-      equalSets(oldState.options.invocationModes, invocationModes)) {
+      equalSets(oldState.options.invocationModes, invocationModes) &&
+      oldState.options.verbosity == verbosity) {
     return oldState;
   }
 
@@ -171,7 +174,8 @@
     ..packagesFileUri = packagesFileUri
     ..explicitExperimentalFlags = explicitExperimentalFlags
     ..verify = verify
-    ..invocationModes = invocationModes;
+    ..invocationModes = invocationModes
+    ..verbosity = verbosity;
   if (nnbdMode != null) options.nnbdMode = nnbdMode;
 
   ProcessedOptions processedOpts = new ProcessedOptions(options: options);
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index 547bbb2..9bfeea8 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -13,6 +13,7 @@
     show
         CompilerOptions,
         InvocationMode,
+        Verbosity,
         parseExperimentalArguments,
         parseExperimentalFlags;
 
diff --git a/pkg/front_end/lib/src/base/command_line_options.dart b/pkg/front_end/lib/src/base/command_line_options.dart
index 862187a..d2e2f84 100644
--- a/pkg/front_end/lib/src/base/command_line_options.dart
+++ b/pkg/front_end/lib/src/base/command_line_options.dart
@@ -38,6 +38,7 @@
   static const String singleRootBase = "--single-root-base";
   static const String singleRootScheme = "--single-root-scheme";
   static const String verbose = "--verbose";
+  static const String verbosity = "--verbosity";
   static const String verify = "--verify";
   static const String verifySkipPlatform = "--verify-skip-platform";
   static const String warnOnReachabilityCheck = "--warn-on-reachability-check";
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index e768713..bc6c7ad 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -26,7 +26,7 @@
 import 'package:package_config/package_config.dart';
 
 import '../api_prototype/compiler_options.dart'
-    show CompilerOptions, InvocationMode, DiagnosticMessage;
+    show CompilerOptions, InvocationMode, Verbosity, DiagnosticMessage;
 
 import '../api_prototype/experimental_flags.dart' as flags;
 
@@ -263,7 +263,9 @@
   }
 
   void _defaultDiagnosticMessageHandler(DiagnosticMessage message) {
-    printDiagnosticMessage(message, print);
+    if (Verbosity.shouldPrint(_raw.verbosity, message)) {
+      printDiagnosticMessage(message, print);
+    }
   }
 
   // TODO(askesc): Remove this and direct callers directly to report.
diff --git a/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart b/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
index 78dc0c5..4029c5c 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
@@ -546,30 +546,75 @@
               statement.expression.fileOffset,
               noLength)
             ..parent = statement;
-        } else if (flattenedExpressionType is! VoidType &&
-            !inferrer.typeSchemaEnvironment
-                .performNullabilityAwareSubtypeCheck(
-                    flattenedExpressionType, futureValueType)
-                .isSubtypeWhenUsingNullabilities()) {
-          // It is a compile-time error if s is `return e;`, flatten(S) is not
-          // void, S is not assignable to T_v, and flatten(S) is not a subtype
-          // of T_v.
-          statement.expression = inferrer.ensureAssignable(
-              futureValueType, expressionType, statement.expression,
-              fileOffset: statement.expression.fileOffset,
-              runtimeCheckedType:
-                  inferrer.computeGreatestClosure2(_returnContext),
-              declaredContextType: returnType,
-              isVoidAllowed: false,
-              errorTemplate: templateInvalidReturnAsync,
-              nullabilityErrorTemplate: templateInvalidReturnAsyncNullability,
-              nullabilityPartErrorTemplate:
-                  templateInvalidReturnAsyncPartNullability,
-              nullabilityNullErrorTemplate:
-                  templateInvalidReturnAsyncNullabilityNull,
-              nullabilityNullTypeErrorTemplate:
-                  templateInvalidReturnAsyncNullabilityNullType)
-            ..parent = statement;
+        } else {
+          DartType futureOrType =
+              inferrer.computeGreatestClosure2(_returnContext);
+          if (flattenedExpressionType is! VoidType &&
+              !inferrer.typeSchemaEnvironment
+                  .performNullabilityAwareSubtypeCheck(
+                      flattenedExpressionType, futureValueType)
+                  .isSubtypeWhenUsingNullabilities()) {
+            // It is a compile-time error if s is `return e;`, flatten(S) is not
+            // void, S is not assignable to T_v, and flatten(S) is not a subtype
+            // of T_v.
+            statement.expression = inferrer.ensureAssignable(
+                futureValueType, expressionType, statement.expression,
+                fileOffset: statement.expression.fileOffset,
+                runtimeCheckedType: futureOrType,
+                declaredContextType: returnType,
+                isVoidAllowed: false,
+                errorTemplate: templateInvalidReturnAsync,
+                nullabilityErrorTemplate: templateInvalidReturnAsyncNullability,
+                nullabilityPartErrorTemplate:
+                    templateInvalidReturnAsyncPartNullability,
+                nullabilityNullErrorTemplate:
+                    templateInvalidReturnAsyncNullabilityNull,
+                nullabilityNullTypeErrorTemplate:
+                    templateInvalidReturnAsyncNullabilityNullType)
+              ..parent = statement;
+          }
+          // For `return e`:
+          // When `f` is an asynchronous non-generator with future value type
+          // T_v, evaluation proceeds as follows:
+          //
+          //    The expression `e` is evaluated to an object `o`.
+          //      If the run-time type of `o` is a subtype of `Future<T_v>`,
+          //         let `v` be a fresh variable bound to `o` and
+          //         evaluate `await v` to an object `r`;
+          //         otherwise let `r` be `o`.
+          //    A dynamic error occurs unless the dynamic type of `r`
+          //      is a subtype of the actual value of T_v.
+          //    Then the return statement `s` completes returning `r`.
+          DartType futureType = new InterfaceType(
+              inferrer.coreTypes.futureClass,
+              Nullability.nonNullable,
+              [futureValueType]);
+          VariableDeclaration variable;
+          Expression isOperand;
+          Expression awaitOperand;
+          Expression resultExpression;
+          if (isPureExpression(statement.expression)) {
+            isOperand = clonePureExpression(statement.expression);
+            awaitOperand = clonePureExpression(statement.expression);
+            resultExpression = statement.expression;
+          } else {
+            variable = createVariable(statement.expression, expressionType);
+            isOperand = createVariableGet(variable);
+            awaitOperand = createVariableGet(variable);
+            resultExpression = createVariableGet(variable);
+          }
+          Expression replacement = new ConditionalExpression(
+              new IsExpression(isOperand, futureType)
+                ..fileOffset = statement.fileOffset,
+              new AwaitExpression(awaitOperand)
+                ..fileOffset = statement.fileOffset,
+              resultExpression,
+              futureOrType)
+            ..fileOffset = statement.fileOffset;
+          if (variable != null) {
+            replacement = createLet(variable, replacement);
+          }
+          statement.expression = replacement..parent = statement;
         }
       }
     } else {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 0b50fbb..4dd7287 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -2514,16 +2514,13 @@
     // `void` if `B’` contains no `yield` expressions.  Otherwise, let `M` be
     // the least upper bound of the types of the `return` expressions in `B’`,
     // or `void` if `B’` contains no `return` expressions.
-    DartType inferredReturnType;
     if (needToSetReturnType) {
-      inferredReturnType = closureContext.inferReturnType(this,
+      DartType inferredReturnType = closureContext.inferReturnType(this,
           hasImplicitReturn: flowAnalysis.isReachable);
-    }
 
-    // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B` with
-    // type `<T0, ..., Tn>(R0, ..., Rn) -> M’` (with some of the `Ri` and `xi`
-    // denoted as optional or named parameters, if appropriate).
-    if (needToSetReturnType) {
+      // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B`
+      // with type `<T0, ..., Tn>(R0, ..., Rn) -> M'` (with some of the `Ri` and
+      // `xi` denoted as optional or named parameters, if appropriate).
       instrumentation?.record(uriForInstrumentation, fileOffset, 'returnType',
           new InstrumentationValueForType(inferredReturnType));
       function.returnType = inferredReturnType;
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 572493d..e422e9d 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -868,6 +868,7 @@
 printf
 println
 proc
+proceeds
 producers
 product
 progresses
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 55be1a1..d3bc3e1a 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -737,6 +737,7 @@
 unassignment
 unawaited
 unbreak
+uncaught
 unconverted
 uncover
 uncovers
diff --git a/pkg/front_end/test/text_representation/data/expressions.dart b/pkg/front_end/test/text_representation/data/expressions.dart
index bf8c23c..4d70d21 100644
--- a/pkg/front_end/test/text_representation/data/expressions.dart
+++ b/pkg/front_end/test/text_representation/data/expressions.dart
@@ -382,7 +382,9 @@
 exprMap() => {0: "foo", 1: "bar"};
 
 /*member: exprAwait:await o*/
-exprAwait(o) async => await o;
+exprAwait(o) async {
+  await o;
+}
 
 /*member: exprLoadLibrary:prefix.loadLibrary()*/
 exprLoadLibrary() => prefix.loadLibrary();
diff --git a/pkg/front_end/test/text_representation/text_representation_test.dart b/pkg/front_end/test/text_representation/text_representation_test.dart
index f804385..d9019d0 100644
--- a/pkg/front_end/test/text_representation/text_representation_test.dart
+++ b/pkg/front_end/test/text_representation/text_representation_test.dart
@@ -156,14 +156,16 @@
 
   @override
   String computeMemberValue(Id id, Member node) {
-    if (node.name.text == 'stmtVariableDeclarationMulti') {
-      print(node);
-    }
     if (node.name.text.startsWith(expressionMarker)) {
       if (node is Procedure) {
         Statement body = node.function.body;
         if (body is ReturnStatement) {
           return body.expression.toText(strategy);
+        } else if (body is Block &&
+            body.statements.isNotEmpty &&
+            body.statements.first is ExpressionStatement) {
+          ExpressionStatement statement = body.statements.first;
+          return statement.expression.toText(strategy);
         }
       } else if (node is Field && node.initializer != null) {
         return node.initializer.toText(strategy);
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
index 0b84933..74694bf 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
@@ -134,28 +134,28 @@
   await for (core::String s in asy::Stream::fromIterable<core::String>(<core::String>["hest"])) {
     core::print(s);
   }
-  return "hest";
+  return let final core::String #t8 = "hest" in #t8 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t8 : #t8;
 }
 static method fisk() → dynamic async {
   lowered core::String? #s1;
   function #s1#get() → core::String
-    return let final core::String? #t8 = #s1 in #t8.==(null) ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
+    return let final core::String? #t9 = #s1 in #t9.==(null) ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
   late String s1 = await hest(); // Error.
-                   ^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::String : #t8{core::String};
-  function #s1#set(core::String #t9) → dynamic
-    return #s1 = #t9;
+                   ^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::String : #t9{core::String};
+  function #s1#set(core::String #t10) → dynamic
+    return #s1 = #t10;
   lowered core::String? #s2;
   function #s2#get() → core::String
-    return let final core::String? #t10 = #s2 in #t10.==(null) ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
+    return let final core::String? #t11 = #s2 in #t11.==(null) ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}'; // Error.
-                             ^^^^^"}${#C1}" : #t10{core::String};
-  function #s2#set(core::String #t11) → dynamic
-    return #s2 = #t11;
+                             ^^^^^"}${#C1}" : #t11{core::String};
+  function #s2#set(core::String #t12) → dynamic
+    return #s2 = #t12;
   lowered core::Function? #f;
   function #f#get() → core::Function
-    return let final core::Function? #t12 = #f in #t12.==(null) ?{core::Function} #f = () → asy::Future<dynamic> async => await self::hest() : #t12{core::Function};
-  function #f#set(core::Function #t13) → dynamic
-    return #f = #t13;
+    return let final core::Function? #t13 = #f in #t13.==(null) ?{core::Function} #f = () → asy::Future<dynamic> async => let final dynamic #t14 = await self::hest() in #t14 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t14 : #t14 : #t13{core::Function};
+  function #f#set(core::Function #t15) → dynamic
+    return #f = #t15;
 }
 static method main() → dynamic {}
 
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 12f0ed3..09236c4 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
@@ -148,6 +148,8 @@
   dynamic :saved_try_context_var1;
   dynamic :exception0;
   dynamic :stack_trace0;
+  FutureOr<dynamic>:async_temporary_0;
+  FutureOr<dynamic>:async_temporary_1;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
@@ -175,7 +177,15 @@
               :result;
             }
         }
-        :return_value = "hest";
+        final core::String #t11 = "hest";
+        if(#t11 is asy::Future<dynamic>) {
+          [yield] let dynamic #t12 = asy::_awaitHelper(#t11, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_1 = _in::unsafeCast<core::String>(:result);
+        }
+        else {
+          :async_temporary_1 = #t11;
+        }
+        :return_value = :async_temporary_1;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -204,21 +214,21 @@
       {
         lowered core::String? #s1;
         function #s1#get() → core::String
-          return let final core::String? #t11 = #s1 in #t11.==(null) ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
+          return let final core::String? #t13 = #s1 in #t13.==(null) ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
   late String s1 = await hest(); // Error.
-                   ^^^^^" : #t11{core::String};
-        function #s1#set(core::String #t12) → dynamic
-          return #s1 = #t12;
+                   ^^^^^" : #t13{core::String};
+        function #s1#set(core::String #t14) → dynamic
+          return #s1 = #t14;
         lowered core::String? #s2;
         function #s2#get() → core::String
-          return let final core::String? #t13 = #s2 in #t13.==(null) ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
+          return let final core::String? #t15 = #s2 in #t15.==(null) ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}'; // Error.
-                             ^^^^^"}${#C1}" : #t13{core::String};
-        function #s2#set(core::String #t14) → dynamic
-          return #s2 = #t14;
+                             ^^^^^"}${#C1}" : #t15{core::String};
+        function #s2#set(core::String #t16) → dynamic
+          return #s2 = #t16;
         lowered core::Function? #f;
         function #f#get() → core::Function
-          return let final core::Function? #t15 = #f in #t15.==(null) ?{core::Function} #f = () → asy::Future<dynamic> /* originally async */ {
+          return let final core::Function? #t17 = #f in #t17.==(null) ?{core::Function} #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;
@@ -227,12 +237,21 @@
             core::int :await_jump_var = 0;
             dynamic :await_ctx_var;
             dynamic :saved_try_context_var0;
+            FutureOr<dynamic>:async_temporary_0;
             function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
               try {
                 #L4:
                 {
-                  [yield] let dynamic #t16 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
-                  :return_value = :result;
+                  [yield] let dynamic #t18 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                  final dynamic #t19 = :result;
+                  if(#t19 is asy::Future<dynamic>) {
+                    [yield] let dynamic #t20 = asy::_awaitHelper(#t19, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = :result;
+                  }
+                  else {
+                    :async_temporary_0 = #t19;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L4;
                 }
                 asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -246,9 +265,9 @@
             :async_op.call();
             :is_sync = true;
             return :async_future;
-          } : #t15{core::Function};
-        function #f#set(core::Function #t17) → dynamic
-          return #f = #t17;
+          } : #t17{core::Function};
+        function #f#set(core::Function #t21) → dynamic
+          return #f = #t21;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
@@ -270,4 +289,4 @@
 
 Extra constant evaluation status:
 Evaluated: VariableGet @ org-dartlang-testcase:///later.dart:46:18 -> IntConstant(42)
-Extra constant evaluation: evaluated: 207, effectively constant: 1
+Extra constant evaluation: evaluated: 234, effectively constant: 1
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
index 7123dd80..0d0243b 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
@@ -154,7 +154,7 @@
   await for (core::String s in asy::Stream::fromIterable<core::String>(<core::String>["hest"])) {
     core::print(s);
   }
-  return "hest";
+  return let final core::String #t8 = "hest" in #t8 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t8 : #t8;
 }
 static method fisk() → dynamic async {
   lowered core::String? #s1;
@@ -168,9 +168,9 @@
     }
     return #s1{core::String};
   }
-  function #s1#set(core::String #t8) → dynamic {
+  function #s1#set(core::String #t9) → dynamic {
     #s1#isSet = true;
-    return #s1 = #t8;
+    return #s1 = #t9;
   }
   lowered core::String? #s2;
   lowered core::bool #s2#isSet = false;
@@ -183,22 +183,22 @@
     }
     return #s2{core::String};
   }
-  function #s2#set(core::String #t9) → dynamic {
+  function #s2#set(core::String #t10) → dynamic {
     #s2#isSet = true;
-    return #s2 = #t9;
+    return #s2 = #t10;
   }
   lowered core::Function? #f;
   lowered core::bool #f#isSet = false;
   function #f#get() → core::Function {
     if(!#f#isSet) {
-      #f = () → asy::Future<dynamic> async => await self::hest();
+      #f = () → asy::Future<dynamic> async => let final dynamic #t11 = await self::hest() in #t11 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t11 : #t11;
       #f#isSet = true;
     }
     return #f{core::Function};
   }
-  function #f#set(core::Function #t10) → dynamic {
+  function #f#set(core::Function #t12) → dynamic {
     #f#isSet = true;
-    return #f = #t10;
+    return #f = #t12;
   }
 }
 static method main() → dynamic {}
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 3bcf2b7..7fe5b1b 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
@@ -168,6 +168,8 @@
   dynamic :saved_try_context_var1;
   dynamic :exception0;
   dynamic :stack_trace0;
+  FutureOr<dynamic>:async_temporary_0;
+  FutureOr<dynamic>:async_temporary_1;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
@@ -195,7 +197,15 @@
               :result;
             }
         }
-        :return_value = "hest";
+        final core::String #t11 = "hest";
+        if(#t11 is asy::Future<dynamic>) {
+          [yield] let dynamic #t12 = asy::_awaitHelper(#t11, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_1 = _in::unsafeCast<core::String>(:result);
+        }
+        else {
+          :async_temporary_1 = #t11;
+        }
+        :return_value = :async_temporary_1;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -233,9 +243,9 @@
           }
           return #s1{core::String};
         }
-        function #s1#set(core::String #t11) → dynamic {
+        function #s1#set(core::String #t13) → dynamic {
           #s1#isSet = true;
-          return #s1 = #t11;
+          return #s1 = #t13;
         }
         lowered core::String? #s2;
         lowered core::bool #s2#isSet = false;
@@ -248,9 +258,9 @@
           }
           return #s2{core::String};
         }
-        function #s2#set(core::String #t12) → dynamic {
+        function #s2#set(core::String #t14) → dynamic {
           #s2#isSet = true;
-          return #s2 = #t12;
+          return #s2 = #t14;
         }
         lowered core::Function? #f;
         lowered core::bool #f#isSet = false;
@@ -265,12 +275,21 @@
               core::int :await_jump_var = 0;
               dynamic :await_ctx_var;
               dynamic :saved_try_context_var0;
+              FutureOr<dynamic>:async_temporary_0;
               function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
                 try {
                   #L4:
                   {
-                    [yield] let dynamic #t13 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
-                    :return_value = :result;
+                    [yield] let dynamic #t15 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                    final dynamic #t16 = :result;
+                    if(#t16 is asy::Future<dynamic>) {
+                      [yield] let dynamic #t17 = asy::_awaitHelper(#t16, :async_op_then, :async_op_error, :async_op) in null;
+                      :async_temporary_0 = :result;
+                    }
+                    else {
+                      :async_temporary_0 = #t16;
+                    }
+                    :return_value = :async_temporary_0;
                     break #L4;
                   }
                   asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -289,9 +308,9 @@
           }
           return #f{core::Function};
         }
-        function #f#set(core::Function #t14) → dynamic {
+        function #f#set(core::Function #t18) → dynamic {
           #f#isSet = true;
-          return #f = #t14;
+          return #f = #t18;
         }
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.expect b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.expect
index 0e66be9..6769397 100644
--- a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.expect
@@ -263,35 +263,35 @@
   }
   function local() → FutureOr<self::A> async {
     if(true) {
-      return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
+      return let final self::B? #t6 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return x; // Error.
-             ^" in x as{TypeError,ForNonNullableByDefault} self::A;
+             ^" in x as{TypeError,ForNonNullableByDefault} self::A in #t6 is asy::Future<self::A> ?{FutureOr<self::A>} await #t6 : #t6;
     }
     else {
-      return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
+      return let final asy::Future<self::B?> #t8 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<B?>.value(x); // Error.
-                 ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A;
+                 ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A in #t8 is asy::Future<self::A> ?{FutureOr<self::A>} await #t8 : #t8;
     }
   }
-  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   return x; // Error.
          ^" in x as{TypeError,ForNonNullableByDefault} self::A;
 }
 static method bar(core::List<self::B?> x, core::List<core::List<self::B?>> l, core::Map<core::List<self::B?>, core::List<self::B?>> m) → core::List<self::A> {
-  self::barContext(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  self::barContext(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   barContext(x); // Error.
              ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>);
-  core::List<self::A> y = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  core::List<self::A> y = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -314,16 +314,16 @@
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   <List<A>, List<A>>{...m}; // Error.
                         ^"};
-  for (final core::List<self::B?> #t11 in l) {
-    core::List<self::A> y = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  for (final core::List<self::B?> #t13 in l) {
+    core::List<self::A> y = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
 Try changing the type of the variable.
   for (List<A> y in l) {} // Error.
-               ^" in #t11 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
+               ^" in #t13 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
   }
-  return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -331,52 +331,52 @@
          ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>;
 }
 static method baz(self::C c) → void {
-  self::bazContext(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
+  self::bazContext(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
   bazContext(c);
-             ^" in (let final self::C #t15 = c in #t15.==(null) ?{() → core::num?} null : #t15.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
+             ^" in (let final self::C #t17 = c in #t17.==(null) ?{() → core::num?} null : #t17.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
 }
 static method boz(Null x) → self::A {
-  self::fooContext(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(x); // Error.
              ^" in x as{TypeError,ForNonNullableByDefault} self::A);
-  self::fooContext(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(null); // Error.
              ^" in null as{TypeError,ForNonNullableByDefault} self::A);
-  self::A a1 = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a1 = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a1 = x; // Error.
          ^" in x as{TypeError,ForNonNullableByDefault} self::A;
-  self::A a2 = let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a2 = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a2 = null; // Error.
          ^" in null as{TypeError,ForNonNullableByDefault} self::A;
   if(true) {
-    return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return x; // Error.
            ^" in x as{TypeError,ForNonNullableByDefault} self::A;
   }
   else {
-    return let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return null; // Error.
            ^" in null as{TypeError,ForNonNullableByDefault} self::A;
   }
   function local() → FutureOr<self::A> async {
     if(true) {
-      return let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
+      return let final Null #t24 = let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return null; // Error.
-             ^" in null as{TypeError,ForNonNullableByDefault} self::A;
+             ^" in null as{TypeError,ForNonNullableByDefault} self::A in #t24 is asy::Future<self::A> ?{FutureOr<self::A>} await #t24 : #t24;
     }
     else {
-      return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
+      return let final asy::Future<Null> #t26 = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<Null>.value(null); // Error.
-                 ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A;
+                 ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A in #t26 is asy::Future<self::A> ?{FutureOr<self::A>} await #t26 : #t26;
     }
   }
 }
diff --git a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.transformed.expect
index bdd60d8..c855781 100644
--- a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.transformed.expect
@@ -180,6 +180,7 @@
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 import "dart:async";
 
@@ -280,25 +281,45 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<self::A>:async_temporary_0;
+    FutureOr<self::A>:async_temporary_1;
+    FutureOr<self::A>:async_temporary_2;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L4:
         {
           if(true) {
-            :return_value = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
+            final self::B? #t10 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return x; // Error.
-             ^" in let self::B? #t11 = x in #t11.==(null) ?{self::A} #t11 as{TypeError,ForNonNullableByDefault} self::A : #t11{self::A};
+             ^" in let self::B? #t12 = x in #t12.==(null) ?{self::A} #t12 as{TypeError,ForNonNullableByDefault} self::A : #t12{self::A};
+            if(#t10 is asy::Future<self::A>) {
+              [yield] let dynamic #t13 = asy::_awaitHelper(#t10, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_0 = _in::unsafeCast<self::B?>(:result);
+            }
+            else {
+              :async_temporary_0 = #t10;
+            }
+            :return_value = :async_temporary_0;
             break #L4;
           }
           else {
-            :return_value = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
+            final asy::Future<self::B?> #t14 = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<B?>.value(x); // Error.
                  ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A;
+            if(#t14 is asy::Future<self::A>) {
+              [yield] let dynamic #t16 = asy::_awaitHelper(#t14, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_2 = _in::unsafeCast<self::B?>(:result);
+            }
+            else {
+              :async_temporary_2 = #t14;
+            }
+            :return_value = :async_temporary_2;
             break #L4;
           }
         }
@@ -314,20 +335,20 @@
     :is_sync = true;
     return :async_future;
   }
-  return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   return x; // Error.
-         ^" in let self::B? #t14 = x in #t14.==(null) ?{self::A} #t14 as{TypeError,ForNonNullableByDefault} self::A : #t14{self::A};
+         ^" in let self::B? #t18 = x in #t18.==(null) ?{self::A} #t18 as{TypeError,ForNonNullableByDefault} self::A : #t18{self::A};
 }
 static method bar(core::List<self::B?> x, core::List<core::List<self::B?>> l, core::Map<core::List<self::B?>, core::List<self::B?>> m) → core::List<self::A> {
-  self::barContext(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  self::barContext(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   barContext(x); // Error.
              ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>);
-  core::List<self::A> y = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  core::List<self::A> y = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -353,19 +374,19 @@
   {
     core::Iterator<core::List<self::B?>> :sync-for-iterator = l.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-      final core::List<self::B?> #t17 = :sync-for-iterator.{core::Iterator::current};
+      final core::List<self::B?> #t21 = :sync-for-iterator.{core::Iterator::current};
       {
-        core::List<self::A> y = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+        core::List<self::A> y = let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
 Try changing the type of the variable.
   for (List<A> y in l) {} // Error.
-               ^" in #t17 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
+               ^" in #t21 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
       }
     }
   }
-  return let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -373,38 +394,38 @@
          ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>;
 }
 static method baz(self::C c) → void {
-  self::bazContext(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
+  self::bazContext(let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
   bazContext(c);
-             ^" in (let final self::C #t21 = c in #t21.==(null) ?{() → core::num?} null : #t21.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
+             ^" in (let final self::C #t25 = c in #t25.==(null) ?{() → core::num?} null : #t25.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
 }
 static method boz(Null x) → self::A {
-  self::fooContext(let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(x); // Error.
-             ^" in let Null #t23 = x in #t23.==(null) ?{self::A} #t23 as{TypeError,ForNonNullableByDefault} self::A : #t23{self::A});
-  self::fooContext(let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+             ^" in let Null #t27 = x in #t27.==(null) ?{self::A} #t27 as{TypeError,ForNonNullableByDefault} self::A : #t27{self::A});
+  self::fooContext(let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(null); // Error.
-             ^" in let Null #t25 = null in #t25.==(null) ?{self::A} #t25 as{TypeError,ForNonNullableByDefault} self::A : #t25{self::A});
-  self::A a1 = let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+             ^" in let Null #t29 = null in #t29.==(null) ?{self::A} #t29 as{TypeError,ForNonNullableByDefault} self::A : #t29{self::A});
+  self::A a1 = let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a1 = x; // Error.
-         ^" in let Null #t27 = x in #t27.==(null) ?{self::A} #t27 as{TypeError,ForNonNullableByDefault} self::A : #t27{self::A};
-  self::A a2 = let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+         ^" in let Null #t31 = x in #t31.==(null) ?{self::A} #t31 as{TypeError,ForNonNullableByDefault} self::A : #t31{self::A};
+  self::A a2 = let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a2 = null; // Error.
-         ^" in let Null #t29 = null in #t29.==(null) ?{self::A} #t29 as{TypeError,ForNonNullableByDefault} self::A : #t29{self::A};
+         ^" in let Null #t33 = null in #t33.==(null) ?{self::A} #t33 as{TypeError,ForNonNullableByDefault} self::A : #t33{self::A};
   if(true) {
-    return let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return x; // Error.
-           ^" in let Null #t31 = x in #t31.==(null) ?{self::A} #t31 as{TypeError,ForNonNullableByDefault} self::A : #t31{self::A};
+           ^" in let Null #t35 = x in #t35.==(null) ?{self::A} #t35 as{TypeError,ForNonNullableByDefault} self::A : #t35{self::A};
   }
   else {
-    return let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return null; // Error.
-           ^" in let Null #t33 = null in #t33.==(null) ?{self::A} #t33 as{TypeError,ForNonNullableByDefault} self::A : #t33{self::A};
+           ^" in let Null #t37 = null in #t37.==(null) ?{self::A} #t37 as{TypeError,ForNonNullableByDefault} self::A : #t37{self::A};
   }
   function local() → FutureOr<self::A> /* originally async */ {
     final asy::_Future<self::A> :async_future = new asy::_Future::•<self::A>();
@@ -414,23 +435,43 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<self::A>:async_temporary_0;
+    FutureOr<self::A>:async_temporary_1;
+    FutureOr<self::A>:async_temporary_2;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L5:
         {
           if(true) {
-            :return_value = let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
+            final Null #t38 = let final<BottomType> #t39 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return null; // Error.
-             ^" in let Null #t35 = null in #t35.==(null) ?{self::A} #t35 as{TypeError,ForNonNullableByDefault} self::A : #t35{self::A};
+             ^" in let Null #t40 = null in #t40.==(null) ?{self::A} #t40 as{TypeError,ForNonNullableByDefault} self::A : #t40{self::A};
+            if(#t38 is asy::Future<self::A>) {
+              [yield] let dynamic #t41 = asy::_awaitHelper(#t38, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_0 = _in::unsafeCast<Null>(:result);
+            }
+            else {
+              :async_temporary_0 = #t38;
+            }
+            :return_value = :async_temporary_0;
             break #L5;
           }
           else {
-            :return_value = let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
+            final asy::Future<Null> #t42 = let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<Null>.value(null); // Error.
                  ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A;
+            if(#t42 is asy::Future<self::A>) {
+              [yield] let dynamic #t44 = asy::_awaitHelper(#t42, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_2 = _in::unsafeCast<Null>(:result);
+            }
+            else {
+              :async_temporary_2 = #t42;
+            }
+            :return_value = :async_temporary_2;
             break #L5;
           }
         }
@@ -466,7 +507,7 @@
 Evaluated: MethodInvocation @ org-dartlang-testcase:///assignability_error_messages.dart:77:14 -> BoolConstant(true)
 Evaluated: VariableGet @ org-dartlang-testcase:///assignability_error_messages.dart:77:14 -> NullConstant(null)
 Evaluated: VariableGet @ org-dartlang-testcase:///assignability_error_messages.dart:77:14 -> NullConstant(null)
-Extra constant evaluation: evaluated: 210, effectively constant: 12
+Extra constant evaluation: evaluated: 266, effectively constant: 12
 
 
 Constructor coverage from constants:
diff --git a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.expect b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.expect
index 0e66be9..6769397 100644
--- a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.expect
@@ -263,35 +263,35 @@
   }
   function local() → FutureOr<self::A> async {
     if(true) {
-      return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
+      return let final self::B? #t6 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return x; // Error.
-             ^" in x as{TypeError,ForNonNullableByDefault} self::A;
+             ^" in x as{TypeError,ForNonNullableByDefault} self::A in #t6 is asy::Future<self::A> ?{FutureOr<self::A>} await #t6 : #t6;
     }
     else {
-      return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
+      return let final asy::Future<self::B?> #t8 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<B?>.value(x); // Error.
-                 ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A;
+                 ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A in #t8 is asy::Future<self::A> ?{FutureOr<self::A>} await #t8 : #t8;
     }
   }
-  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   return x; // Error.
          ^" in x as{TypeError,ForNonNullableByDefault} self::A;
 }
 static method bar(core::List<self::B?> x, core::List<core::List<self::B?>> l, core::Map<core::List<self::B?>, core::List<self::B?>> m) → core::List<self::A> {
-  self::barContext(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  self::barContext(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   barContext(x); // Error.
              ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>);
-  core::List<self::A> y = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  core::List<self::A> y = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -314,16 +314,16 @@
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   <List<A>, List<A>>{...m}; // Error.
                         ^"};
-  for (final core::List<self::B?> #t11 in l) {
-    core::List<self::A> y = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  for (final core::List<self::B?> #t13 in l) {
+    core::List<self::A> y = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
 Try changing the type of the variable.
   for (List<A> y in l) {} // Error.
-               ^" in #t11 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
+               ^" in #t13 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
   }
-  return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -331,52 +331,52 @@
          ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>;
 }
 static method baz(self::C c) → void {
-  self::bazContext(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
+  self::bazContext(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
   bazContext(c);
-             ^" in (let final self::C #t15 = c in #t15.==(null) ?{() → core::num?} null : #t15.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
+             ^" in (let final self::C #t17 = c in #t17.==(null) ?{() → core::num?} null : #t17.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
 }
 static method boz(Null x) → self::A {
-  self::fooContext(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(x); // Error.
              ^" in x as{TypeError,ForNonNullableByDefault} self::A);
-  self::fooContext(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(null); // Error.
              ^" in null as{TypeError,ForNonNullableByDefault} self::A);
-  self::A a1 = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a1 = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a1 = x; // Error.
          ^" in x as{TypeError,ForNonNullableByDefault} self::A;
-  self::A a2 = let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a2 = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a2 = null; // Error.
          ^" in null as{TypeError,ForNonNullableByDefault} self::A;
   if(true) {
-    return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return x; // Error.
            ^" in x as{TypeError,ForNonNullableByDefault} self::A;
   }
   else {
-    return let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return null; // Error.
            ^" in null as{TypeError,ForNonNullableByDefault} self::A;
   }
   function local() → FutureOr<self::A> async {
     if(true) {
-      return let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
+      return let final Null #t24 = let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return null; // Error.
-             ^" in null as{TypeError,ForNonNullableByDefault} self::A;
+             ^" in null as{TypeError,ForNonNullableByDefault} self::A in #t24 is asy::Future<self::A> ?{FutureOr<self::A>} await #t24 : #t24;
     }
     else {
-      return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
+      return let final asy::Future<Null> #t26 = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<Null>.value(null); // Error.
-                 ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A;
+                 ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A in #t26 is asy::Future<self::A> ?{FutureOr<self::A>} await #t26 : #t26;
     }
   }
 }
diff --git a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.transformed.expect
index 4ba3fa1..242b2b4 100644
--- a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.transformed.expect
@@ -180,6 +180,7 @@
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 import "dart:async";
 
@@ -280,25 +281,45 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<self::A>:async_temporary_0;
+    FutureOr<self::A>:async_temporary_1;
+    FutureOr<self::A>:async_temporary_2;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L4:
         {
           if(true) {
-            :return_value = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
+            final self::B? #t6 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return x; // Error.
              ^" in x;
+            if(#t6 is asy::Future<self::A>) {
+              [yield] let dynamic #t8 = asy::_awaitHelper(#t6, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_0 = _in::unsafeCast<self::B?>(:result);
+            }
+            else {
+              :async_temporary_0 = #t6;
+            }
+            :return_value = :async_temporary_0;
             break #L4;
           }
           else {
-            :return_value = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
+            final asy::Future<self::B?> #t9 = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<B?>.value(x); // Error.
                  ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A;
+            if(#t9 is asy::Future<self::A>) {
+              [yield] let dynamic #t11 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_2 = _in::unsafeCast<self::B?>(:result);
+            }
+            else {
+              :async_temporary_2 = #t9;
+            }
+            :return_value = :async_temporary_2;
             break #L4;
           }
         }
@@ -314,20 +335,20 @@
     :is_sync = true;
     return :async_future;
   }
-  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   return x; // Error.
          ^" in x;
 }
 static method bar(core::List<self::B?> x, core::List<core::List<self::B?>> l, core::Map<core::List<self::B?>, core::List<self::B?>> m) → core::List<self::A> {
-  self::barContext(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  self::barContext(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   barContext(x); // Error.
              ^" in x);
-  core::List<self::A> y = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  core::List<self::A> y = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -353,19 +374,19 @@
   {
     core::Iterator<core::List<self::B?>> :sync-for-iterator = l.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-      final core::List<self::B?> #t11 = :sync-for-iterator.{core::Iterator::current};
+      final core::List<self::B?> #t15 = :sync-for-iterator.{core::Iterator::current};
       {
-        core::List<self::A> y = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+        core::List<self::A> y = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
 Try changing the type of the variable.
   for (List<A> y in l) {} // Error.
-               ^" in #t11;
+               ^" in #t15;
       }
     }
   }
-  return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -373,35 +394,35 @@
          ^" in x;
 }
 static method baz(self::C c) → void {
-  self::bazContext(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
+  self::bazContext(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
   bazContext(c);
-             ^" in let final self::C #t15 = c in #t15.==(null) ?{() → core::num?} null : #t15.{self::C::call});
+             ^" in let final self::C #t19 = c in #t19.==(null) ?{() → core::num?} null : #t19.{self::C::call});
 }
 static method boz(Null x) → self::A {
-  self::fooContext(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(x); // Error.
              ^" in x);
-  self::fooContext(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(null); // Error.
              ^" in null);
-  self::A a1 = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a1 = let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a1 = x; // Error.
          ^" in x;
-  self::A a2 = let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a2 = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a2 = null; // Error.
          ^" in null;
   if(true) {
-    return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return x; // Error.
            ^" in x;
   }
   else {
-    return let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return null; // Error.
            ^" in null;
@@ -414,23 +435,43 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<self::A>:async_temporary_0;
+    FutureOr<self::A>:async_temporary_1;
+    FutureOr<self::A>:async_temporary_2;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L5:
         {
           if(true) {
-            :return_value = let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
+            final Null #t26 = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return null; // Error.
              ^" in null;
+            if(#t26 is asy::Future<self::A>) {
+              [yield] let dynamic #t28 = asy::_awaitHelper(#t26, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_0 = _in::unsafeCast<Null>(:result);
+            }
+            else {
+              :async_temporary_0 = #t26;
+            }
+            :return_value = :async_temporary_0;
             break #L5;
           }
           else {
-            :return_value = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
+            final asy::Future<Null> #t29 = let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<Null>.value(null); // Error.
                  ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A;
+            if(#t29 is asy::Future<self::A>) {
+              [yield] let dynamic #t31 = asy::_awaitHelper(#t29, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_2 = _in::unsafeCast<Null>(:result);
+            }
+            else {
+              :async_temporary_2 = #t29;
+            }
+            :return_value = :async_temporary_2;
             break #L5;
           }
         }
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.expect
index f39bdfbd..bda20dd 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.expect
@@ -21,7 +21,7 @@
         else {
           throw core::Exception::•("Invalid response type");
         }
-    return result;
+    return let final self::TestMixin::T% #t1 = result in #t1 is asy::Future<self::TestMixin::T%> ?{FutureOr<self::TestMixin::T%>} await #t1 : #t1;
   }
 }
 class PagingResponse<T extends core::Object? = dynamic> extends core::Object {
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 76b3473..e23e8dd 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
@@ -14,6 +14,7 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<self::TestMixin::T%>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
@@ -35,7 +36,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final self::TestMixin::T% #t2 = result;
+          if(#t2 is asy::Future<self::TestMixin::T%>) {
+            [yield] let dynamic #t3 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<self::TestMixin::T%>(:result);
+          }
+          else {
+            :async_temporary_0 = #t2;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -82,11 +91,12 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L2:
         {
-          [yield] let dynamic #t2 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
+          [yield] let dynamic #t4 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
           final self::Response<core::String> response = _in::unsafeCast<self::Response<core::String>>(:result);
           core::String result;
           if(response is{ForNonNullableByDefault} self::Response<dynamic>) {
@@ -103,7 +113,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final core::String #t5 = result;
+          if(#t5 is asy::Future<core::String>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::String>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
           break #L2;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -141,11 +159,12 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L3:
         {
-          [yield] let dynamic #t3 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
+          [yield] let dynamic #t7 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
           final self::PagingResponse<core::String> response = _in::unsafeCast<self::PagingResponse<core::String>>(:result);
           core::String result;
           if(response is{ForNonNullableByDefault} self::Response<dynamic>) {
@@ -162,7 +181,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final core::String #t8 = result;
+          if(#t8 is asy::Future<core::String>) {
+            [yield] let dynamic #t9 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::String>(:result);
+          }
+          else {
+            :async_temporary_0 = #t8;
+          }
+          :return_value = :async_temporary_0;
           break #L3;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.expect
index f39bdfbd..bda20dd 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.expect
@@ -21,7 +21,7 @@
         else {
           throw core::Exception::•("Invalid response type");
         }
-    return result;
+    return let final self::TestMixin::T% #t1 = result in #t1 is asy::Future<self::TestMixin::T%> ?{FutureOr<self::TestMixin::T%>} await #t1 : #t1;
   }
 }
 class PagingResponse<T extends core::Object? = dynamic> extends core::Object {
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 76b3473..e23e8dd 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
@@ -14,6 +14,7 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<self::TestMixin::T%>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
@@ -35,7 +36,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final self::TestMixin::T% #t2 = result;
+          if(#t2 is asy::Future<self::TestMixin::T%>) {
+            [yield] let dynamic #t3 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<self::TestMixin::T%>(:result);
+          }
+          else {
+            :async_temporary_0 = #t2;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -82,11 +91,12 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L2:
         {
-          [yield] let dynamic #t2 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
+          [yield] let dynamic #t4 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
           final self::Response<core::String> response = _in::unsafeCast<self::Response<core::String>>(:result);
           core::String result;
           if(response is{ForNonNullableByDefault} self::Response<dynamic>) {
@@ -103,7 +113,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final core::String #t5 = result;
+          if(#t5 is asy::Future<core::String>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::String>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
           break #L2;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -141,11 +159,12 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L3:
         {
-          [yield] let dynamic #t3 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
+          [yield] let dynamic #t7 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
           final self::PagingResponse<core::String> response = _in::unsafeCast<self::PagingResponse<core::String>>(:result);
           core::String result;
           if(response is{ForNonNullableByDefault} self::Response<dynamic>) {
@@ -162,7 +181,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final core::String #t8 = result;
+          if(#t8 is asy::Future<core::String>) {
+            [yield] let dynamic #t9 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::String>(:result);
+          }
+          else {
+            :async_temporary_0 = #t8;
+          }
+          :return_value = :async_temporary_0;
           break #L3;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.expect
index 11217a1..ca6b488 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.expect
@@ -55,19 +55,19 @@
   (core::int) → core::String x6 = (core::int v) → Never {
     return self::throwing();
   };
-  (core::int) → asy::Future<core::String> y1 = (core::int v) → asy::Future<Never> async => throw v;
+  (core::int) → asy::Future<core::String> y1 = (core::int v) → asy::Future<Never> async => let final Never #t1 = throw v in #t1 is asy::Future<Never> ?{FutureOr<core::String>} await #t1 : #t1;
   (core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> async {
     throw v;
   };
   (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<Never> async {
-    return throw v;
+    return let final Never #t2 = throw v in #t2 is asy::Future<Never> ?{FutureOr<core::String>} await #t2 : #t2;
   };
-  (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> async => self::throwing();
+  (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> async => let final Never #t3 = self::throwing() in #t3 is asy::Future<Never> ?{FutureOr<core::String>} await #t3 : #t3;
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> async {
     self::throwing();
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<Never> async {
-    return self::throwing();
+    return let final Never #t4 = self::throwing() in #t4 is asy::Future<Never> ?{FutureOr<core::String>} await #t4 : #t4;
   };
 }
 static method errors() → void async {
@@ -77,7 +77,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x2 = (int v) /* error */ {
                             ^" in null;
   };
@@ -87,7 +87,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x3 = (int v) /* error */ {
                             ^" in null;
   };
@@ -97,7 +97,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x5 = (int v) /* error */ {
                             ^" in null;
   };
@@ -107,7 +107,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x6 = (int v) /* error */ {
                             ^" in null;
   };
@@ -117,17 +117,17 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y2 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<core::String> async {
     try {
-      return throw v;
+      return let final Never #t10 = throw v in #t10 is asy::Future<core::String> ?{FutureOr<core::String>} await #t10 : #t10;
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y3 = (int v) async /* error */ {
                                     ^" in null;
   };
@@ -137,17 +137,17 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y5 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<core::String> async {
     try {
-      return self::throwing();
+      return let final Never #t13 = self::throwing() in #t13 is asy::Future<core::String> ?{FutureOr<core::String>} await #t13 : #t13;
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y6 = (int v) async /* error */ {
                                     ^" in null;
   };
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 3e9bef1..515ceec 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
@@ -37,6 +37,7 @@
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 static method throwing() → Never
   return throw "";
@@ -63,11 +64,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
         {
-          :return_value = throw v;
+          final Never #t1 = throw v;
+          if(#t1 is asy::Future<Never>) {
+            [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t1;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -116,11 +127,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L3:
         {
-          :return_value = throw v;
+          final Never #t3 = throw v;
+          if(#t3 is asy::Future<Never>) {
+            [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t3;
+          }
+          :return_value = :async_temporary_0;
           break #L3;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -143,11 +164,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L4:
         {
-          :return_value = self::throwing();
+          final Never #t5 = self::throwing();
+          if(#t5 is asy::Future<Never>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
           break #L4;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -196,11 +227,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L6:
         {
-          :return_value = self::throwing();
+          final Never #t7 = self::throwing();
+          if(#t7 is asy::Future<Never>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t7;
+          }
+          :return_value = :async_temporary_0;
           break #L6;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -234,7 +275,7 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x2 = (int v) /* error */ {
                             ^" in null;
         };
@@ -244,7 +285,7 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x3 = (int v) /* error */ {
                             ^" in null;
         };
@@ -254,7 +295,7 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x5 = (int v) /* error */ {
                             ^" in null;
         };
@@ -264,7 +305,7 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x6 = (int v) /* error */ {
                             ^" in null;
         };
@@ -285,7 +326,7 @@
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y2 = (int v) async /* error */ {
                                     ^" in null;
                 break #L8;
@@ -310,17 +351,28 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          dynamic :saved_try_context_var1;
+          FutureOr<core::String>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L9:
               {
                 try {
-                  :return_value = throw v;
+                  final Never #t14 = throw v;
+                  if(#t14 is asy::Future<core::String>) {
+                    [yield] let dynamic #t15 = asy::_awaitHelper(#t14, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<Never>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t14;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L9;
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y3 = (int v) async /* error */ {
                                     ^" in null;
                 break #L9;
@@ -354,7 +406,7 @@
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y5 = (int v) async /* error */ {
                                     ^" in null;
                 break #L10;
@@ -379,17 +431,28 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          dynamic :saved_try_context_var1;
+          FutureOr<core::String>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L11:
               {
                 try {
-                  :return_value = self::throwing();
+                  final Never #t18 = self::throwing();
+                  if(#t18 is asy::Future<core::String>) {
+                    [yield] let dynamic #t19 = asy::_awaitHelper(#t18, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<Never>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t18;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L11;
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y6 = (int v) async /* error */ {
                                     ^" in null;
                 break #L11;
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect
index 3ced126..344471e 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect
@@ -56,19 +56,19 @@
   (core::int) → core::String x6 = (core::int v) → Never {
     return let final Never #t3 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   };
-  (core::int) → asy::Future<core::String> y1 = (core::int v) → asy::Future<Never> async => throw v;
+  (core::int) → asy::Future<core::String> y1 = (core::int v) → asy::Future<Never> async => let final Never #t4 = throw v in #t4 is asy::Future<Never> ?{FutureOr<core::String>} await #t4 : #t4;
   (core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> async {
     throw v;
   };
   (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<Never> async {
-    return throw v;
+    return let final Never #t5 = throw v in #t5 is asy::Future<Never> ?{FutureOr<core::String>} await #t5 : #t5;
   };
-  (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> async => let final Never #t4 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> async => let final Never #t6 = let final Never #t7 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t6 is asy::Future<Never> ?{FutureOr<core::String>} await #t6 : #t6;
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> async {
-    let final Never #t5 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    let final Never #t8 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<Never> async {
-    return let final Never #t6 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    return let final Never #t9 = let final Never #t10 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t9 is asy::Future<Never> ?{FutureOr<core::String>} await #t9 : #t9;
   };
 }
 static method errors() → void async {
@@ -78,7 +78,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x2 = (int v) /* error */ {
                             ^" in null;
   };
@@ -88,27 +88,27 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x3 = (int v) /* error */ {
                             ^" in null;
   };
   (core::int) → core::String x5 = (core::int v) → core::String {
     try {
-      let final Never #t9 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+      let final Never #t13 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x5 = (int v) /* error */ {
                             ^" in null;
   };
   (core::int) → core::String x6 = (core::int v) → core::String {
     try {
-      return let final Never #t11 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+      return let final Never #t15 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x6 = (int v) /* error */ {
                             ^" in null;
   };
@@ -118,37 +118,37 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y2 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<core::String> async {
     try {
-      return throw v;
+      return let final Never #t18 = throw v in #t18 is asy::Future<core::String> ?{FutureOr<core::String>} await #t18 : #t18;
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y3 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<core::String> async {
     try {
-      let final Never #t15 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+      let final Never #t20 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y5 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<core::String> async {
     try {
-      return let final Never #t17 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+      return let final Never #t22 = let final Never #t23 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t22 is asy::Future<core::String> ?{FutureOr<core::String>} await #t22 : #t22;
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y6 = (int v) async /* error */ {
                                     ^" in null;
   };
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 e3ff8f7..5ebb180 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
@@ -64,11 +64,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
         {
-          :return_value = throw v;
+          final Never #t4 = throw v;
+          if(#t4 is asy::Future<Never>) {
+            [yield] let dynamic #t5 = asy::_awaitHelper(#t4, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t4;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -117,11 +127,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L3:
         {
-          :return_value = throw v;
+          final Never #t6 = throw v;
+          if(#t6 is asy::Future<Never>) {
+            [yield] let dynamic #t7 = asy::_awaitHelper(#t6, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t6;
+          }
+          :return_value = :async_temporary_0;
           break #L3;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -144,11 +164,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L4:
         {
-          :return_value = let final Never #t4 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+          final Never #t8 = let final Never #t9 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+          if(#t8 is asy::Future<Never>) {
+            [yield] let dynamic #t10 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t8;
+          }
+          :return_value = :async_temporary_0;
           break #L4;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -175,7 +205,7 @@
       try {
         #L5:
         {
-          let final Never #t5 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+          let final Never #t11 = 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);
         return;
@@ -197,11 +227,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L6:
         {
-          :return_value = let final Never #t6 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+          final Never #t12 = let final Never #t13 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+          if(#t12 is asy::Future<Never>) {
+            [yield] let dynamic #t14 = asy::_awaitHelper(#t12, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t12;
+          }
+          :return_value = :async_temporary_0;
           break #L6;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -235,7 +275,7 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x2 = (int v) /* error */ {
                             ^" in null;
         };
@@ -245,27 +285,27 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x3 = (int v) /* error */ {
                             ^" in null;
         };
         (core::int) → core::String x5 = (core::int v) → core::String {
           try {
-            let final Never #t9 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+            let final Never #t17 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x5 = (int v) /* error */ {
                             ^" in null;
         };
         (core::int) → core::String x6 = (core::int v) → core::String {
           try {
-            return let final Never #t11 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+            return let final Never #t19 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x6 = (int v) /* error */ {
                             ^" in null;
         };
@@ -286,7 +326,7 @@
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y2 = (int v) async /* error */ {
                                     ^" in null;
                 break #L8;
@@ -311,17 +351,28 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          dynamic :saved_try_context_var1;
+          FutureOr<core::String>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L9:
               {
                 try {
-                  :return_value = throw v;
+                  final Never #t22 = throw v;
+                  if(#t22 is asy::Future<core::String>) {
+                    [yield] let dynamic #t23 = asy::_awaitHelper(#t22, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<Never>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t22;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L9;
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y3 = (int v) async /* error */ {
                                     ^" in null;
                 break #L9;
@@ -351,11 +402,11 @@
               #L10:
               {
                 try {
-                  let final Never #t15 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+                  let final Never #t25 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y5 = (int v) async /* error */ {
                                     ^" in null;
                 break #L10;
@@ -380,17 +431,28 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          dynamic :saved_try_context_var1;
+          FutureOr<core::String>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L11:
               {
                 try {
-                  :return_value = let final Never #t17 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+                  final Never #t27 = let final Never #t28 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+                  if(#t27 is asy::Future<core::String>) {
+                    [yield] let dynamic #t29 = asy::_awaitHelper(#t27, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<Never>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t27;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L11;
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y6 = (int v) async /* error */ {
                                     ^" in null;
                 break #L11;
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.expect
index fbcd99e..d7881ae 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.expect
@@ -34,61 +34,61 @@
 static method getNull() → dynamic
   return null;
 static method getFutureNull() → asy::Future<dynamic> async {
-  return null;
+  return let final Null #t1 = null in #t1 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t1 : #t1;
 }
 static method getFutureBool() → asy::Future<core::bool> async {
-  return true;
+  return let final core::bool #t2 = true in #t2 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t2 : #t2;
 }
 static method test1() → asy::Future<core::bool> async 
-  return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+  return let final dynamic #t3 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t3 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t3 : #t3;
 static method test2() → asy::Future<core::bool>
   return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
 static method test3() → core::bool
   return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
 static method test4() → asy::Future<core::bool> async 
-  return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+  return let final dynamic #t4 = await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t4 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t4 : #t4;
 static method test5() → asy::Future<core::bool>
-  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
 Future<bool> test5() => getFutureNull(); // error
                         ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
 static method test6() → asy::Future<core::bool>
   return self::getFutureBool();
 static method test7() → asy::Future<core::bool> async 
-  return self::getFutureBool();
+  return let final asy::Future<core::bool> #t6 = self::getFutureBool() in #t6 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t6 : #t6;
 static method test() → dynamic async {
   function test1() → asy::Future<core::bool> async 
-    return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+    return let final dynamic #t7 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t7 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t7 : #t7;
   function test2() → asy::Future<core::bool>
     return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
   function test3() → core::bool
     return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
   function test4() → asy::Future<core::bool> async 
-    return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+    return let final dynamic #t8 = await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t8 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t8 : #t8;
   function test5() → asy::Future<core::bool>
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> test5() => getFutureNull(); // error
                           ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   function test6() → asy::Future<core::bool>
     return self::getFutureBool();
   function test7() → asy::Future<core::bool> async 
-    return self::getFutureBool();
-  asy::Future<core::bool> var1 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+    return let final asy::Future<core::bool> #t10 = self::getFutureBool() in #t10 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t10 : #t10;
+  asy::Future<core::bool> var1 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var1 = (() async => await getNull())(); // error
-                                                   ^" in (() → asy::Future<dynamic> async => await self::getNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
+                                                   ^" in (() → asy::Future<dynamic> async => let final dynamic #t12 = await self::getNull() in #t12 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t12 : #t12).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
   core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
-  asy::Future<core::bool> var4 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+  asy::Future<core::bool> var4 = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var4 = (() async => await getFutureNull())(); // error
-                                                         ^" in (() → asy::Future<dynamic> async => await self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
-  asy::Future<core::bool> var5 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+                                                         ^" in (() → asy::Future<dynamic> async => let final dynamic #t14 = await self::getFutureNull() in #t14 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t14 : #t14).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
+  asy::Future<core::bool> var5 = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var5 = (() => getFutureNull())(); // error
                                              ^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   asy::Future<core::bool> var6 = (() → asy::Future<core::bool> => self::getFutureBool()).call();
-  asy::Future<core::bool> var7 = (() → asy::Future<core::bool> async => self::getFutureBool()).call();
+  asy::Future<core::bool> var7 = (() → asy::Future<core::bool> async => let final asy::Future<core::bool> #t16 = self::getFutureBool() in #t16 is asy::Future<core::bool> ?{FutureOr<dynamic>} await #t16 : #t16).call();
 }
 static method main() → dynamic {}
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 b4ab7d2..2b35c4f 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
@@ -30,6 +30,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method getNull() → dynamic
   return null;
@@ -41,11 +42,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<dynamic>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
       {
-        :return_value = null;
+        final Null #t1 = null;
+        if(#t1 is asy::Future<dynamic>) {
+          [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<Null>(:result);
+        }
+        else {
+          :async_temporary_0 = #t1;
+        }
+        :return_value = :async_temporary_0;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -68,11 +79,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L2:
       {
-        :return_value = true;
+        final core::bool #t3 = true;
+        if(#t3 is asy::Future<core::bool>) {
+          [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t3;
+        }
+        :return_value = :async_temporary_0;
         break #L2;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -96,12 +117,21 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L3:
       {
-        [yield] let dynamic #t1 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        [yield] let dynamic #t5 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+        final FutureOr<core::bool>#t6 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        if(#t6 is asy::Future<core::bool>) {
+          [yield] let dynamic #t7 = asy::_awaitHelper(#t6, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t6;
+        }
+        :return_value = :async_temporary_0;
         break #L3;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -129,12 +159,21 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L4:
       {
-        [yield] let dynamic #t2 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        [yield] let dynamic #t8 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+        final FutureOr<core::bool>#t9 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        if(#t9 is asy::Future<core::bool>) {
+          [yield] let dynamic #t10 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t9;
+        }
+        :return_value = :async_temporary_0;
         break #L4;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -150,7 +189,7 @@
   return :async_future;
 }
 static method test5() → asy::Future<core::bool>
-  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+  return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
 Future<bool> test5() => getFutureNull(); // error
                         ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -164,11 +203,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L5:
       {
-        :return_value = self::getFutureBool();
+        final asy::Future<core::bool> #t12 = self::getFutureBool();
+        if(#t12 is asy::Future<core::bool>) {
+          [yield] let dynamic #t13 = asy::_awaitHelper(#t12, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t12;
+        }
+        :return_value = :async_temporary_0;
         break #L5;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -204,12 +253,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L7:
               {
-                [yield] let dynamic #t4 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                [yield] let dynamic #t14 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final FutureOr<core::bool>#t15 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                if(#t15 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t16 = asy::_awaitHelper(#t15, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t15;
+                }
+                :return_value = :async_temporary_0;
                 break #L7;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -237,12 +295,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L8:
               {
-                [yield] let dynamic #t5 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                [yield] let dynamic #t17 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final FutureOr<core::bool>#t18 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                if(#t18 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t19 = asy::_awaitHelper(#t18, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t18;
+                }
+                :return_value = :async_temporary_0;
                 break #L8;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -258,7 +325,7 @@
           return :async_future;
         }
         function test5() → asy::Future<core::bool>
-          return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+          return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> test5() => getFutureNull(); // error
                           ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -272,11 +339,21 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L9:
               {
-                :return_value = self::getFutureBool();
+                final asy::Future<core::bool> #t21 = self::getFutureBool();
+                if(#t21 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t22 = asy::_awaitHelper(#t21, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t21;
+                }
+                :return_value = :async_temporary_0;
                 break #L9;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -291,7 +368,7 @@
           :is_sync = true;
           return :async_future;
         }
-        asy::Future<core::bool> var1 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var1 = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var1 = (() async => await getNull())(); // error
                                                    ^" in (() → asy::Future<dynamic> /* originally async */ {
@@ -303,12 +380,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L10:
               {
-                [yield] let dynamic #t8 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result;
+                [yield] let dynamic #t24 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final dynamic #t25 = :result;
+                if(#t25 is asy::Future<dynamic>) {
+                  [yield] let dynamic #t26 = asy::_awaitHelper(#t25, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = :result;
+                }
+                else {
+                  :async_temporary_0 = #t25;
+                }
+                :return_value = :async_temporary_0;
                 break #L10;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -325,7 +411,7 @@
         }).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
         asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
         core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
-        asy::Future<core::bool> var4 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var4 = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var4 = (() async => await getFutureNull())(); // error
                                                          ^" in (() → asy::Future<dynamic> /* originally async */ {
@@ -337,12 +423,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L11:
               {
-                [yield] let dynamic #t10 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result;
+                [yield] let dynamic #t28 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final dynamic #t29 = :result;
+                if(#t29 is asy::Future<dynamic>) {
+                  [yield] let dynamic #t30 = asy::_awaitHelper(#t29, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = :result;
+                }
+                else {
+                  :async_temporary_0 = #t29;
+                }
+                :return_value = :async_temporary_0;
                 break #L11;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -357,7 +452,7 @@
           :is_sync = true;
           return :async_future;
         }).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
-        asy::Future<core::bool> var5 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var5 = let final<BottomType> #t31 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var5 = (() => getFutureNull())(); // error
                                              ^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -370,11 +465,21 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L12:
               {
-                :return_value = self::getFutureBool();
+                final asy::Future<core::bool> #t32 = self::getFutureBool();
+                if(#t32 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t33 = asy::_awaitHelper(#t32, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t32;
+                }
+                :return_value = :async_temporary_0;
                 break #L12;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.expect
index fbcd99e..d7881ae 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.expect
@@ -34,61 +34,61 @@
 static method getNull() → dynamic
   return null;
 static method getFutureNull() → asy::Future<dynamic> async {
-  return null;
+  return let final Null #t1 = null in #t1 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t1 : #t1;
 }
 static method getFutureBool() → asy::Future<core::bool> async {
-  return true;
+  return let final core::bool #t2 = true in #t2 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t2 : #t2;
 }
 static method test1() → asy::Future<core::bool> async 
-  return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+  return let final dynamic #t3 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t3 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t3 : #t3;
 static method test2() → asy::Future<core::bool>
   return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
 static method test3() → core::bool
   return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
 static method test4() → asy::Future<core::bool> async 
-  return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+  return let final dynamic #t4 = await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t4 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t4 : #t4;
 static method test5() → asy::Future<core::bool>
-  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
 Future<bool> test5() => getFutureNull(); // error
                         ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
 static method test6() → asy::Future<core::bool>
   return self::getFutureBool();
 static method test7() → asy::Future<core::bool> async 
-  return self::getFutureBool();
+  return let final asy::Future<core::bool> #t6 = self::getFutureBool() in #t6 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t6 : #t6;
 static method test() → dynamic async {
   function test1() → asy::Future<core::bool> async 
-    return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+    return let final dynamic #t7 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t7 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t7 : #t7;
   function test2() → asy::Future<core::bool>
     return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
   function test3() → core::bool
     return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
   function test4() → asy::Future<core::bool> async 
-    return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+    return let final dynamic #t8 = await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t8 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t8 : #t8;
   function test5() → asy::Future<core::bool>
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> test5() => getFutureNull(); // error
                           ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   function test6() → asy::Future<core::bool>
     return self::getFutureBool();
   function test7() → asy::Future<core::bool> async 
-    return self::getFutureBool();
-  asy::Future<core::bool> var1 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+    return let final asy::Future<core::bool> #t10 = self::getFutureBool() in #t10 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t10 : #t10;
+  asy::Future<core::bool> var1 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var1 = (() async => await getNull())(); // error
-                                                   ^" in (() → asy::Future<dynamic> async => await self::getNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
+                                                   ^" in (() → asy::Future<dynamic> async => let final dynamic #t12 = await self::getNull() in #t12 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t12 : #t12).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
   core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
-  asy::Future<core::bool> var4 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+  asy::Future<core::bool> var4 = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var4 = (() async => await getFutureNull())(); // error
-                                                         ^" in (() → asy::Future<dynamic> async => await self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
-  asy::Future<core::bool> var5 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+                                                         ^" in (() → asy::Future<dynamic> async => let final dynamic #t14 = await self::getFutureNull() in #t14 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t14 : #t14).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
+  asy::Future<core::bool> var5 = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var5 = (() => getFutureNull())(); // error
                                              ^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   asy::Future<core::bool> var6 = (() → asy::Future<core::bool> => self::getFutureBool()).call();
-  asy::Future<core::bool> var7 = (() → asy::Future<core::bool> async => self::getFutureBool()).call();
+  asy::Future<core::bool> var7 = (() → asy::Future<core::bool> async => let final asy::Future<core::bool> #t16 = self::getFutureBool() in #t16 is asy::Future<core::bool> ?{FutureOr<dynamic>} await #t16 : #t16).call();
 }
 static method main() → dynamic {}
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 b4ab7d2..2b35c4f 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
@@ -30,6 +30,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method getNull() → dynamic
   return null;
@@ -41,11 +42,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<dynamic>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
       {
-        :return_value = null;
+        final Null #t1 = null;
+        if(#t1 is asy::Future<dynamic>) {
+          [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<Null>(:result);
+        }
+        else {
+          :async_temporary_0 = #t1;
+        }
+        :return_value = :async_temporary_0;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -68,11 +79,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L2:
       {
-        :return_value = true;
+        final core::bool #t3 = true;
+        if(#t3 is asy::Future<core::bool>) {
+          [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t3;
+        }
+        :return_value = :async_temporary_0;
         break #L2;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -96,12 +117,21 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L3:
       {
-        [yield] let dynamic #t1 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        [yield] let dynamic #t5 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+        final FutureOr<core::bool>#t6 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        if(#t6 is asy::Future<core::bool>) {
+          [yield] let dynamic #t7 = asy::_awaitHelper(#t6, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t6;
+        }
+        :return_value = :async_temporary_0;
         break #L3;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -129,12 +159,21 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L4:
       {
-        [yield] let dynamic #t2 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        [yield] let dynamic #t8 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+        final FutureOr<core::bool>#t9 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        if(#t9 is asy::Future<core::bool>) {
+          [yield] let dynamic #t10 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t9;
+        }
+        :return_value = :async_temporary_0;
         break #L4;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -150,7 +189,7 @@
   return :async_future;
 }
 static method test5() → asy::Future<core::bool>
-  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+  return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
 Future<bool> test5() => getFutureNull(); // error
                         ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -164,11 +203,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L5:
       {
-        :return_value = self::getFutureBool();
+        final asy::Future<core::bool> #t12 = self::getFutureBool();
+        if(#t12 is asy::Future<core::bool>) {
+          [yield] let dynamic #t13 = asy::_awaitHelper(#t12, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t12;
+        }
+        :return_value = :async_temporary_0;
         break #L5;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -204,12 +253,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L7:
               {
-                [yield] let dynamic #t4 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                [yield] let dynamic #t14 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final FutureOr<core::bool>#t15 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                if(#t15 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t16 = asy::_awaitHelper(#t15, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t15;
+                }
+                :return_value = :async_temporary_0;
                 break #L7;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -237,12 +295,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L8:
               {
-                [yield] let dynamic #t5 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                [yield] let dynamic #t17 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final FutureOr<core::bool>#t18 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                if(#t18 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t19 = asy::_awaitHelper(#t18, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t18;
+                }
+                :return_value = :async_temporary_0;
                 break #L8;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -258,7 +325,7 @@
           return :async_future;
         }
         function test5() → asy::Future<core::bool>
-          return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+          return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> test5() => getFutureNull(); // error
                           ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -272,11 +339,21 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L9:
               {
-                :return_value = self::getFutureBool();
+                final asy::Future<core::bool> #t21 = self::getFutureBool();
+                if(#t21 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t22 = asy::_awaitHelper(#t21, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t21;
+                }
+                :return_value = :async_temporary_0;
                 break #L9;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -291,7 +368,7 @@
           :is_sync = true;
           return :async_future;
         }
-        asy::Future<core::bool> var1 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var1 = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var1 = (() async => await getNull())(); // error
                                                    ^" in (() → asy::Future<dynamic> /* originally async */ {
@@ -303,12 +380,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L10:
               {
-                [yield] let dynamic #t8 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result;
+                [yield] let dynamic #t24 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final dynamic #t25 = :result;
+                if(#t25 is asy::Future<dynamic>) {
+                  [yield] let dynamic #t26 = asy::_awaitHelper(#t25, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = :result;
+                }
+                else {
+                  :async_temporary_0 = #t25;
+                }
+                :return_value = :async_temporary_0;
                 break #L10;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -325,7 +411,7 @@
         }).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
         asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
         core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
-        asy::Future<core::bool> var4 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var4 = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var4 = (() async => await getFutureNull())(); // error
                                                          ^" in (() → asy::Future<dynamic> /* originally async */ {
@@ -337,12 +423,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L11:
               {
-                [yield] let dynamic #t10 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result;
+                [yield] let dynamic #t28 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final dynamic #t29 = :result;
+                if(#t29 is asy::Future<dynamic>) {
+                  [yield] let dynamic #t30 = asy::_awaitHelper(#t29, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = :result;
+                }
+                else {
+                  :async_temporary_0 = #t29;
+                }
+                :return_value = :async_temporary_0;
                 break #L11;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -357,7 +452,7 @@
           :is_sync = true;
           return :async_future;
         }).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
-        asy::Future<core::bool> var5 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var5 = let final<BottomType> #t31 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var5 = (() => getFutureNull())(); // error
                                              ^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -370,11 +465,21 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L12:
               {
-                :return_value = self::getFutureBool();
+                final asy::Future<core::bool> #t32 = self::getFutureBool();
+                if(#t32 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t33 = asy::_awaitHelper(#t32, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t32;
+                }
+                :return_value = :async_temporary_0;
                 break #L12;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.expect
index f0b15fb..58eebef 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.expect
@@ -34,23 +34,23 @@
     return s.{core::num::+}(1);
   };
   <S extends FutureOr<core::num> = FutureOr<core::num>>(S, FutureOr<core::num>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num> = FutureOr<core::num>>(S s, FutureOr<core::num>t) → asy::Future<core::num> async {
-    return (await t).{core::num::+}(1);
+    return let final core::num #t1 = (await t).{core::num::+}(1) in #t1 is asy::Future<core::num> ?{FutureOr<dynamic>} await #t1 : #t1;
   };
 }
 static method test2(self::C<core::num?> c) → dynamic {
   <S extends core::num? = core::num?>(S%) → core::num f1 = c.{self::C::field1} = <S extends core::num? = core::num?>(S% s) → core::num {
-    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
     return s + 1; // error
              ^" in s.{core::num::+}(1);
   };
   <S extends FutureOr<core::num?> = FutureOr<core::num?>>(S%, FutureOr<core::num?>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num?> = FutureOr<core::num?>>(S% s, FutureOr<core::num?>t) → asy::Future<core::num> async {
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
+    return let final core::num #t3 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
     return (await t) + 1; // error
-                     ^" in (await t).{core::num::+}(1);
+                     ^" in (await t).{core::num::+}(1) in #t3 is asy::Future<core::num> ?{FutureOr<dynamic>} await #t3 : #t3;
   };
 }
 static method test3<S extends core::num? = core::num?>(self::test3::S% s) → dynamic
-  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
 test3<S extends num?>(S s) => s + 1; // error
                                 ^" in s.{core::num::+}(1);
 static method main() → dynamic {}
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 b287a57..b08be8f 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
@@ -43,12 +43,21 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<dynamic>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
         {
           [yield] let dynamic #t1 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
-          :return_value = _in::unsafeCast<core::num>(:result).{core::num::+}(1);
+          final core::num #t2 = _in::unsafeCast<core::num>(:result).{core::num::+}(1);
+          if(#t2 is asy::Future<core::num>) {
+            [yield] let dynamic #t3 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::num>(:result);
+          }
+          else {
+            :async_temporary_0 = #t2;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -66,7 +75,7 @@
 }
 static method test2(self::C<core::num?> c) → dynamic {
   <S extends core::num? = core::num?>(S%) → core::num f1 = c.{self::C::field1} = <S extends core::num? = core::num?>(S% s) → core::num {
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+    return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
     return s + 1; // error
              ^" in s.{core::num::+}(1);
   };
@@ -79,15 +88,24 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<dynamic>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L2:
         {
-          final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
+          final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
     return (await t) + 1; // error
                      ^";
-          [yield] let dynamic #t4 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
-          :return_value = _in::unsafeCast<core::num?>(:result).{core::num::+}(1);
+          [yield] let dynamic #t6 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
+          final core::num #t7 = _in::unsafeCast<core::num?>(:result).{core::num::+}(1);
+          if(#t7 is asy::Future<core::num>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::num>(:result);
+          }
+          else {
+            :async_temporary_0 = #t7;
+          }
+          :return_value = :async_temporary_0;
           break #L2;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -104,7 +122,7 @@
   };
 }
 static method test3<S extends core::num? = core::num?>(self::test3::S% s) → dynamic
-  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+  return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
 test3<S extends num?>(S s) => s + 1; // error
                                 ^" in s.{core::num::+}(1);
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.expect
index f0b15fb..58eebef 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.expect
@@ -34,23 +34,23 @@
     return s.{core::num::+}(1);
   };
   <S extends FutureOr<core::num> = FutureOr<core::num>>(S, FutureOr<core::num>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num> = FutureOr<core::num>>(S s, FutureOr<core::num>t) → asy::Future<core::num> async {
-    return (await t).{core::num::+}(1);
+    return let final core::num #t1 = (await t).{core::num::+}(1) in #t1 is asy::Future<core::num> ?{FutureOr<dynamic>} await #t1 : #t1;
   };
 }
 static method test2(self::C<core::num?> c) → dynamic {
   <S extends core::num? = core::num?>(S%) → core::num f1 = c.{self::C::field1} = <S extends core::num? = core::num?>(S% s) → core::num {
-    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
     return s + 1; // error
              ^" in s.{core::num::+}(1);
   };
   <S extends FutureOr<core::num?> = FutureOr<core::num?>>(S%, FutureOr<core::num?>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num?> = FutureOr<core::num?>>(S% s, FutureOr<core::num?>t) → asy::Future<core::num> async {
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
+    return let final core::num #t3 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
     return (await t) + 1; // error
-                     ^" in (await t).{core::num::+}(1);
+                     ^" in (await t).{core::num::+}(1) in #t3 is asy::Future<core::num> ?{FutureOr<dynamic>} await #t3 : #t3;
   };
 }
 static method test3<S extends core::num? = core::num?>(self::test3::S% s) → dynamic
-  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
 test3<S extends num?>(S s) => s + 1; // error
                                 ^" in s.{core::num::+}(1);
 static method main() → dynamic {}
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 b287a57..b08be8f 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
@@ -43,12 +43,21 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<dynamic>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
         {
           [yield] let dynamic #t1 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
-          :return_value = _in::unsafeCast<core::num>(:result).{core::num::+}(1);
+          final core::num #t2 = _in::unsafeCast<core::num>(:result).{core::num::+}(1);
+          if(#t2 is asy::Future<core::num>) {
+            [yield] let dynamic #t3 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::num>(:result);
+          }
+          else {
+            :async_temporary_0 = #t2;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -66,7 +75,7 @@
 }
 static method test2(self::C<core::num?> c) → dynamic {
   <S extends core::num? = core::num?>(S%) → core::num f1 = c.{self::C::field1} = <S extends core::num? = core::num?>(S% s) → core::num {
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+    return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
     return s + 1; // error
              ^" in s.{core::num::+}(1);
   };
@@ -79,15 +88,24 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<dynamic>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L2:
         {
-          final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
+          final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
     return (await t) + 1; // error
                      ^";
-          [yield] let dynamic #t4 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
-          :return_value = _in::unsafeCast<core::num?>(:result).{core::num::+}(1);
+          [yield] let dynamic #t6 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
+          final core::num #t7 = _in::unsafeCast<core::num?>(:result).{core::num::+}(1);
+          if(#t7 is asy::Future<core::num>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::num>(:result);
+          }
+          else {
+            :async_temporary_0 = #t7;
+          }
+          :return_value = :async_temporary_0;
           break #L2;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -104,7 +122,7 @@
   };
 }
 static method test3<S extends core::num? = core::num?>(self::test3::S% s) → dynamic
-  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+  return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
 test3<S extends num?>(S s) => s + 1; // error
                                 ^" in s.{core::num::+}(1);
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42540.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42540.dart.strong.expect
index aaf931d..c1d787d 100644
--- a/pkg/front_end/testcases/nnbd/issue42540.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42540.dart.strong.expect
@@ -7,6 +7,6 @@
   return null;
 static method fn() → asy::Future<core::Object> async {
   core::Object o = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::Object;
-  return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object>;
+  return let final dynamic #t1 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object> in #t1 is asy::Future<core::Object> ?{FutureOr<core::Object>} await #t1 : #t1;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42540.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42540.dart.strong.transformed.expect
index 4e127a6..b5edde0 100644
--- a/pkg/front_end/testcases/nnbd/issue42540.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42540.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method getNull() → dynamic
   return null;
@@ -14,6 +15,7 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::Object>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
@@ -21,7 +23,15 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
         core::Object o = let dynamic #t2 = :result in #t2.==(null) ?{core::Object} #t2 as{TypeError,ForDynamic,ForNonNullableByDefault} core::Object : #t2{core::Object};
         [yield] let dynamic #t3 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = let dynamic #t4 = :result in #t4.==(null) ?{FutureOr<core::Object>} #t4 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object> : #t4{FutureOr<core::Object>};
+        final FutureOr<core::Object>#t4 = let dynamic #t5 = :result in #t5.==(null) ?{FutureOr<core::Object>} #t5 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object> : #t5{FutureOr<core::Object>};
+        if(#t4 is asy::Future<core::Object>) {
+          [yield] let dynamic #t6 = asy::_awaitHelper(#t4, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::Object>(:result);
+        }
+        else {
+          :async_temporary_0 = #t4;
+        }
+        :return_value = :async_temporary_0;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/issue42540.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42540.dart.weak.expect
index aaf931d..c1d787d 100644
--- a/pkg/front_end/testcases/nnbd/issue42540.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42540.dart.weak.expect
@@ -7,6 +7,6 @@
   return null;
 static method fn() → asy::Future<core::Object> async {
   core::Object o = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::Object;
-  return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object>;
+  return let final dynamic #t1 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object> in #t1 is asy::Future<core::Object> ?{FutureOr<core::Object>} await #t1 : #t1;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42540.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42540.dart.weak.transformed.expect
index e61b30d..36497a3 100644
--- a/pkg/front_end/testcases/nnbd/issue42540.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42540.dart.weak.transformed.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method getNull() → dynamic
   return null;
@@ -14,6 +15,7 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::Object>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
@@ -21,7 +23,15 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
         core::Object o = :result;
         [yield] let dynamic #t2 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = :result;
+        final FutureOr<core::Object>#t3 = :result;
+        if(#t3 is asy::Future<core::Object>) {
+          [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::Object>(:result);
+        }
+        else {
+          :async_temporary_0 = #t3;
+        }
+        :return_value = :async_temporary_0;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.expect
index e5372a7..e446f7c 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.expect
@@ -42,11 +42,11 @@
  - 'Future' is from 'dart:async'.
  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
-                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> async => let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> async => let final self::Divergent<core::int> #t2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
  - 'Future' is from 'dart:async'.
   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
-                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>>).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
+                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>> in #t2 is asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> ?{FutureOr<dynamic>} await #t2 : #t2).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
new file mode 100644
index 0000000..5ae2bec
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
@@ -0,0 +1,126 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+//  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+//  - 'Future' is from 'dart:async'.
+//   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/issue42546.dart:14:75: Error: A value of type 'Future<Divergent<Divergent<Divergent<int>>>>' can't be assigned to a variable of type 'Future<Divergent<Divergent<int>>>'.
+//  - 'Future' is from 'dart:async'.
+//  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+//   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+//                                                                           ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class Divergent<T extends core::Object? = dynamic> extends core::Object implements asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>> {
+  synthetic constructor •() → self::Divergent<self::Divergent::T%>
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return super.{core::Object::noSuchMethod}(invocation);
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) →? core::bool test = #C1}) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ whenComplete(() → FutureOr<void>action) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl () →? FutureOr<self::Divergent<self::Divergent<self::Divergent::T%>>>onTimeout = #C1}) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C9: onTimeout}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ then<R extends core::Object? = dynamic>((self::Divergent<self::Divergent<self::Divergent::T%>>) → FutureOr<self::Divergent::then::R%>onValue, {core::Function? onError = #C1}) → asy::Future<self::Divergent::then::R%>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 0, core::List::unmodifiable<core::Type*>(core::_GrowableList::_literal1<core::Type*>(self::Divergent::then::R%)), core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onValue)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C11: onError}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent::then::R%>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Stream<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+}
+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) → 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 {
+      #L1:
+      {
+        asy::Future<self::Divergent<self::Divergent<core::int>>> x = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:75: Error: A value of type 'Future<Divergent<Divergent<Divergent<int>>>>' can't be assigned to a variable of type 'Future<Divergent<Divergent<int>>>'.
+ - 'Future' is from 'dart:async'.
+ - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+  Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> /* originally async */ {
+          final asy::_Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> :async_future = new asy::_Future::•<self::Divergent<self::Divergent<self::Divergent<core::int>>>>();
+          core::bool* :is_sync = false;
+          FutureOr<self::Divergent<self::Divergent<self::Divergent<core::int>>>>? :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;
+          FutureOr<dynamic>:async_temporary_0;
+          function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+            try {
+              #L2:
+              {
+                final self::Divergent<core::int> #t2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+ - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+ - 'Future' is from 'dart:async'.
+  Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>>;
+                if(#t2 is asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>>) {
+                  [yield] let dynamic #t4 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<self::Divergent<self::Divergent<core::int>>>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t2;
+                }
+                :return_value = :async_temporary_0;
+                break #L2;
+              }
+              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.call();
+          :is_sync = true;
+          return :async_future;
+        }).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+  #C2 = #catchError
+  #C3 = <core::Type*>[]
+  #C4 = #test
+  #C5 = #whenComplete
+  #C6 = <dynamic>[]
+  #C7 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C6}
+  #C8 = #timeout
+  #C9 = #onTimeout
+  #C10 = #then
+  #C11 = #onError
+  #C12 = #asStream
+}
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.expect
index e5372a7..e446f7c 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.expect
@@ -42,11 +42,11 @@
  - 'Future' is from 'dart:async'.
  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
-                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> async => let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> async => let final self::Divergent<core::int> #t2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
  - 'Future' is from 'dart:async'.
   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
-                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>>).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
+                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>> in #t2 is asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> ?{FutureOr<dynamic>} await #t2 : #t2).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
new file mode 100644
index 0000000..5ae2bec
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
@@ -0,0 +1,126 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+//  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+//  - 'Future' is from 'dart:async'.
+//   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/issue42546.dart:14:75: Error: A value of type 'Future<Divergent<Divergent<Divergent<int>>>>' can't be assigned to a variable of type 'Future<Divergent<Divergent<int>>>'.
+//  - 'Future' is from 'dart:async'.
+//  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+//   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+//                                                                           ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class Divergent<T extends core::Object? = dynamic> extends core::Object implements asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>> {
+  synthetic constructor •() → self::Divergent<self::Divergent::T%>
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return super.{core::Object::noSuchMethod}(invocation);
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) →? core::bool test = #C1}) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ whenComplete(() → FutureOr<void>action) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl () →? FutureOr<self::Divergent<self::Divergent<self::Divergent::T%>>>onTimeout = #C1}) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C9: onTimeout}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ then<R extends core::Object? = dynamic>((self::Divergent<self::Divergent<self::Divergent::T%>>) → FutureOr<self::Divergent::then::R%>onValue, {core::Function? onError = #C1}) → asy::Future<self::Divergent::then::R%>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 0, core::List::unmodifiable<core::Type*>(core::_GrowableList::_literal1<core::Type*>(self::Divergent::then::R%)), core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onValue)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C11: onError}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent::then::R%>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Stream<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+}
+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) → 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 {
+      #L1:
+      {
+        asy::Future<self::Divergent<self::Divergent<core::int>>> x = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:75: Error: A value of type 'Future<Divergent<Divergent<Divergent<int>>>>' can't be assigned to a variable of type 'Future<Divergent<Divergent<int>>>'.
+ - 'Future' is from 'dart:async'.
+ - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+  Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> /* originally async */ {
+          final asy::_Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> :async_future = new asy::_Future::•<self::Divergent<self::Divergent<self::Divergent<core::int>>>>();
+          core::bool* :is_sync = false;
+          FutureOr<self::Divergent<self::Divergent<self::Divergent<core::int>>>>? :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;
+          FutureOr<dynamic>:async_temporary_0;
+          function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+            try {
+              #L2:
+              {
+                final self::Divergent<core::int> #t2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+ - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+ - 'Future' is from 'dart:async'.
+  Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>>;
+                if(#t2 is asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>>) {
+                  [yield] let dynamic #t4 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<self::Divergent<self::Divergent<core::int>>>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t2;
+                }
+                :return_value = :async_temporary_0;
+                break #L2;
+              }
+              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.call();
+          :is_sync = true;
+          return :async_future;
+        }).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+  #C2 = #catchError
+  #C3 = <core::Type*>[]
+  #C4 = #test
+  #C5 = #whenComplete
+  #C6 = <dynamic>[]
+  #C7 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C6}
+  #C8 = #timeout
+  #C9 = #onTimeout
+  #C10 = #then
+  #C11 = #onError
+  #C12 = #asStream
+}
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.expect
index 1d21b07..eaaabba4 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.expect
@@ -11,6 +11,6 @@
   };
   (dynamic _) → asy::Future<core::int?> async {
     if(b)
-      return 42;
+      return let final core::int #t1 = 42 in #t1 is asy::Future<core::int?> ?{FutureOr<dynamic>} await #t1 : #t1;
   };
 }
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 0ab4a75..1509333 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
@@ -28,12 +29,22 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L2:
               {
                 if(b) {
-                  :return_value = 42;
+                  final core::int #t1 = 42;
+                  if(#t1 is asy::Future<core::int?>) {
+                    [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t1;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L2;
                 }
               }
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.expect
index 1d21b07..eaaabba4 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.expect
@@ -11,6 +11,6 @@
   };
   (dynamic _) → asy::Future<core::int?> async {
     if(b)
-      return 42;
+      return let final core::int #t1 = 42 in #t1 is asy::Future<core::int?> ?{FutureOr<dynamic>} await #t1 : #t1;
   };
 }
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 0ab4a75..1509333 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
@@ -28,12 +29,22 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L2:
               {
                 if(b) {
-                  :return_value = 42;
+                  final core::int #t1 = 42;
+                  if(#t1 is asy::Future<core::int?>) {
+                    [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t1;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L2;
                 }
               }
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
index df47af6..17dcee5 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
@@ -120,7 +120,7 @@
   await for (core::String s in asy::Stream::fromIterable<core::String>(<core::String>["hest"])) {
     core::print(s);
   }
-  return "hest";
+  return let final core::String #t2 = "hest" in #t2 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t2 : #t2;
 }
 static method fisk() → dynamic async {
   late core::String s1 = invalid-expression "pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
@@ -129,7 +129,7 @@
   late core::String s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}';
                              ^^^^^"}${#C1}";
-  late core::Function f = () → asy::Future<dynamic> async => await self::hest();
+  late core::Function f = () → asy::Future<dynamic> async => let final dynamic #t3 = await self::hest() in #t3 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t3 : #t3;
 }
 static method main() → dynamic {}
 
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 2aba575..53a4028 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
@@ -135,6 +135,8 @@
   dynamic :saved_try_context_var1;
   dynamic :exception0;
   dynamic :stack_trace0;
+  FutureOr<dynamic>:async_temporary_0;
+  FutureOr<dynamic>:async_temporary_1;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
@@ -162,7 +164,15 @@
               :result;
             }
         }
-        :return_value = "hest";
+        final core::String #t5 = "hest";
+        if(#t5 is asy::Future<dynamic>) {
+          [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_1 = _in::unsafeCast<core::String>(:result);
+        }
+        else {
+          :async_temporary_1 = #t5;
+        }
+        :return_value = :async_temporary_1;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -209,12 +219,21 @@
             core::int :await_jump_var = 0;
             dynamic :await_ctx_var;
             dynamic :saved_try_context_var0;
+            FutureOr<dynamic>:async_temporary_0;
             function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
               try {
                 #L4:
                 {
-                  [yield] let dynamic #t5 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
-                  :return_value = :result;
+                  [yield] let dynamic #t7 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                  final dynamic #t8 = :result;
+                  if(#t8 is asy::Future<dynamic>) {
+                    [yield] let dynamic #t9 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = :result;
+                  }
+                  else {
+                    :async_temporary_0 = #t8;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L4;
                 }
                 asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
index df47af6..17dcee5 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
@@ -120,7 +120,7 @@
   await for (core::String s in asy::Stream::fromIterable<core::String>(<core::String>["hest"])) {
     core::print(s);
   }
-  return "hest";
+  return let final core::String #t2 = "hest" in #t2 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t2 : #t2;
 }
 static method fisk() → dynamic async {
   late core::String s1 = invalid-expression "pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
@@ -129,7 +129,7 @@
   late core::String s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}';
                              ^^^^^"}${#C1}";
-  late core::Function f = () → asy::Future<dynamic> async => await self::hest();
+  late core::Function f = () → asy::Future<dynamic> async => let final dynamic #t3 = await self::hest() in #t3 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t3 : #t3;
 }
 static method main() → dynamic {}
 
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 2aba575..53a4028 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
@@ -135,6 +135,8 @@
   dynamic :saved_try_context_var1;
   dynamic :exception0;
   dynamic :stack_trace0;
+  FutureOr<dynamic>:async_temporary_0;
+  FutureOr<dynamic>:async_temporary_1;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
@@ -162,7 +164,15 @@
               :result;
             }
         }
-        :return_value = "hest";
+        final core::String #t5 = "hest";
+        if(#t5 is asy::Future<dynamic>) {
+          [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_1 = _in::unsafeCast<core::String>(:result);
+        }
+        else {
+          :async_temporary_1 = #t5;
+        }
+        :return_value = :async_temporary_1;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -209,12 +219,21 @@
             core::int :await_jump_var = 0;
             dynamic :await_ctx_var;
             dynamic :saved_try_context_var0;
+            FutureOr<dynamic>:async_temporary_0;
             function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
               try {
                 #L4:
                 {
-                  [yield] let dynamic #t5 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
-                  :return_value = :result;
+                  [yield] let dynamic #t7 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                  final dynamic #t8 = :result;
+                  if(#t8 is asy::Future<dynamic>) {
+                    [yield] let dynamic #t9 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = :result;
+                  }
+                  else {
+                    :async_temporary_0 = #t8;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L4;
                 }
                 asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.strong.expect b/pkg/front_end/testcases/nnbd/return_async.dart.strong.expect
index 2c50b42..7fe1ab7 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.strong.expect
@@ -28,6 +28,6 @@
   }, (core::Object e, core::StackTrace s) → void {
     completer.{asy::Completer::completeError}(e, s);
   });
-  return completer.{asy::Completer::future};
+  return let final asy::Future<void> #t1 = completer.{asy::Completer::future} in #t1 is asy::Future<void> ?{FutureOr<void>} await #t1 : #t1;
 }
 static method main() → dynamic {}
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 b9094ae..d88bd46 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
@@ -106,6 +106,8 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<void>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L4:
@@ -142,7 +144,15 @@
         }, (core::Object e, core::StackTrace s) → void {
           completer.{asy::Completer::completeError}(e, s);
         });
-        :return_value = completer.{asy::Completer::future};
+        final asy::Future<void> #t7 = completer.{asy::Completer::future};
+        if(#t7 is asy::Future<void>) {
+          [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<void>(:result);
+        }
+        else {
+          :async_temporary_0 = #t7;
+        }
+        :return_value = :async_temporary_0;
         break #L4;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.weak.expect b/pkg/front_end/testcases/nnbd/return_async.dart.weak.expect
index 2c50b42..7fe1ab7 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.weak.expect
@@ -28,6 +28,6 @@
   }, (core::Object e, core::StackTrace s) → void {
     completer.{asy::Completer::completeError}(e, s);
   });
-  return completer.{asy::Completer::future};
+  return let final asy::Future<void> #t1 = completer.{asy::Completer::future} in #t1 is asy::Future<void> ?{FutureOr<void>} await #t1 : #t1;
 }
 static method main() → dynamic {}
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 b9094ae..d88bd46 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
@@ -106,6 +106,8 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<void>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L4:
@@ -142,7 +144,15 @@
         }, (core::Object e, core::StackTrace s) → void {
           completer.{asy::Completer::completeError}(e, s);
         });
-        :return_value = completer.{asy::Completer::future};
+        final asy::Future<void> #t7 = completer.{asy::Completer::future};
+        if(#t7 is asy::Future<void>) {
+          [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<void>(:result);
+        }
+        else {
+          :async_temporary_0 = #t7;
+        }
+        :return_value = :async_temporary_0;
         break #L4;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart b/pkg/front_end/testcases/nnbd/return_from_async.dart
new file mode 100644
index 0000000..93e646e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2020, 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';
+
+bool caughtFutureOrInt = false;
+
+FutureOr<int> throwFutureOrInt() async {
+  throw 'FutureOr<int>';
+}
+
+Future<int> callFutureOrInt() async {
+  try {
+    return throwFutureOrInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureOrInt = true;
+    return 0;
+  }
+}
+
+bool caughtInt = false;
+
+int throwInt() {
+  throw 'int';
+}
+
+Future<int> callInt() async {
+  try {
+    return throwInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtInt = true;
+    return 0;
+  }
+}
+
+bool caughtFutureInt = false;
+
+Future<int> throwFutureInt() async {
+  throw 'Future<int>';
+}
+
+Future<int> callFutureInt() async {
+  try {
+    return throwFutureInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureInt = true;
+    return 0;
+  }
+}
+
+bool caughtDynamic = false;
+
+dynamic throwDynamic() {
+  throw 'dynamic';
+}
+
+Future<int> callDynamic() async {
+  try {
+    return throwDynamic();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtDynamic = true;
+    return 0;
+  }
+}
+
+bool caughtFutureNum = false;
+
+Future<int> throwFutureNum() async {
+  throw 'Future<num>';
+}
+
+Future<num> callFutureNum() async {
+  try {
+    return throwFutureNum();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureNum = true;
+    return 0;
+  }
+}
+
+void main() async {
+  await callFutureOrInt();
+  if (!caughtFutureOrInt) throw 'Uncaught async return';
+  await callInt();
+  if (!caughtInt) throw 'Uncaught async return';
+  await callFutureInt();
+  if (!caughtFutureInt) throw 'Uncaught async return';
+  await callDynamic();
+  if (!caughtDynamic) throw 'Uncaught async return';
+  await callFutureNum();
+  if (!caughtFutureNum) throw 'Uncaught async return';
+}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.outline.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.outline.expect
new file mode 100644
index 0000000..fce58f8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.outline.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+static field core::bool caughtFutureOrInt;
+static field core::bool caughtInt;
+static field core::bool caughtFutureInt;
+static field core::bool caughtDynamic;
+static field core::bool caughtFutureNum;
+static method throwFutureOrInt() → FutureOr<core::int> async 
+  ;
+static method callFutureOrInt() → asy::Future<core::int> async 
+  ;
+static method throwInt() → core::int
+  ;
+static method callInt() → asy::Future<core::int> async 
+  ;
+static method throwFutureInt() → asy::Future<core::int> async 
+  ;
+static method callFutureInt() → asy::Future<core::int> async 
+  ;
+static method throwDynamic() → dynamic
+  ;
+static method callDynamic() → asy::Future<core::int> async 
+  ;
+static method throwFutureNum() → asy::Future<core::int> async 
+  ;
+static method callFutureNum() → asy::Future<core::num> async 
+  ;
+static method main() → void async 
+  ;
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.expect
new file mode 100644
index 0000000..07f9c6e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.expect
@@ -0,0 +1,94 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method throwFutureOrInt() → FutureOr<core::int> async {
+  throw "FutureOr<int>";
+}
+static method callFutureOrInt() → asy::Future<core::int> async {
+  try {
+    return let final FutureOr<core::int>#t1 = self::throwFutureOrInt() in #t1 is asy::Future<core::int> ?{FutureOr<core::int>} await #t1 : #t1;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureOrInt = true;
+    return let final core::int #t2 = 0 in #t2 is asy::Future<core::int> ?{FutureOr<core::int>} await #t2 : #t2;
+  }
+}
+static method throwInt() → core::int {
+  throw "int";
+}
+static method callInt() → asy::Future<core::int> async {
+  try {
+    return let final core::int #t3 = self::throwInt() in #t3 is asy::Future<core::int> ?{FutureOr<core::int>} await #t3 : #t3;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtInt = true;
+    return let final core::int #t4 = 0 in #t4 is asy::Future<core::int> ?{FutureOr<core::int>} await #t4 : #t4;
+  }
+}
+static method throwFutureInt() → asy::Future<core::int> async {
+  throw "Future<int>";
+}
+static method callFutureInt() → asy::Future<core::int> async {
+  try {
+    return let final asy::Future<core::int> #t5 = self::throwFutureInt() in #t5 is asy::Future<core::int> ?{FutureOr<core::int>} await #t5 : #t5;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureInt = true;
+    return let final core::int #t6 = 0 in #t6 is asy::Future<core::int> ?{FutureOr<core::int>} await #t6 : #t6;
+  }
+}
+static method throwDynamic() → dynamic {
+  throw "dynamic";
+}
+static method callDynamic() → asy::Future<core::int> async {
+  try {
+    return let final dynamic #t7 = self::throwDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int> in #t7 is asy::Future<core::int> ?{FutureOr<core::int>} await #t7 : #t7;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtDynamic = true;
+    return let final core::int #t8 = 0 in #t8 is asy::Future<core::int> ?{FutureOr<core::int>} await #t8 : #t8;
+  }
+}
+static method throwFutureNum() → asy::Future<core::int> async {
+  throw "Future<num>";
+}
+static method callFutureNum() → asy::Future<core::num> async {
+  try {
+    return let final asy::Future<core::int> #t9 = self::throwFutureNum() in #t9 is asy::Future<core::num> ?{FutureOr<core::num>} await #t9 : #t9;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureNum = true;
+    return let final core::int #t10 = 0 in #t10 is asy::Future<core::num> ?{FutureOr<core::num>} await #t10 : #t10;
+  }
+}
+static method main() → void async {
+  await self::callFutureOrInt();
+  if(!self::caughtFutureOrInt)
+    throw "Uncaught async return";
+  await self::callInt();
+  if(!self::caughtInt)
+    throw "Uncaught async return";
+  await self::callFutureInt();
+  if(!self::caughtFutureInt)
+    throw "Uncaught async return";
+  await self::callDynamic();
+  if(!self::caughtDynamic)
+    throw "Uncaught async return";
+  await self::callFutureNum();
+  if(!self::caughtFutureNum)
+    throw "Uncaught async return";
+}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.transformed.expect
new file mode 100644
index 0000000..5bd5d9f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.transformed.expect
@@ -0,0 +1,433 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method throwFutureOrInt() → 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;
+  (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 {
+      #L1:
+      {
+        throw "FutureOr<int>";
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureOrInt() → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        try {
+          final FutureOr<core::int>#t1 = self::throwFutureOrInt();
+          if(#t1 is asy::Future<core::int>) {
+            [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t1;
+          }
+          :return_value = :async_temporary_0;
+          break #L2;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureOrInt = true;
+          final core::int #t3 = 0;
+          if(#t3 is asy::Future<core::int>) {
+            [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t3;
+          }
+          :return_value = :async_temporary_2;
+          break #L2;
+        }
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwInt() → core::int {
+  throw "int";
+}
+static method callInt() → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        try {
+          final core::int #t5 = self::throwInt();
+          if(#t5 is asy::Future<core::int>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
+          break #L3;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtInt = true;
+          final core::int #t7 = 0;
+          if(#t7 is asy::Future<core::int>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t7;
+          }
+          :return_value = :async_temporary_2;
+          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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwFutureInt() → 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;
+  (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 {
+      #L4:
+      {
+        throw "Future<int>";
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureInt() → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L5:
+      {
+        try {
+          final asy::Future<core::int> #t9 = self::throwFutureInt();
+          if(#t9 is asy::Future<core::int>) {
+            [yield] let dynamic #t10 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t9;
+          }
+          :return_value = :async_temporary_0;
+          break #L5;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureInt = true;
+          final core::int #t11 = 0;
+          if(#t11 is asy::Future<core::int>) {
+            [yield] let dynamic #t12 = asy::_awaitHelper(#t11, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t11;
+          }
+          :return_value = :async_temporary_2;
+          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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwDynamic() → dynamic {
+  throw "dynamic";
+}
+static method callDynamic() → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L6:
+      {
+        try {
+          final FutureOr<core::int>#t13 = self::throwDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int>;
+          if(#t13 is asy::Future<core::int>) {
+            [yield] let dynamic #t14 = asy::_awaitHelper(#t13, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t13;
+          }
+          :return_value = :async_temporary_0;
+          break #L6;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtDynamic = true;
+          final core::int #t15 = 0;
+          if(#t15 is asy::Future<core::int>) {
+            [yield] let dynamic #t16 = asy::_awaitHelper(#t15, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t15;
+          }
+          :return_value = :async_temporary_2;
+          break #L6;
+        }
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwFutureNum() → 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;
+  (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:
+      {
+        throw "Future<num>";
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureNum() → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::num>:async_temporary_0;
+  FutureOr<core::num>:async_temporary_1;
+  FutureOr<core::num>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L8:
+      {
+        try {
+          final asy::Future<core::int> #t17 = self::throwFutureNum();
+          if(#t17 is asy::Future<core::num>) {
+            [yield] let dynamic #t18 = asy::_awaitHelper(#t17, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t17;
+          }
+          :return_value = :async_temporary_0;
+          break #L8;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureNum = true;
+          final core::int #t19 = 0;
+          if(#t19 is asy::Future<core::num>) {
+            [yield] let dynamic #t20 = asy::_awaitHelper(#t19, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t19;
+          }
+          :return_value = :async_temporary_2;
+          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.call();
+  :is_sync = true;
+  return :async_future;
+}
+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) → 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 #t21 = asy::_awaitHelper(self::callFutureOrInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureOrInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t22 = asy::_awaitHelper(self::callInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t23 = asy::_awaitHelper(self::callFutureInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t24 = asy::_awaitHelper(self::callDynamic(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtDynamic)
+          throw "Uncaught async return";
+        [yield] let dynamic #t25 = asy::_awaitHelper(self::callFutureNum(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::num>(:result);
+        if(!self::caughtFutureNum)
+          throw "Uncaught async return";
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline.expect
new file mode 100644
index 0000000..bc32d23
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline.expect
@@ -0,0 +1,18 @@
+import 'dart:async';
+
+bool caughtFutureOrInt = false;
+FutureOr<int> throwFutureOrInt() async {}
+Future<int> callFutureOrInt() async {}
+bool caughtInt = false;
+int throwInt() {}
+Future<int> callInt() async {}
+bool caughtFutureInt = false;
+Future<int> throwFutureInt() async {}
+Future<int> callFutureInt() async {}
+bool caughtDynamic = false;
+dynamic throwDynamic() {}
+Future<int> callDynamic() async {}
+bool caughtFutureNum = false;
+Future<int> throwFutureNum() async {}
+Future<num> callFutureNum() async {}
+void main() async {}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7a7e905
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline_modelled.expect
@@ -0,0 +1,18 @@
+import 'dart:async';
+
+Future<int> callDynamic() async {}
+Future<int> callFutureInt() async {}
+Future<int> callFutureOrInt() async {}
+Future<int> callInt() async {}
+Future<int> throwFutureInt() async {}
+Future<int> throwFutureNum() async {}
+Future<num> callFutureNum() async {}
+FutureOr<int> throwFutureOrInt() async {}
+bool caughtDynamic = false;
+bool caughtFutureInt = false;
+bool caughtFutureNum = false;
+bool caughtFutureOrInt = false;
+bool caughtInt = false;
+dynamic throwDynamic() {}
+int throwInt() {}
+void main() async {}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.expect
new file mode 100644
index 0000000..07f9c6e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.expect
@@ -0,0 +1,94 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method throwFutureOrInt() → FutureOr<core::int> async {
+  throw "FutureOr<int>";
+}
+static method callFutureOrInt() → asy::Future<core::int> async {
+  try {
+    return let final FutureOr<core::int>#t1 = self::throwFutureOrInt() in #t1 is asy::Future<core::int> ?{FutureOr<core::int>} await #t1 : #t1;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureOrInt = true;
+    return let final core::int #t2 = 0 in #t2 is asy::Future<core::int> ?{FutureOr<core::int>} await #t2 : #t2;
+  }
+}
+static method throwInt() → core::int {
+  throw "int";
+}
+static method callInt() → asy::Future<core::int> async {
+  try {
+    return let final core::int #t3 = self::throwInt() in #t3 is asy::Future<core::int> ?{FutureOr<core::int>} await #t3 : #t3;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtInt = true;
+    return let final core::int #t4 = 0 in #t4 is asy::Future<core::int> ?{FutureOr<core::int>} await #t4 : #t4;
+  }
+}
+static method throwFutureInt() → asy::Future<core::int> async {
+  throw "Future<int>";
+}
+static method callFutureInt() → asy::Future<core::int> async {
+  try {
+    return let final asy::Future<core::int> #t5 = self::throwFutureInt() in #t5 is asy::Future<core::int> ?{FutureOr<core::int>} await #t5 : #t5;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureInt = true;
+    return let final core::int #t6 = 0 in #t6 is asy::Future<core::int> ?{FutureOr<core::int>} await #t6 : #t6;
+  }
+}
+static method throwDynamic() → dynamic {
+  throw "dynamic";
+}
+static method callDynamic() → asy::Future<core::int> async {
+  try {
+    return let final dynamic #t7 = self::throwDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int> in #t7 is asy::Future<core::int> ?{FutureOr<core::int>} await #t7 : #t7;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtDynamic = true;
+    return let final core::int #t8 = 0 in #t8 is asy::Future<core::int> ?{FutureOr<core::int>} await #t8 : #t8;
+  }
+}
+static method throwFutureNum() → asy::Future<core::int> async {
+  throw "Future<num>";
+}
+static method callFutureNum() → asy::Future<core::num> async {
+  try {
+    return let final asy::Future<core::int> #t9 = self::throwFutureNum() in #t9 is asy::Future<core::num> ?{FutureOr<core::num>} await #t9 : #t9;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureNum = true;
+    return let final core::int #t10 = 0 in #t10 is asy::Future<core::num> ?{FutureOr<core::num>} await #t10 : #t10;
+  }
+}
+static method main() → void async {
+  await self::callFutureOrInt();
+  if(!self::caughtFutureOrInt)
+    throw "Uncaught async return";
+  await self::callInt();
+  if(!self::caughtInt)
+    throw "Uncaught async return";
+  await self::callFutureInt();
+  if(!self::caughtFutureInt)
+    throw "Uncaught async return";
+  await self::callDynamic();
+  if(!self::caughtDynamic)
+    throw "Uncaught async return";
+  await self::callFutureNum();
+  if(!self::caughtFutureNum)
+    throw "Uncaught async return";
+}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.transformed.expect
new file mode 100644
index 0000000..5bd5d9f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.transformed.expect
@@ -0,0 +1,433 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method throwFutureOrInt() → 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;
+  (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 {
+      #L1:
+      {
+        throw "FutureOr<int>";
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureOrInt() → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        try {
+          final FutureOr<core::int>#t1 = self::throwFutureOrInt();
+          if(#t1 is asy::Future<core::int>) {
+            [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t1;
+          }
+          :return_value = :async_temporary_0;
+          break #L2;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureOrInt = true;
+          final core::int #t3 = 0;
+          if(#t3 is asy::Future<core::int>) {
+            [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t3;
+          }
+          :return_value = :async_temporary_2;
+          break #L2;
+        }
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwInt() → core::int {
+  throw "int";
+}
+static method callInt() → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        try {
+          final core::int #t5 = self::throwInt();
+          if(#t5 is asy::Future<core::int>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
+          break #L3;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtInt = true;
+          final core::int #t7 = 0;
+          if(#t7 is asy::Future<core::int>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t7;
+          }
+          :return_value = :async_temporary_2;
+          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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwFutureInt() → 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;
+  (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 {
+      #L4:
+      {
+        throw "Future<int>";
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureInt() → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L5:
+      {
+        try {
+          final asy::Future<core::int> #t9 = self::throwFutureInt();
+          if(#t9 is asy::Future<core::int>) {
+            [yield] let dynamic #t10 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t9;
+          }
+          :return_value = :async_temporary_0;
+          break #L5;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureInt = true;
+          final core::int #t11 = 0;
+          if(#t11 is asy::Future<core::int>) {
+            [yield] let dynamic #t12 = asy::_awaitHelper(#t11, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t11;
+          }
+          :return_value = :async_temporary_2;
+          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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwDynamic() → dynamic {
+  throw "dynamic";
+}
+static method callDynamic() → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L6:
+      {
+        try {
+          final FutureOr<core::int>#t13 = self::throwDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int>;
+          if(#t13 is asy::Future<core::int>) {
+            [yield] let dynamic #t14 = asy::_awaitHelper(#t13, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t13;
+          }
+          :return_value = :async_temporary_0;
+          break #L6;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtDynamic = true;
+          final core::int #t15 = 0;
+          if(#t15 is asy::Future<core::int>) {
+            [yield] let dynamic #t16 = asy::_awaitHelper(#t15, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t15;
+          }
+          :return_value = :async_temporary_2;
+          break #L6;
+        }
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwFutureNum() → 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;
+  (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:
+      {
+        throw "Future<num>";
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureNum() → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::num>:async_temporary_0;
+  FutureOr<core::num>:async_temporary_1;
+  FutureOr<core::num>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L8:
+      {
+        try {
+          final asy::Future<core::int> #t17 = self::throwFutureNum();
+          if(#t17 is asy::Future<core::num>) {
+            [yield] let dynamic #t18 = asy::_awaitHelper(#t17, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t17;
+          }
+          :return_value = :async_temporary_0;
+          break #L8;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureNum = true;
+          final core::int #t19 = 0;
+          if(#t19 is asy::Future<core::num>) {
+            [yield] let dynamic #t20 = asy::_awaitHelper(#t19, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t19;
+          }
+          :return_value = :async_temporary_2;
+          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.call();
+  :is_sync = true;
+  return :async_future;
+}
+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) → 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 #t21 = asy::_awaitHelper(self::callFutureOrInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureOrInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t22 = asy::_awaitHelper(self::callInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t23 = asy::_awaitHelper(self::callFutureInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t24 = asy::_awaitHelper(self::callDynamic(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtDynamic)
+          throw "Uncaught async return";
+        [yield] let dynamic #t25 = asy::_awaitHelper(self::callFutureNum(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::num>(:result);
+        if(!self::caughtFutureNum)
+          throw "Uncaught async return";
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect b/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
index 70d918b..dab461b 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
@@ -103,7 +103,7 @@
 static method returnAsync4() → FutureOr<core::int?> async {}
 static method returnAsync5() → dynamic async {}
 static method returnAsync6() → asy::Future<core::int?> async {
-  return null;
+  return let final Null #t6 = null in #t6 is asy::Future<core::int?> ?{FutureOr<core::int?>} await #t6 : #t6;
 }
 static method returnAsync7() → asy::Future<core::int?> async {}
 static method yieldSync() → core::Iterable<dynamic> sync* {}
@@ -133,7 +133,7 @@
     default:
       {}
   }
-  return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+  return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
 Enum caseReturn2(Enum e) /* error */ {
      ^" in null;
@@ -141,38 +141,38 @@
 static method localFunctions() → dynamic {
   function returnImplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnImplicit() /* error */ {
   ^" in null;
   }
   function returnExplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
     return null; // error
            ^" in null as{TypeError,ForNonNullableByDefault} core::String;
   }
   function returnMixed(core::bool b) → core::String {
     if(b) {
       core::print("foo");
-      return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+      return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
       return null; // error
              ^" in null as{TypeError,ForNonNullableByDefault} core::String;
     }
-    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnMixed(bool b) /* error */ {
   ^" in null;
   }
   function returnAsync1() → asy::Future<dynamic> async {}
   function returnAsync2() → FutureOr<dynamic> async {}
   function returnAsync3() → FutureOr<core::int> async {
-    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
   FutureOr<int> returnAsync3() async {} // error
   ^" in null;
   }
   function returnAsync4() → FutureOr<core::int?> async {}
   function returnAsync5() → asy::Future<Null> async {}
   function returnAsync6() → asy::Future<core::int?> async {
-    return null;
+    return let final Null #t13 = null in #t13 is asy::Future<core::int?> ?{FutureOr<core::int?>} await #t13 : #t13;
   }
   function returnAsync7() → asy::Future<core::int?> async {}
   function yieldSync() → core::Iterable<dynamic> sync* {}
@@ -202,7 +202,7 @@
       default:
         {}
     }
-    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
   Enum caseReturn2(Enum e) /* error */ {
   ^" in null;
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 2b1a3dc..af2d2ae 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
@@ -55,6 +55,7 @@
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 import "dart:async";
 
@@ -226,11 +227,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::int?>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L6:
       {
-        :return_value = null;
+        final Null #t8 = null;
+        if(#t8 is asy::Future<core::int?>) {
+          [yield] let dynamic #t9 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<Null>(:result);
+        }
+        else {
+          :async_temporary_0 = #t8;
+        }
+        :return_value = :async_temporary_0;
         break #L6;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -332,7 +343,7 @@
     default:
       {}
   }
-  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+  return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
 Enum caseReturn2(Enum e) /* error */ {
      ^" in null;
@@ -340,24 +351,24 @@
 static method localFunctions() → dynamic {
   function returnImplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnImplicit() /* error */ {
   ^" in null;
   }
   function returnExplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
     return null; // error
-           ^" in let Null #t11 = null in #t11.==(null) ?{core::String} #t11 as{TypeError,ForNonNullableByDefault} core::String : #t11{core::String};
+           ^" in let Null #t13 = null in #t13.==(null) ?{core::String} #t13 as{TypeError,ForNonNullableByDefault} core::String : #t13{core::String};
   }
   function returnMixed(core::bool b) → core::String {
     if(b) {
       core::print("foo");
-      return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+      return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
       return null; // error
-             ^" in let Null #t13 = null in #t13.==(null) ?{core::String} #t13 as{TypeError,ForNonNullableByDefault} core::String : #t13{core::String};
+             ^" in let Null #t15 = null in #t15.==(null) ?{core::String} #t15 as{TypeError,ForNonNullableByDefault} core::String : #t15{core::String};
     }
-    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnMixed(bool b) /* error */ {
   ^" in null;
   }
@@ -421,7 +432,7 @@
       try {
         #L15:
         {
-          :return_value = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+          :return_value = let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
   FutureOr<int> returnAsync3() async {} // error
   ^" in null;
           break #L15;
@@ -494,11 +505,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::int?>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L18:
         {
-          :return_value = null;
+          final Null #t18 = null;
+          if(#t18 is asy::Future<core::int?>) {
+            [yield] let dynamic #t19 = asy::_awaitHelper(#t18, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Null>(:result);
+          }
+          else {
+            :async_temporary_0 = #t18;
+          }
+          :return_value = :async_temporary_0;
           break #L18;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -600,7 +621,7 @@
       default:
         {}
     }
-    return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+    return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
   Enum caseReturn2(Enum e) /* error */ {
   ^" in null;
@@ -642,7 +663,7 @@
 Evaluated: MethodInvocation @ org-dartlang-testcase:///return_null.dart:75:14 -> BoolConstant(true)
 Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:75:14 -> NullConstant(null)
 Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:75:14 -> NullConstant(null)
-Extra constant evaluation: evaluated: 394, effectively constant: 12
+Extra constant evaluation: evaluated: 422, effectively constant: 12
 
 
 Constructor coverage from constants:
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect b/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
index 0513741..aef28a4 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
@@ -104,7 +104,7 @@
 static method returnAsync4() → FutureOr<core::int?> async {}
 static method returnAsync5() → dynamic async {}
 static method returnAsync6() → asy::Future<core::int?> async {
-  return null;
+  return let final Null #t6 = null in #t6 is asy::Future<core::int?> ?{FutureOr<core::int?>} await #t6 : #t6;
 }
 static method returnAsync7() → asy::Future<core::int?> async {}
 static method yieldSync() → core::Iterable<dynamic> sync* {}
@@ -137,7 +137,7 @@
     default:
       {}
   }
-  return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+  return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
 Enum caseReturn2(Enum e) /* error */ {
      ^" in null;
@@ -145,38 +145,38 @@
 static method localFunctions() → dynamic {
   function returnImplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnImplicit() /* error */ {
   ^" in null;
   }
   function returnExplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
     return null; // error
            ^" in null as{TypeError,ForNonNullableByDefault} core::String;
   }
   function returnMixed(core::bool b) → core::String {
     if(b) {
       core::print("foo");
-      return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+      return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
       return null; // error
              ^" in null as{TypeError,ForNonNullableByDefault} core::String;
     }
-    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnMixed(bool b) /* error */ {
   ^" in null;
   }
   function returnAsync1() → asy::Future<dynamic> async {}
   function returnAsync2() → FutureOr<dynamic> async {}
   function returnAsync3() → FutureOr<core::int> async {
-    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
   FutureOr<int> returnAsync3() async {} // error
   ^" in null;
   }
   function returnAsync4() → FutureOr<core::int?> async {}
   function returnAsync5() → asy::Future<Null> async {}
   function returnAsync6() → asy::Future<core::int?> async {
-    return null;
+    return let final Null #t13 = null in #t13 is asy::Future<core::int?> ?{FutureOr<core::int?>} await #t13 : #t13;
   }
   function returnAsync7() → asy::Future<core::int?> async {}
   function yieldSync() → core::Iterable<dynamic> sync* {}
@@ -209,7 +209,7 @@
       default:
         {}
     }
-    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
   Enum caseReturn2(Enum e) /* error */ {
   ^" in null;
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 3643cf7..dba40e5 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
@@ -227,11 +227,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::int?>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L6:
       {
-        :return_value = null;
+        final Null #t6 = null;
+        if(#t6 is asy::Future<core::int?>) {
+          [yield] let dynamic #t7 = asy::_awaitHelper(#t6, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<Null>(:result);
+        }
+        else {
+          :async_temporary_0 = #t6;
+        }
+        :return_value = :async_temporary_0;
         break #L6;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -336,7 +346,7 @@
     default:
       {}
   }
-  return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
 Enum caseReturn2(Enum e) /* error */ {
      ^" in null;
@@ -344,24 +354,24 @@
 static method localFunctions() → dynamic {
   function returnImplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnImplicit() /* error */ {
   ^" in null;
   }
   function returnExplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
     return null; // error
            ^" in null;
   }
   function returnMixed(core::bool b) → core::String {
     if(b) {
       core::print("foo");
-      return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+      return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
       return null; // error
              ^" in null;
     }
-    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnMixed(bool b) /* error */ {
   ^" in null;
   }
@@ -425,7 +435,7 @@
       try {
         #L16:
         {
-          :return_value = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+          :return_value = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
   FutureOr<int> returnAsync3() async {} // error
   ^" in null;
           break #L16;
@@ -498,11 +508,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::int?>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L19:
         {
-          :return_value = null;
+          final Null #t14 = null;
+          if(#t14 is asy::Future<core::int?>) {
+            [yield] let dynamic #t15 = asy::_awaitHelper(#t14, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Null>(:result);
+          }
+          else {
+            :async_temporary_0 = #t14;
+          }
+          :return_value = :async_temporary_0;
           break #L19;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -607,7 +627,7 @@
       default:
         {}
     }
-    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+    return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
   Enum caseReturn2(Enum e) /* error */ {
   ^" in null;
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart
new file mode 100644
index 0000000..5b167d0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2020, 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';
+import 'return_from_async_lib.dart';
+
+abstract class Class {
+  FutureOr<int> throwFutureOrInt();
+
+  int throwInt();
+
+  Future<int> throwFutureInt();
+
+  dynamic throwDynamic();
+
+  Future<num> throwFutureNum();
+}
+
+bool caughtFutureOrInt = false;
+
+Future<int> callFutureOrInt(Class c) async {
+  try {
+    return c.throwFutureOrInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureOrInt = true;
+    return 0;
+  }
+}
+
+bool caughtInt = false;
+
+Future<int> callInt(Class c) async {
+  try {
+    return c.throwInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtInt = true;
+    return 0;
+  }
+}
+
+bool caughtFutureInt = false;
+
+Future<int> callFutureInt(Class c) async {
+  try {
+    return c.throwFutureInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureInt = true;
+    return 0;
+  }
+}
+
+bool caughtDynamic = false;
+
+Future<int> callDynamic(Class c) async {
+  try {
+    return c.throwDynamic();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtDynamic = true;
+    return 0;
+  }
+}
+
+bool caughtFutureNum = false;
+
+Future<num> callFutureNum(Class c) async {
+  try {
+    return c.throwFutureNum();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureNum = true;
+    return 0;
+  }
+}
+
+void main() async {
+  Class c = new Subclass();
+  await callFutureOrInt(c);
+  if (!caughtFutureOrInt) throw 'Uncaught async return';
+  await callInt(c);
+  if (!caughtInt) throw 'Uncaught async return';
+  await callFutureInt(c);
+  if (!caughtFutureInt) throw 'Uncaught async return';
+  await callDynamic(c);
+  if (!caughtDynamic) throw 'Uncaught async return';
+  await callFutureNum(c);
+  if (!caughtFutureNum) throw 'Uncaught async return';
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline.expect
new file mode 100644
index 0000000..66339b5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+import 'dart:async';
+import 'return_from_async_lib.dart';
+
+abstract class Class {
+  FutureOr<int> throwFutureOrInt();
+  int throwInt();
+  Future<int> throwFutureInt();
+  dynamic throwDynamic();
+  Future<num> throwFutureNum();
+}
+
+bool caughtFutureOrInt = false;
+Future<int> callFutureOrInt(Class c) async {}
+bool caughtInt = false;
+Future<int> callInt(Class c) async {}
+bool caughtFutureInt = false;
+Future<int> callFutureInt(Class c) async {}
+bool caughtDynamic = false;
+Future<int> callDynamic(Class c) async {}
+bool caughtFutureNum = false;
+Future<num> callFutureNum(Class c) async {}
+void main() async {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c8dcd7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline_modelled.expect
@@ -0,0 +1,23 @@
+import 'dart:async';
+import 'return_from_async_lib.dart';
+
+Future<int> callDynamic(Class c) async {}
+Future<int> callFutureInt(Class c) async {}
+Future<int> callFutureOrInt(Class c) async {}
+Future<int> callInt(Class c) async {}
+Future<num> callFutureNum(Class c) async {}
+
+abstract class Class {
+  Future<int> throwFutureInt();
+  Future<num> throwFutureNum();
+  FutureOr<int> throwFutureOrInt();
+  dynamic throwDynamic();
+  int throwInt();
+}
+
+bool caughtDynamic = false;
+bool caughtFutureInt = false;
+bool caughtFutureNum = false;
+bool caughtFutureOrInt = false;
+bool caughtInt = false;
+void main() async {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.expect
new file mode 100644
index 0000000..0a614de
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.expect
@@ -0,0 +1,122 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "return_from_async_lib.dart" as ret;
+
+import "dart:async";
+import "org-dartlang-testcase:///return_from_async_lib.dart";
+
+abstract class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  abstract method throwFutureOrInt() → FutureOr<core::int>;
+  abstract method throwInt() → core::int;
+  abstract method throwFutureInt() → asy::Future<core::int>;
+  abstract method throwDynamic() → dynamic;
+  abstract method throwFutureNum() → asy::Future<core::num>;
+}
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method callFutureOrInt(self::Class c) → asy::Future<core::int> async {
+  try {
+    return let final FutureOr<core::int>#t1 = c.{self::Class::throwFutureOrInt}() in #t1 is asy::Future<core::int> ?{FutureOr<core::int>} await #t1 : #t1;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureOrInt = true;
+    return let final core::int #t2 = 0 in #t2 is asy::Future<core::int> ?{FutureOr<core::int>} await #t2 : #t2;
+  }
+}
+static method callInt(self::Class c) → asy::Future<core::int> async {
+  try {
+    return let final core::int #t3 = c.{self::Class::throwInt}() in #t3 is asy::Future<core::int> ?{FutureOr<core::int>} await #t3 : #t3;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtInt = true;
+    return let final core::int #t4 = 0 in #t4 is asy::Future<core::int> ?{FutureOr<core::int>} await #t4 : #t4;
+  }
+}
+static method callFutureInt(self::Class c) → asy::Future<core::int> async {
+  try {
+    return let final asy::Future<core::int> #t5 = c.{self::Class::throwFutureInt}() in #t5 is asy::Future<core::int> ?{FutureOr<core::int>} await #t5 : #t5;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureInt = true;
+    return let final core::int #t6 = 0 in #t6 is asy::Future<core::int> ?{FutureOr<core::int>} await #t6 : #t6;
+  }
+}
+static method callDynamic(self::Class c) → asy::Future<core::int> async {
+  try {
+    return let final dynamic #t7 = c.{self::Class::throwDynamic}() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int> in #t7 is asy::Future<core::int> ?{FutureOr<core::int>} await #t7 : #t7;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtDynamic = true;
+    return let final core::int #t8 = 0 in #t8 is asy::Future<core::int> ?{FutureOr<core::int>} await #t8 : #t8;
+  }
+}
+static method callFutureNum(self::Class c) → asy::Future<core::num> async {
+  try {
+    return let final asy::Future<core::num> #t9 = c.{self::Class::throwFutureNum}() in #t9 is asy::Future<core::num> ?{FutureOr<core::num>} await #t9 : #t9;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureNum = true;
+    return let final core::int #t10 = 0 in #t10 is asy::Future<core::num> ?{FutureOr<core::num>} await #t10 : #t10;
+  }
+}
+static method main() → void async {
+  self::Class c = new ret::Subclass::•();
+  await self::callFutureOrInt(c);
+  if(!self::caughtFutureOrInt)
+    throw "Uncaught async return";
+  await self::callInt(c);
+  if(!self::caughtInt)
+    throw "Uncaught async return";
+  await self::callFutureInt(c);
+  if(!self::caughtFutureInt)
+    throw "Uncaught async return";
+  await self::callDynamic(c);
+  if(!self::caughtDynamic)
+    throw "Uncaught async return";
+  await self::callFutureNum(c);
+  if(!self::caughtFutureNum)
+    throw "Uncaught async return";
+}
+
+library /*isNonNullableByDefault*/;
+import self as ret;
+import "dart:core" as core;
+import "return_from_async.dart" as self;
+import "dart:async" as asy;
+
+import "dart:async";
+import "org-dartlang-testcase:///return_from_async.dart";
+
+class Subclass extends core::Object implements self::Class {
+  synthetic constructor •() → ret::Subclass
+    : super core::Object::•()
+    ;
+  method throwFutureOrInt() → FutureOr<core::int> async {
+    throw "FutureOr<int>";
+  }
+  method throwInt() → core::int {
+    throw "int";
+  }
+  method throwFutureInt() → asy::Future<core::int> async {
+    throw "Future<int>";
+  }
+  method throwDynamic() → dynamic {
+    throw "dynamic";
+  }
+  method throwFutureNum() → asy::Future<core::num> async {
+    throw "Future<num>";
+  }
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.transformed.expect
new file mode 100644
index 0000000..1924b7e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.transformed.expect
@@ -0,0 +1,461 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+import "return_from_async_lib.dart" as ret;
+
+import "dart:async";
+import "org-dartlang-testcase:///return_from_async_lib.dart";
+
+abstract class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  abstract method throwFutureOrInt() → FutureOr<core::int>;
+  abstract method throwInt() → core::int;
+  abstract method throwFutureInt() → asy::Future<core::int>;
+  abstract method throwDynamic() → dynamic;
+  abstract method throwFutureNum() → asy::Future<core::num>;
+}
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method callFutureOrInt(self::Class c) → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        try {
+          final FutureOr<core::int>#t1 = c.{self::Class::throwFutureOrInt}();
+          if(#t1 is asy::Future<core::int>) {
+            [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t1;
+          }
+          :return_value = :async_temporary_0;
+          break #L1;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureOrInt = true;
+          final core::int #t3 = 0;
+          if(#t3 is asy::Future<core::int>) {
+            [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t3;
+          }
+          :return_value = :async_temporary_2;
+          break #L1;
+        }
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callInt(self::Class c) → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        try {
+          final core::int #t5 = c.{self::Class::throwInt}();
+          if(#t5 is asy::Future<core::int>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
+          break #L2;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtInt = true;
+          final core::int #t7 = 0;
+          if(#t7 is asy::Future<core::int>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t7;
+          }
+          :return_value = :async_temporary_2;
+          break #L2;
+        }
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureInt(self::Class c) → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        try {
+          final asy::Future<core::int> #t9 = c.{self::Class::throwFutureInt}();
+          if(#t9 is asy::Future<core::int>) {
+            [yield] let dynamic #t10 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t9;
+          }
+          :return_value = :async_temporary_0;
+          break #L3;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureInt = true;
+          final core::int #t11 = 0;
+          if(#t11 is asy::Future<core::int>) {
+            [yield] let dynamic #t12 = asy::_awaitHelper(#t11, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t11;
+          }
+          :return_value = :async_temporary_2;
+          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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callDynamic(self::Class c) → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L4:
+      {
+        try {
+          final FutureOr<core::int>#t13 = c.{self::Class::throwDynamic}() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int>;
+          if(#t13 is asy::Future<core::int>) {
+            [yield] let dynamic #t14 = asy::_awaitHelper(#t13, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t13;
+          }
+          :return_value = :async_temporary_0;
+          break #L4;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtDynamic = true;
+          final core::int #t15 = 0;
+          if(#t15 is asy::Future<core::int>) {
+            [yield] let dynamic #t16 = asy::_awaitHelper(#t15, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t15;
+          }
+          :return_value = :async_temporary_2;
+          break #L4;
+        }
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureNum(self::Class c) → 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;
+  (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;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::num>:async_temporary_0;
+  FutureOr<core::num>:async_temporary_1;
+  FutureOr<core::num>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L5:
+      {
+        try {
+          final asy::Future<core::num> #t17 = c.{self::Class::throwFutureNum}();
+          if(#t17 is asy::Future<core::num>) {
+            [yield] let dynamic #t18 = asy::_awaitHelper(#t17, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::num>(:result);
+          }
+          else {
+            :async_temporary_0 = #t17;
+          }
+          :return_value = :async_temporary_0;
+          break #L5;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureNum = true;
+          final core::int #t19 = 0;
+          if(#t19 is asy::Future<core::num>) {
+            [yield] let dynamic #t20 = asy::_awaitHelper(#t19, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t19;
+          }
+          :return_value = :async_temporary_2;
+          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.call();
+  :is_sync = true;
+  return :async_future;
+}
+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) → 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:
+      {
+        self::Class c = new ret::Subclass::•();
+        [yield] let dynamic #t21 = asy::_awaitHelper(self::callFutureOrInt(c), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureOrInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t22 = asy::_awaitHelper(self::callInt(c), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t23 = asy::_awaitHelper(self::callFutureInt(c), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t24 = asy::_awaitHelper(self::callDynamic(c), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtDynamic)
+          throw "Uncaught async return";
+        [yield] let dynamic #t25 = asy::_awaitHelper(self::callFutureNum(c), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::num>(:result);
+        if(!self::caughtFutureNum)
+          throw "Uncaught async return";
+      }
+      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.call();
+  :is_sync = true;
+  return :async_future;
+}
+
+library /*isNonNullableByDefault*/;
+import self as ret;
+import "dart:core" as core;
+import "return_from_async.dart" as self;
+import "dart:async" as asy;
+
+import "dart:async";
+import "org-dartlang-testcase:///return_from_async.dart";
+
+class Subclass extends core::Object implements self::Class {
+  synthetic constructor •() → ret::Subclass
+    : super core::Object::•()
+    ;
+  method throwFutureOrInt() → 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;
+    (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:
+        {
+          throw "FutureOr<int>";
+        }
+        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.call();
+    :is_sync = true;
+    return :async_future;
+  }
+  method throwInt() → core::int {
+    throw "int";
+  }
+  method throwFutureInt() → 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;
+    (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:
+        {
+          throw "Future<int>";
+        }
+        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.call();
+    :is_sync = true;
+    return :async_future;
+  }
+  method throwDynamic() → dynamic {
+    throw "dynamic";
+  }
+  method throwFutureNum() → 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;
+    (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 {
+        #L9:
+        {
+          throw "Future<num>";
+        }
+        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.call();
+    :is_sync = true;
+    return :async_future;
+  }
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async_lib.dart b/pkg/front_end/testcases/nnbd_mixed/return_from_async_lib.dart
new file mode 100644
index 0000000..0e4cbb7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async_lib.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2020, 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';
+import 'return_from_async.dart';
+
+class Subclass implements Class {
+  FutureOr<int> throwFutureOrInt() async {
+    throw 'FutureOr<int>';
+  }
+
+  int throwInt() {
+    throw 'int';
+  }
+
+  Future<int> throwFutureInt() async {
+    throw 'Future<int>';
+  }
+
+  dynamic throwDynamic() {
+    throw 'dynamic';
+  }
+
+  Future<num> throwFutureNum() async {
+    throw 'Future<num>';
+  }
+}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 2e35c64..bbb5c64 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -171,7 +171,6 @@
 nnbd/covariant_late_field: TypeCheckError
 nnbd/getter_vs_setter_type: TypeCheckError
 nnbd/issue41180: RuntimeError # Strong mode runtime checking fails due to mixed strong mode.
-nnbd/issue42546: TypeCheckError
 nnbd/issue42603: TypeCheckError
 nnbd/no_support_for_old_null_aware_index_access_syntax: RuntimeError # Expected.
 nnbd/nullable_object_access: TypeCheckError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index a59dfcd..c21c124 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -171,7 +171,6 @@
 nnbd/covariant_late_field: TypeCheckError
 nnbd/getter_vs_setter_type: TypeCheckError
 nnbd/issue41180: RuntimeError
-nnbd/issue42546: TypeCheckError
 nnbd/issue42603: TypeCheckError
 nnbd/no_support_for_old_null_aware_index_access_syntax: RuntimeError # Expected.
 nnbd/nullable_object_access: TypeCheckError
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 56c47dc..731df3e 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -58,7 +58,6 @@
 late_lowering/covariant_late_field: TypeCheckError
 nnbd/covariant_late_field: TypeCheckError
 nnbd/getter_vs_setter_type: TypeCheckError
-nnbd/issue42546: TypeCheckError
 nnbd/issue42603: TypeCheckError
 nnbd/no_support_for_old_null_aware_index_access_syntax: RuntimeError # Expected.
 nnbd/nullable_object_access: TypeCheckError
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 4eb7083..09c977b 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -195,6 +195,7 @@
   Flags.nnbdAgnosticMode: const BoolValue(false),
   Flags.target: const StringValue(),
   Flags.verbose: const BoolValue(false),
+  Flags.verbosity: const StringValue(),
   Flags.verify: const BoolValue(false),
   Flags.verifySkipPlatform: const BoolValue(false),
   Flags.warnOnReachabilityCheck: const BoolValue(false),
@@ -308,6 +309,8 @@
 
   final String invocationModes = options[Flags.invocationModes] ?? '';
 
+  final String verbosity = options[Flags.verbosity] ?? Verbosity.defaultValue;
+
   if (nnbdStrongMode && nnbdWeakMode) {
     return throw new CommandLineProblem.deprecated(
         "Can't specify both '${Flags.nnbdStrongMode}' and "
@@ -359,7 +362,8 @@
     ..additionalDills = linkDependencies
     ..emitDeps = !noDeps
     ..warnOnReachabilityCheck = warnOnReachabilityCheck
-    ..invocationModes = InvocationMode.parseArguments(invocationModes);
+    ..invocationModes = InvocationMode.parseArguments(invocationModes)
+    ..verbosity = Verbosity.parseArgument(verbosity);
 
   if (programName == "compile_platform") {
     if (arguments.length != 5) {
diff --git a/pkg/nnbd_migration/lib/src/preview/preview_site.dart b/pkg/nnbd_migration/lib/src/preview/preview_site.dart
index c02b3c1..bd690a9 100644
--- a/pkg/nnbd_migration/lib/src/preview/preview_site.dart
+++ b/pkg/nnbd_migration/lib/src/preview/preview_site.dart
@@ -220,22 +220,26 @@
     if (line.length > lineStart + 1 &&
         line.codeUnitAt(lineStart) == $slash &&
         line.codeUnitAt(lineStart + 1) == $slash) {
-      // Comment.
+      // [line] is a comment.
+
       if (index == length) {
         // [code] consists _only_ of one comment line.
         return '$code$newline$newline// @dart=2.9$newline';
       }
       var previousLineIndex = index;
+      String newlinesAfterDlvc;
       while (true) {
         previousLineIndex = index;
         line = getLine();
         lineStart = line.indexOf(_nonWhitespaceChar);
         if (lineStart < 0) {
-          // Line of whitespace; end of block comment.
+          // Line of zero-or-more whitespace; end of block comment.
+          newlinesAfterDlvc = newline;
           break;
         }
         if (line.length <= lineStart + 1) {
           // Only one character; not a comment; end of block comment.
+          newlinesAfterDlvc = '$newline$newline';
           break;
         }
         if (line.codeUnitAt(lineStart) == $slash &&
@@ -248,13 +252,14 @@
           continue;
         } else {
           // Non-blank, non-comment line.
+          newlinesAfterDlvc = '$newline$newline';
           break;
         }
       }
       // [previousLineIndex] points to the start of [line], which is the first
       // non-comment line following the first comment.
       return '${code.substring(0, previousLineIndex)}$newline'
-          '// @dart=2.9$newline$newline'
+          '// @dart=2.9$newlinesAfterDlvc'
           '${code.substring(previousLineIndex)}';
     } else {
       // [code] does not start with a block comment.
diff --git a/pkg/nnbd_migration/test/preview/preview_site_test.dart b/pkg/nnbd_migration/test/preview/preview_site_test.dart
index d351962..550cd92 100644
--- a/pkg/nnbd_migration/test/preview/preview_site_test.dart
+++ b/pkg/nnbd_migration/test/preview/preview_site_test.dart
@@ -156,14 +156,20 @@
   void test_optOutOfNullSafety_commentThenCode() {
     expect(
         IncrementalPlan.optCodeOutOfNullSafety('// comment\n\nvoid main() {}'),
-        equals('// comment\n\n// @dart=2.9\n\n\nvoid main() {}'));
+        equals('// comment\n\n// @dart=2.9\n\nvoid main() {}'));
+  }
+
+  void test_optOutOfNullSafety_commentThenSemicolon() {
+    expect(
+        IncrementalPlan.optCodeOutOfNullSafety('// comment\n;\nvoid main() {}'),
+        equals('// comment\n\n// @dart=2.9\n\n;\nvoid main() {}'));
   }
 
   void test_optOutOfNullSafety_commentThenCode_windows() {
     expect(
         IncrementalPlan.optCodeOutOfNullSafety(
             '// comment\r\n\r\nvoid main() {}'),
-        equals('// comment\r\n\r\n// @dart=2.9\r\n\r\n\r\nvoid main() {}'));
+        equals('// comment\r\n\r\n// @dart=2.9\r\n\r\nvoid main() {}'));
   }
 
   void test_optOutOfNullSafety_commentThenDirective() {
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 5f226e7..2a57c7b 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -95,7 +95,8 @@
     List<String> experimentalFlags,
     Uri packagesUri,
     List<String> errors,
-    String invocationModes) {
+    String invocationModes,
+    String verbosityLevel) {
   final expFlags = <String>[];
   if (experimentalFlags != null) {
     for (String flag in experimentalFlags) {
@@ -103,6 +104,7 @@
     }
   }
 
+  Verbosity verbosity = Verbosity.parseArgument(verbosityLevel);
   return new CompilerOptions()
     ..fileSystem = fileSystem
     ..target = new VmTarget(new TargetFlags(
@@ -139,13 +141,16 @@
         case Severity.ignored:
           throw "Unexpected severity: ${message.severity}";
       }
-      if (printToStdErr) {
-        printDiagnosticMessage(message, stderr.writeln);
-      } else if (printToStdOut) {
-        printDiagnosticMessage(message, stdout.writeln);
+      if (Verbosity.shouldPrint(verbosity, message)) {
+        if (printToStdErr) {
+          printDiagnosticMessage(message, stderr.writeln);
+        } else if (printToStdOut) {
+          printDiagnosticMessage(message, stdout.writeln);
+        }
       }
     }
-    ..invocationModes = InvocationMode.parseArguments(invocationModes);
+    ..invocationModes = InvocationMode.parseArguments(invocationModes)
+    ..verbosity = verbosity;
 }
 
 abstract class Compiler {
@@ -158,6 +163,7 @@
   final List<String> experimentalFlags;
   final String packageConfig;
   final String invocationModes;
+  final String verbosityLevel;
 
   // Code coverage and hot reload are only supported by incremental compiler,
   // which is used if vm-service is enabled.
@@ -176,7 +182,8 @@
       this.supportCodeCoverage: false,
       this.supportHotReload: false,
       this.packageConfig: null,
-      this.invocationModes: ''}) {
+      this.invocationModes: '',
+      this.verbosityLevel: Verbosity.defaultValue}) {
     Uri packagesUri = null;
     if (packageConfig != null) {
       packagesUri = Uri.parse(packageConfig);
@@ -200,7 +207,8 @@
         experimentalFlags,
         packagesUri,
         errors,
-        invocationModes);
+        invocationModes,
+        verbosityLevel);
   }
 
   Future<CompilerResult> compile(Uri script) {
@@ -291,7 +299,8 @@
       int nullSafety: kNullSafetyOptionUnspecified,
       List<String> experimentalFlags: null,
       String packageConfig: null,
-      String invocationModes: ''})
+      String invocationModes: '',
+      String verbosityLevel: Verbosity.defaultValue})
       : super(isolateId, fileSystem, platformKernelPath,
             suppressWarnings: suppressWarnings,
             enableAsserts: enableAsserts,
@@ -300,7 +309,8 @@
             supportHotReload: true,
             supportCodeCoverage: true,
             packageConfig: packageConfig,
-            invocationModes: invocationModes);
+            invocationModes: invocationModes,
+            verbosityLevel: verbosityLevel);
 
   factory IncrementalCompilerWrapper.forExpressionCompilationOnly(
       Component component,
@@ -379,14 +389,16 @@
       int nullSafety: kNullSafetyOptionUnspecified,
       List<String> experimentalFlags: null,
       String packageConfig: null,
-      String invocationModes: ''})
+      String invocationModes: '',
+      String verbosityLevel: Verbosity.defaultValue})
       : super(isolateId, fileSystem, platformKernelPath,
             suppressWarnings: suppressWarnings,
             enableAsserts: enableAsserts,
             nullSafety: nullSafety,
             experimentalFlags: experimentalFlags,
             packageConfig: packageConfig,
-            invocationModes: invocationModes);
+            invocationModes: invocationModes,
+            verbosityLevel: verbosityLevel);
 
   @override
   Future<CompilerResult> compileInternal(Uri script) async {
@@ -423,7 +435,8 @@
     String packageConfig: null,
     String multirootFilepaths,
     String multirootScheme,
-    String invocationModes: ''}) async {
+    String invocationModes: '',
+    String verbosityLevel: Verbosity.defaultValue}) async {
   IncrementalCompilerWrapper compiler = lookupIncrementalCompiler(isolateId);
   if (compiler != null) {
     updateSources(compiler, sourceFiles);
@@ -453,7 +466,8 @@
           nullSafety: nullSafety,
           experimentalFlags: experimentalFlags,
           packageConfig: packageConfig,
-          invocationModes: invocationModes);
+          invocationModes: invocationModes,
+          verbosityLevel: verbosityLevel);
     }
     isolateCompilers[isolateId] = compiler;
   }
@@ -755,6 +769,8 @@
   final String multirootFilepaths = request[13];
   final String multirootScheme = request[14];
   final String workingDirectory = request[15];
+  // TODO(johnniwinther,bkonyi): Pass verbosity from command line arguments.
+  final String verbosityLevel = Verbosity.defaultValue;
 
   Uri platformKernelPath = null;
   List<int> platformKernel = null;
@@ -823,7 +839,8 @@
         experimentalFlags,
         packagesUri,
         errors,
-        invocationModes);
+        invocationModes,
+        verbosityLevel);
 
     // script should only be null for kUpdateSourcesTag.
     assert(script != null);
@@ -850,7 +867,8 @@
         packageConfig: packageConfig,
         multirootFilepaths: multirootFilepaths,
         multirootScheme: multirootScheme,
-        invocationModes: invocationModes);
+        invocationModes: invocationModes,
+        verbosityLevel: verbosityLevel);
   } else {
     FileSystem fileSystem = _buildFileSystem(
         sourceFiles, platformKernel, multirootFilepaths, multirootScheme);
@@ -862,7 +880,8 @@
         nullSafety: nullSafety,
         experimentalFlags: experimentalFlags,
         packageConfig: packageConfig,
-        invocationModes: invocationModes);
+        invocationModes: invocationModes,
+        verbosityLevel: verbosityLevel);
   }
 
   CompilationResult result;
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index a1fc45e..e0368f7 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -33,6 +33,7 @@
         ProcessedOptions,
         Severity,
         StandardFileSystem,
+        Verbosity,
         getMessageUri,
         kernelForProgram,
         parseExperimentalArguments,
@@ -131,6 +132,10 @@
   args.addOption('invocation-modes',
       help: 'Provides information to the front end about how it is invoked.',
       defaultsTo: '');
+  args.addOption('verbosity',
+      help: 'Sets the verbosity level used for filtering messages during '
+          'compilation.',
+      defaultsTo: Verbosity.defaultValue);
 }
 
 /// Create ArgParser and populate it with options consumed by [runCompiler].
@@ -215,7 +220,8 @@
     mainUri = await convertToPackageUri(fileSystem, mainUri, packagesUri);
   }
 
-  final errorPrinter = new ErrorPrinter();
+  final verbosity = Verbosity.parseArgument(options['verbosity']);
+  final errorPrinter = new ErrorPrinter(verbosity);
   final errorDetector = new ErrorDetector(previousErrorHandler: errorPrinter);
 
   final CompilerOptions compilerOptions = new CompilerOptions()
@@ -232,7 +238,8 @@
     }
     ..embedSourceText = embedSources
     ..invocationModes =
-        InvocationMode.parseArguments(options['invocation-modes']);
+        InvocationMode.parseArguments(options['invocation-modes'])
+    ..verbosity = verbosity;
 
   if (nullSafety == null &&
       compilerOptions.isExperimentEnabled(ExperimentalFlag.nonNullable)) {
@@ -489,10 +496,11 @@
 }
 
 class ErrorPrinter {
+  final Verbosity verbosity;
   final DiagnosticMessageHandler previousErrorHandler;
   final compilationMessages = <Uri, List<DiagnosticMessage>>{};
 
-  ErrorPrinter({this.previousErrorHandler});
+  ErrorPrinter(this.verbosity, {this.previousErrorHandler});
 
   void call(DiagnosticMessage message) {
     final sourceUri = getMessageUri(message);
@@ -516,7 +524,9 @@
       });
     for (final Uri sourceUri in sortedUris) {
       for (final DiagnosticMessage message in compilationMessages[sourceUri]) {
-        printDiagnosticMessage(message, print);
+        if (Verbosity.shouldPrint(verbosity, message)) {
+          printDiagnosticMessage(message, print);
+        }
       }
     }
   }
diff --git a/pkg/vm_service/test/async_single_step_out_test.dart b/pkg/vm_service/test/async_single_step_out_test.dart
index a0a3d83..7e5f200 100644
--- a/pkg/vm_service/test/async_single_step_out_test.dart
+++ b/pkg/vm_service/test/async_single_step_out_test.dart
@@ -44,6 +44,10 @@
   stepInto, // exit helper via a single step.
 
   hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B), // await helper
+  stepInto,
+
+  hasStoppedAtBreakpoint,
   stoppedAtLine(20), // return null (weird dispatching)
   stepInto, // exit helper via a single step.
 
diff --git a/runtime/observatory/tests/service/async_single_step_out_test.dart b/runtime/observatory/tests/service/async_single_step_out_test.dart
index cfeac6c..3c6de1b 100644
--- a/runtime/observatory/tests/service/async_single_step_out_test.dart
+++ b/runtime/observatory/tests/service/async_single_step_out_test.dart
@@ -44,6 +44,10 @@
   stepInto, // exit helper via a single step.
 
   hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B), // await helper
+  stepInto,
+
+  hasStoppedAtBreakpoint,
   stoppedAtLine(20), // return null (weird dispatching)
   stepInto, // exit helper via a single step.
 
diff --git a/runtime/tests/vm/dart/causal_stacks/utils.dart b/runtime/tests/vm/dart/causal_stacks/utils.dart
index 73ffe1d..fdebc07 100644
--- a/runtime/tests/vm/dart/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart/causal_stacks/utils.dart
@@ -720,20 +720,22 @@
   final mixedYieldsExpected = const <String>[
     r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
     r'^<asynchronous suspension>$',
-    r'^#1      mixedYields2 \(.*/utils.dart:66(:3)?\)$',
+    r'^#1      mixedYields3 \(.*/utils.dart:70(:3)?\)$',
     r'^<asynchronous suspension>$',
-    r'^#2      mixedYields \(.*/utils.dart:61(:3)?\)$',
+    r'^#2      mixedYields2 \(.*/utils.dart:66(:3)?\)$',
+    r'^<asynchronous suspension>$',
+    r'^#3      mixedYields \(.*/utils.dart:61(:3)?\)$',
     r'^<asynchronous suspension>$',
   ];
   await doTestAwait(
       mixedYields,
       mixedYieldsExpected +
           const <String>[
-            r'^#3      doTestAwait ',
+            r'^#4      doTestAwait ',
             r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
+            r'^#5      doTestsLazy ',
             r'^<asynchronous suspension>$',
-            r'^#5      main ',
+            r'^#6      main ',
             r'^<asynchronous suspension>$',
           ],
       debugInfoFilename);
@@ -741,7 +743,7 @@
       mixedYields,
       mixedYieldsExpected +
           const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
+            r'^#4      doTestAwaitThen.<anonymous closure> ',
             r'^<asynchronous suspension>$',
           ],
       debugInfoFilename);
@@ -782,20 +784,22 @@
   final nonAsyncNoStackExpected = const <String>[
     r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
     r'^<asynchronous suspension>$',
-    r'^#1      nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$',
+    r'^#1      nonAsyncNoStack2 \(.*/utils.dart:97(:36)?\)$',
     r'^<asynchronous suspension>$',
-    r'^#2      nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$',
+    r'^#2      nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$',
+    r'^<asynchronous suspension>$',
+    r'^#3      nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$',
     r'^<asynchronous suspension>$',
   ];
   await doTestAwait(
       nonAsyncNoStack,
       nonAsyncNoStackExpected +
           const <String>[
-            r'^#3      doTestAwait ',
+            r'^#4      doTestAwait ',
             r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
+            r'^#5      doTestsLazy ',
             r'^<asynchronous suspension>$',
-            r'^#5      main ',
+            r'^#6      main ',
             r'^<asynchronous suspension>$',
           ],
       debugInfoFilename);
@@ -803,7 +807,7 @@
       nonAsyncNoStack,
       nonAsyncNoStackExpected +
           const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
+            r'^#4      doTestAwaitThen.<anonymous closure> ',
             r'^<asynchronous suspension>$',
           ],
       debugInfoFilename);
diff --git a/sdk/lib/_http/http_parser.dart b/sdk/lib/_http/http_parser.dart
index 23e4a2b..93b6518 100644
--- a/sdk/lib/_http/http_parser.dart
+++ b/sdk/lib/_http/http_parser.dart
@@ -684,11 +684,16 @@
           } else {
             String headerField = new String.fromCharCodes(_headerField);
             String headerValue = new String.fromCharCodes(_headerValue);
+            const errorIfBothText = "Both Content-Length and Transfer-Encoding "
+                "are specified, at most one is allowed";
             if (headerField == HttpHeaders.contentLengthHeader) {
               // Content Length header should not have more than one occurance
               // or coexist with Transfer Encoding header.
-              if (_contentLength || _transferEncoding) {
-                _statusCode = HttpStatus.badRequest;
+              if (_contentLength) {
+                throw HttpException("The Content-Length header occurred "
+                    "more than once, at most one is allowed.");
+              } else if (_transferEncoding) {
+                throw HttpException(errorIfBothText);
               }
               _contentLength = true;
             } else if (headerField == HttpHeaders.transferEncodingHeader) {
@@ -697,7 +702,7 @@
                 _chunked = true;
               }
               if (_contentLength) {
-                _statusCode = HttpStatus.badRequest;
+                throw HttpException(errorIfBothText);
               }
             }
             var headers = _headers!;
diff --git a/tests/language/async/explicit_await_test.dart b/tests/language/async/explicit_await_test.dart
new file mode 100644
index 0000000..545e5c5
--- /dev/null
+++ b/tests/language/async/explicit_await_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2021, 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 'package:expect/expect.dart';
+
+bool caughtInMethod1 = false;
+bool caughtInMethod2 = false;
+bool caughtInMain = false;
+
+Future<Object> f() {
+  return new Future<Future<Object>>.value(new Future<Object>.delayed(
+      const Duration(seconds: 1), () => throw 'foo'));
+}
+
+Future<Object> method1() async {
+  try {
+    return await f();
+  } catch (e) {
+    print('caught in method1: $e');
+    caughtInMethod1 = true;
+  }
+  return new Object();
+}
+
+Future<Object> method2() async {
+  try {
+    return method1();
+  } catch (e) {
+    print('caught in method2: $e');
+    caughtInMethod2 = true;
+  }
+  return new Object();
+}
+
+void main() async {
+  try {
+    print(await method2());
+    print('Done');
+  } catch (e) {
+    print('caught in main: $e');
+    caughtInMain = true;
+  }
+  Expect.isTrue(caughtInMethod1, "Exception should be caught in 'method1'.");
+  Expect.isFalse(
+      caughtInMethod2, "Exception should not be caught in 'method2'.");
+  Expect.isFalse(caughtInMain, "Exception should not be caught in 'main'.");
+}
diff --git a/tests/language/async/implicit_await_test.dart b/tests/language/async/implicit_await_test.dart
new file mode 100644
index 0000000..9c79259
--- /dev/null
+++ b/tests/language/async/implicit_await_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2021, 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 'package:expect/expect.dart';
+
+bool caughtInF = false;
+bool caughtInMain = false;
+
+class A {}
+
+class AAndFutureOfA implements A, Future<A> {
+  noSuchMethod(Invocation i) => throw 0;
+}
+
+Future<A> f(A a) async {
+  try {
+    // Statically looks like no `await` is needed, but dynamically it is needed.
+    // So we should check dynamically whether to await.
+    return a;
+  } catch (e) {
+    caughtInF = true;
+  }
+  return new A();
+}
+
+void main() async {
+  try {
+    print(await f(AAndFutureOfA()));
+    print('Done');
+  } catch (e) {
+    caughtInMain = true;
+  }
+  Expect.isTrue(caughtInF, "Exception should be caught in 'f'.");
+  Expect.isFalse(caughtInMain, "Exception should not be caught in 'main'.");
+}
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index fa7499c..022a9b9 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -461,36 +461,6 @@
     _testParseRequest(request, "POST", "/test",
         expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
 
-    // Test mixing chunked encoding and content length (content length
-    // is ignored).
-    request = """
-POST /test HTTP/1.1\r
-Content-Length: 7\r
-Transfer-Encoding: chunked\r
-\r
-5\r
-01234\r
-5\r
-56789\r
-0\r\n\r\n""";
-    _testParseRequest(request, "POST", "/test",
-        expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
-
-    // Test mixing chunked encoding and content length (content length
-    // is ignored).
-    request = """
-POST /test HTTP/1.1\r
-Transfer-Encoding: chunked\r
-Content-Length: 3\r
-\r
-5\r
-01234\r
-5\r
-56789\r
-0\r\n\r\n""";
-    _testParseRequest(request, "POST", "/test",
-        expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
-
     // Test upper and lower case hex digits in chunked encoding.
     request = """
 POST /test HTTP/1.1\r
@@ -772,6 +742,32 @@
 
     request = "GET / HTTP/1.1\r\nKeep-Alive: False\r\nbadheader\r\n\r\n";
     _testParseInvalidRequest(request);
+
+    // Content-Length and "Transfer-Encoding: chunked" are specified (error
+    // per RFC-7320).
+    request = """
+POST /test HTTP/1.1\r
+Content-Length: 7\r
+Transfer-Encoding: chunked\r
+\r
+5\r
+01234\r
+5\r
+56789\r
+0\r\n\r\n""";
+    _testParseInvalidRequest(request);
+
+    request = """
+POST /test HTTP/1.1\r
+Transfer-Encoding: chunked\r
+Content-Length: 7\r
+\r
+5\r
+01234\r
+5\r
+56789\r
+0\r\n\r\n""";
+    _testParseInvalidRequest(request);
   }
 
   static void testParseInvalidResponse() {
diff --git a/tools/VERSION b/tools/VERSION
index 927bbe8..4aae745 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 254
+PRERELEASE 255
 PRERELEASE_PATCH 0
\ No newline at end of file