Version 2.17.0-277.0.dev

Merge commit '8178fdea4046837c4855e06d67c373543b9ffcbc' into 'dev'
diff --git a/DEPS b/DEPS
index a5a4e52..db1a550 100644
--- a/DEPS
+++ b/DEPS
@@ -110,7 +110,7 @@
   "dart_style_rev": "d7b73536a8079331c888b7da539b80e6825270ea",
 
   "dartdoc_rev" : "334072b0cad436c05f6bcecf8a1a59f2f0809b84",
-  "devtools_rev" : "2a707ca56c1a9d5eeef212c28c573548a051fdd2",
+  "devtools_rev" : "8c525828ba33029ed664bf8ea2829b6e5370535f",
   "ffi_rev": "4dd32429880a57b64edaf54c9d5af8a9fa9a4ffb",
   "fixnum_rev": "848341f061359ef7ddc0cad472c2ecbb036b28ac",
   "file_rev": "1ebc38852ffed24b564910317982298b56c2cedd",
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 527f2fa..0ec9bc0 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -31,8 +31,7 @@
 import '../universe/feature.dart';
 import '../universe/selector.dart';
 import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
-import '../universe/world_impact.dart'
-    show WorldImpact, WorldImpactBuilderImpl, WorldImpactVisitor;
+import '../universe/world_impact.dart' show WorldImpact, WorldImpactBuilderImpl;
 import '../util/enumset.dart';
 import '../util/util.dart';
 import '../world.dart';
@@ -201,15 +200,6 @@
     sink.end(tag);
   }
 
-  @override
-  void apply(WorldImpactVisitor visitor) {
-    staticUses.forEach((StaticUse use) => visitor.visitStaticUse(member, use));
-    dynamicUses.forEach((DynamicUse use) => visitor.visitDynamicUse);
-    typeUses.forEach((TypeUse use) => visitor.visitTypeUse(member, use));
-    constantUses
-        .forEach((ConstantUse use) => visitor.visitConstantUse(member, use));
-  }
-
   void registerTypeVariableBoundsSubtypeCheck(
       DartType subtype, DartType supertype) {
     _typeVariableBoundsSubtypeChecks ??= {};
diff --git a/pkg/compiler/lib/src/deferred_load/entity_data_info.dart b/pkg/compiler/lib/src/deferred_load/entity_data_info.dart
index 6f6c33a..7c0c07d 100644
--- a/pkg/compiler/lib/src/deferred_load/entity_data_info.dart
+++ b/pkg/compiler/lib/src/deferred_load/entity_data_info.dart
@@ -19,7 +19,7 @@
 import '../kernel/element_map.dart';
 import '../kernel/kernel_world.dart';
 import '../universe/use.dart';
-import '../universe/world_impact.dart' show WorldImpact, WorldImpactVisitorImpl;
+import '../universe/world_impact.dart' show WorldImpact;
 
 /// [EntityDataInfo] is meta data about [EntityData] for a given compilation
 /// [Entity].
@@ -239,16 +239,13 @@
   /// Extract any dependencies that are known from the impact of [element].
   void _addDependenciesFromImpact(MemberEntity element) {
     WorldImpact worldImpact = impactCache[element];
-    worldImpact.apply(WorldImpactVisitorImpl(
-        visitStaticUse: (MemberEntity member, StaticUse staticUse) {
-      _addFromStaticUse(element, staticUse);
-    }, visitTypeUse: (MemberEntity member, TypeUse typeUse) {
-      _addFromTypeUse(element, typeUse);
-    }, visitDynamicUse: (MemberEntity member, DynamicUse dynamicUse) {
-      // TODO(johnniwinther): Use rti need data to skip unneeded type
-      // arguments.
-      addTypeListDependencies(dynamicUse.typeArguments);
-    }));
+    worldImpact.forEachStaticUse(_addFromStaticUse);
+    worldImpact.forEachTypeUse(_addFromTypeUse);
+
+    // TODO(johnniwinther): Use rti need data to skip unneeded type
+    // arguments.
+    worldImpact.forEachDynamicUse(
+        (_, use) => addTypeListDependencies(use.typeArguments));
   }
 }
 
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 0101783..35a0e17 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -27,7 +27,7 @@
 import 'js/js.dart' as jsAst;
 import 'js_model/js_strategy.dart';
 import 'js_backend/field_analysis.dart';
-import 'universe/world_impact.dart' show WorldImpact, WorldImpactVisitorImpl;
+import 'universe/world_impact.dart' show WorldImpact;
 import 'util/sink_adapter.dart';
 import 'world.dart' show JClosedWorld;
 
@@ -891,16 +891,17 @@
     if (impact == null) return const <Selection>[];
 
     var selections = <Selection>[];
-    impact.apply(WorldImpactVisitorImpl(visitDynamicUse: (member, dynamicUse) {
+    impact.forEachDynamicUse((_, dynamicUse) {
       AbstractValue mask = dynamicUse.receiverConstraint;
       selections.addAll(closedWorld
           // TODO(het): Handle `call` on `Closure` through
           // `world.includesClosureCall`.
           .locateMembers(dynamicUse.selector, mask)
           .map((MemberEntity e) => Selection(e, mask)));
-    }, visitStaticUse: (member, staticUse) {
+    });
+    impact.forEachStaticUse((_, staticUse) {
       selections.add(Selection(staticUse.element, null));
-    }));
+    });
     unregisterImpact(entity);
     return selections;
   }
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 075a591..e003a60 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -11,7 +11,7 @@
 import 'elements/entities.dart';
 import 'elements/types.dart';
 import 'universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
-import 'universe/world_impact.dart' show WorldImpact, WorldImpactVisitor;
+import 'universe/world_impact.dart' show WorldImpact;
 
 abstract class EnqueuerListener {
   /// Called to instruct to the backend that [type] has been instantiated.
@@ -80,8 +80,6 @@
   // side-effects.
   static bool skipEnqueuerCheckForTesting = false;
 
-  WorldImpactVisitor get impactVisitor;
-
   bool queueIsClosed;
 
   bool get queueIsEmpty;
@@ -91,7 +89,10 @@
   /// Apply the [worldImpact] to this enqueuer.
   void applyImpact(WorldImpact worldImpact) {
     if (worldImpact.isEmpty) return;
-    worldImpact.apply(impactVisitor);
+    worldImpact.forEachStaticUse(processStaticUse);
+    worldImpact.forEachDynamicUse((_, use) => processDynamicUse(use));
+    worldImpact.forEachTypeUse(processTypeUse);
+    worldImpact.forEachConstantUse((_, use) => processConstantUse(use));
   }
 
   bool checkNoEnqueuedInvokedInstanceMethods(
@@ -137,32 +138,6 @@
   }
 }
 
-class EnqueuerImpactVisitor implements WorldImpactVisitor {
-  final Enqueuer enqueuer;
-
-  EnqueuerImpactVisitor(this.enqueuer);
-
-  @override
-  void visitDynamicUse(MemberEntity member, DynamicUse dynamicUse) {
-    enqueuer.processDynamicUse(dynamicUse);
-  }
-
-  @override
-  void visitStaticUse(MemberEntity member, StaticUse staticUse) {
-    enqueuer.processStaticUse(member, staticUse);
-  }
-
-  @override
-  void visitTypeUse(MemberEntity member, TypeUse typeUse) {
-    enqueuer.processTypeUse(member, typeUse);
-  }
-
-  @override
-  void visitConstantUse(MemberEntity member, ConstantUse constantUse) {
-    enqueuer.processConstantUse(constantUse);
-  }
-}
-
 /// Interface for creating work items for enqueued member entities.
 abstract class WorkItemBuilder {
   WorkItem createWorkItem(covariant MemberEntity entity);
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index aa490af..716ea52 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -99,6 +99,12 @@
     _stateAfterWhenFalseInternal = whenFalse;
   }
 
+  /// Removes from the current [_state] any data from the boolean value of the
+  /// most recently visited node.
+  void _clearConditionalStateAfter() {
+    _stateAfterWhenTrueInternal = _stateAfterWhenFalseInternal = null;
+  }
+
   final SideEffectsBuilder _sideEffectsBuilder;
   final Map<JumpTarget, List<LocalState>> _breaksFor =
       <JumpTarget, List<LocalState>>{};
@@ -257,15 +263,16 @@
     var oldAccumulateIsChecks = _accumulateIsChecks;
     _accumulateIsChecks = conditionContext;
     var result = node?.accept(this);
+
+    // Clear the conditional state to ensure we don't accidentally carry over
+    // conclusions from a nested condition into an outer condition. For example:
+    //
+    //   if (methodCall(x is T && true)) { /* don't assume x is T here. */ }
+    if (!conditionContext) _clearConditionalStateAfter();
     _accumulateIsChecks = oldAccumulateIsChecks;
     return result;
   }
 
-  void visitList(List<ir.Node> nodes) {
-    if (nodes == null) return;
-    nodes.forEach(visit);
-  }
-
   void handleParameter(ir.VariableDeclaration node, {bool isOptional}) {
     Local local = _localsMap.getLocalVariable(node);
     DartType type = _localsMap.getLocalType(_elementMap, local);
@@ -1696,11 +1703,7 @@
   }
 
   TypeInformation handleCondition(ir.Node node) {
-    bool oldAccumulateIsChecks = _accumulateIsChecks;
-    _accumulateIsChecks = true;
-    TypeInformation result = visit(node, conditionContext: true);
-    _accumulateIsChecks = oldAccumulateIsChecks;
-    return result;
+    return visit(node, conditionContext: true);
   }
 
   void _potentiallyAddIsCheck(ir.IsExpression node) {
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index 5fd435b..9185917 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -24,7 +24,6 @@
         StaticUseKind,
         TypeUse,
         TypeUseKind;
-import '../universe/world_impact.dart' show WorldImpactVisitor;
 import '../util/enumset.dart';
 import '../util/util.dart' show Setlet;
 
@@ -44,9 +43,6 @@
   final EnqueuerListener listener;
   final AnnotationsData _annotationsData;
 
-  @override
-  WorldImpactVisitor impactVisitor;
-
   final Queue<WorkItem> _queue = Queue<WorkItem>();
 
   /// All declaration elements that have been processed by codegen.
@@ -58,9 +54,7 @@
 
   CodegenEnqueuer(this.task, this.worldBuilder, this._workItemBuilder,
       this.listener, this._annotationsData)
-      : this.name = 'codegen enqueuer' {
-    impactVisitor = EnqueuerImpactVisitor(this);
-  }
+      : this.name = 'codegen enqueuer';
 
   @override
   Iterable<ClassEntity> get directlyInstantiatedClasses =>
diff --git a/pkg/compiler/lib/src/kernel/transformations/async_lowering.dart b/pkg/compiler/lib/src/kernel/transformations/async_lowering.dart
index 30dd0b8..8f60070 100644
--- a/pkg/compiler/lib/src/kernel/transformations/async_lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/async_lowering.dart
@@ -10,9 +10,15 @@
 
 class _FunctionData {
   final List<AwaitExpression> awaits = [];
-  final List<ReturnStatement> returnStatements = [];
+  final Set<ReturnStatement> returnStatements = {};
 
   _FunctionData();
+
+  /// Returns true if all [AwaitExpression]s are children of [ReturnStatement]s.
+  bool allAwaitsDirectReturn() {
+    return awaits.every(
+        (awaitExpression) => returnStatements.contains(awaitExpression.parent));
+  }
 }
 
 /// Handles simplification of basic 'async' functions into [Future]s.
@@ -59,9 +65,23 @@
             ]))));
   }
 
+  void _transformDirectReturnAwaits(
+      FunctionNode node, _FunctionData functionData) {
+    // If every await is the direct child of a return statement then we can
+    // do the following transformation:
+    // return await e; --> return e;
+    final updatedReturns = <ReturnStatement>{};
+    for (final awaitExpression in functionData.awaits) {
+      final returnStatement = awaitExpression.parent as ReturnStatement;
+      updatedReturns.add(returnStatement);
+      awaitExpression.replaceWith(awaitExpression.operand);
+    }
+  }
+
   void _transformAsyncFunctionNode(FunctionNode node) {
     assert(_functions.isNotEmpty, 'Must be within a function scope.');
     final functionData = _functions.last;
+    var isLowered = false;
     if (functionData.awaits.isEmpty) {
       // There are no awaits within this function so convert to a simple
       // Future.sync call with the function's returned expressions. We use
@@ -90,6 +110,12 @@
       //    handle the unpacking of the returned future in that case.
       // 3) The return type of the function is not specified. In this case we
       //    instantiate Future.value with 'dynamic'.
+      isLowered = true;
+    } else if (functionData.allAwaitsDirectReturn()) {
+      _transformDirectReturnAwaits(node, functionData);
+      isLowered = true;
+    }
+    if (isLowered) {
       _wrapBodySync(node);
     }
   }
diff --git a/pkg/compiler/lib/src/resolution/enqueuer.dart b/pkg/compiler/lib/src/resolution/enqueuer.dart
index 89fcb44..6a20e9d 100644
--- a/pkg/compiler/lib/src/resolution/enqueuer.dart
+++ b/pkg/compiler/lib/src/resolution/enqueuer.dart
@@ -22,7 +22,6 @@
         StaticUseKind,
         TypeUse,
         TypeUseKind;
-import '../universe/world_impact.dart' show WorldImpactVisitor;
 import '../util/enumset.dart';
 import '../util/util.dart' show Setlet;
 
@@ -44,9 +43,6 @@
   @override
   bool queueIsClosed = false;
 
-  @override
-  WorldImpactVisitor impactVisitor;
-
   final Queue<WorkItem> _queue = Queue<WorkItem>();
 
   // If not `null` this is called when the queue has been emptied. It allows for
@@ -55,9 +51,7 @@
 
   ResolutionEnqueuer(this.task, this._reporter, this.listener,
       this.worldBuilder, this._workItemBuilder, this._annotationsData,
-      [this.name = 'resolution enqueuer']) {
-    impactVisitor = EnqueuerImpactVisitor(this);
-  }
+      [this.name = 'resolution enqueuer']);
 
   @override
   Iterable<ClassEntity> get directlyInstantiatedClasses =>
diff --git a/pkg/compiler/lib/src/universe/world_impact.dart b/pkg/compiler/lib/src/universe/world_impact.dart
index 0d319ea..acd7038 100644
--- a/pkg/compiler/lib/src/universe/world_impact.dart
+++ b/pkg/compiler/lib/src/universe/world_impact.dart
@@ -37,16 +37,19 @@
 
   Iterable<ConstantUse> get constantUses => const [];
 
-  bool get isEmpty => true;
+  void _forEach<U>(Iterable<U> uses, void Function(MemberEntity, U) visitUse) =>
+      uses.forEach((use) => visitUse(member, use));
 
-  void apply(WorldImpactVisitor visitor) {
-    staticUses.forEach((StaticUse use) => visitor.visitStaticUse(member, use));
-    dynamicUses
-        .forEach((DynamicUse use) => visitor.visitDynamicUse(member, use));
-    typeUses.forEach((TypeUse use) => visitor.visitTypeUse(member, use));
-    constantUses
-        .forEach((ConstantUse use) => visitor.visitConstantUse(member, use));
-  }
+  void forEachDynamicUse(void Function(MemberEntity, DynamicUse) visitUse) =>
+      _forEach(dynamicUses, visitUse);
+  void forEachStaticUse(void Function(MemberEntity, StaticUse) visitUse) =>
+      _forEach(staticUses, visitUse);
+  void forEachTypeUse(void Function(MemberEntity, TypeUse) visitUse) =>
+      _forEach(typeUses, visitUse);
+  void forEachConstantUse(void Function(MemberEntity, ConstantUse) visitUse) =>
+      _forEach(constantUses, visitUse);
+
+  bool get isEmpty => true;
 
   @override
   String toString() => dump(this);
@@ -240,59 +243,3 @@
     return sb.toString();
   }
 }
-
-/// Visitor used to process the uses of a [WorldImpact].
-abstract class WorldImpactVisitor {
-  void visitStaticUse(MemberEntity member, StaticUse staticUse);
-  void visitDynamicUse(MemberEntity member, DynamicUse dynamicUse);
-  void visitTypeUse(MemberEntity member, TypeUse typeUse);
-  void visitConstantUse(MemberEntity member, ConstantUse typeUse);
-}
-
-// TODO(johnniwinther): Remove these when we get anonymous local classes.
-typedef VisitUse<U> = void Function(MemberEntity member, U use);
-
-class WorldImpactVisitorImpl implements WorldImpactVisitor {
-  final VisitUse<StaticUse> _visitStaticUse;
-  final VisitUse<DynamicUse> _visitDynamicUse;
-  final VisitUse<TypeUse> _visitTypeUse;
-  final VisitUse<ConstantUse> _visitConstantUse;
-
-  WorldImpactVisitorImpl(
-      {VisitUse<StaticUse> visitStaticUse,
-      VisitUse<DynamicUse> visitDynamicUse,
-      VisitUse<TypeUse> visitTypeUse,
-      VisitUse<ConstantUse> visitConstantUse})
-      : _visitStaticUse = visitStaticUse,
-        _visitDynamicUse = visitDynamicUse,
-        _visitTypeUse = visitTypeUse,
-        _visitConstantUse = visitConstantUse;
-
-  @override
-  void visitStaticUse(MemberEntity member, StaticUse use) {
-    if (_visitStaticUse != null) {
-      _visitStaticUse(member, use);
-    }
-  }
-
-  @override
-  void visitDynamicUse(MemberEntity member, DynamicUse use) {
-    if (_visitDynamicUse != null) {
-      _visitDynamicUse(member, use);
-    }
-  }
-
-  @override
-  void visitTypeUse(MemberEntity member, TypeUse use) {
-    if (_visitTypeUse != null) {
-      _visitTypeUse(member, use);
-    }
-  }
-
-  @override
-  void visitConstantUse(MemberEntity member, ConstantUse use) {
-    if (_visitConstantUse != null) {
-      _visitConstantUse(member, use);
-    }
-  }
-}
diff --git a/pkg/compiler/test/inference/data/issue_48571.dart b/pkg/compiler/test/inference/data/issue_48571.dart
new file mode 100644
index 0000000..c9c6a9c
--- /dev/null
+++ b/pkg/compiler/test/inference/data/issue_48571.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*member: Base.:[subclass=Base]*/
+abstract class Base {}
+
+/*member: Child1.:[exact=Child1]*/
+class Child1 extends Base {}
+
+/*member: Child2.:[exact=Child2]*/
+class Child2 extends Base {}
+
+/*member: trivial:Value([exact=JSBool], value: true)*/
+bool trivial(/*[exact=JSBool]*/ x) => true;
+
+/*member: either:Union([exact=Child1], [exact=Child2])*/
+Base either = DateTime.now()
+            . /*[exact=DateTime]*/ millisecondsSinceEpoch /*invoke: [subclass=JSInt]*/ >
+        0
+    ? Child2()
+    : Child1();
+
+/*member: test1:Union(null, [exact=Child1], [exact=Child2])*/
+test1() {
+  Base child = either;
+  if (trivial(child is Child1 && true)) return child;
+  return null;
+}
+
+/*member: test2:Union(null, [exact=Child1], [exact=Child2])*/
+test2() {
+  Base child = either;
+  if (child is Child1 || trivial(child is Child1 && true)) return child;
+  return null;
+}
+
+/*member: test3:[null|exact=Child2]*/
+test3() {
+  Base child = either;
+  if (trivial(child is Child1 && true) && child is Child2) return child;
+  return null;
+}
+
+/*member: test4:[null|exact=Child2]*/
+test4() {
+  Base child = either;
+  if (child is Child2 && trivial(child is Child1 && true)) return child;
+  return null;
+}
+
+/*member: test5:Union(null, [exact=Child1], [exact=Child2])*/
+test5() {
+  Base child = either;
+  if ((child is Child1 && true) /*invoke: [exact=JSBool]*/ == false)
+    return child;
+  return null;
+}
+
+/*member: test6:Union(null, [exact=Child1], [exact=Child2])*/
+test6() {
+  Base child = either;
+  if (trivial(child is Child1 ? false : true)) return child;
+  return null;
+}
+
+/*member: test7:Union(null, [exact=Child1], [exact=Child2])*/
+test7() {
+  Base child = either;
+  if (trivial(trivial(child is Child1 && true))) return child;
+  return null;
+}
+
+/*member: main:[null]*/
+main() {
+  test1();
+  test2();
+  test3();
+  test4();
+  test5();
+  test6();
+  test7();
+}
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart
new file mode 100644
index 0000000..8f917fa
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart
@@ -0,0 +1,26 @@
+Future<int> bar() {
+  return Future.value(123);
+}
+
+// Simple return-await statement.
+Future<int> foo1() async {
+  return await bar();
+}
+
+// Multiple return-await statements.
+Future<int> foo2(bool x) async {
+  if (x) return await Future.value(345);
+  return await bar();
+}
+
+// Combination of await and non-await returns. Wrap unawaited returns.
+Future<int> foo3(bool x) async {
+  if (x) return 234;
+  return await Future.value(123);
+}
+
+void main() {
+  foo1();
+  foo2(true);
+  foo3(true);
+}
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.strong.expect b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.strong.expect
new file mode 100644
index 0000000..7ea06af
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.strong.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method bar() → asy::Future<core::int> {
+  return asy::Future::value<core::int>(123);
+}
+static method foo1() → asy::Future<core::int> async /* futureValueType= core::int */ {
+  return await self::bar();
+}
+static method foo2(core::bool x) → asy::Future<core::int> async /* futureValueType= core::int */ {
+  if(x)
+    return await asy::Future::value<core::int>(345);
+  return await self::bar();
+}
+static method foo3(core::bool x) → asy::Future<core::int> async /* futureValueType= core::int */ {
+  if(x)
+    return 234;
+  return await asy::Future::value<core::int>(123);
+}
+static method main() → void {
+  self::foo1();
+  self::foo2(true);
+  self::foo3(true);
+}
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.strong.transformed.expect
new file mode 100644
index 0000000..0e794df
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.strong.transformed.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method bar() → asy::Future<core::int> {
+  return asy::Future::value<core::int>(123);
+}
+static method foo1() → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */ 
+  return asy::Future::sync<core::int>(() → FutureOr<core::int> {
+    return self::bar();
+  });
+static method foo2(core::bool x) → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */ 
+  return asy::Future::sync<core::int>(() → FutureOr<core::int> {
+    if(x)
+      return asy::Future::value<core::int>(345);
+    return self::bar();
+  });
+static method foo3(core::bool x) → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */ 
+  return asy::Future::sync<core::int>(() → FutureOr<core::int> {
+    if(x)
+      return 234;
+    return asy::Future::value<core::int>(123);
+  });
+static method main() → void {
+  self::foo1();
+  self::foo2(true);
+  self::foo3(true);
+}
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.textual_outline.expect
new file mode 100644
index 0000000..a361918
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+Future<int> bar() {}
+Future<int> foo1() async {}
+Future<int> foo2(bool x) async {}
+Future<int> foo3(bool x) async {}
+void main() {}
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a361918
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.textual_outline_modelled.expect
@@ -0,0 +1,5 @@
+Future<int> bar() {}
+Future<int> foo1() async {}
+Future<int> foo2(bool x) async {}
+Future<int> foo3(bool x) async {}
+void main() {}
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.expect b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.expect
new file mode 100644
index 0000000..7ea06af
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method bar() → asy::Future<core::int> {
+  return asy::Future::value<core::int>(123);
+}
+static method foo1() → asy::Future<core::int> async /* futureValueType= core::int */ {
+  return await self::bar();
+}
+static method foo2(core::bool x) → asy::Future<core::int> async /* futureValueType= core::int */ {
+  if(x)
+    return await asy::Future::value<core::int>(345);
+  return await self::bar();
+}
+static method foo3(core::bool x) → asy::Future<core::int> async /* futureValueType= core::int */ {
+  if(x)
+    return 234;
+  return await asy::Future::value<core::int>(123);
+}
+static method main() → void {
+  self::foo1();
+  self::foo2(true);
+  self::foo3(true);
+}
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.modular.expect
new file mode 100644
index 0000000..7ea06af
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.modular.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method bar() → asy::Future<core::int> {
+  return asy::Future::value<core::int>(123);
+}
+static method foo1() → asy::Future<core::int> async /* futureValueType= core::int */ {
+  return await self::bar();
+}
+static method foo2(core::bool x) → asy::Future<core::int> async /* futureValueType= core::int */ {
+  if(x)
+    return await asy::Future::value<core::int>(345);
+  return await self::bar();
+}
+static method foo3(core::bool x) → asy::Future<core::int> async /* futureValueType= core::int */ {
+  if(x)
+    return 234;
+  return await asy::Future::value<core::int>(123);
+}
+static method main() → void {
+  self::foo1();
+  self::foo2(true);
+  self::foo3(true);
+}
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.outline.expect
new file mode 100644
index 0000000..b0cdf1c
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.outline.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method bar() → asy::Future<core::int>
+  ;
+static method foo1() → asy::Future<core::int> async 
+  ;
+static method foo2(core::bool x) → asy::Future<core::int> async 
+  ;
+static method foo3(core::bool x) → asy::Future<core::int> async 
+  ;
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.transformed.expect
new file mode 100644
index 0000000..0e794df
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/async_lowering/collapse_return_await.dart.weak.transformed.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+static method bar() → asy::Future<core::int> {
+  return asy::Future::value<core::int>(123);
+}
+static method foo1() → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */ 
+  return asy::Future::sync<core::int>(() → FutureOr<core::int> {
+    return self::bar();
+  });
+static method foo2(core::bool x) → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */ 
+  return asy::Future::sync<core::int>(() → FutureOr<core::int> {
+    if(x)
+      return asy::Future::value<core::int>(345);
+    return self::bar();
+  });
+static method foo3(core::bool x) → asy::Future<core::int> /* futureValueType= core::int */ /* originally async */ 
+  return asy::Future::sync<core::int>(() → FutureOr<core::int> {
+    if(x)
+      return 234;
+    return asy::Future::value<core::int>(123);
+  });
+static method main() → void {
+  self::foo1();
+  self::foo2(true);
+  self::foo3(true);
+}
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart
index 8581d4c..bbef654 100644
--- a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart
+++ b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart
@@ -1,9 +1,11 @@
+// Contains await with no return.
 Future<void> foo1() async {
   await 6;
 }
 
+// Await is not direct child of return.
 Future<int> foo2() async {
-  return await 6;
+  return (await 6) + 3;
 }
 
 void main() {
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.strong.expect b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.strong.expect
index 10798bd8..eb616ff 100644
--- a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.strong.expect
+++ b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.strong.expect
@@ -7,7 +7,7 @@
   await 6;
 }
 static method foo2() → asy::Future<core::int> async /* futureValueType= core::int */ {
-  return await 6;
+  return (await 6).{core::num::+}(3){(core::num) → core::int};
 }
 static method main() → void {
   self::foo1();
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.strong.transformed.expect
index 10798bd8..eb616ff 100644
--- a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
   await 6;
 }
 static method foo2() → asy::Future<core::int> async /* futureValueType= core::int */ {
-  return await 6;
+  return (await 6).{core::num::+}(3){(core::num) → core::int};
 }
 static method main() → void {
   self::foo1();
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.expect b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.expect
index 10798bd8..eb616ff 100644
--- a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.expect
+++ b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.expect
@@ -7,7 +7,7 @@
   await 6;
 }
 static method foo2() → asy::Future<core::int> async /* futureValueType= core::int */ {
-  return await 6;
+  return (await 6).{core::num::+}(3){(core::num) → core::int};
 }
 static method main() → void {
   self::foo1();
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.modular.expect
index 10798bd8..eb616ff 100644
--- a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.modular.expect
@@ -7,7 +7,7 @@
   await 6;
 }
 static method foo2() → asy::Future<core::int> async /* futureValueType= core::int */ {
-  return await 6;
+  return (await 6).{core::num::+}(3){(core::num) → core::int};
 }
 static method main() → void {
   self::foo1();
diff --git a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.transformed.expect
index 10798bd8..eb616ff 100644
--- a/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/async_lowering/no_transform.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
   await 6;
 }
 static method foo2() → asy::Future<core::int> async /* futureValueType= core::int */ {
-  return await 6;
+  return (await 6).{core::num::+}(3){(core::num) → core::int};
 }
 static method main() → void {
   self::foo1();
diff --git a/tests/web/regress/issue/48571_test.dart b/tests/web/regress/issue/48571_test.dart
new file mode 100644
index 0000000..9a15a70
--- /dev/null
+++ b/tests/web/regress/issue/48571_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+abstract class Base {}
+
+class Child1 extends Base {}
+
+class Child2 extends Base {}
+
+bool trivial(x) => true;
+Base either = DateTime.now().millisecondsSinceEpoch > 0 ? Child2() : Child1();
+
+test1() {
+  Base child = either;
+  if (trivial(child is Child1 && true)) return child;
+  return null;
+}
+
+test2() {
+  Base child = either;
+  if (child is Child1 || trivial(child is Child1 && true)) return child;
+  return null;
+}
+
+test3() {
+  Base child = either;
+  if (trivial(child is Child1 && true) && child is Child2) return child;
+  return null;
+}
+
+test4() {
+  Base child = either;
+  if (child is Child2 && trivial(child is Child1 && true)) return child;
+  return null;
+}
+
+test5() {
+  Base child = either;
+  if ((child is Child1 && true) == false) return child;
+  return null;
+}
+
+test6() {
+  Base child = either;
+  if (trivial(child is Child1 ? false : true)) return child;
+  return null;
+}
+
+test7() {
+  Base child = either;
+  if (trivial(trivial(child is Child1 && true))) return child;
+  return null;
+}
+
+main() {
+  Expect.isTrue(test1() is Child2, "test1");
+  Expect.isTrue(test2() is Child2, "test2");
+  Expect.isTrue(test3() is Child2, "test3");
+  Expect.isTrue(test4() is Child2, "test4");
+  Expect.isTrue(test5() is Child2, "test5");
+  Expect.isTrue(test6() is Child2, "test6");
+  Expect.isTrue(test7() is Child2, "test7");
+}
diff --git a/tests/web_2/regress/issue/48571_test.dart b/tests/web_2/regress/issue/48571_test.dart
new file mode 100644
index 0000000..d724ffa
--- /dev/null
+++ b/tests/web_2/regress/issue/48571_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.7
+
+import 'package:expect/expect.dart';
+
+abstract class Base {}
+
+class Child1 extends Base {}
+
+class Child2 extends Base {}
+
+bool trivial(x) => true;
+Base either = DateTime.now().millisecondsSinceEpoch > 0 ? Child2() : Child1();
+
+test1() {
+  Base child = either;
+  if (trivial(child is Child1 && true)) return child;
+  return null;
+}
+
+test2() {
+  Base child = either;
+  if (child is Child1 || trivial(child is Child1 && true)) return child;
+  return null;
+}
+
+test3() {
+  Base child = either;
+  if (trivial(child is Child1 && true) && child is Child2) return child;
+  return null;
+}
+
+test4() {
+  Base child = either;
+  if (child is Child2 && trivial(child is Child1 && true)) return child;
+  return null;
+}
+
+test5() {
+  Base child = either;
+  if ((child is Child1 && true) == false) return child;
+  return null;
+}
+
+test6() {
+  Base child = either;
+  if (trivial(child is Child1 ? false : true)) return child;
+  return null;
+}
+
+test7() {
+  Base child = either;
+  if (trivial(trivial(child is Child1 && true))) return child;
+  return null;
+}
+
+main() {
+  Expect.isTrue(test1() is Child2, "test1");
+  Expect.isTrue(test2() is Child2, "test2");
+  Expect.isTrue(test3() is Child2, "test3");
+  Expect.isTrue(test4() is Child2, "test4");
+  Expect.isTrue(test5() is Child2, "test5");
+  Expect.isTrue(test6() is Child2, "test6");
+  Expect.isTrue(test7() is Child2, "test7");
+}
diff --git a/tools/VERSION b/tools/VERSION
index 8d5cf70..6233344 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 276
+PRERELEASE 277
 PRERELEASE_PATCH 0
\ No newline at end of file