Version 2.17.0-86.0.dev

Merge commit 'c9f223c5bd92762266423f3f6756595e7fed8cc5' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95cb252..fec38ce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -42,14 +42,14 @@
   was intended for use only by build systems like bazel, `build_web_compilers`
   and `flutter_tools`. The functionality remains available for those systems,
   but it is no longer exposed as a command-line tool in the SDK.
-  Please share any concerns in the 
+  Please share any concerns in the
   [breaking change tracking issue](https://github.com/dart-lang/sdk/issues/46100).
 
 - **Breaking Change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
   The standalone `dartdoc` tool has been removed as
   previously announced. Its replacement is the `dart doc` command.
 
-## 2.16.0
+## 2.16.0 - 2022-02-03
 
 ### Core libraries
 
@@ -118,7 +118,7 @@
 Updated the Linter to `1.18.0`, which includes changes that
 
 - extends `camel_case_types` to cover enums.
-- fixes `no_leading_underscores_for_local_identifiers` to not 
+- fixes `no_leading_underscores_for_local_identifiers` to not
   mis-flag field formal parameters with default values.
 - fixes `prefer_function_declarations_over_variables` to not
   mis-flag non-final fields.
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
index d35a1b0..36b560b 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
@@ -24,21 +24,14 @@
 /// This api is only available to the declaration and definition phases of
 /// macro expansion.
 abstract class TypeResolver {
-  /// Resolves [typeAnnotation] to a [StaticType].
+  /// Instantiates a new [StaticType] for a given [type] annotation.
   ///
-  /// Throws an error if the type annotation cannot be resolved. This should
-  /// only happen in the case of incomplete or invalid programs, but macros
-  /// may be asked to run in this state during the development cycle. It is
-  /// helpful for users if macros provide a best effort implementation in that
-  /// case or handle the error in a useful way.
-  Future<StaticType> instantiateType(covariant TypeAnnotation typeAnnotation);
-
-  /// Instantiates a new [StaticType] for a given [code] expression, which must
-  /// be a type expression.
-  ///
-  /// All type identifiers in [code] must be instances of [Identifier] and not
-  /// bare strings.
-  Future<StaticType> instantiateCode(ExpressionCode code);
+  /// Throws an error if the [type] object contains [Identifier]s which cannot
+  /// be resolved. This should only happen in the case of incomplete or invalid
+  /// programs, but macros may be asked to run in this state during the
+  /// development cycle. It may be helpful for users if macros provide a best
+  /// effort implementation in that case or handle the error in a useful way.
+  Future<StaticType> resolve(TypeAnnotationCode type);
 }
 
 /// The api used to introspect on a [ClassDeclaration].
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
index e7af1bd..6563aef 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/code.dart
@@ -32,18 +32,6 @@
   DeclarationCode.fromParts(List<Object> parts) : super.fromParts(parts);
 }
 
-/// A piece of code representing a syntactically valid element.
-///
-/// Should not include any trailing commas,
-class ElementCode extends Code {
-  @override
-  CodeKind get kind => CodeKind.element;
-
-  ElementCode.fromString(String code) : super.fromString(code);
-
-  ElementCode.fromParts(List<Object> parts) : super.fromParts(parts);
-}
-
 /// A piece of code representing a syntactically valid expression.
 class ExpressionCode extends Code {
   @override
@@ -69,67 +57,200 @@
   FunctionBodyCode.fromParts(List<Object> parts) : super.fromParts(parts);
 }
 
-/// A piece of code identifying a named argument.
-///
-/// This should not include any trailing commas.
-class NamedArgumentCode extends Code {
-  @override
-  CodeKind get kind => CodeKind.namedArgument;
-
-  NamedArgumentCode.fromString(String code) : super.fromString(code);
-
-  NamedArgumentCode.fromParts(List<Object> parts) : super.fromParts(parts);
-}
-
 /// A piece of code identifying a syntactically valid function parameter.
 ///
-/// This should not include any trailing commas, but may include modifiers
-/// such as `required`, and default values.
+/// There is no distinction here made between named and positional parameters.
 ///
-/// There is no distinction here made between named and positional parameters,
-/// nor between optional or required parameters. It is the job of the user to
-/// construct and combine these together in a way that creates valid parameter
-/// lists.
-class ParameterCode extends Code {
+/// It is the job of the user to construct and combine these together in a way
+/// that creates valid parameter lists.
+class ParameterCode implements Code {
+  final Code? defaultValue;
+  final List<String> keywords;
+  final String name;
+  final TypeAnnotationCode? type;
+
   @override
   CodeKind get kind => CodeKind.parameter;
 
-  ParameterCode.fromString(String code) : super.fromString(code);
-
-  ParameterCode.fromParts(List<Object> parts) : super.fromParts(parts);
-}
-
-/// A piece of code representing a syntactically valid statement.
-///
-/// Should always end with a semicolon.
-class StatementCode extends Code {
   @override
-  CodeKind get kind => CodeKind.statement;
+  List<Object> get parts => [
+        if (keywords.isNotEmpty) ...[
+          ...keywords.joinAsCode(' '),
+          ' ',
+        ],
+        if (type != null) ...[
+          type!,
+          ' ',
+        ],
+        name,
+        if (defaultValue != null) ...[
+          ' = ',
+          defaultValue!,
+        ]
+      ];
 
-  StatementCode.fromString(String code) : super.fromString(code);
-
-  StatementCode.fromParts(List<Object> parts) : super.fromParts(parts);
+  ParameterCode({
+    this.defaultValue,
+    this.keywords = const [],
+    required this.name,
+    this.type,
+  });
 }
 
-extension Join<T extends Code> on List<T> {
+/// A piece of code representing a type annotation.
+abstract class TypeAnnotationCode implements Code {
+  /// Returns a [TypeAnnotationCode] object which is a non-nullable version
+  /// of this one.
+  ///
+  /// Returns the current instance if it is already non-nullable.
+  TypeAnnotationCode get asNonNullable => this;
+
+  /// Returns a [TypeAnnotationCode] object which is a non-nullable version
+  /// of this one.
+  ///
+  /// Returns the current instance if it is already nullable.
+  NullableTypeAnnotationCode get asNullable =>
+      new NullableTypeAnnotationCode(this);
+
+  /// Whether or not this type is nullable.
+  bool get isNullable => false;
+}
+
+/// The nullable version of an underlying type annotation.
+class NullableTypeAnnotationCode implements TypeAnnotationCode {
+  /// The underlying type that is being made nullable.
+  TypeAnnotationCode underlyingType;
+
+  @override
+  CodeKind get kind => CodeKind.nullableTypeAnnotation;
+
+  @override
+  List<Object> get parts => [...underlyingType.parts, '?'];
+
+  /// Creates a nullable [underlyingType] annotation.
+  ///
+  /// If [underlyingType] is a NullableTypeAnnotationCode, returns that
+  /// same type.
+  NullableTypeAnnotationCode(this.underlyingType);
+
+  @override
+  TypeAnnotationCode get asNonNullable => underlyingType;
+
+  @override
+  NullableTypeAnnotationCode get asNullable => this;
+
+  @override
+  bool get isNullable => true;
+}
+
+/// A piece of code representing a reference to a named type.
+class NamedTypeAnnotationCode extends TypeAnnotationCode {
+  final Identifier name;
+
+  final List<TypeAnnotationCode> typeArguments;
+
+  @override
+  CodeKind get kind => CodeKind.namedTypeAnnotation;
+
+  @override
+  List<Object> get parts => [
+        name,
+        if (typeArguments.isNotEmpty) ...[
+          '<',
+          ...typeArguments.joinAsCode(', '),
+          '>',
+        ],
+      ];
+
+  NamedTypeAnnotationCode({required this.name, this.typeArguments = const []});
+}
+
+/// A piece of code representing a function type annotation.
+class FunctionTypeAnnotationCode extends TypeAnnotationCode {
+  final List<ParameterCode> namedParameters;
+
+  final List<ParameterCode> positionalParameters;
+
+  final TypeAnnotationCode? returnType;
+
+  final List<TypeParameterCode> typeParameters;
+
+  @override
+  CodeKind get kind => CodeKind.functionTypeAnnotation;
+
+  @override
+  List<Object> get parts => [
+        if (returnType != null) returnType!,
+        ' Function',
+        if (typeParameters.isNotEmpty) ...[
+          '<',
+          ...typeParameters.joinAsCode(', '),
+          '>',
+        ],
+        '(',
+        for (ParameterCode positional in positionalParameters) ...[
+          positional,
+          ', ',
+        ],
+        if (namedParameters.isNotEmpty) ...[
+          '{',
+          for (ParameterCode named in namedParameters) ...[
+            named,
+            ', ',
+          ],
+          '}',
+        ],
+        ')',
+      ];
+
+  FunctionTypeAnnotationCode({
+    this.namedParameters = const [],
+    this.positionalParameters = const [],
+    this.returnType,
+    this.typeParameters = const [],
+  });
+}
+
+/// A piece of code representing a valid named type parameter.
+class TypeParameterCode implements Code {
+  final TypeAnnotationCode? bound;
+  final String name;
+
+  @override
+  CodeKind get kind => CodeKind.typeParameter;
+
+  @override
+  List<Object> get parts => [
+        name,
+        if (bound != null) ...[
+          ' extends ',
+          bound!,
+        ]
+      ];
+
+  TypeParameterCode({this.bound, required this.name});
+}
+
+extension Join<T extends Object> on List<T> {
   /// Joins all the items in [this] with [separator], and returns
   /// a new list.
-  List<Code> joinAsCode(String separator) => [
+  List<Object> joinAsCode(String separator) => [
         for (int i = 0; i < length - 1; i++) ...[
           this[i],
-          new Code.fromString(separator),
+          separator,
         ],
         last,
       ];
 }
 
 enum CodeKind {
-  raw,
   declaration,
-  element,
   expression,
   functionBody,
-  namedArgument,
+  functionTypeAnnotation,
+  namedTypeAnnotation,
+  nullableTypeAnnotation,
   parameter,
-  statement,
+  raw,
+  typeParameter,
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
index d78d9e4..f9296fc 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
@@ -24,10 +24,9 @@
   /// trailing `?`)
   bool get isNullable;
 
-  /// A convenience method to get a [Code] object representation of this full
-  /// type annotation, including support for generic type arguments as well as
-  /// function types.
-  Code get code;
+  /// A convenience method to get a [Code] object equivalent to this type
+  /// annotation.
+  TypeAnnotationCode get code;
 }
 
 /// The base class for function type declarations.
@@ -176,10 +175,6 @@
 
   /// The type of this field.
   TypeAnnotation get type;
-
-  /// A [ExpressionCode] object representing the initializer for this field, if
-  /// present.
-  ExpressionCode? get initializer;
 }
 
 /// Field introspection information.
@@ -198,13 +193,19 @@
   /// parameter or an optional parameter with the `required` keyword.
   bool get isRequired;
 
-  /// A [Code] object representing the default value for this parameter, if
-  /// present. Can be used to copy default values to other parameters.
-  Code? get defaultValue;
+  /// A convenience method to get a `code` object equivalent to this parameter.
+  ///
+  /// Note that the original default value will not be included, as it is not a
+  /// part of this API.
+  ParameterCode get code;
 }
 
 /// Type parameter introspection information.
 abstract class TypeParameterDeclaration implements Declaration {
-  /// The bounds for this type parameter, if it has any.
-  TypeAnnotation? get bounds;
+  /// The bound for this type parameter, if it has any.
+  TypeAnnotation? get bound;
+
+  /// A convenience method to get a `code` object equivalent to this type
+  /// parameter.
+  TypeParameterCode get code;
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
index caba317..9f14be98 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/builder_impls.dart
@@ -72,12 +72,8 @@
       classIntrospector.superclassOf(clazz);
 
   @override
-  Future<StaticType> instantiateCode(ExpressionCode code) =>
-      typeResolver.instantiateCode(code);
-
-  @override
-  Future<StaticType> instantiateType(TypeAnnotation typeAnnotation) =>
-      typeResolver.instantiateType(typeAnnotation);
+  Future<StaticType> resolve(TypeAnnotationCode code) =>
+      typeResolver.resolve(code);
 }
 
 class DeclarationBuilderImpl extends DeclarationBuilderBase
@@ -323,31 +319,23 @@
       '<',
       for (TypeParameterDeclaration typeParam
           in declaration.typeParameters) ...[
-        typeParam.identifier,
-        if (typeParam.bounds != null) ...['extends ', typeParam.bounds!.code],
+        typeParam.identifier.name,
+        if (typeParam.bound != null) ...[' extends ', typeParam.bound!.code],
         if (typeParam != declaration.typeParameters.last) ', ',
       ],
       '>',
     ],
     '(',
     for (ParameterDeclaration positionalRequired
-        in declaration.positionalParameters.where((p) => p.isRequired)) ...[
-      new ParameterCode.fromParts([
-        positionalRequired.type.code,
-        ' ',
-        positionalRequired.identifier.name,
-      ]),
-      ', '
+        in declaration.positionalParameters.takeWhile((p) => p.isRequired)) ...[
+      positionalRequired.code,
+      ', ',
     ],
     if (declaration.positionalParameters.any((p) => !p.isRequired)) ...[
       '[',
       for (ParameterDeclaration positionalOptional
           in declaration.positionalParameters.where((p) => !p.isRequired)) ...[
-        new ParameterCode.fromParts([
-          positionalOptional.type.code,
-          ' ',
-          positionalOptional.identifier.name,
-        ]),
+        positionalOptional.code,
         ', ',
       ],
       ']',
@@ -355,16 +343,7 @@
     if (declaration.namedParameters.isNotEmpty) ...[
       '{',
       for (ParameterDeclaration named in declaration.namedParameters) ...[
-        new ParameterCode.fromParts([
-          if (named.isRequired) 'required ',
-          named.type.code,
-          ' ',
-          named.identifier,
-          if (named.defaultValue != null) ...[
-            ' = ',
-            named.defaultValue!,
-          ],
-        ]),
+        named.code,
         ', ',
       ],
       '}',
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
index 9fbb7c1..baf884d 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/introspection_impls.dart
@@ -48,16 +48,13 @@
 class NamedTypeAnnotationImpl extends TypeAnnotationImpl
     implements NamedTypeAnnotation {
   @override
-  Code get code => new Code.fromParts([
-        identifier,
-        if (typeArguments.isNotEmpty) ...[
-          '<',
-          typeArguments.first.code,
-          for (TypeAnnotation arg in typeArguments.skip(1)) ...[', ', arg.code],
-          '>',
-        ],
-        if (isNullable) '?',
-      ]);
+  TypeAnnotationCode get code {
+    NamedTypeAnnotationCode underlyingType =
+        new NamedTypeAnnotationCode(name: identifier, typeArguments: [
+      for (TypeAnnotation typeArg in typeArguments) typeArg.code,
+    ]);
+    return isNullable ? underlyingType.asNullable : underlyingType;
+  }
 
   @override
   final IdentifierImpl identifier;
@@ -95,39 +92,23 @@
 class FunctionTypeAnnotationImpl extends TypeAnnotationImpl
     implements FunctionTypeAnnotation {
   @override
-  Code get code => new Code.fromParts([
-        returnType.code,
-        'Function',
-        if (typeParameters.isNotEmpty) ...[
-          '<',
-          typeParameters.first.identifier.name,
-          if (typeParameters.first.bounds != null) ...[
-            ' extends ',
-            typeParameters.first.bounds!.code,
-          ],
-          for (TypeParameterDeclaration arg in typeParameters.skip(1)) ...[
-            ', ',
-            arg.identifier.name,
-            if (arg.bounds != null) ...[' extends ', arg.bounds!.code],
-          ],
-          '>',
-        ],
-        '(',
-        for (ParameterDeclaration positional in positionalParameters) ...[
-          positional.type.code,
-          ' ${positional.identifier.name}',
-        ],
-        if (namedParameters.isNotEmpty) ...[
-          '{',
-          for (ParameterDeclaration named in namedParameters) ...[
-            named.type.code,
-            ' ${named.identifier.name}',
-          ],
-          '}',
-        ],
-        ')',
-        if (isNullable) '?',
-      ]);
+  TypeAnnotationCode get code {
+    FunctionTypeAnnotationCode underlyingType = new FunctionTypeAnnotationCode(
+      returnType: returnType.code,
+      typeParameters: [
+        for (TypeParameterDeclaration typeParam in typeParameters)
+          typeParam.code,
+      ],
+      positionalParameters: [
+        for (ParameterDeclaration positional in positionalParameters)
+          positional.code,
+      ],
+      namedParameters: [
+        for (ParameterDeclaration named in namedParameters) named.code,
+      ],
+    );
+    return isNullable ? underlyingType.asNullable : underlyingType;
+  }
 
   @override
   final List<ParameterDeclarationImpl> namedParameters;
@@ -203,9 +184,6 @@
 class ParameterDeclarationImpl extends DeclarationImpl
     implements ParameterDeclaration {
   @override
-  final Code? defaultValue;
-
-  @override
   final bool isNamed;
 
   @override
@@ -220,7 +198,6 @@
   ParameterDeclarationImpl({
     required int id,
     required IdentifierImpl identifier,
-    required this.defaultValue,
     required this.isNamed,
     required this.isRequired,
     required this.type,
@@ -234,21 +211,22 @@
       return;
     }
 
-    if (defaultValue == null) {
-      serializer.addNull();
-    } else {
-      defaultValue!.serialize(serializer);
-    }
     serializer.addBool(isNamed);
     serializer.addBool(isRequired);
     type.serialize(serializer);
   }
+
+  @override
+  ParameterCode get code =>
+      new ParameterCode(name: identifier.name, type: type.code, keywords: [
+        if (isNamed && isRequired) 'required',
+      ]);
 }
 
 class TypeParameterDeclarationImpl extends DeclarationImpl
     implements TypeParameterDeclaration {
   @override
-  final TypeAnnotationImpl? bounds;
+  final TypeAnnotationImpl? bound;
 
   @override
   RemoteInstanceKind get kind => RemoteInstanceKind.typeParameterDeclaration;
@@ -256,7 +234,7 @@
   TypeParameterDeclarationImpl({
     required int id,
     required IdentifierImpl identifier,
-    required this.bounds,
+    required this.bound,
   }) : super(id: id, identifier: identifier);
 
   @override
@@ -267,13 +245,17 @@
       return;
     }
 
-    TypeAnnotationImpl? bounds = this.bounds;
-    if (bounds == null) {
+    TypeAnnotationImpl? bound = this.bound;
+    if (bound == null) {
       serializer.addNull();
     } else {
-      bounds.serialize(serializer);
+      bound.serialize(serializer);
     }
   }
+
+  @override
+  TypeParameterCode get code =>
+      new TypeParameterCode(name: identifier.name, bound: bound?.code);
 }
 
 class FunctionDeclarationImpl extends DeclarationImpl
@@ -462,9 +444,6 @@
 class VariableDeclarationImpl extends DeclarationImpl
     implements VariableDeclaration {
   @override
-  final ExpressionCode? initializer;
-
-  @override
   final bool isExternal;
 
   @override
@@ -482,7 +461,6 @@
   VariableDeclarationImpl({
     required int id,
     required IdentifierImpl identifier,
-    required this.initializer,
     required this.isExternal,
     required this.isFinal,
     required this.isLate,
@@ -497,7 +475,6 @@
       return;
     }
 
-    initializer.serializeNullable(serializer);
     serializer
       ..addBool(isExternal)
       ..addBool(isFinal)
@@ -516,7 +493,6 @@
     required int id,
     required IdentifierImpl identifier,
     // Variable fields
-    required ExpressionCode? initializer,
     required bool isExternal,
     required bool isFinal,
     required bool isLate,
@@ -526,7 +502,6 @@
   }) : super(
             id: id,
             identifier: identifier,
-            initializer: initializer,
             isExternal: isExternal,
             isFinal: isFinal,
             isLate: isLate,
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
index 7dd6004..f3a3bf7 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/protocol.dart
@@ -343,26 +343,26 @@
   }
 }
 
-/// A request to reflect on a type annotation
-class InstantiateTypeRequest extends Request {
-  final TypeAnnotationImpl typeAnnotation;
+/// A request to resolve on a type annotation code object
+class ResolveTypeRequest extends Request {
+  final TypeAnnotationCode typeAnnotationCode;
   final RemoteInstanceImpl typeResolver;
 
-  InstantiateTypeRequest(this.typeAnnotation, this.typeResolver,
+  ResolveTypeRequest(this.typeAnnotationCode, this.typeResolver,
       {required int serializationZoneId})
       : super(serializationZoneId: serializationZoneId);
 
   /// When deserializing we have already consumed the message type, so we don't
   /// consume it again.
-  InstantiateTypeRequest.deserialize(
+  ResolveTypeRequest.deserialize(
       Deserializer deserializer, int serializationZoneId)
-      : typeAnnotation = RemoteInstance.deserialize(deserializer),
+      : typeAnnotationCode = (deserializer..moveNext()).expectCode(),
         typeResolver = RemoteInstance.deserialize(deserializer),
         super.deserialize(deserializer, serializationZoneId);
 
   void serialize(Serializer serializer) {
-    serializer.addNum(MessageType.instantiateTypeRequest.index);
-    typeAnnotation.serialize(serializer);
+    serializer.addNum(MessageType.resolveTypeRequest.index);
+    typeAnnotationCode.serialize(serializer);
     typeResolver.serialize(serializer);
     super.serialize(serializer);
   }
@@ -491,8 +491,8 @@
       {required this.remoteInstance, required this.serializationZoneId});
 
   @override
-  Future<StaticType> instantiateType(TypeAnnotationImpl typeAnnotation) async {
-    InstantiateTypeRequest request = new InstantiateTypeRequest(
+  Future<StaticType> resolve(TypeAnnotationCode typeAnnotation) async {
+    ResolveTypeRequest request = new ResolveTypeRequest(
         typeAnnotation, remoteInstance,
         serializationZoneId: serializationZoneId);
     RemoteInstanceImpl remoteType =
@@ -512,12 +512,6 @@
             '${remoteType.kind}');
     }
   }
-
-  @override
-  Future<StaticType> instantiateCode(ExpressionCode code) {
-    // TODO: implement instantiateCode
-    throw new UnimplementedError();
-  }
 }
 
 class ClientStaticTypeImpl implements StaticType {
@@ -705,7 +699,7 @@
   executeDefinitionsPhaseRequest,
   executeTypesPhaseRequest,
   instantiateMacroRequest,
-  instantiateTypeRequest,
+  resolveTypeRequest,
   isExactlyTypeRequest,
   isSubtypeOfRequest,
   loadMacroRequest,
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
index d11ec37..191509f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/serialization_extensions.dart
@@ -97,7 +97,6 @@
       new ParameterDeclarationImpl(
         id: id,
         identifier: expectRemoteInstance(),
-        defaultValue: (this..moveNext()).checkNull() ? null : expectCode(),
         isNamed: (this..moveNext()).expectBool(),
         isRequired: (this..moveNext()).expectBool(),
         type: RemoteInstance.deserialize(this),
@@ -107,7 +106,7 @@
       new TypeParameterDeclarationImpl(
         id: id,
         identifier: expectRemoteInstance(),
-        bounds: (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
+        bound: (this..moveNext()).checkNull() ? null : expectRemoteInstance(),
       );
 
   FunctionDeclaration _expectFunctionDeclaration(int id) =>
@@ -162,7 +161,6 @@
       new VariableDeclarationImpl(
         id: id,
         identifier: expectRemoteInstance(),
-        initializer: (this..moveNext()).expectNullableCode(),
         isExternal: (this..moveNext()).expectBool(),
         isFinal: (this..moveNext()).expectBool(),
         isLate: (this..moveNext()).expectBool(),
@@ -172,7 +170,6 @@
   FieldDeclaration _expectFieldDeclaration(int id) => new FieldDeclarationImpl(
         id: id,
         identifier: expectRemoteInstance(),
-        initializer: (this..moveNext()).expectNullableCode(),
         isExternal: (this..moveNext()).expectBool(),
         isFinal: (this..moveNext()).expectBool(),
         isLate: (this..moveNext()).expectBool(),
@@ -200,44 +197,83 @@
         aliasedType: RemoteInstance.deserialize(this),
       );
 
-  T expectCode<T extends Code>() {
-    CodeKind kind = CodeKind.values[expectNum()];
+  List<String> _readStringList() => [
+        for (bool hasNext = (this
+                  ..moveNext()
+                  ..expectList())
+                .moveNext();
+            hasNext;
+            hasNext = moveNext())
+          expectString(),
+      ];
+
+  List<T> _readCodeList<T extends Code>() => [
+        for (bool hasNext = (this
+                  ..moveNext()
+                  ..expectList())
+                .moveNext();
+            hasNext;
+            hasNext = moveNext())
+          expectCode(),
+      ];
+
+  List<Object> _readParts() {
     moveNext();
     expectList();
     List<Object> parts = [];
     while (moveNext()) {
-      CodePartKind partKind = CodePartKind.values[expectNum()];
+      _CodePartKind partKind = _CodePartKind.values[expectNum()];
       moveNext();
       switch (partKind) {
-        case CodePartKind.code:
+        case _CodePartKind.code:
           parts.add(expectCode());
           break;
-        case CodePartKind.string:
+        case _CodePartKind.string:
           parts.add(expectString());
           break;
-        case CodePartKind.identifier:
+        case _CodePartKind.identifier:
           parts.add(expectRemoteInstance());
           break;
       }
     }
+    return parts;
+  }
+
+  T expectCode<T extends Code>() {
+    CodeKind kind = CodeKind.values[expectNum()];
 
     switch (kind) {
       case CodeKind.raw:
-        return new Code.fromParts(parts) as T;
+        return new Code.fromParts(_readParts()) as T;
       case CodeKind.declaration:
-        return new DeclarationCode.fromParts(parts) as T;
-      case CodeKind.element:
-        return new ElementCode.fromParts(parts) as T;
+        return new DeclarationCode.fromParts(_readParts()) as T;
       case CodeKind.expression:
-        return new ExpressionCode.fromParts(parts) as T;
+        return new ExpressionCode.fromParts(_readParts()) as T;
       case CodeKind.functionBody:
-        return new FunctionBodyCode.fromParts(parts) as T;
-      case CodeKind.namedArgument:
-        return new NamedArgumentCode.fromParts(parts) as T;
+        return new FunctionBodyCode.fromParts(_readParts()) as T;
+      case CodeKind.functionTypeAnnotation:
+        return new FunctionTypeAnnotationCode(
+            namedParameters: _readCodeList(),
+            positionalParameters: _readCodeList(),
+            returnType: (this..moveNext()).expectNullableCode(),
+            typeParameters: _readCodeList()) as T;
+      case CodeKind.namedTypeAnnotation:
+        return new NamedTypeAnnotationCode(
+            name: RemoteInstance.deserialize(this),
+            typeArguments: _readCodeList()) as T;
+      case CodeKind.nullableTypeAnnotation:
+        return new NullableTypeAnnotationCode((this..moveNext()).expectCode())
+            as T;
       case CodeKind.parameter:
-        return new ParameterCode.fromParts(parts) as T;
-      case CodeKind.statement:
-        return new StatementCode.fromParts(parts) as T;
+        return new ParameterCode(
+            defaultValue: (this..moveNext()).expectNullableCode(),
+            keywords: _readStringList(),
+            name: (this..moveNext()).expectString(),
+            type: (this..moveNext()).expectNullableCode()) as T;
+      case CodeKind.typeParameter:
+        return new TypeParameterCode(
+            bound: (this..moveNext()).expectNullableCode(),
+            name: (this..moveNext()).expectString()) as T;
     }
   }
 
@@ -273,29 +309,82 @@
 
 extension SerializeCode on Code {
   void serialize(Serializer serializer) {
-    serializer
-      ..addNum(kind.index)
-      ..startList();
-    for (Object part in parts) {
-      if (part is String) {
+    serializer.addNum(kind.index);
+    switch (kind) {
+      case CodeKind.namedTypeAnnotation:
+        NamedTypeAnnotationCode self = this as NamedTypeAnnotationCode;
+        (self.name as IdentifierImpl).serialize(serializer);
+        serializer.startList();
+        for (TypeAnnotationCode typeArg in self.typeArguments) {
+          typeArg.serialize(serializer);
+        }
+        serializer.endList();
+        return;
+      case CodeKind.functionTypeAnnotation:
+        FunctionTypeAnnotationCode self = this as FunctionTypeAnnotationCode;
+        serializer.startList();
+        for (ParameterCode named in self.namedParameters) {
+          named.serialize(serializer);
+        }
         serializer
-          ..addNum(CodePartKind.string.index)
-          ..addString(part);
-      } else if (part is Code) {
-        serializer.addNum(CodePartKind.code.index);
-        part.serialize(serializer);
-      } else if (part is IdentifierImpl) {
-        serializer.addNum(CodePartKind.identifier.index);
-        part.serialize(serializer);
-      } else {
-        throw new StateError('Unrecognized code part $part');
-      }
+          ..endList()
+          ..startList();
+        for (ParameterCode positional in self.positionalParameters) {
+          positional.serialize(serializer);
+        }
+        serializer..endList();
+        self.returnType.serializeNullable(serializer);
+        serializer.startList();
+        for (TypeParameterCode typeParam in self.typeParameters) {
+          typeParam.serialize(serializer);
+        }
+        serializer.endList();
+        return;
+      case CodeKind.nullableTypeAnnotation:
+        NullableTypeAnnotationCode self = this as NullableTypeAnnotationCode;
+        self.underlyingType.serialize(serializer);
+        return;
+      case CodeKind.parameter:
+        ParameterCode self = this as ParameterCode;
+        self.defaultValue.serializeNullable(serializer);
+        serializer.startList();
+        for (String keyword in self.keywords) {
+          serializer.addString(keyword);
+        }
+        serializer
+          ..endList()
+          ..addString(self.name);
+        self.type.serializeNullable(serializer);
+        return;
+      case CodeKind.typeParameter:
+        TypeParameterCode self = this as TypeParameterCode;
+        self.bound.serializeNullable(serializer);
+        serializer.addString(self.name);
+        return;
+      default:
+        serializer.startList();
+        for (Object part in parts) {
+          if (part is String) {
+            serializer
+              ..addNum(_CodePartKind.string.index)
+              ..addString(part);
+          } else if (part is Code) {
+            serializer.addNum(_CodePartKind.code.index);
+            part.serialize(serializer);
+          } else if (part is IdentifierImpl) {
+            serializer.addNum(_CodePartKind.identifier.index);
+            part.serialize(serializer);
+          } else {
+            throw new StateError('Unrecognized code part $part');
+          }
+        }
+        serializer.endList();
+        return;
     }
-    serializer.endList();
   }
 }
 
-enum CodePartKind {
+enum _CodePartKind {
   string,
   code,
   identifier,
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
index 198d388..7713aa3 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolated_executor/isolated_executor.dart
@@ -151,12 +151,12 @@
               }
               completer.complete(response);
               break;
-            case MessageType.instantiateTypeRequest:
-              InstantiateTypeRequest request =
-                  new InstantiateTypeRequest.deserialize(deserializer, zoneId);
+            case MessageType.resolveTypeRequest:
+              ResolveTypeRequest request =
+                  new ResolveTypeRequest.deserialize(deserializer, zoneId);
               StaticType instance =
                   await (request.typeResolver.instance as TypeResolver)
-                      .instantiateType(request.typeAnnotation);
+                      .resolve(request.typeAnnotationCode);
               SerializableResponse response = new SerializableResponse(
                   response: new RemoteInstanceImpl(
                       id: RemoteInstance.uniqueId,
diff --git a/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart b/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
index aabcf97..879ae11 100644
--- a/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/executor_shared/serialization_test.dart
@@ -124,7 +124,6 @@
 
       final fooNamedParam = ParameterDeclarationImpl(
           id: RemoteInstance.uniqueId,
-          defaultValue: null,
           isNamed: true,
           isRequired: true,
           identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'foo'),
@@ -132,7 +131,6 @@
 
       final barPositionalParam = ParameterDeclarationImpl(
           id: RemoteInstance.uniqueId,
-          defaultValue: Code.fromString('const Bar()'),
           isNamed: false,
           isRequired: false,
           identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'bar'),
@@ -141,7 +139,7 @@
       final zapTypeParam = TypeParameterDeclarationImpl(
           id: RemoteInstance.uniqueId,
           identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'Zap'),
-          bounds: barType);
+          bound: barType);
 
       // Transitively tests `TypeParameterDeclaration` and
       // `ParameterDeclaration`.
@@ -218,7 +216,6 @@
           isExternal: true,
           isFinal: false,
           isLate: true,
-          initializer: ExpressionCode.fromString('Bar()'),
           type: barType,
         );
         expectSerializationEquality(bar);
@@ -231,7 +228,6 @@
           isExternal: false,
           isFinal: true,
           isLate: false,
-          initializer: null,
           type: barType,
           definingClass: fooType.identifier,
         );
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
index 30fac31..a2223c9 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/isolate_mirror_executor_test.dart
@@ -77,7 +77,7 @@
           typeParameters: [],
         ),
         TestTypeResolver({
-          returnType:
+          returnType.identifier:
               TestNamedStaticType(returnType.identifier, 'dart:core', [])
         }),
         FakeClassIntrospector(),
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
index 7972041..f23aa43 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolate_mirror_executor/simple_macro.dart
@@ -27,7 +27,7 @@
     }
 
     // Test the type resolver and static type interfaces
-    var staticReturnType = await builder.instantiateType(method.returnType);
+    var staticReturnType = await builder.resolve(method.returnType.code);
     if (!(await staticReturnType.isExactly(staticReturnType))) {
       throw StateError('The return type should be exactly equal to itself!');
     }
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
index cdd1725..5710e81 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/isolated_executor_test.dart
@@ -350,7 +350,7 @@
                   augment super = value;
                 }'''),
               equalsIgnoringWhitespace('''
-                augment final String _myVariable = '';
+                augment final String _myVariable = 'new initial value' + augment super;
                 '''),
             ]));
       });
@@ -415,6 +415,7 @@
   augment set myField(String value) {
     augment super = value;
   }
+  augment String myField = \'new initial value\' + augment super;
 }''');
 
 final methodDefinitionMatchers = [
diff --git a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
index 79f9b2e..b5a2d2d 100644
--- a/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/isolated_executor/simple_macro.dart
@@ -204,7 +204,7 @@
     var constructors = (await builder.constructorsOf(parentClass));
 
     // Test the type resolver and static type interfaces
-    var staticReturnType = await builder.instantiateType(method.returnType);
+    var staticReturnType = await builder.resolve(method.returnType.code);
     if (!(await staticReturnType.isExactly(staticReturnType))) {
       throw StateError('The return type should be exactly equal to itself!');
     }
@@ -213,8 +213,7 @@
     }
 
     // TODO: Use `builder.instantiateCode` instead once implemented.
-    var classType =
-        await builder.instantiateType(constructors.first.returnType);
+    var classType = await builder.resolve(constructors.first.returnType.code);
     if (await staticReturnType.isExactly(classType)) {
       throw StateError(
           'The return type should not be exactly equal to the class type');
@@ -270,7 +269,8 @@
         variable.type.code,
         ' value) { augment super = value; }'
       ]),
-      initializer: variable.initializer,
+      initializer:
+          ExpressionCode.fromString("'new initial value' + augment super"),
     );
   }
 
@@ -282,9 +282,9 @@
       return [
         if (!isFirst) ', ',
         typeParam.identifier.name,
-        if (typeParam.bounds != null) ...[
+        if (typeParam.bound != null) ...[
           ' extends ',
-          typeParam.bounds!.code,
+          typeParam.bound!.code,
         ]
       ];
     }
@@ -374,19 +374,17 @@
         "print('positionalParam: ",
         param.type.code,
         ' ${param.identifier.name}',
-        if (param.defaultValue != null) ...[' = ', param.defaultValue!],
         "');\n",
       ],
       for (var param in function.namedParameters) ...[
         "print('namedParam: ",
         param.type.code,
         ' ${param.identifier.name}',
-        if (param.defaultValue != null) ...[' = ', param.defaultValue!],
         "');\n",
       ],
       for (var param in function.typeParameters) ...[
         "print('typeParam: ${param.identifier.name} ",
-        if (param.bounds != null) param.bounds!.code,
+        if (param.bound != null) param.bound!.code,
         "');\n",
       ],
       'return augment super',
diff --git a/pkg/_fe_analyzer_shared/test/macros/util.dart b/pkg/_fe_analyzer_shared/test/macros/util.dart
index d9c1f51..34625b2 100644
--- a/pkg/_fe_analyzer_shared/test/macros/util.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/util.dart
@@ -76,20 +76,14 @@
 }
 
 class TestTypeResolver implements TypeResolver {
-  final Map<TypeAnnotation, StaticType> staticTypes;
+  final Map<Identifier, StaticType> staticTypes;
 
   TestTypeResolver(this.staticTypes);
 
   @override
-  Future<StaticType> instantiateType(
-      covariant TypeAnnotation typeAnnotation) async {
-    return staticTypes[typeAnnotation]!;
-  }
-
-  @override
-  Future<StaticType> instantiateCode(ExpressionCode code) {
-    // TODO: implement instantiateCode
-    throw UnimplementedError();
+  Future<StaticType> resolve(covariant TypeAnnotationCode type) async {
+    assert(type.parts.length == 1);
+    return staticTypes[type.parts.first]!;
   }
 }
 
@@ -262,7 +256,6 @@
       id: RemoteInstance.uniqueId,
       identifier:
           IdentifierImpl(id: RemoteInstance.uniqueId, name: '_myVariable'),
-      initializer: ExpressionCode.fromString("''"),
       isExternal: false,
       isFinal: true,
       isLate: false,
@@ -295,7 +288,6 @@
             id: RemoteInstance.uniqueId,
             identifier:
                 IdentifierImpl(id: RemoteInstance.uniqueId, name: 'value'),
-            defaultValue: null,
             isNamed: false,
             isRequired: true,
             type: stringType)
@@ -353,7 +345,6 @@
   static final myField = FieldDeclarationImpl(
       id: RemoteInstance.uniqueId,
       identifier: IdentifierImpl(id: RemoteInstance.uniqueId, name: 'myField'),
-      initializer: null,
       isExternal: false,
       isFinal: false,
       isLate: false,
@@ -404,8 +395,9 @@
       myClassType.identifier, 'package:my_package/my_package.dart', []);
 
   static final testTypeResolver = TestTypeResolver({
-    stringType: TestNamedStaticType(stringType.identifier, 'dart:core', []),
-    myClassType: myClassStaticType,
+    stringType.identifier:
+        TestNamedStaticType(stringType.identifier, 'dart:core', []),
+    myClass.identifier: myClassStaticType,
   });
   static final testClassIntrospector = TestClassIntrospector(
     constructors: {
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
index ffba325..5e3a9c5 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -36,7 +36,6 @@
     aliasedType: aliasedType,
     parameters: elementParameters,
     returnType: elementReturnType,
-    libraryUri: element.library?.source.uri.toString(),
   );
 }
 
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index 4f6aaaa3..25a8bf9 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -131,7 +131,7 @@
       });
 
       var result = CiderCompletionResult._(
-        suggestions: suggestions,
+        suggestions: suggestions.map((e) => e.build()).toList(),
         performance: CiderCompletionPerformance._(
           operations: _performanceRoot.children.first,
         ),
@@ -157,25 +157,25 @@
   ///
   /// TODO(scheglov) Implement show / hide combinators.
   /// TODO(scheglov) Implement prefixes.
-  List<CompletionSuggestion> _importedLibrariesSuggestions({
+  List<CompletionSuggestionBuilder> _importedLibrariesSuggestions({
     required LibraryElement target,
     required OperationPerformanceImpl performance,
   }) {
-    var suggestions = <CompletionSuggestion>[];
+    var suggestionBuilders = <CompletionSuggestionBuilder>[];
     for (var importedLibrary in target.importedLibraries) {
       var importedSuggestions = _importedLibrarySuggestions(
         element: importedLibrary,
         performance: performance,
       );
-      suggestions.addAll(importedSuggestions);
+      suggestionBuilders.addAll(importedSuggestions);
     }
-    performance.getDataInt('count').add(suggestions.length);
-    return suggestions;
+    performance.getDataInt('count').add(suggestionBuilders.length);
+    return suggestionBuilders;
   }
 
   /// Return cached, or compute unprefixed suggestions for all elements
   /// exported from the library.
-  List<CompletionSuggestion> _importedLibrarySuggestions({
+  List<CompletionSuggestionBuilder> _importedLibrarySuggestions({
     required LibraryElement element,
     required OperationPerformanceImpl performance,
   }) {
@@ -198,13 +198,15 @@
       );
       _cache._importedLibraries[path] = cacheEntry;
     }
-    return cacheEntry.suggestions;
+    return cacheEntry.suggestionBuilders;
   }
 
   /// Compute all unprefixed suggestions for all elements exported from
   /// the library.
-  List<CompletionSuggestion> _librarySuggestions(LibraryElement element) {
+  List<CompletionSuggestionBuilder> _librarySuggestions(
+      LibraryElement element) {
     var suggestionBuilder = SuggestionBuilder(_dartCompletionRequest);
+    suggestionBuilder.libraryUriStr = element.source.uri.toString();
     var visitor = LibraryElementSuggestionBuilder(
         _dartCompletionRequest, suggestionBuilder);
     var exportMap = element.exportNamespace.definedNames;
@@ -250,7 +252,7 @@
 
 class _CiderImportedLibrarySuggestions {
   final String signature;
-  final List<CompletionSuggestion> suggestions;
+  final List<CompletionSuggestionBuilder> suggestionBuilders;
 
-  _CiderImportedLibrarySuggestions(this.signature, this.suggestions);
+  _CiderImportedLibrarySuggestions(this.signature, this.suggestionBuilders);
 }
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 45ccc9b..9f3043e 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -68,7 +68,7 @@
   /// automatically called when a client listens to the stream returned by
   /// [results]. Subclasses should override this method, append at least one
   /// result to the [controller], and close the controller stream once complete.
-  Future<List<CompletionSuggestion>> computeSuggestions({
+  Future<List<CompletionSuggestionBuilder>> computeSuggestions({
     required CompletionBudget budget,
     required OperationPerformanceImpl performance,
     required DartCompletionRequest request,
@@ -87,7 +87,7 @@
     //
     // Compute completions generated by server.
     //
-    var suggestions = <CompletionSuggestion>[];
+    var suggestions = <CompletionSuggestionBuilder>[];
     await performance.runAsync('computeSuggestions', (performance) async {
       var manager = DartCompletionManager(
         budget: budget,
@@ -357,9 +357,9 @@
         setNewRequest(completionRequest);
 
         var notImportedSuggestions = NotImportedSuggestions();
-        var suggestions = <CompletionSuggestion>[];
+        var suggestionBuilders = <CompletionSuggestionBuilder>[];
         try {
-          suggestions = await computeSuggestions(
+          suggestionBuilders = await computeSuggestions(
             budget: budget,
             performance: performance,
             request: completionRequest,
@@ -377,36 +377,29 @@
         }
 
         performance.run('filter', (performance) {
-          performance.getDataInt('count').add(suggestions.length);
-          suggestions = fuzzyFilterSort(
+          performance.getDataInt('count').add(suggestionBuilders.length);
+          suggestionBuilders = fuzzyFilterSort(
             pattern: completionRequest.targetPrefix,
-            suggestions: suggestions,
+            suggestions: suggestionBuilders,
           );
-          performance.getDataInt('matchCount').add(suggestions.length);
+          performance.getDataInt('matchCount').add(suggestionBuilders.length);
         });
 
-        var lengthRestricted = suggestions.take(params.maxResults).toList();
+        var lengthRestricted =
+            suggestionBuilders.take(params.maxResults).toList();
         completionPerformance.suggestionCount = lengthRestricted.length;
 
-        // Update `isNotImported` for not yet imported.
-        for (var i = 0; i < lengthRestricted.length; i++) {
-          var suggestion = lengthRestricted[i];
-          if (notImportedSuggestions.set.contains(suggestion)) {
-            lengthRestricted[i] = suggestion.copyWith(
-              isNotImported: CopyWithValue(true),
-            );
-          }
-        }
+        var suggestions = lengthRestricted.map((e) => e.build()).toList();
 
         var isIncomplete = notImportedSuggestions.isIncomplete ||
-            lengthRestricted.length < suggestions.length;
+            lengthRestricted.length < suggestionBuilders.length;
 
         performance.run('sendResponse', (_) {
           server.sendResponse(
             CompletionGetSuggestions2Result(
               completionRequest.replacementOffset,
               completionRequest.replacementLength,
-              lengthRestricted,
+              suggestions,
               isIncomplete,
             ).toResponse(request.id),
           );
@@ -569,9 +562,9 @@
 
         // Compute suggestions in the background
         try {
-          var suggestions = <CompletionSuggestion>[];
+          var suggestionBuilders = <CompletionSuggestionBuilder>[];
           try {
-            suggestions = await computeSuggestions(
+            suggestionBuilders = await computeSuggestions(
               budget: budget,
               performance: performance,
               request: completionRequest,
@@ -603,7 +596,7 @@
               completionId,
               completionRequest.replacementOffset,
               completionRequest.replacementLength,
-              suggestions,
+              suggestionBuilders.map((e) => e.build()).toList(),
               libraryFile,
               includedSuggestionSets,
               includedElementKinds?.toList(),
@@ -611,7 +604,7 @@
             );
           });
 
-          completionPerformance.suggestionCount = suggestions.length;
+          completionPerformance.suggestionCount = suggestionBuilders.length;
         } finally {
           ifMatchesRequestClear(completionRequest);
         }
@@ -694,7 +687,7 @@
   Future<void> _addPluginSuggestions(
     CompletionBudget budget,
     _RequestToPlugins requestToPlugins,
-    List<CompletionSuggestion> suggestions,
+    List<CompletionSuggestionBuilder> suggestionBuilders,
   ) async {
     var responses = await waitForResponses(
       requestToPlugins.futures,
@@ -712,7 +705,11 @@
                   ' replacement offset/length: ${result.toJson()}');
           continue;
         }
-        suggestions.addAll(result.results);
+        suggestionBuilders.addAll(
+          result.results.map(
+            (suggestion) => ValueCompletionSuggestionBuilder(suggestion),
+          ),
+        );
       }
     }
   }
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index e0eedc4..4fc64eb 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -74,12 +74,13 @@
       offset: targetOffset,
     );
 
-    var suggestions = await DartCompletionManager(
+    var serverSuggestions = await DartCompletionManager(
       budget: CompletionBudget(CompletionBudget.defaultDuration),
     ).computeSuggestions(
       dartRequest,
       OperationPerformanceImpl('<root>'),
     );
+    var suggestions = serverSuggestions.map((e) => e.build()).toList();
 
     // Remove completions with synthetic import prefixes.
     suggestions.removeWhere((s) => s.completion.startsWith('__prefix'));
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 736ab90..6338b96 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -256,11 +256,15 @@
             includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
           );
 
-          final serverSuggestions = await contributor.computeSuggestions(
+          final serverSuggestions2 = await contributor.computeSuggestions(
             completionRequest,
             performance,
           );
 
+          final serverSuggestions = serverSuggestions2.map((serverSuggestion) {
+            return serverSuggestion.build();
+          }).toList();
+
           final insertLength = _computeInsertLength(
             offset,
             completionRequest.replacementOffset,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index b2ef7d6d..53b553c 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -117,7 +117,7 @@
                 includedElementNames == null &&
                 includedSuggestionRelevanceTags == null));
 
-  Future<List<CompletionSuggestion>> computeSuggestions(
+  Future<List<CompletionSuggestionBuilder>> computeSuggestions(
     DartCompletionRequest request,
     OperationPerformanceImpl performance, {
     bool enableOverrideContributor = true,
@@ -126,12 +126,12 @@
     request.checkAborted();
     var pathContext = request.resourceProvider.pathContext;
     if (!file_paths.isDart(pathContext, request.path)) {
-      return const <CompletionSuggestion>[];
+      return const <CompletionSuggestionBuilder>[];
     }
 
     // Don't suggest in comments.
     if (request.target.isCommentText) {
-      return const <CompletionSuggestion>[];
+      return const <CompletionSuggestionBuilder>[];
     }
 
     request.checkAborted();
@@ -503,8 +503,6 @@
 
 /// Information provided by [NotImportedContributor] in addition to suggestions.
 class NotImportedSuggestions {
-  final Set<protocol.CompletionSuggestion> set = Set.identity();
-
   /// This flag is set to `true` if the contributor decided to stop before it
   /// processed all available libraries, e.g. we ran out of budget.
   bool isIncomplete = false;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart b/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
index 4408a7a..59a5f61 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/fuzzy_filter_sort.dart
@@ -3,17 +3,18 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
 import 'package:analysis_server/src/services/completion/filtering/fuzzy_matcher.dart';
 
 /// Filters and scores [suggestions] according to how well they match the
 /// [pattern]. Sorts [suggestions] by the score, relevance, and name.
-List<CompletionSuggestion> fuzzyFilterSort({
+List<CompletionSuggestionBuilder> fuzzyFilterSort({
   required String pattern,
-  required List<CompletionSuggestion> suggestions,
+  required List<CompletionSuggestionBuilder> suggestions,
 }) {
   var matcher = FuzzyMatcher(pattern, matchStyle: MatchStyle.SYMBOL);
 
-  double score(CompletionSuggestion suggestion) {
+  double score(CompletionSuggestionBuilder suggestion) {
     var suggestionTextToMatch = suggestion.completion;
 
     if (suggestion.kind == CompletionSuggestionKind.NAMED_ARGUMENT) {
@@ -53,7 +54,7 @@
 
 /// [CompletionSuggestion] scored using [FuzzyMatcher].
 class _FuzzyScoredSuggestion {
-  final CompletionSuggestion suggestion;
+  final CompletionSuggestionBuilder suggestion;
   final double score;
 
   _FuzzyScoredSuggestion(this.suggestion, this.score);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
index 3277593..5ef87a7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
@@ -7,6 +7,7 @@
 import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart'
     show SuggestionBuilder;
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 
 /// A contributor for calculating suggestions for imported top level members.
@@ -27,8 +28,11 @@
     for (var importElement in imports) {
       var libraryElement = importElement.importedLibrary;
       if (libraryElement != null) {
-        _buildSuggestions(importElement.namespace,
-            prefix: importElement.prefix?.name);
+        _buildSuggestions(
+          libraryElement: libraryElement,
+          namespace: importElement.namespace,
+          prefix: importElement.prefix?.name,
+        );
         if (libraryElement.isDartCore &&
             request.opType.includeTypeNameSuggestions) {
           builder.suggestName('Never');
@@ -37,10 +41,16 @@
     }
   }
 
-  void _buildSuggestions(Namespace namespace, {String? prefix}) {
+  void _buildSuggestions({
+    required LibraryElement libraryElement,
+    required Namespace namespace,
+    String? prefix,
+  }) {
+    builder.libraryUriStr = libraryElement.source.uri.toString();
     var visitor = LibraryElementSuggestionBuilder(request, builder, prefix);
     for (var elem in namespace.definedNames.values) {
       elem.accept(visitor);
     }
+    builder.libraryUriStr = null;
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
index d9675cb..b78b89e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
@@ -41,6 +41,7 @@
       if (importElem.prefix?.name == elem.name) {
         var library = importElem.importedLibrary;
         if (library != null) {
+          builder.libraryUriStr = library.source.uri.toString();
           for (var element in importElem.namespace.definedNames.values) {
             if (typesOnly && isConstructor) {
               // Suggest constructors from the imported libraries.
@@ -72,6 +73,7 @@
           if (!typesOnly && importElem.isDeferred) {
             builder.suggestLoadLibraryFunction(library.loadLibraryFunction);
           }
+          builder.libraryUriStr = null;
         }
       }
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
index 8bbff4f..52e893e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
@@ -81,11 +81,9 @@
       var exportNamespace = element.exportNamespace;
       var exportElements = exportNamespace.definedNames.values.toList();
 
+      builder.libraryUriStr = file.uriStr;
       builder.isNotImportedLibrary = true;
       builder.laterReplacesEarlier = false;
-      builder.suggestionAdded = (suggestion) {
-        additionalData.set.add(suggestion);
-      };
 
       if (request.includeIdentifiers) {
         _buildSuggestions(exportElements);
@@ -95,9 +93,9 @@
         _extensions(exportElements),
       );
 
+      builder.libraryUriStr = null;
       builder.isNotImportedLibrary = false;
       builder.laterReplacesEarlier = true;
-      builder.suggestionAdded = null;
     }
   }
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 829a3e5..c1661dc 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -21,18 +21,122 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/range_factory.dart';
 
-/// Wrapper around a potentially nullable value.
-///
-/// When the wrapper instance is provided for a property, the property
-/// value is replaced, even if the value to set is `null` itself.
-class CopyWithValue<T> {
-  final T value;
+/// A container with enough information to do filtering, and if necessary
+/// build the [CompletionSuggestion] instance.
+abstract class CompletionSuggestionBuilder {
+  /// See [CompletionSuggestion.completion].
+  String get completion;
 
-  CopyWithValue(this.value);
+  /// The key used to de-duplicate suggestions.
+  String get key => completion;
+
+  /// See [CompletionSuggestion.kind].
+  CompletionSuggestionKind get kind;
+
+  /// See [CompletionSuggestion.relevance].
+  int get relevance;
+
+  CompletionSuggestion build();
+}
+
+/// The implementation of [CompletionSuggestionBuilder] that is based on
+/// [ElementCompletionData] and location specific information.
+class CompletionSuggestionBuilderImpl implements CompletionSuggestionBuilder {
+  final ElementCompletionData element;
+
+  @override
+  final CompletionSuggestionKind kind;
+
+  @override
+  final int relevance;
+
+  final String? completionOverride;
+  final String? libraryUriStr;
+  final bool isNotImported;
+
+  CompletionSuggestionBuilderImpl({
+    required this.element,
+    required this.kind,
+    required this.completionOverride,
+    required this.relevance,
+    required this.libraryUriStr,
+    required this.isNotImported,
+  });
+
+  @override
+  String get completion => completionOverride ?? element.completion;
+
+  /// TODO(scheglov) implement better key for not-yet-imported
+  @override
+  String get key {
+    var key = completion;
+    if (element.element.kind == protocol.ElementKind.CONSTRUCTOR) {
+      key = '$key()';
+    }
+    return key;
+  }
+
+  @override
+  CompletionSuggestion build() {
+    return CompletionSuggestion(
+      kind,
+      relevance,
+      completion,
+      completion.length /*selectionOffset*/,
+      0 /*selectionLength*/,
+      element.isDeprecated,
+      false /*isPotential*/,
+      element: element.element,
+      docSummary: element.documentation?.summary,
+      docComplete: element.documentation?.full,
+      declaringType: element.declaringType,
+      returnType: element.returnType,
+      requiredParameterCount: element.requiredParameterCount,
+      hasNamedParameters: element.hasNamedParameters,
+      parameterNames: element.parameterNames,
+      parameterTypes: element.parameterTypes,
+      defaultArgumentListString: element.defaultArgumentList?.text,
+      defaultArgumentListTextRanges: element.defaultArgumentList?.ranges,
+      libraryUri: libraryUriStr,
+      isNotImported: isNotImported ? true : null,
+    );
+  }
+}
+
+/// Information about an [Element] that does not depend on the location where
+/// this element is suggested. For some often used elements, such as classes,
+/// it might be cached, so created only once.
+class ElementCompletionData {
+  final String completion;
+  final bool isDeprecated;
+  final String? declaringType;
+  final String? returnType;
+  final List<String>? parameterNames;
+  final List<String>? parameterTypes;
+  final int? requiredParameterCount;
+  final bool? hasNamedParameters;
+  CompletionDefaultArgumentList? defaultArgumentList;
+  final _ElementDocumentation? documentation;
+  final protocol.Element element;
+
+  ElementCompletionData({
+    required this.completion,
+    required this.isDeprecated,
+    required this.declaringType,
+    required this.returnType,
+    required this.parameterNames,
+    required this.parameterTypes,
+    required this.requiredParameterCount,
+    required this.hasNamedParameters,
+    required this.defaultArgumentList,
+    required this.documentation,
+    required this.element,
+  });
 }
 
 /// This class provides suggestions based upon the visible instance members in
@@ -151,22 +255,6 @@
 /// An object used to build a list of suggestions in response to a single
 /// completion request.
 class SuggestionBuilder {
-  /// The cache of suggestions for [Element]s. We use it to avoid computing
-  /// the same documentation, parameters, return type, etc for elements that
-  /// are exactly the same (the same instances) as they were the last time.
-  ///
-  /// This cache works because:
-  /// 1. Flutter applications usually reference many libraries, which they
-  /// consume, but don't change. So, all their elements stay unchanged.
-  /// 2. The analyzer keeps the same library instances loaded as the user
-  /// types in the application, so the instances of all elements stay the
-  /// same, and the cache works.
-  /// 3. The analyzer does not patch elements (at least not after the linking
-  /// process is done, and the elements are exposed to any client code). So,
-  /// any type information, or documentation, stays the same. If this changes,
-  /// we would need a signal, e.g. some modification counter on the element.
-  static final _elementSuggestionCache = Expando<_CompletionSuggestionEntry>();
-
   /// The completion request for which suggestions are being built.
   final DartCompletionRequest request;
 
@@ -174,12 +262,13 @@
   /// suggestions, or `null` if no notification should occur.
   final SuggestionListener? listener;
 
-  /// The function to be invoked when a new suggestion is added.
-  void Function(protocol.CompletionSuggestion)? suggestionAdded;
-
   /// A map from a completion identifier to a completion suggestion.
-  final Map<String, CompletionSuggestion> _suggestionMap =
-      <String, CompletionSuggestion>{};
+  final Map<String, CompletionSuggestionBuilder> _suggestionMap = {};
+
+  /// The URI of the library from which suggestions are being added.
+  /// This URI is not necessary the same as the URI that declares an element,
+  /// because of exports.
+  String? libraryUriStr;
 
   /// This flag is set to `true` while adding suggestions for top-level
   /// elements from not-yet-imported libraries.
@@ -211,7 +300,8 @@
 
   /// Return an iterable that can be used to access the completion suggestions
   /// that have been built.
-  Iterable<CompletionSuggestion> get suggestions => _suggestionMap.values;
+  Iterable<CompletionSuggestionBuilder> get suggestions =>
+      _suggestionMap.values;
 
   /// Return the name of the member containing the completion location, or
   /// `null` if the completion location isn't within a member or if the target
@@ -279,11 +369,12 @@
         superMatches: superMatches,
         inheritanceDistance: inheritanceDistance,
       );
-      _add(
-        _createSuggestion(
+      _addBuilder(
+        _createCompletionSuggestionBuilder(
           accessor,
           kind: CompletionSuggestionKind.IDENTIFIER,
           relevance: relevance,
+          isNotImported: isNotImportedLibrary,
         ),
       );
     }
@@ -303,12 +394,13 @@
       elementKind: elementKind,
       isConstant: isConstant,
     );
-    _add(
-      _createSuggestion(
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
         parameter,
         elementKind: protocol.ElementKind.PARAMETER,
         kind: CompletionSuggestionKind.IDENTIFIER,
         relevance: relevance,
+        isNotImported: isNotImportedLibrary,
       ),
     );
   }
@@ -318,12 +410,13 @@
   void suggestClass(ClassElement classElement, {String? prefix}) {
     var relevance = _computeTopLevelRelevance(classElement,
         elementType: _instantiateClassElement(classElement));
-    _add(
-      _createSuggestion(
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
         classElement,
         kind: CompletionSuggestionKind.IDENTIFIER,
         prefix: prefix,
         relevance: relevance,
+        isNotImported: isNotImportedLibrary,
       ),
     );
   }
@@ -368,16 +461,20 @@
       );
     }
 
-    _add(createSuggestion(
-      completion: blockBuffer.toString(),
-      displayText: '$parametersString {}',
-      selectionOffset: blockSelectionOffset,
-    ));
-    _add(createSuggestion(
-      completion: expressionBuffer.toString(),
-      displayText: '$parametersString =>',
-      selectionOffset: expressionSelectionOffset,
-    ));
+    _addSuggestion(
+      createSuggestion(
+        completion: blockBuffer.toString(),
+        displayText: '$parametersString {}',
+        selectionOffset: blockSelectionOffset,
+      ),
+    );
+    _addSuggestion(
+      createSuggestion(
+        completion: expressionBuffer.toString(),
+        displayText: '$parametersString =>',
+        selectionOffset: expressionSelectionOffset,
+      ),
+    );
   }
 
   /// Add a suggestion for a [constructor]. If a [kind] is provided it will be
@@ -421,11 +518,16 @@
     var returnType = _instantiateClassElement(enclosingClass);
     var relevance =
         _computeTopLevelRelevance(constructor, elementType: returnType);
-    _add(_createSuggestion(constructor,
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
+        constructor,
         completion: completion,
         kind: kind,
         prefix: prefix,
-        relevance: relevance));
+        relevance: relevance,
+        isNotImported: isNotImportedLibrary,
+      ),
+    );
   }
 
   /// Add a suggestion for a top-level [element]. If a [kind] is provided it
@@ -460,13 +562,14 @@
     var completion = '$enumName.$constantName';
     var relevance =
         _computeTopLevelRelevance(constant, elementType: constant.type);
-    _add(
-      _createSuggestion(
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
         constant,
         completion: completion,
         kind: CompletionSuggestionKind.IDENTIFIER,
         prefix: prefix,
         relevance: relevance,
+        isNotImported: isNotImportedLibrary,
       ),
     );
   }
@@ -479,8 +582,15 @@
       String? prefix}) {
     var relevance = _computeTopLevelRelevance(extension,
         elementType: extension.extendedType);
-    _add(_createSuggestion(extension,
-        kind: kind, prefix: prefix, relevance: relevance));
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
+        extension,
+        kind: kind,
+        prefix: prefix,
+        relevance: relevance,
+        isNotImported: isNotImportedLibrary,
+      ),
+    );
   }
 
   /// Add a suggestion for a [field]. If the field is being referenced with a
@@ -509,11 +619,12 @@
       superMatches: superMatches,
       inheritanceDistance: inheritanceDistance,
     );
-    _add(
-      _createSuggestion(
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
         field,
         kind: CompletionSuggestionKind.IDENTIFIER,
         relevance: relevance,
+        isNotImported: isNotImportedLibrary,
       ),
     );
   }
@@ -522,11 +633,12 @@
   void suggestFieldFormalParameter(FieldElement field) {
     // TODO(brianwilkerson) Add a parameter (`bool includePrefix`) indicating
     //  whether to include the `this.` prefix in the completion.
-    _add(
-      _createSuggestion(
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
         field,
         kind: CompletionSuggestionKind.IDENTIFIER,
         relevance: Relevance.fieldFormalParameter,
+        isNotImported: isNotImportedLibrary,
       ),
     );
   }
@@ -539,22 +651,24 @@
         typeParameters: null,
         parameters: '()',
         returnType: 'void');
-    _add(CompletionSuggestion(
-      CompletionSuggestionKind.INVOCATION,
-      Relevance.callFunction,
-      FunctionElement.CALL_METHOD_NAME,
-      FunctionElement.CALL_METHOD_NAME.length,
-      0,
-      false,
-      false,
-      displayText: 'call()',
-      element: element,
-      returnType: 'void',
-      parameterNames: [],
-      parameterTypes: [],
-      requiredParameterCount: 0,
-      hasNamedParameters: false,
-    ));
+    _addSuggestion(
+      CompletionSuggestion(
+        CompletionSuggestionKind.INVOCATION,
+        Relevance.callFunction,
+        FunctionElement.CALL_METHOD_NAME,
+        FunctionElement.CALL_METHOD_NAME.length,
+        0,
+        false,
+        false,
+        displayText: 'call()',
+        element: element,
+        returnType: 'void',
+        parameterNames: [],
+        parameterTypes: [],
+        requiredParameterCount: 0,
+        hasNamedParameters: false,
+      ),
+    );
   }
 
   /// Add a suggestion for a [keyword]. The [offset] is the offset from the
@@ -574,8 +688,8 @@
       contextType: contextType,
       keyword: keywordFeature,
     );
-    _add(CompletionSuggestion(CompletionSuggestionKind.KEYWORD, relevance,
-        keyword, offset ?? keyword.length, 0, false, false));
+    _addSuggestion(CompletionSuggestion(CompletionSuggestionKind.KEYWORD,
+        relevance, keyword, offset ?? keyword.length, 0, false, false));
   }
 
   /// Add a suggestion for a [label].
@@ -588,7 +702,7 @@
           Relevance.label, completion, completion.length, 0, false, false);
       suggestion.element = createLocalElement(
           request.source, protocol.ElementKind.LABEL, label.label);
-      _add(suggestion);
+      _addSuggestion(suggestion);
     }
   }
 
@@ -598,11 +712,12 @@
     // TODO(brianwilkerson) This might want to use the context type rather than
     //  a fixed value.
     var relevance = Relevance.loadLibrary;
-    _add(
-      _createSuggestion(
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
         function,
         kind: CompletionSuggestionKind.INVOCATION,
         relevance: relevance,
+        isNotImported: isNotImportedLibrary,
       ),
     );
   }
@@ -628,11 +743,12 @@
       isConstant: isConstant,
       localVariableDistance: localVariableDistance,
     );
-    _add(
-      _createSuggestion(
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
         variable,
         kind: CompletionSuggestionKind.IDENTIFIER,
         relevance: relevance,
+        isNotImported: isNotImportedLibrary,
       ),
     );
   }
@@ -675,46 +791,55 @@
       inheritanceDistance: inheritanceDistance,
     );
 
-    var suggestion =
-        _createSuggestion(method, kind: kind, relevance: relevance);
-    if (suggestion != null) {
-      var enclosingElement = method.enclosingElement;
-      if (method.name == 'setState' &&
-          enclosingElement is ClassElement &&
-          flutter.isExactState(enclosingElement)) {
-        // TODO(brianwilkerson) Make this more efficient by creating the correct
-        //  suggestion in the first place.
-        // Find the line indentation.
-        var indent = getRequestLineIndent(request);
+    var enclosingElement = method.enclosingElement;
+    if (method.name == 'setState' &&
+        enclosingElement is ClassElement &&
+        flutter.isExactState(enclosingElement)) {
+      // TODO(brianwilkerson) Make this more efficient by creating the correct
+      //  suggestion in the first place.
+      // Find the line indentation.
+      var indent = getRequestLineIndent(request);
 
-        // Let the user know that we are going to insert a complete statement.
-        suggestion.displayText = 'setState(() {});';
+      // Build the completion and the selection offset.
+      var buffer = StringBuffer();
+      buffer.writeln('setState(() {');
+      buffer.write('$indent  ');
+      var selectionOffset = buffer.length;
+      buffer.writeln();
+      buffer.write('$indent});');
 
-        // Build the completion and the selection offset.
-        var buffer = StringBuffer();
-        buffer.writeln('setState(() {');
-        buffer.write('$indent  ');
-        suggestion.selectionOffset = buffer.length;
-        buffer.writeln();
-        buffer.write('$indent});');
-        suggestion.completion = buffer.toString();
-
-        // There are no arguments to fill.
-        suggestion.parameterNames = null;
-        suggestion.parameterTypes = null;
-        suggestion.requiredParameterCount = null;
-        suggestion.hasNamedParameters = null;
-      }
-      _add(suggestion);
+      _addSuggestion(
+        CompletionSuggestion(
+          kind,
+          relevance,
+          buffer.toString(),
+          selectionOffset,
+          0,
+          false,
+          false,
+          // Let the user know that we are going to insert a complete statement.
+          displayText: 'setState(() {});',
+        ),
+      );
+      return;
     }
+
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
+        method,
+        kind: kind,
+        relevance: relevance,
+        isNotImported: isNotImportedLibrary,
+      ),
+    );
   }
 
   /// Add a suggestion to use the [name] at a declaration site.
   void suggestName(String name) {
     // TODO(brianwilkerson) Explore whether there are any features of the name
     //  that can be used to provide better relevance scores.
-    _add(CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER, 500, name,
-        name.length, 0, false, false));
+    _addSuggestion(CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER,
+        500, name, name.length, 0, false, false));
   }
 
   /// Add a suggestion to add a named argument corresponding to the [parameter].
@@ -783,7 +908,8 @@
       suggestion.element =
           convertElement(parameter, withNullability: _isNonNullableByDefault);
     }
-    _add(suggestion);
+
+    _addSuggestion(suggestion);
   }
 
   /// Add a suggestion to replace the [targetId] with an override of the given
@@ -842,7 +968,7 @@
         displayText: displayText);
     suggestion.element = protocol.convertElement(element,
         withNullability: _isNonNullableByDefault);
-    _add(suggestion);
+    _addSuggestion(suggestion);
   }
 
   /// Add a suggestion for a [parameter].
@@ -861,11 +987,12 @@
       elementKind: elementKind,
       isConstant: isConstant,
     );
-    _add(
-      _createSuggestion(
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
         parameter,
         kind: CompletionSuggestionKind.IDENTIFIER,
         relevance: relevance,
+        isNotImported: isNotImportedLibrary,
       ),
     );
   }
@@ -879,19 +1006,25 @@
     var relevance = _computeRelevance(
       elementKind: elementKind,
     );
-    _add(_createSuggestion(library,
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
+        library,
         completion: prefix,
         kind: CompletionSuggestionKind.IDENTIFIER,
-        relevance: relevance));
+        relevance: relevance,
+        isNotImported: isNotImportedLibrary,
+      ),
+    );
   }
 
   /// Add a suggestion to reference a [parameter] in a super formal parameter.
   void suggestSuperFormalParameter(ParameterElement parameter) {
-    _add(
-      _createSuggestion(
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
         parameter,
         kind: CompletionSuggestionKind.IDENTIFIER,
         relevance: Relevance.superFormalParameter,
+        isNotImported: isNotImportedLibrary,
       ),
     );
   }
@@ -904,8 +1037,15 @@
       String? prefix}) {
     var relevance =
         _computeTopLevelRelevance(function, elementType: function.returnType);
-    _add(_createSuggestion(function,
-        kind: kind, prefix: prefix, relevance: relevance));
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
+        function,
+        kind: kind,
+        prefix: prefix,
+        relevance: relevance,
+        isNotImported: isNotImportedLibrary,
+      ),
+    );
   }
 
   /// Add a suggestion for a top-level property [accessor]. If a [kind] is
@@ -951,12 +1091,13 @@
         startsWithDollar: startsWithDollar,
         superMatches: superMatches,
       );
-      _add(
-        _createSuggestion(
+      _addBuilder(
+        _createCompletionSuggestionBuilder(
           accessor,
           kind: CompletionSuggestionKind.IDENTIFIER,
           prefix: prefix,
           relevance: relevance,
+          isNotImported: isNotImportedLibrary,
         ),
       );
     }
@@ -970,12 +1111,13 @@
     assert(variable.enclosingElement is CompilationUnitElement);
     var relevance =
         _computeTopLevelRelevance(variable, elementType: variable.type);
-    _add(
-      _createSuggestion(
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
         variable,
         kind: CompletionSuggestionKind.IDENTIFIER,
         prefix: prefix,
         relevance: relevance,
+        isNotImported: isNotImportedLibrary,
       ),
     );
   }
@@ -986,12 +1128,13 @@
   void suggestTypeAlias(TypeAliasElement typeAlias, {String? prefix}) {
     var relevance = _computeTopLevelRelevance(typeAlias,
         elementType: _instantiateTypeAlias(typeAlias));
-    _add(
-      _createSuggestion(
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
         typeAlias,
         kind: CompletionSuggestionKind.IDENTIFIER,
         prefix: prefix,
         relevance: relevance,
+        isNotImported: isNotImportedLibrary,
       ),
     );
   }
@@ -1006,34 +1149,46 @@
       elementKind: elementKind,
       isConstant: isConstant,
     );
-    _add(_createSuggestion(parameter,
-        kind: CompletionSuggestionKind.IDENTIFIER, relevance: relevance));
+    _addBuilder(
+      _createCompletionSuggestionBuilder(
+        parameter,
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        relevance: relevance,
+        isNotImported: isNotImportedLibrary,
+      ),
+    );
   }
 
   /// Add a suggestion to use the [uri] in an import, export, or part directive.
   void suggestUri(String uri) {
     var relevance =
         uri == 'dart:core' ? Relevance.importDartCore : Relevance.import;
-    _add(CompletionSuggestion(CompletionSuggestionKind.IMPORT, relevance, uri,
-        uri.length, 0, false, false));
+    _addSuggestion(
+      CompletionSuggestion(CompletionSuggestionKind.IMPORT, relevance, uri,
+          uri.length, 0, false, false),
+    );
   }
 
   /// Add the given [suggestion] if it isn't `null` and if it isn't shadowed by
   /// a previously added suggestion.
-  void _add(protocol.CompletionSuggestion? suggestion) {
+  void _addBuilder(CompletionSuggestionBuilder? suggestion) {
     if (suggestion != null) {
-      var key = suggestion.completion;
-      if (suggestion.element?.kind == protocol.ElementKind.CONSTRUCTOR) {
-        key = '$key()';
-      }
+      var key = suggestion.key;
       listener?.builtSuggestion(suggestion);
       if (laterReplacesEarlier || !_suggestionMap.containsKey(key)) {
         _suggestionMap[key] = suggestion;
-        suggestionAdded?.call(suggestion);
       }
     }
   }
 
+  /// Add the given [suggestion] if it isn't shadowed by a previously added
+  /// suggestion.
+  void _addSuggestion(protocol.CompletionSuggestion suggestion) {
+    _addBuilder(
+      ValueCompletionSuggestionBuilder(suggestion),
+    );
+  }
+
   /// Compute the value of the _element kind_ feature for the given [element] in
   /// the completion context.
   double _computeElementKind(Element element, {double? distance}) {
@@ -1119,112 +1274,174 @@
     );
   }
 
-  /// Return a suggestion based on the [element], or `null` if a suggestion is
-  /// not appropriate for the element. If the completion should be something
+  /// Return a [CompletionSuggestionBuilder] based on the [element], or `null`
+  /// if the element cannot be suggested. If the completion should be something
   /// different than the name of the element, then the [completion] should be
   /// supplied. If an [elementKind] is provided, then it will be used rather
   /// than the kind normally used for the element. If a [prefix] is provided,
   /// then the element name (or completion) will be prefixed. The [relevance] is
   /// the relevance of the suggestion.
-  CompletionSuggestion? _createSuggestion(Element element,
-      {String? completion,
-      protocol.ElementKind? elementKind,
-      required CompletionSuggestionKind kind,
-      String? prefix,
-      required int relevance}) {
-    var inputs = _CompletionSuggestionInputs(
-      completion: completion,
-      elementKind: elementKind,
-      kind: kind,
-      prefix: prefix,
-    );
-
-    var cacheEntry = _elementSuggestionCache[element];
-    if (cacheEntry != null) {
-      if (cacheEntry.inputs == inputs) {
-        final suggestion = cacheEntry.suggestion;
-        suggestion.relevance = relevance;
-        return suggestion;
-      }
-    }
-
-    var suggestion = _createSuggestion0(
+  ///
+  /// TODO(scheglov) Consider removing [elementKind]
+  CompletionSuggestionBuilder? _createCompletionSuggestionBuilder(
+    Element element, {
+    String? completion,
+    protocol.ElementKind? elementKind,
+    required CompletionSuggestionKind kind,
+    required int relevance,
+    required bool isNotImported,
+    String? prefix,
+  }) {
+    var elementData = _getElementCompletionData(
       element,
-      completion: completion,
       elementKind: elementKind,
-      kind: kind,
-      prefix: prefix,
-      relevance: relevance,
     );
-    if (suggestion == null) {
+    if (elementData == null) {
       return null;
     }
 
-    _elementSuggestionCache[element] = _CompletionSuggestionEntry(
-      inputs: inputs,
-      suggestion: suggestion,
+    if (prefix != null) {
+      completion ??= elementData.completion;
+      completion = prefix + '.' + completion;
+    }
+
+    return CompletionSuggestionBuilderImpl(
+      element: elementData,
+      kind: kind,
+      completionOverride: completion,
+      relevance: relevance,
+      libraryUriStr: libraryUriStr,
+      isNotImported: isNotImported,
     );
-    return suggestion;
   }
 
-  /// The non-caching implementation of [_createSuggestion].
-  CompletionSuggestion? _createSuggestion0(
+  /// The non-caching implementation of [_getElementCompletionData].
+  ElementCompletionData? _createElementCompletionData(
     Element element, {
-    required String? completion,
-    required protocol.ElementKind? elementKind,
-    required CompletionSuggestionKind kind,
-    required String? prefix,
-    required int relevance,
+    protocol.ElementKind? elementKind,
   }) {
+    // Do not include operators in suggestions.
     if (element is ExecutableElement && element.isOperator) {
-      // Do not include operators in suggestions
       return null;
     }
-    completion ??= element.displayName;
-    if (completion.isEmpty) {
-      return null;
-    }
-    if (prefix != null && prefix.isNotEmpty) {
-      completion = '$prefix.$completion';
-    }
-    var suggestion = CompletionSuggestion(kind, relevance, completion,
-        completion.length, 0, element.hasOrInheritsDeprecated, false);
 
-    _setDocumentation(suggestion, element);
-    var suggestedElement = suggestion.element = protocol.convertElement(element,
+    var completion = element.displayName;
+    var documentation = _getDocumentation(element);
+
+    var suggestedElement = protocol.convertElement(element,
         withNullability: _isNonNullableByDefault);
+
+    // TODO(scheglov) Update a copy.
     if (elementKind != null) {
       suggestedElement.kind = elementKind;
     }
+
     var enclosingElement = element.enclosingElement;
+
+    String? declaringType;
     if (enclosingElement is ClassElement) {
-      suggestion.declaringType = enclosingElement.displayName;
+      declaringType = enclosingElement.displayName;
     }
-    suggestion.returnType =
-        getReturnTypeString(element, withNullability: _isNonNullableByDefault);
+
+    var returnType = getReturnTypeString(
+      element,
+      withNullability: _isNonNullableByDefault,
+    );
+
+    List<String>? parameterNames;
+    List<String>? parameterTypes;
+    int? requiredParameterCount;
+    bool? hasNamedParameters;
+    CompletionDefaultArgumentList? defaultArgumentList;
     if (element is ExecutableElement && element is! PropertyAccessorElement) {
-      suggestion.parameterNames = element.parameters
-          .map((ParameterElement parameter) => parameter.name)
-          .toList();
-      suggestion.parameterTypes =
-          element.parameters.map((ParameterElement parameter) {
-        var paramType = parameter.type;
-        return paramType.getDisplayString(
-            withNullability: _isNonNullableByDefault);
+      parameterNames = element.parameters.map((parameter) {
+        return parameter.name;
+      }).toList();
+      parameterTypes = element.parameters.map((ParameterElement parameter) {
+        return parameter.type.getDisplayString(
+          withNullability: _isNonNullableByDefault,
+        );
       }).toList();
 
       var requiredParameters = element.parameters
           .where((ParameterElement param) => param.isRequiredPositional);
-      suggestion.requiredParameterCount = requiredParameters.length;
+      requiredParameterCount = requiredParameters.length;
 
       var namedParameters =
           element.parameters.where((ParameterElement param) => param.isNamed);
-      suggestion.hasNamedParameters = namedParameters.isNotEmpty;
+      hasNamedParameters = namedParameters.isNotEmpty;
 
-      addDefaultArgDetails(
-          suggestion, element, requiredParameters, namedParameters);
+      defaultArgumentList = computeCompletionDefaultArgumentList(
+          element, requiredParameters, namedParameters);
     }
-    return suggestion;
+
+    return ElementCompletionData(
+      completion: completion,
+      isDeprecated: element.hasOrInheritsDeprecated,
+      declaringType: declaringType,
+      returnType: returnType,
+      parameterNames: parameterNames,
+      parameterTypes: parameterTypes,
+      requiredParameterCount: requiredParameterCount,
+      hasNamedParameters: hasNamedParameters,
+      documentation: documentation,
+      defaultArgumentList: defaultArgumentList,
+      element: suggestedElement,
+    );
+  }
+
+  /// If the [element] has a documentation comment, return it.
+  _ElementDocumentation? _getDocumentation(Element element) {
+    var documentationCache = request.documentationCache;
+    var data = documentationCache?.dataFor(element);
+    if (data != null) {
+      return _ElementDocumentation(
+        full: data.full,
+        summary: data.summary,
+      );
+    }
+    var doc = DartUnitHoverComputer.computeDocumentation(
+      request.dartdocDirectiveInfo,
+      element,
+      includeSummary: true,
+    );
+    if (doc is DocumentationWithSummary) {
+      return _ElementDocumentation(
+        full: doc.full,
+        summary: doc.summary,
+      );
+    }
+    if (doc is Documentation) {
+      return _ElementDocumentation(
+        full: doc.full,
+        summary: null,
+      );
+    }
+    return null;
+  }
+
+  /// Return [ElementCompletionData] for the [element], or `null` if the
+  /// element cannot be suggested for completion.
+  ///
+  /// TODO(scheglov) Consider removing [elementKind]
+  ElementCompletionData? _getElementCompletionData(
+    Element element, {
+    protocol.ElementKind? elementKind,
+  }) {
+    ElementCompletionData? result;
+
+    var hasCompletionData = element.ifTypeOrNull<HasCompletionData>();
+    if (hasCompletionData != null) {
+      result = hasCompletionData.completionData.ifTypeOrNull();
+    }
+
+    result ??= _createElementCompletionData(
+      element,
+      elementKind: elementKind,
+    );
+
+    hasCompletionData?.completionData = result;
+    return result;
   }
 
   /// Return the type associated with the [accessor], maybe `null` if an
@@ -1300,7 +1517,7 @@
 
 abstract class SuggestionListener {
   /// Invoked when a suggestion has been built.
-  void builtSuggestion(protocol.CompletionSuggestion suggestion);
+  void builtSuggestion(CompletionSuggestionBuilder suggestionBuilder);
 
   /// Invoked with the values of the features that were computed in the process
   /// of building a suggestion. This method is invoked prior to invoking
@@ -1329,80 +1546,44 @@
   void missingElementKindTableFor(String completionLocation);
 }
 
-/// The entry of the element to suggestion cache.
-class _CompletionSuggestionEntry {
-  final _CompletionSuggestionInputs inputs;
+/// [CompletionSuggestionBuilder] that is based on a [CompletionSuggestion].
+class ValueCompletionSuggestionBuilder implements CompletionSuggestionBuilder {
+  final CompletionSuggestion _suggestion;
 
-  /// The suggestion computed for the element and [inputs].
-  final CompletionSuggestion suggestion;
-
-  _CompletionSuggestionEntry({
-    required this.inputs,
-    required this.suggestion,
-  });
-}
-
-/// The inputs, other than the [Element], that were provided to create an
-/// instance of [CompletionSuggestion].
-class _CompletionSuggestionInputs {
-  final String? completion;
-  final protocol.ElementKind? elementKind;
-  final CompletionSuggestionKind kind;
-  final String? prefix;
-
-  _CompletionSuggestionInputs({
-    required this.completion,
-    required this.elementKind,
-    required this.kind,
-    required this.prefix,
-  });
+  ValueCompletionSuggestionBuilder(this._suggestion);
 
   @override
-  bool operator ==(Object other) {
-    return other is _CompletionSuggestionInputs &&
-        other.completion == completion &&
-        other.elementKind == elementKind &&
-        other.kind == kind &&
-        other.prefix == prefix;
+  String get completion => _suggestion.completion;
+
+  @override
+  String get key => completion;
+
+  @override
+  protocol.CompletionSuggestionKind get kind => _suggestion.kind;
+
+  @override
+  int get relevance => _suggestion.relevance;
+
+  @override
+  CompletionSuggestion build() {
+    return _suggestion;
   }
 }
 
-extension CompletionSuggestionExtension on CompletionSuggestion {
-  CompletionSuggestion copyWith({
-    CopyWithValue<bool?>? isNotImported,
-  }) {
-    return protocol.CompletionSuggestion(
-      kind,
-      relevance,
-      completion,
-      selectionOffset,
-      selectionLength,
-      isDeprecated,
-      isPotential,
-      displayText: displayText,
-      replacementOffset: replacementOffset,
-      replacementLength: replacementLength,
-      docSummary: docSummary,
-      docComplete: docComplete,
-      declaringType: declaringType,
-      defaultArgumentListString: defaultArgumentListString,
-      defaultArgumentListTextRanges: defaultArgumentListTextRanges,
-      element: element,
-      returnType: returnType,
-      parameterNames: parameterNames,
-      parameterTypes: parameterTypes,
-      requiredParameterCount: requiredParameterCount,
-      hasNamedParameters: hasNamedParameters,
-      parameterName: parameterName,
-      parameterType: parameterType,
-      isNotImported: isNotImported.orElse(this.isNotImported),
-    );
-  }
+class _ElementDocumentation {
+  final String full;
+  final String? summary;
+
+  _ElementDocumentation({
+    required this.full,
+    required this.summary,
+  });
 }
 
-extension _CopyWithValueExtension<T> on CopyWithValue<T>? {
-  T orElse(T defaultValue) {
+extension on Object? {
+  /// If the target is [T], return it, otherwise `null`.
+  T? ifTypeOrNull<T>() {
     final self = this;
-    return self != null ? self.value : defaultValue;
+    return self is T ? self : null;
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index eef975c..279afd7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -25,13 +25,55 @@
   return b.relevance.compareTo(a.relevance);
 };
 
-/// Add default argument list text and ranges based on the given
+String buildClosureParameters(FunctionType type) {
+  var buffer = StringBuffer();
+  buffer.write('(');
+
+  var hasNamed = false;
+  var hasOptionalPositional = false;
+  var parameters = type.parameters;
+  var existingNames = parameters.map((p) => p.name).toSet();
+  for (var i = 0; i < parameters.length; ++i) {
+    var parameter = parameters[i];
+    if (i != 0) {
+      buffer.write(', ');
+    }
+    if (parameter.isNamed && !hasNamed) {
+      hasNamed = true;
+      buffer.write('{');
+    } else if (parameter.isOptionalPositional && !hasOptionalPositional) {
+      hasOptionalPositional = true;
+      buffer.write('[');
+    }
+    var name = parameter.name;
+    if (name.isEmpty) {
+      name = 'p$i';
+      var index = 1;
+      while (existingNames.contains(name)) {
+        name = 'p${i}_$index';
+        index++;
+      }
+    }
+    buffer.write(name);
+  }
+
+  if (hasNamed) {
+    buffer.write('}');
+  } else if (hasOptionalPositional) {
+    buffer.write(']');
+  }
+
+  buffer.write(')');
+  return buffer.toString();
+}
+
+/// Compute default argument list text and ranges based on the given
 /// [requiredParams] and [namedParams].
-void addDefaultArgDetails(
-    CompletionSuggestion suggestion,
-    Element element,
-    Iterable<ParameterElement> requiredParams,
-    Iterable<ParameterElement> namedParams) {
+CompletionDefaultArgumentList computeCompletionDefaultArgumentList(
+  Element element,
+  Iterable<ParameterElement> requiredParams,
+  Iterable<ParameterElement> namedParams,
+) {
   var sb = StringBuffer();
   var ranges = <int>[];
 
@@ -95,50 +137,10 @@
     }
   }
 
-  suggestion.defaultArgumentListString = sb.isNotEmpty ? sb.toString() : null;
-  suggestion.defaultArgumentListTextRanges = ranges.isNotEmpty ? ranges : null;
-}
-
-String buildClosureParameters(FunctionType type) {
-  var buffer = StringBuffer();
-  buffer.write('(');
-
-  var hasNamed = false;
-  var hasOptionalPositional = false;
-  var parameters = type.parameters;
-  var existingNames = parameters.map((p) => p.name).toSet();
-  for (var i = 0; i < parameters.length; ++i) {
-    var parameter = parameters[i];
-    if (i != 0) {
-      buffer.write(', ');
-    }
-    if (parameter.isNamed && !hasNamed) {
-      hasNamed = true;
-      buffer.write('{');
-    } else if (parameter.isOptionalPositional && !hasOptionalPositional) {
-      hasOptionalPositional = true;
-      buffer.write('[');
-    }
-    var name = parameter.name;
-    if (name.isEmpty) {
-      name = 'p$i';
-      var index = 1;
-      while (existingNames.contains(name)) {
-        name = 'p${i}_$index';
-        index++;
-      }
-    }
-    buffer.write(name);
-  }
-
-  if (hasNamed) {
-    buffer.write('}');
-  } else if (hasOptionalPositional) {
-    buffer.write(']');
-  }
-
-  buffer.write(')');
-  return buffer.toString();
+  return CompletionDefaultArgumentList(
+    text: sb.isNotEmpty ? sb.toString() : null,
+    ranges: ranges.isNotEmpty ? ranges : null,
+  );
 }
 
 /// Create a new protocol Element for inclusion in a completion suggestion.
@@ -246,6 +248,16 @@
   return type.getDisplayString(withNullability: false);
 }
 
+class CompletionDefaultArgumentList {
+  final String? text;
+  final List<int>? ranges;
+
+  CompletionDefaultArgumentList({
+    required this.text,
+    required this.ranges,
+  });
+}
+
 /// A tuple of text to insert and an (optional) location for the cursor.
 class DefaultArgument {
   /// The text to insert.
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 6f03e81..8b4050d 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -1162,10 +1162,14 @@
     check(response).suggestions.matches([
       (suggestion) => suggestion
         ..completion.isEqualTo('foo01')
-        ..isGetter,
+        ..isGetter
+        ..libraryUri.isNull
+        ..isNotImported.isNull,
       (suggestion) => suggestion
         ..completion.isEqualTo('foo02')
-        ..isGetter,
+        ..isGetter
+        ..libraryUri.isNull
+        ..isNotImported.isNull,
     ]);
   }
 
@@ -1609,6 +1613,29 @@
     ]);
   }
 
+  Future<void> test_prefixed_importPrefix_class() async {
+    await _configureWithWorkspaceRoot();
+
+    var response = await _getTestCodeSuggestions('''
+import 'dart:math' as math;
+
+void f() {
+  math.Rand^
+}
+''');
+
+    check(response)
+      ..assertComplete()
+      ..hasReplacement(left: 4);
+
+    check(response).suggestions.withElementClass.matches([
+      (suggestion) => suggestion
+        ..completion.isEqualTo('Random')
+        ..libraryUri.isEqualTo('dart:math')
+        ..isNotImported.isNull,
+    ]);
+  }
+
   Future<void> test_unprefixed_filters() async {
     await _configureWithWorkspaceRoot();
 
@@ -1664,10 +1691,14 @@
     check(response).suggestions.withElementClass.matches([
       (suggestion) => suggestion
         ..completion.isEqualTo('A01')
-        ..isClass,
+        ..isClass
+        ..libraryUri.isEqualTo('package:test/a.dart')
+        ..isNotImported.isNull,
       (suggestion) => suggestion
         ..completion.isEqualTo('A02')
-        ..isClass,
+        ..isClass
+        ..libraryUri.isEqualTo('package:test/b.dart')
+        ..isNotImported.isNull,
     ]);
   }
 
@@ -1698,10 +1729,14 @@
     check(response).suggestions.matches([
       (suggestion) => suggestion
         ..completion.isEqualTo('foo01')
-        ..isTopLevelVariable,
+        ..isTopLevelVariable
+        ..libraryUri.isEqualTo('package:test/a.dart')
+        ..isNotImported.isNull,
       (suggestion) => suggestion
         ..completion.isEqualTo('foo02')
-        ..isTopLevelVariable,
+        ..isTopLevelVariable
+        ..libraryUri.isEqualTo('package:test/b.dart')
+        ..isNotImported.isNull,
     ]);
   }
 
@@ -1724,7 +1759,8 @@
     check(response).suggestions.withElementClass.matches([
       (suggestion) => suggestion
         ..completion.isEqualTo('math.Random')
-        ..libraryUriToImport.isNull,
+        ..libraryUri.isEqualTo('dart:math')
+        ..isNotImported.isNull,
     ]);
   }
 
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 1e7cde4..3e1ed40 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -305,6 +305,7 @@
           'hasNamedParameters': isBool,
           'parameterName': isString,
           'parameterType': isString,
+          'libraryUri': isString,
           'isNotImported': isBool
         }));
 
@@ -384,8 +385,7 @@
       'parameters': isString,
       'returnType': isString,
       'typeParameters': isString,
-      'aliasedType': isString,
-      'libraryUri': isString
+      'aliasedType': isString
     }));
 
 /// ElementDeclaration
diff --git a/pkg/analysis_server/test/search/type_hierarchy_test.dart b/pkg/analysis_server/test/search/type_hierarchy_test.dart
index 28f9cba..2ed436f 100644
--- a/pkg/analysis_server/test/search/type_hierarchy_test.dart
+++ b/pkg/analysis_server/test/search/type_hierarchy_test.dart
@@ -64,8 +64,7 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [],
@@ -77,8 +76,7 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 0,
         'interfaces': [],
@@ -118,8 +116,7 @@
           'kind': 'CLASS',
           'name': 'AAA',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [],
@@ -131,8 +128,7 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'interfaces': [],
         'mixins': [],
@@ -143,8 +139,7 @@
           'kind': 'CLASS',
           'name': 'BBB',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 0,
         'interfaces': [],
@@ -156,8 +151,7 @@
           'kind': 'CLASS',
           'name': 'CCC',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 0,
         'interfaces': [],
@@ -210,8 +204,7 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [],
@@ -223,8 +216,7 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'interfaces': [],
         'mixins': [],
@@ -235,8 +227,7 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 0,
         'interfaces': [],
@@ -248,8 +239,7 @@
           'kind': 'CLASS',
           'name': 'C',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 2,
         'interfaces': [],
@@ -275,8 +265,7 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [],
@@ -288,8 +277,7 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 2,
         'interfaces': [],
@@ -301,8 +289,7 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'interfaces': [],
         'mixins': [],
@@ -313,8 +300,7 @@
           'kind': 'CLASS',
           'name': 'C',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 0,
         'interfaces': [],
@@ -340,8 +326,7 @@
           'kind': 'CLASS',
           'name': 'C',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [],
@@ -353,8 +338,7 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 2,
         'interfaces': [],
@@ -366,8 +350,7 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 3,
         'interfaces': [],
@@ -379,8 +362,7 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'interfaces': [],
         'mixins': [],
@@ -405,8 +387,7 @@
           'kind': 'CLASS',
           'name': 'T',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [2, 3],
@@ -418,8 +399,7 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'interfaces': [],
         'mixins': [],
@@ -430,8 +410,7 @@
           'kind': 'CLASS',
           'name': 'MA',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [],
@@ -443,8 +422,7 @@
           'kind': 'CLASS',
           'name': 'MB',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [],
@@ -471,8 +449,7 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [],
@@ -484,8 +461,7 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'interfaces': [],
         'mixins': [],
@@ -496,8 +472,7 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 0,
         'interfaces': [],
@@ -509,8 +484,7 @@
           'kind': 'CLASS',
           'name': 'C',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 0,
         'interfaces': [],
@@ -522,8 +496,7 @@
           'kind': 'CLASS',
           'name': 'D',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 0,
         'interfaces': [],
@@ -535,8 +508,7 @@
           'kind': 'CLASS',
           'name': 'E',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 0,
         'interfaces': [],
@@ -548,8 +520,7 @@
           'kind': 'CLASS',
           'name': 'F',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 4,
         'interfaces': [],
@@ -561,8 +532,7 @@
           'kind': 'CLASS',
           'name': 'G',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 4,
         'interfaces': [],
@@ -588,8 +558,7 @@
           'kind': 'CLASS',
           'name': 'T',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [],
@@ -601,8 +570,7 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'interfaces': [],
         'mixins': [],
@@ -613,8 +581,7 @@
           'kind': 'CLASS',
           'name': 'MA',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [],
@@ -626,8 +593,7 @@
           'kind': 'CLASS',
           'name': 'MB',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [],
@@ -1167,8 +1133,7 @@
           'kind': 'CLASS',
           'name': 'C',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 1,
         'interfaces': [3],
@@ -1180,8 +1145,7 @@
           'kind': 'CLASS',
           'name': 'A',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 2,
         'interfaces': [],
@@ -1193,8 +1157,7 @@
           'kind': 'CLASS',
           'name': 'Object',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'interfaces': [],
         'mixins': [],
@@ -1205,8 +1168,7 @@
           'kind': 'CLASS',
           'name': 'B',
           'location': anything,
-          'flags': 0,
-          'libraryUri': anything
+          'flags': 0
         },
         'superclass': 2,
         'interfaces': [],
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_check.dart b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
index 222d9dd..6ecb423 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_check.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
@@ -251,10 +251,18 @@
   }
 
   @useResult
+  CheckTarget<String?> get libraryUri {
+    return nest(
+      value.suggestion.libraryUri,
+      (selected) => 'has libraryUri ${valueStr(selected)}',
+    );
+  }
+
+  @useResult
   CheckTarget<String?> get libraryUriToImport {
     return nest(
       value.suggestion.isNotImported == true
-          ? value.suggestion.element?.libraryUri
+          ? value.suggestion.libraryUri
           : null,
       (selected) => 'has libraryUriToImport ${valueStr(selected)}',
     );
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index f721cc8..c05f315 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -49,7 +49,7 @@
     var builder = SuggestionBuilder(request);
     var contributor = createContributor(request, builder);
     await contributor.computeSuggestions();
-    return builder.suggestions.toList();
+    return builder.suggestions.map((e) => e.build()).toList();
   }
 
   DartCompletionContributor createContributor(
diff --git a/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart b/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
index 9f66816..3ee46d5 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
@@ -33,7 +33,7 @@
     );
     var builder = SuggestionBuilder(request);
     builder.suggestTopLevelFunction(findElement.topFunction('f'));
-    var suggestions = builder.suggestions.toList();
+    var suggestions = builder.suggestions.map((e) => e.build()).toList();
     expect(suggestions, hasLength(1));
     return suggestions[0];
   }
diff --git a/pkg/analysis_server/test/stress/completion/completion_runner.dart b/pkg/analysis_server/test/stress/completion/completion_runner.dart
index 2f7a688..301c2ad 100644
--- a/pkg/analysis_server/test/stress/completion/completion_runner.dart
+++ b/pkg/analysis_server/test/stress/completion/completion_runner.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
 import 'package:analysis_server/src/utilities/null_string_sink.dart';
 import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/dart/analysis/results.dart';
@@ -11,7 +12,6 @@
 import 'package:analyzer/file_system/overlay_file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/src/util/performance/operation_performance.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
 
 /// A runner that can request code completion at the location of each identifier
 /// in a Dart file.
@@ -203,8 +203,8 @@
     }
   }
 
-  List<CompletionSuggestion> _filterBy(
-      List<CompletionSuggestion> suggestions, String pattern) {
+  List<CompletionSuggestionBuilder> _filterBy(
+      List<CompletionSuggestionBuilder> suggestions, String pattern) {
     return suggestions
         .where((suggestion) => suggestion.completion.startsWith(pattern))
         .toList();
@@ -220,7 +220,8 @@
 
   /// If the given list of [suggestions] includes a suggestion for the given
   /// [identifier], return the index of the suggestion. Otherwise, return `-1`.
-  int _indexOf(List<CompletionSuggestion> suggestions, String identifier) {
+  int _indexOf(
+      List<CompletionSuggestionBuilder> suggestions, String identifier) {
     for (var i = 0; i < suggestions.length; i++) {
       if (suggestions[i].completion == identifier) {
         return i;
@@ -237,7 +238,7 @@
   }
 
   /// Print information about the given [suggestions].
-  void _printSuggestions(List<CompletionSuggestion> suggestions) {
+  void _printSuggestions(List<CompletionSuggestionBuilder> suggestions) {
     if (suggestions.isEmpty) {
       output.writeln('  No suggestions');
       return;
@@ -248,7 +249,8 @@
     }
   }
 
-  List<CompletionSuggestion> _sort(List<CompletionSuggestion> suggestions) {
+  List<CompletionSuggestionBuilder> _sort(
+      List<CompletionSuggestionBuilder> suggestions) {
     suggestions.sort((first, second) => second.relevance - first.relevance);
     return suggestions;
   }
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index 7007b15..d6f8764 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1217,11 +1217,14 @@
     var budget = CompletionBudget(Duration(seconds: 30));
     if (declarationsTracker == null) {
       // available suggestions == false
-      suggestions = await DartCompletionManager(
-              budget: budget,
-              listener: listener,
-              notImportedSuggestions: notImportedSuggestions)
-          .computeSuggestions(dartRequest, performance);
+      var serverSuggestions = await DartCompletionManager(
+        budget: budget,
+        listener: listener,
+        notImportedSuggestions: notImportedSuggestions,
+      ).computeSuggestions(dartRequest, performance);
+      suggestions = serverSuggestions.map((serverSuggestion) {
+        return serverSuggestion.build();
+      }).toList();
     } else {
       // available suggestions == true
       var includedElementKinds = <protocol.ElementKind>{};
@@ -1229,13 +1232,16 @@
       var includedSuggestionRelevanceTagList =
           <protocol.IncludedSuggestionRelevanceTag>[];
       var includedSuggestionSetList = <protocol.IncludedSuggestionSet>[];
-      suggestions = await DartCompletionManager(
+      var serverSuggestions = await DartCompletionManager(
         budget: budget,
         includedElementKinds: includedElementKinds,
         includedElementNames: includedElementNames,
         includedSuggestionRelevanceTags: includedSuggestionRelevanceTagList,
         listener: listener,
       ).computeSuggestions(dartRequest, performance);
+      suggestions = serverSuggestions.map((serverSuggestion) {
+        return serverSuggestion.build();
+      }).toList();
 
       computeIncludedSetList(declarationsTracker, dartRequest,
           includedSuggestionSetList, includedElementNames);
@@ -1923,7 +1929,8 @@
   String? missingCompletionLocationTable;
 
   @override
-  void builtSuggestion(protocol.CompletionSuggestion suggestion) {
+  void builtSuggestion(CompletionSuggestionBuilder suggestionBuilder) {
+    var suggestion = suggestionBuilder.build();
     featureMap[suggestion] = cachedFeatures;
     cachedFeatures = noFeatures;
   }
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
index f73aa41..9bc6c74 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
@@ -176,6 +176,21 @@
   private final String parameterType;
 
   /**
+   * This field is omitted if getSuggestions was used rather than getSuggestions2.
+   *
+   * This field is omitted if this suggestion corresponds to a locally declared element.
+   *
+   * If this suggestion corresponds to an already imported element, then this field is the URI of a
+   * library that provides this element, not the URI of the library where the element is declared.
+   *
+   * If this suggestion corresponds to an element from a not yet imported library, this field is the
+   * URI of a library that could be imported to make this suggestion accessible in the file where
+   * completion was requested, such as package:foo/bar.dart or
+   * file:///home/me/workspace/foo/test/bar_test.dart.
+   */
+  private final String libraryUri;
+
+  /**
    * True if the suggestion is for an element from a not yet imported library. This field is omitted
    * if the element is declared locally, or is from library is already imported, so that the
    * suggestion can be inserted as is, or if getSuggestions was used rather than getSuggestions2.
@@ -185,7 +200,7 @@
   /**
    * Constructor for {@link CompletionSuggestion}.
    */
-  public CompletionSuggestion(String kind, int relevance, String completion, String displayText, Integer replacementOffset, Integer replacementLength, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, Boolean isNotImported) {
+  public CompletionSuggestion(String kind, int relevance, String completion, String displayText, Integer replacementOffset, Integer replacementLength, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, String libraryUri, Boolean isNotImported) {
     this.kind = kind;
     this.relevance = relevance;
     this.completion = completion;
@@ -209,6 +224,7 @@
     this.hasNamedParameters = hasNamedParameters;
     this.parameterName = parameterName;
     this.parameterType = parameterType;
+    this.libraryUri = libraryUri;
     this.isNotImported = isNotImported;
   }
 
@@ -240,6 +256,7 @@
         ObjectUtilities.equals(other.hasNamedParameters, hasNamedParameters) &&
         ObjectUtilities.equals(other.parameterName, parameterName) &&
         ObjectUtilities.equals(other.parameterType, parameterType) &&
+        ObjectUtilities.equals(other.libraryUri, libraryUri) &&
         ObjectUtilities.equals(other.isNotImported, isNotImported);
     }
     return false;
@@ -269,8 +286,9 @@
     Boolean hasNamedParameters = jsonObject.get("hasNamedParameters") == null ? null : jsonObject.get("hasNamedParameters").getAsBoolean();
     String parameterName = jsonObject.get("parameterName") == null ? null : jsonObject.get("parameterName").getAsString();
     String parameterType = jsonObject.get("parameterType") == null ? null : jsonObject.get("parameterType").getAsString();
+    String libraryUri = jsonObject.get("libraryUri") == null ? null : jsonObject.get("libraryUri").getAsString();
     Boolean isNotImported = jsonObject.get("isNotImported") == null ? null : jsonObject.get("isNotImported").getAsBoolean();
-    return new CompletionSuggestion(kind, relevance, completion, displayText, replacementOffset, replacementLength, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, isNotImported);
+    return new CompletionSuggestion(kind, relevance, completion, displayText, replacementOffset, replacementLength, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, libraryUri, isNotImported);
   }
 
   public static List<CompletionSuggestion> fromJsonArray(JsonArray jsonArray) {
@@ -391,6 +409,23 @@
   }
 
   /**
+   * This field is omitted if getSuggestions was used rather than getSuggestions2.
+   *
+   * This field is omitted if this suggestion corresponds to a locally declared element.
+   *
+   * If this suggestion corresponds to an already imported element, then this field is the URI of a
+   * library that provides this element, not the URI of the library where the element is declared.
+   *
+   * If this suggestion corresponds to an element from a not yet imported library, this field is the
+   * URI of a library that could be imported to make this suggestion accessible in the file where
+   * completion was requested, such as package:foo/bar.dart or
+   * file:///home/me/workspace/foo/test/bar_test.dart.
+   */
+  public String getLibraryUri() {
+    return libraryUri;
+  }
+
+  /**
    * The name of the optional parameter being suggested. This field is omitted if the suggestion is
    * not the addition of an optional argument within an argument list.
    */
@@ -505,6 +540,7 @@
     builder.append(hasNamedParameters);
     builder.append(parameterName);
     builder.append(parameterType);
+    builder.append(libraryUri);
     builder.append(isNotImported);
     return builder.toHashCode();
   }
@@ -578,6 +614,9 @@
     if (parameterType != null) {
       jsonObject.addProperty("parameterType", parameterType);
     }
+    if (libraryUri != null) {
+      jsonObject.addProperty("libraryUri", libraryUri);
+    }
     if (isNotImported != null) {
       jsonObject.addProperty("isNotImported", isNotImported);
     }
@@ -634,6 +673,8 @@
     builder.append(parameterName + ", ");
     builder.append("parameterType=");
     builder.append(parameterType + ", ");
+    builder.append("libraryUri=");
+    builder.append(libraryUri + ", ");
     builder.append("isNotImported=");
     builder.append(isNotImported);
     builder.append("]");
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Element.java b/pkg/analysis_server/tool/spec/generated/java/types/Element.java
index 0648fc7..690f101 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Element.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Element.java
@@ -101,15 +101,9 @@
   private final String aliasedType;
 
   /**
-   * If the element belongs to a library, the URI of the library. Otherwise, this field will not be
-   * defined.
-   */
-  private final String libraryUri;
-
-  /**
    * Constructor for {@link Element}.
    */
-  public Element(String kind, String name, Location location, int flags, String parameters, String returnType, String typeParameters, String aliasedType, String libraryUri) {
+  public Element(String kind, String name, Location location, int flags, String parameters, String returnType, String typeParameters, String aliasedType) {
     this.kind = kind;
     this.name = name;
     this.location = location;
@@ -118,7 +112,6 @@
     this.returnType = returnType;
     this.typeParameters = typeParameters;
     this.aliasedType = aliasedType;
-    this.libraryUri = libraryUri;
   }
 
   @Override
@@ -133,8 +126,7 @@
         ObjectUtilities.equals(other.parameters, parameters) &&
         ObjectUtilities.equals(other.returnType, returnType) &&
         ObjectUtilities.equals(other.typeParameters, typeParameters) &&
-        ObjectUtilities.equals(other.aliasedType, aliasedType) &&
-        ObjectUtilities.equals(other.libraryUri, libraryUri);
+        ObjectUtilities.equals(other.aliasedType, aliasedType);
     }
     return false;
   }
@@ -148,8 +140,7 @@
     String returnType = jsonObject.get("returnType") == null ? null : jsonObject.get("returnType").getAsString();
     String typeParameters = jsonObject.get("typeParameters") == null ? null : jsonObject.get("typeParameters").getAsString();
     String aliasedType = jsonObject.get("aliasedType") == null ? null : jsonObject.get("aliasedType").getAsString();
-    String libraryUri = jsonObject.get("libraryUri") == null ? null : jsonObject.get("libraryUri").getAsString();
-    return new Element(kind, name, location, flags, parameters, returnType, typeParameters, aliasedType, libraryUri);
+    return new Element(kind, name, location, flags, parameters, returnType, typeParameters, aliasedType);
   }
 
   public static List<Element> fromJsonArray(JsonArray jsonArray) {
@@ -194,14 +185,6 @@
   }
 
   /**
-   * If the element belongs to a library, the URI of the library. Otherwise, this field will not be
-   * defined.
-   */
-  public String getLibraryUri() {
-    return libraryUri;
-  }
-
-  /**
    * The location of the name in the declaration of the element.
    */
   public Location getLocation() {
@@ -252,7 +235,6 @@
     builder.append(returnType);
     builder.append(typeParameters);
     builder.append(aliasedType);
-    builder.append(libraryUri);
     return builder.toHashCode();
   }
 
@@ -300,9 +282,6 @@
     if (aliasedType != null) {
       jsonObject.addProperty("aliasedType", aliasedType);
     }
-    if (libraryUri != null) {
-      jsonObject.addProperty("libraryUri", libraryUri);
-    }
     return jsonObject;
   }
 
@@ -325,9 +304,7 @@
     builder.append("typeParameters=");
     builder.append(typeParameters + ", ");
     builder.append("aliasedType=");
-    builder.append(aliasedType + ", ");
-    builder.append("libraryUri=");
-    builder.append(libraryUri);
+    builder.append(aliasedType);
     builder.append("]");
     return builder.toString();
   }
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
index c1a528b..71431b4 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -612,6 +612,23 @@
   /// if the parameterName field is omitted.
   String? parameterType;
 
+  /// This field is omitted if getSuggestions was used rather than
+  /// getSuggestions2.
+  ///
+  /// This field is omitted if this suggestion corresponds to a locally
+  /// declared element.
+  ///
+  /// If this suggestion corresponds to an already imported element, then this
+  /// field is the URI of a library that provides this element, not the URI of
+  /// the library where the element is declared.
+  ///
+  /// If this suggestion corresponds to an element from a not yet imported
+  /// library, this field is the URI of a library that could be imported to
+  /// make this suggestion accessible in the file where completion was
+  /// requested, such as package:foo/bar.dart or
+  /// file:///home/me/workspace/foo/test/bar_test.dart.
+  String? libraryUri;
+
   /// True if the suggestion is for an element from a not yet imported library.
   /// This field is omitted if the element is declared locally, or is from
   /// library is already imported, so that the suggestion can be inserted as
@@ -642,6 +659,7 @@
       this.hasNamedParameters,
       this.parameterName,
       this.parameterType,
+      this.libraryUri,
       this.isNotImported});
 
   factory CompletionSuggestion.fromJson(
@@ -781,6 +799,11 @@
         parameterType = jsonDecoder.decodeString(
             jsonPath + '.parameterType', json['parameterType']);
       }
+      String? libraryUri;
+      if (json.containsKey('libraryUri')) {
+        libraryUri = jsonDecoder.decodeString(
+            jsonPath + '.libraryUri', json['libraryUri']);
+      }
       bool? isNotImported;
       if (json.containsKey('isNotImported')) {
         isNotImported = jsonDecoder.decodeBool(
@@ -804,6 +827,7 @@
           hasNamedParameters: hasNamedParameters,
           parameterName: parameterName,
           parameterType: parameterType,
+          libraryUri: libraryUri,
           isNotImported: isNotImported);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'CompletionSuggestion', json);
@@ -884,6 +908,10 @@
     if (parameterType != null) {
       result['parameterType'] = parameterType;
     }
+    var libraryUri = this.libraryUri;
+    if (libraryUri != null) {
+      result['libraryUri'] = libraryUri;
+    }
     var isNotImported = this.isNotImported;
     if (isNotImported != null) {
       result['isNotImported'] = isNotImported;
@@ -923,6 +951,7 @@
           hasNamedParameters == other.hasNamedParameters &&
           parameterName == other.parameterName &&
           parameterType == other.parameterType &&
+          libraryUri == other.libraryUri &&
           isNotImported == other.isNotImported;
     }
     return false;
@@ -953,6 +982,7 @@
         hasNamedParameters,
         parameterName,
         parameterType,
+        libraryUri,
         isNotImported,
       ]);
 }
@@ -1234,17 +1264,12 @@
   /// this field will not be defined.
   String? aliasedType;
 
-  /// If the element belongs to a library, the URI of the library. Otherwise,
-  /// this field will not be defined.
-  String? libraryUri;
-
   Element(this.kind, this.name, this.flags,
       {this.location,
       this.parameters,
       this.returnType,
       this.typeParameters,
-      this.aliasedType,
-      this.libraryUri});
+      this.aliasedType});
 
   factory Element.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -1294,18 +1319,12 @@
         aliasedType = jsonDecoder.decodeString(
             jsonPath + '.aliasedType', json['aliasedType']);
       }
-      String? libraryUri;
-      if (json.containsKey('libraryUri')) {
-        libraryUri = jsonDecoder.decodeString(
-            jsonPath + '.libraryUri', json['libraryUri']);
-      }
       return Element(kind, name, flags,
           location: location,
           parameters: parameters,
           returnType: returnType,
           typeParameters: typeParameters,
-          aliasedType: aliasedType,
-          libraryUri: libraryUri);
+          aliasedType: aliasedType);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'Element', json);
     }
@@ -1344,10 +1363,6 @@
     if (aliasedType != null) {
       result['aliasedType'] = aliasedType;
     }
-    var libraryUri = this.libraryUri;
-    if (libraryUri != null) {
-      result['libraryUri'] = libraryUri;
-    }
     return result;
   }
 
@@ -1364,8 +1379,7 @@
           parameters == other.parameters &&
           returnType == other.returnType &&
           typeParameters == other.typeParameters &&
-          aliasedType == other.aliasedType &&
-          libraryUri == other.libraryUri;
+          aliasedType == other.aliasedType;
     }
     return false;
   }
@@ -1380,7 +1394,6 @@
         returnType,
         typeParameters,
         aliasedType,
-        libraryUri,
       );
 }
 
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 14a910c..487f5f95 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -104,8 +104,10 @@
   CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD,
   CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
   CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS,
+  CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_ENUM,
   CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION,
   CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_CLASS,
+  CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM,
   CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION,
   CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_MIXIN,
   CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MIXIN,
diff --git a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
index 103c1a6..2f3fd34 100644
--- a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
@@ -14,7 +14,7 @@
 import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
-import 'package:cli_util/cli_util.dart';
+import 'package:analyzer/src/util/sdk.dart';
 
 /// An implementation of [AnalysisContextCollection].
 class AnalysisContextCollectionImpl implements AnalysisContextCollection {
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index a9c0df3..e1ae643 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -27,8 +27,8 @@
 import 'package:analyzer/src/summary/summary_sdk.dart';
 import 'package:analyzer/src/summary2/package_bundle_format.dart';
 import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/util/sdk.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
-import 'package:cli_util/cli_util.dart';
 
 /// An implementation of a context builder.
 class ContextBuilderImpl implements ContextBuilder {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index b0f4037..a5e5f49 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -46,7 +46,7 @@
 
 /// A concrete implementation of a [ClassElement].
 abstract class AbstractClassElementImpl extends _ExistingElementImpl
-    with TypeParameterizedElementMixin
+    with TypeParameterizedElementMixin, HasCompletionData
     implements ClassElement {
   /// The superclass of the class, or `null` for [Object].
   InterfaceType? _supertype;
@@ -2803,7 +2803,7 @@
 
 /// A base class for concrete implementations of an [ExecutableElement].
 abstract class ExecutableElementImpl extends _ExistingElementImpl
-    with TypeParameterizedElementMixin
+    with TypeParameterizedElementMixin, HasCompletionData
     implements ExecutableElement, ElementImplWithFunctionType {
   /// A list containing all of the parameters defined by this executable
   /// element.
@@ -3474,6 +3474,11 @@
   }
 }
 
+/// This mixins is added to elements that can have cache completion data.
+mixin HasCompletionData {
+  Object? completionData;
+}
+
 /// A concrete implementation of a [HideElementCombinator].
 class HideElementCombinatorImpl implements HideElementCombinator {
   @override
@@ -5103,12 +5108,12 @@
 
   @override
   Element get nonSynthetic {
-    if (enclosingElement is EnumElementImpl) {
-      if (name == 'index' || name == 'values') {
-        return enclosingElement;
-      }
+    final variable = this.variable;
+    if (!variable.isSynthetic) {
+      return variable;
     }
-    return variable;
+    assert(enclosingElement is EnumElementImpl);
+    return enclosingElement;
   }
 
   @override
@@ -5435,6 +5440,7 @@
 
 /// A concrete implementation of a [TopLevelVariableElement].
 class TopLevelVariableElementImpl extends PropertyInducingElementImpl
+    with HasCompletionData
     implements TopLevelVariableElement {
   /// Initialize a newly created synthetic top-level variable element to have
   /// the given [name] and [offset].
diff --git a/pkg/analyzer/lib/src/error/codes.g.dart b/pkg/analyzer/lib/src/error/codes.g.dart
index 6cccc05..a9c1500 100644
--- a/pkg/analyzer/lib/src/error/codes.g.dart
+++ b/pkg/analyzer/lib/src/error/codes.g.dart
@@ -1886,6 +1886,20 @@
    * Parameters:
    * 0: the name of the type variable
    */
+  static const CompileTimeErrorCode CONFLICTING_TYPE_VARIABLE_AND_ENUM =
+      CompileTimeErrorCode(
+    'CONFLICTING_TYPE_VARIABLE_AND_CONTAINER',
+    "'{0}' can't be used to name both a type variable and the enum in which "
+        "the type variable is defined.",
+    correctionMessage: "Try renaming either the type variable or the enum.",
+    hasPublishedDocs: true,
+    uniqueName: 'CONFLICTING_TYPE_VARIABLE_AND_ENUM',
+  );
+
+  /**
+   * Parameters:
+   * 0: the name of the type variable
+   */
   static const CompileTimeErrorCode CONFLICTING_TYPE_VARIABLE_AND_EXTENSION =
       CompileTimeErrorCode(
     'CONFLICTING_TYPE_VARIABLE_AND_CONTAINER',
@@ -1941,6 +1955,20 @@
    * Parameters:
    * 0: the name of the type variable
    */
+  static const CompileTimeErrorCode CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM =
+      CompileTimeErrorCode(
+    'CONFLICTING_TYPE_VARIABLE_AND_MEMBER',
+    "'{0}' can't be used to name both a type variable and a member in this "
+        "enum.",
+    correctionMessage: "Try renaming either the type variable or the member.",
+    hasPublishedDocs: true,
+    uniqueName: 'CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM',
+  );
+
+  /**
+   * Parameters:
+   * 0: the name of the type variable
+   */
   static const CompileTimeErrorCode
       CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION = CompileTimeErrorCode(
     'CONFLICTING_TYPE_VARIABLE_AND_MEMBER',
@@ -14215,8 +14243,8 @@
 
   /**
    * Parameters:
-   * 0: the name of the enumeration constant that is not defined
-   * 1: the name of the enumeration used to access the constant
+   * 0: the name of the enum constant that is not defined
+   * 1: the name of the enum used to access the constant
    */
   // #### Description
   //
@@ -16450,7 +16478,7 @@
   // #### Description
   //
   // The analyzer produces this diagnostic when a `switch` statement for an enum
-  // doesn't include an option for one of the values in the enumeration.
+  // doesn't include an option for one of the values in the enum.
   //
   // Note that `null` is always a possible value for an enum and therefore also
   // must be handled.
diff --git a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
index 2978a39..00fadde 100644
--- a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
+++ b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
@@ -40,6 +40,11 @@
     _initFieldsMap(node.declaredElement!);
   }
 
+  void enterEnum(EnumDeclaration node) {
+    _isInNativeClass = false;
+    _initFieldsMap(node.declaredElement!);
+  }
+
   void leaveClass() {
     _isInNativeClass = false;
     _initialFieldMap = null;
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index 113dae0..08b53b9 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -8,21 +8,20 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/error/codes.dart';
 
 class DuplicateDefinitionVerifier {
-  static final Set<String> _enumInstanceMembers = {
-    'hashCode',
-    'index',
-    FunctionElement.NO_SUCH_METHOD_METHOD_NAME,
-    'runtimeType',
-    'toString',
-  };
-
+  final InheritanceManager3 _inheritanceManager;
   final LibraryElement _currentLibrary;
   final ErrorReporter _errorReporter;
 
-  DuplicateDefinitionVerifier(this._currentLibrary, this._errorReporter);
+  DuplicateDefinitionVerifier(
+    this._inheritanceManager,
+    this._currentLibrary,
+    this._errorReporter,
+  );
 
   /// Check that the exception and stack trace parameters have different names.
   void checkCatchClause(CatchClause node) {
@@ -45,30 +44,65 @@
 
   /// Check that there are no members with the same name.
   void checkEnum(EnumDeclaration node) {
-    ClassElement element = node.declaredElement!;
+    var enumElement = node.declaredElement as EnumElementImpl;
+    var enumName = enumElement.name;
 
-    Map<String, Element> staticGetters = {
-      'values': element.getGetter('values')!
-    };
+    var instanceGetters = <String, Element>{};
+    var instanceSetters = <String, Element>{};
+    var staticGetters = <String, Element>{};
+    var staticSetters = <String, Element>{};
 
     for (EnumConstantDeclaration constant in node.constants) {
       _checkDuplicateIdentifier(staticGetters, constant.name);
     }
 
-    String enumName = element.name;
-    for (EnumConstantDeclaration constant in node.constants) {
-      SimpleIdentifier identifier = constant.name;
-      String name = identifier.name;
-      if (name == enumName) {
+    for (var member in node.members) {
+      if (member is FieldDeclaration) {
+        for (var field in member.fields.variables) {
+          var identifier = field.name;
+          _checkDuplicateIdentifier(
+            member.isStatic ? staticGetters : instanceGetters,
+            identifier,
+            setterScope: member.isStatic ? staticSetters : instanceSetters,
+          );
+        }
+      } else if (member is MethodDeclaration) {
+        _checkDuplicateIdentifier(
+          member.isStatic ? staticGetters : instanceGetters,
+          member.name,
+          setterScope: member.isStatic ? staticSetters : instanceSetters,
+        );
+      }
+    }
+
+    for (var constant in node.constants) {
+      if (constant.name.name == enumName) {
         _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING,
-          identifier,
+          constant.name,
         );
-      } else if (_enumInstanceMembers.contains(name)) {
-        _errorReporter.reportErrorForNode(
+      }
+    }
+
+    var staticExecutable = [
+      ...enumElement.accessors,
+      ...enumElement.methods,
+    ].where((element) => element.isStatic);
+    for (var executable in staticExecutable) {
+      var baseName = executable.displayName;
+      var instanceGetter = _inheritanceManager.getMember2(
+        enumElement,
+        Name(_currentLibrary.source.uri, baseName),
+      );
+      var instanceSetter = _inheritanceManager.getMember2(
+        enumElement,
+        Name(_currentLibrary.source.uri, '$baseName='),
+      );
+      if (instanceGetter != null || instanceSetter != null) {
+        _errorReporter.reportErrorForElement(
           CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE,
-          identifier,
-          [enumName, name, enumName],
+          executable,
+          [enumName, baseName, enumName],
         );
       }
     }
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 233fb5f..42cca4f 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -246,8 +246,8 @@
             _UninstantiatedBoundChecker(errorReporter),
         _checkUseVerifier = UseResultVerifier(errorReporter),
         _requiredParametersVerifier = RequiredParametersVerifier(errorReporter),
-        _duplicateDefinitionVerifier =
-            DuplicateDefinitionVerifier(_currentLibrary, errorReporter) {
+        _duplicateDefinitionVerifier = DuplicateDefinitionVerifier(
+            _inheritanceManager, _currentLibrary, errorReporter) {
     _isInSystemLibrary = _currentLibrary.source.uri.isScheme('dart');
     _isInCatchClause = false;
     _isInStaticVariableDeclaration = false;
@@ -561,14 +561,13 @@
   void visitEnumDeclaration(EnumDeclaration node) {
     var outerClass = _enclosingClass;
     try {
-      _enclosingClass = node.declaredElement;
+      var element = node.declaredElement as EnumElementImpl;
+      _enclosingClass = element;
       _duplicateDefinitionVerifier.checkEnum(node);
 
-      // TODO(scheglov) implement
-      // List<ClassMember> members = node.members;
       _checkForBuiltInIdentifierAsName(
           node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
-      // _checkForConflictingClassTypeVariableErrorCodes();
+      _checkForConflictingEnumTypeVariableErrorCodes(element);
       var implementsClause = node.implementsClause;
       var withClause = node.withClause;
 
@@ -578,8 +577,8 @@
 
       // TODO(scheglov) implement
       // _checkForConflictingClassMembers();
-      // _constructorFieldsVerifier.enterClass(node);
-      // _checkForFinalNotInitializedInClass(members);
+      _constructorFieldsVerifier.enterEnum(node);
+      _checkForFinalNotInitializedInClass(node.members);
       _checkForWrongTypeParameterVarianceInSuperinterfaces();
       _checkForMainFunction(node.name);
 
@@ -1845,6 +1844,32 @@
     }
   }
 
+  void _checkForConflictingEnumTypeVariableErrorCodes(
+    EnumElementImpl element,
+  ) {
+    for (var typeParameter in element.typeParameters) {
+      var name = typeParameter.name;
+      // name is same as the name of the enclosing enum
+      if (element.name == name) {
+        errorReporter.reportErrorForElement(
+          CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_ENUM,
+          typeParameter,
+          [name],
+        );
+      }
+      // check members
+      if (element.getMethod(name) != null ||
+          element.getGetter(name) != null ||
+          element.getSetter(name) != null) {
+        errorReporter.reportErrorForElement(
+          CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM,
+          typeParameter,
+          [name],
+        );
+      }
+    }
+  }
+
   /// Verify all conflicts between type variable and enclosing extension.
   ///
   /// See [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_EXTENSION], and
diff --git a/pkg/analyzer/lib/src/util/sdk.dart b/pkg/analyzer/lib/src/util/sdk.dart
index d588cc3..6e73efb 100644
--- a/pkg/analyzer/lib/src/util/sdk.dart
+++ b/pkg/analyzer/lib/src/util/sdk.dart
@@ -6,27 +6,5 @@
 
 import 'package:path/path.dart' as path;
 
-String getSdkPath([List<String>? args]) {
-  // Look for --dart-sdk on the command line.
-  if (args != null) {
-    int index = args.indexOf('--dart-sdk');
-
-    if (index != -1 && (index + 1 < args.length)) {
-      return args[index + 1];
-    }
-
-    for (String arg in args) {
-      if (arg.startsWith('--dart-sdk=')) {
-        return arg.substring('--dart-sdk='.length);
-      }
-    }
-  }
-
-  // Look in env['DART_SDK']
-  if (Platform.environment['DART_SDK'] != null) {
-    return Platform.environment['DART_SDK']!;
-  }
-
-  // Use Platform.resolvedExecutable.
-  return path.dirname(path.dirname(Platform.resolvedExecutable));
-}
+/// Return the path to the runtime Dart SDK.
+String getSdkPath() => path.dirname(path.dirname(Platform.resolvedExecutable));
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index 58539a7..b63ff5f 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -1852,6 +1852,14 @@
       ```dart
       class C<T> {}
       ```
+  CONFLICTING_TYPE_VARIABLE_AND_ENUM:
+    sharedName: CONFLICTING_TYPE_VARIABLE_AND_CONTAINER
+    problemMessage: "'{0}' can't be used to name both a type variable and the enum in which the type variable is defined."
+    correctionMessage: Try renaming either the type variable or the enum.
+    hasPublishedDocs: true
+    comment: |-
+      Parameters:
+      0: the name of the type variable
   CONFLICTING_TYPE_VARIABLE_AND_EXTENSION:
     sharedName: CONFLICTING_TYPE_VARIABLE_AND_CONTAINER
     problemMessage: "'{0}' can't be used to name both a type variable and the extension in which the type variable is defined."
@@ -1911,6 +1919,14 @@
     comment: |-
       Parameters:
       0: the name of the type variable
+  CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM:
+    sharedName: CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+    problemMessage: "'{0}' can't be used to name both a type variable and a member in this enum."
+    correctionMessage: Try renaming either the type variable or the member.
+    hasPublishedDocs: true
+    comment: |-
+      Parameters:
+      0: the name of the type variable
   CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION:
     sharedName: CONFLICTING_TYPE_VARIABLE_AND_MEMBER
     problemMessage: "'{0}' can't be used to name both a type variable and a member in this extension."
@@ -12216,8 +12232,8 @@
     hasPublishedDocs: true
     comment: |-
       Parameters:
-      0: the name of the enumeration constant that is not defined
-      1: the name of the enumeration used to access the constant
+      0: the name of the enum constant that is not defined
+      1: the name of the enum used to access the constant
     documentation: |-
       #### Description
 
@@ -19852,7 +19868,7 @@
       #### Description
 
       The analyzer produces this diagnostic when a `switch` statement for an enum
-      doesn't include an option for one of the values in the enumeration.
+      doesn't include an option for one of the values in the enum.
 
       Note that `null` is always a possible value for an enum and therefore also
       must be handled.
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 424d0ce..b030e30 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -8,7 +8,6 @@
 
 dependencies:
   _fe_analyzer_shared: ^34.0.0
-  cli_util: ^0.3.0
   collection: ^1.15.0
   convert: ^3.0.0
   crypto: ^3.0.0
diff --git a/pkg/analyzer/test/src/dart/resolution/class_test.dart b/pkg/analyzer/test/src/dart/resolution/class_test.dart
index fd7aa57..c2ee4c7 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_test.dart
@@ -2,9 +2,7 @@
 // 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:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'context_collection_resolution.dart';
@@ -123,364 +121,6 @@
     );
   }
 
-  test_error_conflictingConstructorAndStaticField_field() async {
-    await assertErrorsInCode(r'''
-class C {
-  C.foo();
-  static int foo = 0;
-}
-''', [
-      error(
-          CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD, 14, 3),
-    ]);
-  }
-
-  test_error_conflictingConstructorAndStaticField_getter() async {
-    await assertErrorsInCode(r'''
-class C {
-  C.foo();
-  static int get foo => 0;
-}
-''', [
-      error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER, 14,
-          3),
-    ]);
-  }
-
-  test_error_conflictingConstructorAndStaticField_OK_notSameClass() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  static int foo = 0;
-}
-class B extends A {
-  B.foo();
-}
-''');
-  }
-
-  test_error_conflictingConstructorAndStaticField_OK_notStatic() async {
-    await assertNoErrorsInCode(r'''
-class C {
-  C.foo();
-  int foo = 0;
-}
-''');
-  }
-
-  test_error_conflictingConstructorAndStaticField_setter() async {
-    await assertErrorsInCode(r'''
-class C {
-  C.foo();
-  static void set foo(_) {}
-}
-''', [
-      error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER, 14,
-          3),
-    ]);
-  }
-
-  test_error_conflictingConstructorAndStaticMethod() async {
-    await assertErrorsInCode(r'''
-class C {
-  C.foo();
-  static void foo() {}
-}
-''', [
-      error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD, 14,
-          3),
-    ]);
-  }
-
-  test_error_conflictingConstructorAndStaticMethod_OK_notSameClass() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  static void foo() {}
-}
-class B extends A {
-  B.foo();
-}
-''');
-  }
-
-  test_error_conflictingConstructorAndStaticMethod_OK_notStatic() async {
-    await assertNoErrorsInCode(r'''
-class C {
-  C.foo();
-  void foo() {}
-}
-''');
-  }
-
-  test_error_conflictingFieldAndMethod_inSuper_field() async {
-    await assertErrorsInCode(r'''
-class A {
-  foo() {}
-}
-class B extends A {
-  int foo = 0;
-}
-''', [
-      error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
-    ]);
-  }
-
-  test_error_conflictingFieldAndMethod_inSuper_getter() async {
-    await assertErrorsInCode(r'''
-class A {
-  foo() {}
-}
-class B extends A {
-  get foo => 0;
-}
-''', [
-      error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
-    ]);
-  }
-
-  test_error_conflictingFieldAndMethod_inSuper_setter() async {
-    await assertErrorsInCode(r'''
-class A {
-  foo() {}
-}
-class B extends A {
-  set foo(_) {}
-}
-''', [
-      error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
-    ]);
-  }
-
-  test_error_conflictingMethodAndField_inSuper_field() async {
-    await assertErrorsInCode(r'''
-class A {
-  int foo = 0;
-}
-class B extends A {
-  foo() {}
-}
-''', [
-      error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 49, 3),
-    ]);
-  }
-
-  test_error_conflictingMethodAndField_inSuper_getter() async {
-    await assertErrorsInCode(r'''
-class A {
-  get foo => 0;
-}
-class B extends A {
-  foo() {}
-}
-''', [
-      error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 50, 3),
-    ]);
-  }
-
-  test_error_conflictingMethodAndField_inSuper_setter() async {
-    await assertErrorsInCode(r'''
-class A {
-  set foo(_) {}
-}
-class B extends A {
-  foo() {}
-}
-''', [
-      error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 50, 3),
-    ]);
-  }
-
-  test_error_duplicateConstructorNamed() async {
-    await assertErrorsInCode(r'''
-class C {
-  C.foo();
-  C.foo();
-}
-''', [
-      error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME, 23, 5),
-    ]);
-  }
-
-  test_error_duplicateConstructorNamed_oneIsInvalid() async {
-    await assertErrorsInCode(r'''
-class A {}
-class C {
-  A.foo();
-  C.foo();
-}
-''', [
-      error(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 23, 1),
-    ]);
-  }
-
-  test_error_duplicateConstructorUnnamed() async {
-    await assertErrorsInCode(r'''
-class C {
-  C();
-  C();
-}
-''', [
-      error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 19, 1),
-    ]);
-  }
-
-  test_error_duplicateConstructorUnnamed_bothNew() async {
-    await assertErrorsInCode(r'''
-class C {
-  C.new();
-  C.new();
-}
-''', [
-      error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 23, 5),
-    ]);
-  }
-
-  test_error_duplicateConstructorUnnamed_oneIsInvalid() async {
-    await assertErrorsInCode(r'''
-class A {}
-class C {
-  A.new();
-  C();
-}
-''', [
-      error(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 23, 1),
-    ]);
-  }
-
-  test_error_duplicateConstructorUnnamed_oneNew() async {
-    await assertErrorsInCode(r'''
-class C {
-  C();
-  C.new();
-}
-''', [
-      error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 19, 5),
-    ]);
-  }
-
-  test_error_extendsNonClass_dynamic() async {
-    await assertErrorsInCode(r'''
-class A extends dynamic {}
-''', [
-      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 16, 7),
-    ]);
-
-    var a = findElement.class_('A');
-    assertType(a.supertype, 'Object');
-  }
-
-  test_error_extendsNonClass_enum() async {
-    await assertErrorsInCode(r'''
-enum E { ONE }
-class A extends E {}
-''', [
-      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 31, 1),
-    ]);
-
-    var a = findElement.class_('A');
-    assertType(a.supertype, 'Object');
-
-    var eRef = findNode.namedType('E {}');
-    assertNamedType(eRef, findElement.enum_('E'), 'E');
-  }
-
-  test_error_extendsNonClass_mixin() async {
-    await assertErrorsInCode(r'''
-mixin M {}
-class A extends M {} // ref
-''', [
-      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
-    ]);
-
-    var a = findElement.class_('A');
-    assertType(a.supertype, 'Object');
-
-    var mRef = findNode.namedType('M {} // ref');
-    assertNamedType(mRef, findElement.mixin('M'), 'M');
-  }
-
-  test_error_extendsNonClass_variable() async {
-    await assertErrorsInCode(r'''
-int v = 0;
-class A extends v {}
-''', [
-      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
-    ]);
-
-    var a = findElement.class_('A');
-    assertType(a.supertype, 'Object');
-  }
-
-  test_error_extendsNonClass_variable_generic() async {
-    await assertErrorsInCode(r'''
-int v = 0;
-class A extends v<int> {}
-''', [
-      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
-    ]);
-
-    var a = findElement.class_('A');
-    assertType(a.supertype, 'Object');
-  }
-
-  test_error_memberWithClassName_field() async {
-    await assertErrorsInCode(r'''
-class C {
-  int C = 42;
-}
-''', [
-      error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
-    ]);
-  }
-
-  test_error_memberWithClassName_getter() async {
-    await assertErrorsInCode(r'''
-class C {
-  int get C => 0;
-}
-''', [
-      error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 20, 1),
-    ]);
-  }
-
-  test_error_memberWithClassName_getter_static() async {
-    await assertErrorsInCode(r'''
-class C {
-  static int get C => 0;
-}
-''', [
-      error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 27, 1),
-    ]);
-
-    var method = findNode.methodDeclaration('C =>');
-    expect(method.isGetter, isTrue);
-    expect(method.isStatic, isTrue);
-    assertElement(method, findElement.getter('C'));
-  }
-
-  test_error_memberWithClassName_setter() async {
-    await assertErrorsInCode(r'''
-class C {
-  set C(_) {}
-}
-''', [
-      error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
-    ]);
-  }
-
-  test_error_memberWithClassName_setter_static() async {
-    await assertErrorsInCode(r'''
-class C {
-  static set C(_) {}
-}
-''', [
-      error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 23, 1),
-    ]);
-
-    var method = findNode.methodDeclaration('C(_)');
-    expect(method.isSetter, isTrue);
-    expect(method.isStatic, isTrue);
-  }
-
   test_issue32815() async {
     await assertErrorsInCode(r'''
 class A<T> extends B<T> {}
@@ -503,230 +143,4 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 150, 1),
     ]);
   }
-
-  test_recursiveInterfaceInheritance_extends() async {
-    await assertErrorsInCode(r'''
-class A extends B {}
-class B extends A {}
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 27, 1),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritance_extends_implements() async {
-    await assertErrorsInCode(r'''
-class A extends B {}
-class B implements A {}
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 27, 1),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritance_implements() async {
-    await assertErrorsInCode(r'''
-class A implements B {}
-class B implements A {}
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 30, 1),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritance_mixin() async {
-    await assertErrorsInCode(r'''
-class M1 = Object with M2;
-class M2 = Object with M1;
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 2),
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 33, 2),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritance_mixin_superclass() async {
-    // Make sure we don't get CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS in
-    // addition--that would just be confusing.
-    await assertErrorsInCode('''
-class C = D with M;
-class D = C with M;
-class M {}
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 26, 1),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritance_tail() async {
-    await assertErrorsInCode(r'''
-abstract class A implements A {}
-class B implements A {}
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 15,
-          1),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritance_tail2() async {
-    await assertErrorsInCode(r'''
-abstract class A implements B {}
-abstract class B implements A {}
-class C implements A {}
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 15, 1),
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 48, 1),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritance_tail3() async {
-    await assertErrorsInCode(r'''
-abstract class A implements B {}
-abstract class B implements C {}
-abstract class C implements A {}
-class D implements A {}
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 15, 1),
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 48, 1),
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 81, 1),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritanceExtends() async {
-    await assertErrorsInCode(r'''
-class A extends A {}
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS, 6, 1),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritanceExtends_abstract() async {
-    await assertErrorsInCode(r'''
-class C extends C {
-  var bar = 0;
-  m();
-}
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS, 6, 1),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritanceImplements() async {
-    await assertErrorsInCode('''
-class A implements A {}
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 6,
-          1),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritanceImplements_typeAlias() async {
-    await assertErrorsInCode(r'''
-class A {}
-class M {}
-class B = A with M implements B;
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 28,
-          1),
-    ]);
-  }
-
-  test_recursiveInterfaceInheritanceWith() async {
-    await assertErrorsInCode(r'''
-class M = Object with M;
-''', [
-      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_WITH, 6, 1),
-    ]);
-  }
-
-  test_undefinedSuperGetter() async {
-    await assertErrorsInCode(r'''
-class A {}
-class B extends A {
-  get g {
-    return super.g;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.UNDEFINED_SUPER_GETTER, 58, 1),
-    ]);
-  }
-
-  test_undefinedSuperMethod() async {
-    await assertErrorsInCode(r'''
-class A {}
-class B extends A {
-  m() {
-    return super.m();
-  }
-}
-''', [
-      error(CompileTimeErrorCode.UNDEFINED_SUPER_METHOD, 56, 1),
-    ]);
-  }
-
-  test_undefinedSuperOperator_binaryExpression() async {
-    await assertErrorsInCode(r'''
-class A {}
-class B extends A {
-  operator +(value) {
-    return super + value;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 1),
-    ]);
-  }
-
-  test_undefinedSuperOperator_indexBoth() async {
-    await assertErrorsInCode(r'''
-class A {}
-class B extends A {
-  operator [](index) {
-    return super[index]++;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 7),
-      error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 7),
-    ]);
-  }
-
-  test_undefinedSuperOperator_indexGetter() async {
-    await assertErrorsInCode(r'''
-class A {}
-class B extends A {
-  operator [](index) {
-    return super[index + 1];
-  }
-}
-''', [
-      error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 11),
-    ]);
-  }
-
-  test_undefinedSuperOperator_indexSetter() async {
-    await assertErrorsInCode(r'''
-class A {}
-class B extends A {
-  operator []=(index, value) {
-    super[index] = 0;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 71, 7),
-    ]);
-  }
-
-  test_undefinedSuperSetter() async {
-    await assertErrorsInCode(r'''
-class A {}
-class B extends A {
-  f() {
-    super.m = 0;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.UNDEFINED_SUPER_SETTER, 49, 1),
-    ]);
-  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_field_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_field_test.dart
new file mode 100644
index 0000000..6cb825d
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_field_test.dart
@@ -0,0 +1,74 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConflictingConstructorAndStaticFieldTest);
+  });
+}
+
+@reflectiveTest
+class ConflictingConstructorAndStaticFieldTest
+    extends PubPackageResolutionTest {
+  test_class_field() async {
+    await assertErrorsInCode(r'''
+class C {
+  C.foo();
+  static int foo = 0;
+}
+''', [
+      error(
+          CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_FIELD, 14, 3),
+    ]);
+  }
+
+  test_class_getter() async {
+    await assertErrorsInCode(r'''
+class C {
+  C.foo();
+  static int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_GETTER, 14,
+          3),
+    ]);
+  }
+
+  test_class_OK_notSameClass() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  static int foo = 0;
+}
+class B extends A {
+  B.foo();
+}
+''');
+  }
+
+  test_class_OK_notStatic() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C.foo();
+  int foo = 0;
+}
+''');
+  }
+
+  test_class_setter() async {
+    await assertErrorsInCode(r'''
+class C {
+  C.foo();
+  static void set foo(_) {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_SETTER, 14,
+          3),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_method_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_method_test.dart
new file mode 100644
index 0000000..a880ff5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_constructor_and_static_method_test.dart
@@ -0,0 +1,50 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConflictingConstructorAndStaticMethodTest);
+  });
+}
+
+@reflectiveTest
+class ConflictingConstructorAndStaticMethodTest
+    extends PubPackageResolutionTest {
+  test_class_OK_notSameClass() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  static void foo() {}
+}
+class B extends A {
+  B.foo();
+}
+''');
+  }
+
+  test_class_OK_notStatic() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C.foo();
+  void foo() {}
+}
+''');
+  }
+
+  test_error_conflictingConstructorAndStaticMethod() async {
+    await assertErrorsInCode(r'''
+class C {
+  C.foo();
+  static void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR_AND_STATIC_METHOD, 14,
+          3),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_field_and_method_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_field_and_method_test.dart
new file mode 100644
index 0000000..2abf55f
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_field_and_method_test.dart
@@ -0,0 +1,56 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConflictingFieldAndMethodTest);
+  });
+}
+
+@reflectiveTest
+class ConflictingFieldAndMethodTest extends PubPackageResolutionTest {
+  test_class_inSuper_field() async {
+    await assertErrorsInCode(r'''
+class A {
+  foo() {}
+}
+class B extends A {
+  int foo = 0;
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
+    ]);
+  }
+
+  test_class_inSuper_getter() async {
+    await assertErrorsInCode(r'''
+class A {
+  foo() {}
+}
+class B extends A {
+  get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
+    ]);
+  }
+
+  test_class_inSuper_setter() async {
+    await assertErrorsInCode(r'''
+class A {
+  foo() {}
+}
+class B extends A {
+  set foo(_) {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_FIELD_AND_METHOD, 49, 3),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_method_and_field_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_method_and_field_test.dart
new file mode 100644
index 0000000..1366e18
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_method_and_field_test.dart
@@ -0,0 +1,56 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConflictingMethodAndFieldTest);
+  });
+}
+
+@reflectiveTest
+class ConflictingMethodAndFieldTest extends PubPackageResolutionTest {
+  test_class_inSuper_field() async {
+    await assertErrorsInCode(r'''
+class A {
+  int foo = 0;
+}
+class B extends A {
+  foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 49, 3),
+    ]);
+  }
+
+  test_class_inSuper_getter() async {
+    await assertErrorsInCode(r'''
+class A {
+  get foo => 0;
+}
+class B extends A {
+  foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 50, 3),
+    ]);
+  }
+
+  test_class_inSuper_setter() async {
+    await assertErrorsInCode(r'''
+class A {
+  set foo(_) {}
+}
+class B extends A {
+  foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, 50, 3),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart
index 85205db..cd47d2e 100644
--- a/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_static_and_instance_test.dart
@@ -451,7 +451,7 @@
 
 @reflectiveTest
 class ConflictingStaticAndInstanceEnumTest extends PubPackageResolutionTest {
-  test_hashCode() async {
+  test_constant_hashCode() async {
     await assertErrorsInCode(r'''
 enum E {
   a, hashCode, b
@@ -461,7 +461,7 @@
     ]);
   }
 
-  test_index() async {
+  test_constant_index() async {
     await assertErrorsInCode(r'''
 enum E {
   a, index, b
@@ -471,7 +471,7 @@
     ]);
   }
 
-  test_noSuchMethod() async {
+  test_constant_noSuchMethod() async {
     await assertErrorsInCode(r'''
 enum E {
   a, noSuchMethod, b
@@ -481,7 +481,7 @@
     ]);
   }
 
-  test_runtimeType() async {
+  test_constant_runtimeType() async {
     await assertErrorsInCode(r'''
 enum E {
   a, runtimeType, b
@@ -491,7 +491,7 @@
     ]);
   }
 
-  test_toString() async {
+  test_constant_toString() async {
     await assertErrorsInCode(r'''
 enum E {
   a, toString, b
@@ -500,6 +500,214 @@
       error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 14, 8),
     ]);
   }
+
+  test_field_dartCoreEnum() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static final int hashCode = 0;
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 33, 8),
+    ]);
+  }
+
+  test_field_mixin_getter() async {
+    await assertErrorsInCode(r'''
+mixin M {
+  int get foo => 0;
+}
+
+enum E with M {
+  v;
+  static final int foo = 0;
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 73, 3),
+    ]);
+  }
+
+  test_field_mixin_method() async {
+    await assertErrorsInCode(r'''
+mixin M {
+  void foo() {}
+}
+
+enum E with M {
+  v;
+  static final int foo = 0;
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 69, 3),
+    ]);
+  }
+
+  test_field_mixin_setter() async {
+    await assertErrorsInCode(r'''
+mixin M {
+  set foo(int _) {}
+}
+
+enum E with M {
+  v;
+  static final int foo = 0;
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 73, 3),
+    ]);
+  }
+
+  test_field_this_getter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static final int foo = 0;
+  int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 33, 3),
+    ]);
+  }
+
+  test_field_this_method() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static final int foo = 0;
+  void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 33, 3),
+    ]);
+  }
+
+  test_field_this_setter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static final int foo = 0;
+  set foo(int _) {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 33, 3),
+    ]);
+  }
+
+  test_getter_this_setter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static int get foo => 0;
+  set foo(_) {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 31, 3),
+    ]);
+  }
+
+  test_method_dartCoreEnum() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static int hashCode() => 0;
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 27, 8),
+    ]);
+  }
+
+  test_method_mixin_getter() async {
+    await assertErrorsInCode(r'''
+mixin M {
+  int get foo => 0;
+}
+
+enum E with M {
+  v;
+  static void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 68, 3),
+    ]);
+  }
+
+  test_method_mixin_method() async {
+    await assertErrorsInCode(r'''
+mixin M {
+  void foo() {}
+}
+
+enum E with M {
+  v;
+  static void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 64, 3),
+    ]);
+  }
+
+  test_method_mixin_setter() async {
+    await assertErrorsInCode(r'''
+mixin M {
+  set foo(int _) {}
+}
+
+enum E with M {
+  v;
+  static void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 68, 3),
+    ]);
+  }
+
+  test_method_this_getter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static void foo() {}
+  int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 28, 3),
+    ]);
+  }
+
+  test_method_this_method() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static void foo() {}
+  void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 28, 3),
+    ]);
+  }
+
+  test_method_this_setter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static void foo() {}
+  set foo(int _) {}
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 28, 3),
+    ]);
+  }
+
+  test_setter_this_getter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static set foo(_) {}
+  int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, 27, 3),
+    ]);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_container_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_container_test.dart
index ecf579a..14f3ce5 100644
--- a/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_container_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_container_test.dart
@@ -10,6 +10,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ConflictingTypeVariableAndClassTest);
+    defineReflectiveTests(ConflictingTypeVariableAndEnumTest);
     defineReflectiveTests(ConflictingTypeVariableAndExtensionTest);
     defineReflectiveTests(ConflictingTypeVariableAndMixinTest);
   });
@@ -27,6 +28,19 @@
 }
 
 @reflectiveTest
+class ConflictingTypeVariableAndEnumTest extends PubPackageResolutionTest {
+  test_conflict() async {
+    await assertErrorsInCode(r'''
+enum E<E> {
+  v
+}
+''', [
+      error(CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_ENUM, 7, 1),
+    ]);
+  }
+}
+
+@reflectiveTest
 class ConflictingTypeVariableAndExtensionTest extends PubPackageResolutionTest {
   test_conflict() async {
     await assertErrorsInCode(r'''
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart
index efab14b..00ce562 100644
--- a/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_type_variable_and_member_test.dart
@@ -10,6 +10,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ConflictingTypeVariableAndMemberClassTest);
+    defineReflectiveTests(ConflictingTypeVariableAndMemberEnumTest);
     defineReflectiveTests(ConflictingTypeVariableAndMemberExtensionTest);
     defineReflectiveTests(ConflictingTypeVariableAndMemberMixinTest);
   });
@@ -86,6 +87,46 @@
 }
 
 @reflectiveTest
+class ConflictingTypeVariableAndMemberEnumTest
+    extends PubPackageResolutionTest {
+  test_getter() async {
+    await assertErrorsInCode(r'''
+enum A<T> {
+  v;
+  get T => null;
+}
+''', [
+      error(
+          CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM, 7, 1),
+    ]);
+  }
+
+  test_method() async {
+    await assertErrorsInCode(r'''
+enum A<T> {
+  v;
+  void T() {}
+}
+''', [
+      error(
+          CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM, 7, 1),
+    ]);
+  }
+
+  test_setter() async {
+    await assertErrorsInCode(r'''
+enum A<T> {
+  v;
+  set T(x) {}
+}
+''', [
+      error(
+          CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_ENUM, 7, 1),
+    ]);
+  }
+}
+
+@reflectiveTest
 class ConflictingTypeVariableAndMemberExtensionTest
     extends PubPackageResolutionTest {
   test_getter() async {
diff --git a/pkg/analyzer/test/src/diagnostics/const_not_initialized_test.dart b/pkg/analyzer/test/src/diagnostics/const_not_initialized_test.dart
index 85b1174..3fe5d0c 100644
--- a/pkg/analyzer/test/src/diagnostics/const_not_initialized_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_not_initialized_test.dart
@@ -16,19 +16,21 @@
 
 @reflectiveTest
 class ConstNotInitializedTest extends PubPackageResolutionTest
-    with ConstNotInitializedTestCases {}
-
-mixin ConstNotInitializedTestCases on PubPackageResolutionTest {
-  test_extension_static() async {
+    with ConstNotInitializedTestCases {
+  test_enum_static() async {
     await assertErrorsInCode('''
-extension E on String {
+enum E {
+  v;
   static const F;
-}''', [
-      error(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 39, 1),
+}
+''', [
+      error(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 29, 1),
     ]);
   }
+}
 
-  test_instanceField_static() async {
+mixin ConstNotInitializedTestCases on PubPackageResolutionTest {
+  test_class_static() async {
     await assertErrorsInCode(r'''
 class A {
   static const F;
@@ -38,6 +40,16 @@
     ]);
   }
 
+  test_extension_static() async {
+    await assertErrorsInCode('''
+extension E on String {
+  static const F;
+}
+''', [
+      error(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 39, 1),
+    ]);
+  }
+
   test_local() async {
     await assertErrorsInCode(r'''
 f() {
@@ -49,7 +61,7 @@
     ]);
   }
 
-  test_top_level() async {
+  test_topLevel() async {
     await assertErrorsInCode('''
 const F;
 ''', [
diff --git a/pkg/analyzer/test/src/diagnostics/duplicate_constructor_default_test.dart b/pkg/analyzer/test/src/diagnostics/duplicate_constructor_default_test.dart
new file mode 100644
index 0000000..d0d1172
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/duplicate_constructor_default_test.dart
@@ -0,0 +1,50 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DuplicateConstructorDefaultTest);
+  });
+}
+
+@reflectiveTest
+class DuplicateConstructorDefaultTest extends PubPackageResolutionTest {
+  test_class_empty_empty() async {
+    await assertErrorsInCode(r'''
+class C {
+  C();
+  C();
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 19, 1),
+    ]);
+  }
+
+  test_class_empty_new() async {
+    await assertErrorsInCode(r'''
+class C {
+  C();
+  C.new();
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 19, 5),
+    ]);
+  }
+
+  test_class_new_new() async {
+    await assertErrorsInCode(r'''
+class C {
+  C.new();
+  C.new();
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, 23, 5),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/duplicate_constructor_name_test.dart b/pkg/analyzer/test/src/diagnostics/duplicate_constructor_name_test.dart
new file mode 100644
index 0000000..b99fc99
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/duplicate_constructor_name_test.dart
@@ -0,0 +1,28 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DuplicateConstructorNameTest);
+  });
+}
+
+@reflectiveTest
+class DuplicateConstructorNameTest extends PubPackageResolutionTest {
+  test_class() async {
+    await assertErrorsInCode(r'''
+class C {
+  C.foo();
+  C.foo();
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME, 23, 5),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart b/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
index 66df7dcab..09a546f 100644
--- a/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
@@ -13,6 +13,7 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(DuplicateDefinitionTest);
     defineReflectiveTests(DuplicateDefinitionClassTest);
+    defineReflectiveTests(DuplicateDefinitionEnumTest);
     defineReflectiveTests(DuplicateDefinitionExtensionTest);
     defineReflectiveTests(DuplicateDefinitionMixinTest);
   });
@@ -327,6 +328,333 @@
 }
 
 @reflectiveTest
+class DuplicateDefinitionEnumTest extends PubPackageResolutionTest {
+  test_instance_field_field() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  final int foo = 0;
+  final int foo = 0;
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 47, 3),
+    ]);
+  }
+
+  test_instance_field_getter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  final int foo = 0;
+  int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 45, 3),
+    ]);
+  }
+
+  test_instance_field_method() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  final int foo = 0;
+  void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 42, 3),
+    ]);
+  }
+
+  test_instance_fieldFinal_getter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  final int foo = 0;
+  int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 45, 3),
+    ]);
+  }
+
+  test_instance_fieldFinal_setter() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v;
+  final int foo = 0;
+  set foo(int x) {}
+}
+''');
+  }
+
+  test_instance_getter_getter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  int get foo => 0;
+  int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 44, 3),
+    ]);
+  }
+
+  test_instance_getter_method() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  int get foo => 0;
+  void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 41, 3),
+    ]);
+  }
+
+  test_instance_getter_setter() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v;
+  int get foo => 0;
+  set foo(_) {}
+}
+''');
+  }
+
+  test_instance_method_getter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  void foo() {}
+  int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 40, 3),
+    ]);
+  }
+
+  test_instance_method_method() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  void foo() {}
+  void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 37, 3),
+    ]);
+  }
+
+  test_instance_method_setter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  void foo() {}
+  set foo(_) {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 36, 3),
+    ]);
+  }
+
+  test_instance_setter_getter() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v;
+  set foo(_) {}
+  int get foo => 0;
+}
+''');
+  }
+
+  test_instance_setter_method() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  set foo(_) {}
+  void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 37, 3),
+    ]);
+  }
+
+  test_instance_setter_setter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  void set foo(_) {}
+  void set foo(_) {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 46, 3),
+    ]);
+  }
+
+  test_static_field_field() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static int foo = 0;
+  static int foo = 0;
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 49, 3),
+    ]);
+  }
+
+  test_static_field_getter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static int foo = 0;
+  static int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 53, 3),
+    ]);
+  }
+
+  test_static_field_method() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static int foo = 0;
+  static void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 50, 3),
+    ]);
+  }
+
+  test_static_fieldFinal_getter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static final int foo = 0;
+  static int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 59, 3),
+    ]);
+  }
+
+  test_static_fieldFinal_setter() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v;
+  static final int foo = 0;
+  static set foo(int x) {}
+}
+''');
+  }
+
+  test_static_getter_getter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static int get foo => 0;
+  static int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 58, 3),
+    ]);
+  }
+
+  test_static_getter_method() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static int get foo => 0;
+  static void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 55, 3),
+    ]);
+  }
+
+  test_static_getter_setter() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v;
+  static int get foo => 0;
+  static set foo(_) {}
+}
+''');
+  }
+
+  test_static_method_getter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static void foo() {}
+  static int get foo => 0;
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 54, 3),
+    ]);
+  }
+
+  test_static_method_method() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static void foo() {}
+  static void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 51, 3),
+    ]);
+  }
+
+  test_static_method_setter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static void foo() {}
+  static set foo(_) {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 50, 3),
+    ]);
+  }
+
+  test_static_setter_getter() async {
+    await assertNoErrorsInCode(r'''
+enum E {
+  v;
+  static set foo(_) {}
+  static int get foo => 0;
+}
+''');
+  }
+
+  test_static_setter_method() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static set foo(_) {}
+  static void foo() {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 51, 3),
+    ]);
+  }
+
+  test_static_setter_setter() async {
+    await assertErrorsInCode(r'''
+enum E {
+  v;
+  static void set foo(_) {}
+  static void set foo(_) {}
+}
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 60, 3),
+    ]);
+  }
+}
+
+@reflectiveTest
 class DuplicateDefinitionExtensionTest extends PubPackageResolutionTest {
   test_extendedType_instance() async {
     await assertNoErrorsInCode('''
diff --git a/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart b/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart
index ab697b0..e38a3bb 100644
--- a/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart
@@ -15,6 +15,71 @@
 
 @reflectiveTest
 class ExtendsNonClassTest extends PubPackageResolutionTest {
+  test_class_dynamic() async {
+    await assertErrorsInCode(r'''
+class A extends dynamic {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 16, 7),
+    ]);
+
+    var a = findElement.class_('A');
+    assertType(a.supertype, 'Object');
+  }
+
+  test_class_enum() async {
+    await assertErrorsInCode(r'''
+enum E { ONE }
+class A extends E {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 31, 1),
+    ]);
+
+    var a = findElement.class_('A');
+    assertType(a.supertype, 'Object');
+
+    var eRef = findNode.namedType('E {}');
+    assertNamedType(eRef, findElement.enum_('E'), 'E');
+  }
+
+  test_class_mixin() async {
+    await assertErrorsInCode(r'''
+mixin M {}
+class A extends M {} // ref
+''', [
+      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
+    ]);
+
+    var a = findElement.class_('A');
+    assertType(a.supertype, 'Object');
+
+    var mRef = findNode.namedType('M {} // ref');
+    assertNamedType(mRef, findElement.mixin('M'), 'M');
+  }
+
+  test_class_variable() async {
+    await assertErrorsInCode(r'''
+int v = 0;
+class A extends v {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
+    ]);
+
+    var a = findElement.class_('A');
+    assertType(a.supertype, 'Object');
+  }
+
+  test_class_variable_generic() async {
+    await assertErrorsInCode(r'''
+int v = 0;
+class A extends v<int> {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 27, 1),
+    ]);
+
+    var a = findElement.class_('A');
+    assertType(a.supertype, 'Object');
+  }
+
   test_Never() async {
     await assertErrorsInCode('''
 class A extends Never {}
diff --git a/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart b/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
index e4fb280..d5bb2f6 100644
--- a/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
@@ -92,7 +92,7 @@
 
 @reflectiveTest
 class FinalNotInitializedWithNullSafetyTest extends PubPackageResolutionTest {
-  test_field_abstract() async {
+  test_class_field_abstract() async {
     await assertNoErrorsInCode('''
 abstract class A {
   abstract final int x;
@@ -100,7 +100,7 @@
 ''');
   }
 
-  test_field_abstract_with_constructor() async {
+  test_class_field_abstract_with_constructor() async {
     await assertNoErrorsInCode('''
 abstract class A {
   abstract final int x;
@@ -109,7 +109,7 @@
 ''');
   }
 
-  test_field_external() async {
+  test_class_field_external() async {
     await assertNoErrorsInCode('''
 class A {
   external final int x;
@@ -117,7 +117,15 @@
 ''');
   }
 
-  test_field_external_with_constructor() async {
+  test_class_field_external_static() async {
+    await assertNoErrorsInCode('''
+class A {
+  external static final int x;
+}
+''');
+  }
+
+  test_class_field_external_with_constructor() async {
     await assertNoErrorsInCode('''
 class A {
   external final int x;
@@ -126,15 +134,7 @@
 ''');
   }
 
-  test_field_noConstructor_initializer() async {
-    await assertNoErrorsInCode('''
-class C {
-  late final f = 1;
-}
-''');
-  }
-
-  test_field_noConstructor_noInitializer() async {
+  test_class_field_late_noConstructor_noInitializer() async {
     await assertNoErrorsInCode('''
 class C {
   late final f;
@@ -142,7 +142,24 @@
 ''');
   }
 
-  test_field_ofClass() async {
+  test_class_field_late_unnamedConstructor_noInitializer() async {
+    await assertNoErrorsInCode('''
+class C {
+  late final f;
+  C();
+}
+''');
+  }
+
+  test_class_field_noConstructor_initializer() async {
+    await assertNoErrorsInCode('''
+class C {
+  final f = 1;
+}
+''');
+  }
+
+  test_class_field_noConstructor_noInitializer() async {
     await assertErrorsInCode('''
 abstract class A {
   final int x;
@@ -152,42 +169,73 @@
     ]);
   }
 
-  test_field_unnamedConstructor_constructorInitializer() async {
+  test_class_field_unnamedConstructor_constructorInitializer() async {
     await assertNoErrorsInCode('''
 class C {
-  late final f;
+  final f;
   C() : f = 2;
 }
 ''');
   }
 
-  test_field_unnamedConstructor_fieldFormalParameter() async {
+  test_class_field_unnamedConstructor_fieldFormalParameter() async {
     await assertNoErrorsInCode('''
 class C {
-  late final f;
+  final f;
   C(this.f);
 }
 ''');
   }
 
-  test_field_unnamedConstructor_initializer() async {
+  test_class_field_unnamedConstructor_initializer() async {
     await assertNoErrorsInCode('''
 class C {
-  late final f = 1;
+  final f = 1;
   C();
 }
 ''');
   }
 
-  test_field_unnamedConstructor_noInitializer() async {
+  test_enum_field_constructorFieldInitializer() async {
     await assertNoErrorsInCode('''
-class C {
-  late final f;
-  C();
+enum E {
+  v;
+  final int x;
+  const E() : x = 0;
 }
 ''');
   }
 
+  test_enum_field_fieldFormalParameter() async {
+    await assertNoErrorsInCode('''
+enum E {
+  v(0);
+  final int x;
+  const E(this.x);
+}
+''');
+  }
+
+  test_enum_field_hasInitializer() async {
+    await assertNoErrorsInCode('''
+enum E {
+  v;
+  final int x = 0;
+}
+''');
+  }
+
+  test_enum_field_noConstructor_noInitializer() async {
+    await assertErrorsInCode('''
+enum E {
+  v;
+  final int x;
+}
+''', [
+      error(CompileTimeErrorCode.FINAL_NOT_INITIALIZED, 26, 1),
+    ]);
+  }
+
   test_localVariable_initializer() async {
     await assertErrorsInCode('''
 f() {
@@ -208,15 +256,7 @@
     ]);
   }
 
-  test_static_field_external() async {
-    await assertNoErrorsInCode('''
-class A {
-  external static final int x;
-}
-''');
-  }
-
-  test_variable_external() async {
+  test_topLevel_external() async {
     await assertNoErrorsInCode('''
 external final int x;
 ''');
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_constructor_name_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_constructor_name_test.dart
index 049f378..d6692a3 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_constructor_name_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_constructor_name_test.dart
@@ -26,6 +26,31 @@
     ]);
   }
 
+  test_notEnclosingClassName_named() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B {
+  A.foo();
+  B.foo();
+}
+''', [
+      error(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 23, 1),
+    ]);
+  }
+
+  test_notEnclosingClassName_new() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+class B {
+  A.new();
+  B();
+}
+''', [
+      error(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 24, 1),
+    ]);
+  }
+
   test_notEnclosingClassName_undefined() async {
     await assertErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/late_final_field_with_const_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/late_final_field_with_const_constructor_test.dart
index 688771e..47b76c5 100644
--- a/pkg/analyzer/test/src/diagnostics/late_final_field_with_const_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/late_final_field_with_const_constructor_test.dart
@@ -87,7 +87,27 @@
 ''');
   }
 
-  test_inExtension() async {
+  test_enum_instance_hasInitializer() async {
+    await assertErrorsInCode('''
+enum E {
+  v;
+  late final f = 0;
+}
+''', [
+      error(_errorCode, 16, 4),
+    ]);
+  }
+
+  test_enum_static() async {
+    await assertNoErrorsInCode('''
+enum E {
+  v;
+  static late final f = 0;
+}
+''');
+  }
+
+  test_extension() async {
     // https://github.com/dart-lang/sdk/issues/46952
     // This test is here because the code that tests for
     // LATE_FINAL_FIELD_WITH_CONST_CONSTRUCTOR is where the referenced issue was
diff --git a/pkg/analyzer/test/src/diagnostics/member_with_class_name_test.dart b/pkg/analyzer/test/src/diagnostics/member_with_class_name_test.dart
index d9583c5..9057423 100644
--- a/pkg/analyzer/test/src/diagnostics/member_with_class_name_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/member_with_class_name_test.dart
@@ -45,11 +45,41 @@
     ]);
   }
 
+  test_class_getter_static() async {
+    await assertErrorsInCode(r'''
+class A {
+  static int get A => 0;
+}
+''', [
+      error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 27, 1),
+    ]);
+  }
+
   test_class_method() async {
     // No test because a method named the same as the enclosing class is
     // indistinguishable from a constructor.
   }
 
+  test_class_setter() async {
+    await assertErrorsInCode(r'''
+class A {
+  set A(_) {}
+}
+''', [
+      error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
+    ]);
+  }
+
+  test_class_setter_static() async {
+    await assertErrorsInCode(r'''
+class A {
+  static set A(_) {}
+}
+''', [
+      error(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 23, 1),
+    ]);
+  }
+
   test_mixin_getter() async {
     await assertErrorsInCode(r'''
 mixin M {
diff --git a/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_extends_test.dart b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_extends_test.dart
new file mode 100644
index 0000000..a3123c8
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_extends_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RecursiveInterfaceInheritanceExtendsTest);
+  });
+}
+
+@reflectiveTest
+class RecursiveInterfaceInheritanceExtendsTest
+    extends PubPackageResolutionTest {
+  test_class() async {
+    await assertErrorsInCode(r'''
+class A extends A {}
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS, 6, 1),
+    ]);
+  }
+
+  test_class_abstract() async {
+    await assertErrorsInCode(r'''
+class C extends C {
+  var foo = 0;
+  bar();
+}
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_EXTENDS, 6, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_implements_test.dart b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_implements_test.dart
new file mode 100644
index 0000000..aaf824b
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_implements_test.dart
@@ -0,0 +1,48 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RecursiveInterfaceInheritanceImplementsTest);
+  });
+}
+
+@reflectiveTest
+class RecursiveInterfaceInheritanceImplementsTest
+    extends PubPackageResolutionTest {
+  test_class() async {
+    await assertErrorsInCode('''
+class A implements A {}
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 6,
+          1),
+    ]);
+  }
+
+  test_class_tail() async {
+    await assertErrorsInCode(r'''
+abstract class A implements A {}
+class B implements A {}
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 15,
+          1),
+    ]);
+  }
+
+  test_classTypeAlias() async {
+    await assertErrorsInCode(r'''
+class A {}
+class M {}
+class B = A with M implements B;
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_IMPLEMENTS, 28,
+          1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_test.dart b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_test.dart
index 472f7914..eee8fc5 100644
--- a/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_test.dart
@@ -15,7 +15,27 @@
 
 @reflectiveTest
 class RecursiveInterfaceInheritanceTest extends PubPackageResolutionTest {
-  test_loop() async {
+  test_class_extends() async {
+    await assertErrorsInCode(r'''
+class A extends B {}
+class B extends A {}
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 27, 1),
+    ]);
+  }
+
+  test_class_extends_implements() async {
+    await assertErrorsInCode(r'''
+class A extends B {}
+class B implements A {}
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 27, 1),
+    ]);
+  }
+
+  test_class_implements() async {
     await assertErrorsInCode('''
 class A implements B {}
 class B implements A {}
@@ -25,7 +45,7 @@
     ]);
   }
 
-  test_loop_generic() async {
+  test_class_implements_generic() async {
     await assertErrorsInCode('''
 class A<T> implements B<T> {}
 class B<T> implements A<T> {}
@@ -35,7 +55,7 @@
     ]);
   }
 
-  test_loop_generic_typeArgument() async {
+  test_class_implements_generic_typeArgument() async {
     await assertErrorsInCode('''
 class A<T> implements B<List<T>> {}
 class B<T> implements A<List<T>> {}
@@ -44,4 +64,51 @@
       error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 42, 1),
     ]);
   }
+
+  test_class_implements_tail2() async {
+    await assertErrorsInCode(r'''
+abstract class A implements B {}
+abstract class B implements A {}
+class C implements A {}
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 15, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 48, 1),
+    ]);
+  }
+
+  test_class_implements_tail3() async {
+    await assertErrorsInCode(r'''
+abstract class A implements B {}
+abstract class B implements C {}
+abstract class C implements A {}
+class D implements A {}
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 15, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 48, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 81, 1),
+    ]);
+  }
+
+  test_classTypeAlias_mixin() async {
+    await assertErrorsInCode(r'''
+class M1 = Object with M2;
+class M2 = Object with M1;
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 2),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 33, 2),
+    ]);
+  }
+
+  test_classTypeAlias_mixin_superclass() async {
+    // Make sure we don't get CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS in
+    // addition--that would just be confusing.
+    await assertErrorsInCode('''
+class C = D with M;
+class D = C with M;
+class M {}
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1),
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 26, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_with_test.dart b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_with_test.dart
new file mode 100644
index 0000000..b9130d5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/recursive_interface_inheritance_with_test.dart
@@ -0,0 +1,25 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RecursiveInterfaceInheritanceWithTest);
+  });
+}
+
+@reflectiveTest
+class RecursiveInterfaceInheritanceWithTest extends PubPackageResolutionTest {
+  test_classTypeAlias() async {
+    await assertErrorsInCode(r'''
+class M = Object with M;
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_WITH, 6, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 5ca7e69..3c0d14a 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -64,8 +64,14 @@
     as class_instantiation_access_to_member;
 import 'concrete_class_with_abstract_member_test.dart'
     as concrete_class_with_abstract_member;
+import 'conflicting_constructor_and_static_field_test.dart'
+    as conflicting_constructor_and_static_field;
+import 'conflicting_constructor_and_static_method_test.dart'
+    as conflicting_constructor_and_static_method;
+import 'conflicting_field_and_method_test.dart' as conflicting_field_and_method;
 import 'conflicting_generic_interfaces_test.dart'
     as conflicting_generic_interfaces;
+import 'conflicting_method_and_field_test.dart' as conflicting_method_and_field;
 import 'conflicting_static_and_instance_test.dart'
     as conflicting_static_and_instance;
 import 'conflicting_type_variable_and_container_test.dart'
@@ -136,6 +142,9 @@
 import 'deprecated_member_use_test.dart' as deprecated_member_use;
 import 'deprecated_mixin_function_test.dart' as deprecated_mixin_function;
 import 'division_optimization_test.dart' as division_optimization;
+import 'duplicate_constructor_default_test.dart'
+    as duplicate_constructor_default;
+import 'duplicate_constructor_name_test.dart' as duplicate_constructor_name;
 import 'duplicate_definition_test.dart' as duplicate_definition;
 import 'duplicate_field_formal_parameter_test.dart'
     as duplicate_field_formal_parameter;
@@ -583,8 +592,14 @@
 import 'recursive_constructor_redirect_test.dart'
     as recursive_constructor_redirect;
 import 'recursive_factory_redirect_test.dart' as recursive_factory_redirect;
+import 'recursive_interface_inheritance_extends_test.dart'
+    as recursive_interface_inheritance_extends;
+import 'recursive_interface_inheritance_implements_test.dart'
+    as recursive_interface_inheritance_implements;
 import 'recursive_interface_inheritance_test.dart'
     as recursive_interface_inheritance;
+import 'recursive_interface_inheritance_with_test.dart'
+    as recursive_interface_inheritance_with;
 import 'redirect_generative_to_missing_constructor_test.dart'
     as redirect_generative_to_missing_constructor;
 import 'redirect_generative_to_non_generative_constructor_test.dart'
@@ -710,7 +725,10 @@
     as undefined_referenced_parameter;
 import 'undefined_setter_test.dart' as undefined_setter;
 import 'undefined_shown_name_test.dart' as undefined_shown_name;
+import 'undefined_super_getter_test.dart' as undefined_super_getter;
 import 'undefined_super_method_test.dart' as undefined_super_method;
+import 'undefined_super_operator_test.dart' as undefined_super_operator;
+import 'undefined_super_setter_test.dart' as undefined_super_setter;
 import 'unignorable_ignore_test.dart' as unignorable_ignore;
 import 'unnecessary_cast_test.dart' as unnecessary_cast;
 import 'unnecessary_ignore_test.dart' as unnecessary_ignore;
@@ -800,7 +818,11 @@
     cast_to_non_type.main();
     class_instantiation_access_to_member.main();
     concrete_class_with_abstract_member.main();
+    conflicting_constructor_and_static_field.main();
+    conflicting_constructor_and_static_method.main();
+    conflicting_field_and_method.main();
     conflicting_generic_interfaces.main();
+    conflicting_method_and_field.main();
     conflicting_static_and_instance.main();
     conflicting_type_variable_and_container.main();
     conflicting_type_variable_and_member.main();
@@ -847,6 +869,8 @@
     deprecated_member_use.main();
     deprecated_mixin_function.main();
     division_optimization.main();
+    duplicate_constructor_default.main();
+    duplicate_constructor_name.main();
     duplicate_definition.main();
     duplicate_field_formal_parameter.main();
     duplicate_hidden_name.main();
@@ -1139,7 +1163,10 @@
     recursive_compile_time_constant.main();
     recursive_constructor_redirect.main();
     recursive_factory_redirect.main();
+    recursive_interface_inheritance_extends.main();
+    recursive_interface_inheritance_implements.main();
     recursive_interface_inheritance.main();
+    recursive_interface_inheritance_with.main();
     redirect_generative_to_missing_constructor.main();
     redirect_generative_to_non_generative_constructor.main();
     redirect_to_abstract_class_constructor.main();
@@ -1226,7 +1253,10 @@
     undefined_referenced_parameter.main();
     undefined_setter.main();
     undefined_shown_name.main();
+    undefined_super_getter.main();
     undefined_super_method.main();
+    undefined_super_operator.main();
+    undefined_super_setter.main();
     unignorable_ignore.main();
     unnecessary_import.main();
     unnecessary_cast.main();
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_super_getter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_super_getter_test.dart
new file mode 100644
index 0000000..d932f3e
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_super_getter_test.dart
@@ -0,0 +1,30 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UndefinedSuperGetterTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedSuperGetterTest extends PubPackageResolutionTest {
+  test_class() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+  get g {
+    return super.g;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_SUPER_GETTER, 58, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_super_method_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_super_method_test.dart
index 0c1192c..8c77143 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_super_method_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_super_method_test.dart
@@ -15,20 +15,39 @@
 
 @reflectiveTest
 class UndefinedSuperMethodTest extends PubPackageResolutionTest {
-  test_error_undefinedSuperMethod() async {
+  test_class() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+class B extends A {
+  void bar() {
+    super.foo();
+  }
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_SUPER_METHOD, 57, 3),
+    ]);
+
+    var invocation = findNode.methodInvocation('foo()');
+    assertElementNull(invocation.methodName);
+    assertInvokeTypeDynamic(invocation);
+    assertTypeDynamic(invocation);
+  }
+
+  test_mixin() async {
     await assertErrorsInCode(r'''
 class A {}
 
 mixin M on A {
   void bar() {
-    super.foo(42);
+    super.foo();
   }
 }
 ''', [
       error(CompileTimeErrorCode.UNDEFINED_SUPER_METHOD, 52, 3),
     ]);
 
-    var invocation = findNode.methodInvocation('foo(42)');
+    var invocation = findNode.methodInvocation('foo()');
     assertElementNull(invocation.methodName);
     assertInvokeTypeDynamic(invocation);
     assertTypeDynamic(invocation);
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_super_operator_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_super_operator_test.dart
new file mode 100644
index 0000000..623f271
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_super_operator_test.dart
@@ -0,0 +1,70 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UndefinedSuperOperatorTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedSuperOperatorTest extends PubPackageResolutionTest {
+  test_class_binaryExpression() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+  operator +(value) {
+    return super + value;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 1),
+    ]);
+  }
+
+  test_class_indexBoth() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+  operator [](index) {
+    return super[index]++;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 7),
+      error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 7),
+    ]);
+  }
+
+  test_class_indexGetter() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+  operator [](index) {
+    return super[index + 1];
+  }
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 70, 11),
+    ]);
+  }
+
+  test_class_indexSetter() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+  operator []=(index, value) {
+    super[index] = 0;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR, 71, 7),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_super_setter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_super_setter_test.dart
new file mode 100644
index 0000000..934fbd5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_super_setter_test.dart
@@ -0,0 +1,30 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UndefinedSuperSetterTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedSuperSetterTest extends PubPackageResolutionTest {
+  test_class() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+  f() {
+    super.m = 0;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_SUPER_SETTER, 49, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/lint/pub_test.dart b/pkg/analyzer/test/src/lint/pub_test.dart
index b5fbe2a..aa4dfe1 100644
--- a/pkg/analyzer/test/src/lint/pub_test.dart
+++ b/pkg/analyzer/test/src/lint/pub_test.dart
@@ -35,7 +35,6 @@
     hosted: http://your-package-server.com
     version: '>=0.4.0 <1.0.0'
   analyzer: '0.24.0-dev.1'
-  cli_util: '>=0.0.1 <0.1.0'
   semver: '>=0.2.0 <0.3.0'
   yaml: '>=2.1.2 <3.0.0'
   kittens:
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 76fd405..ebd48c9 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -2026,6 +2026,9 @@
 _'{0}' can't be used to name both a type variable and the class in which the
 type variable is defined._
 
+_'{0}' can't be used to name both a type variable and the enum in which the type
+variable is defined._
+
 _'{0}' can't be used to name both a type variable and the extension in which the
 type variable is defined._
 
@@ -2059,6 +2062,8 @@
 
 _'{0}' can't be used to name both a type variable and a member in this class._
 
+_'{0}' can't be used to name both a type variable and a member in this enum._
+
 _'{0}' can't be used to name both a type variable and a member in this
 extension._
 
@@ -8830,7 +8835,7 @@
 #### Description
 
 The analyzer produces this diagnostic when a `switch` statement for an enum
-doesn't include an option for one of the values in the enumeration.
+doesn't include an option for one of the values in the enum.
 
 Note that `null` is always a possible value for an enum and therefore also
 must be handled.
diff --git a/pkg/analyzer/tool/summary/build_sdk_summaries.dart b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
index 746feb2..da7a3af 100644
--- a/pkg/analyzer/tool/summary/build_sdk_summaries.dart
+++ b/pkg/analyzer/tool/summary/build_sdk_summaries.dart
@@ -6,7 +6,7 @@
 
 import 'package:analyzer/dart/sdk/build_sdk_summary.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:cli_util/cli_util.dart';
+import 'package:analyzer/src/util/sdk.dart';
 
 void main(List<String> args) {
   String command;
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 4ad9d00..a7278e1 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -329,7 +329,7 @@
       }
 
       // Infer if unspecified.
-      sdkPath ??= getSdkPath(args);
+      sdkPath ??= getSdkPath();
 
       var pathContext = resourceProvider.pathContext;
       options.dartSdkPath = file_paths.absoluteNormalized(pathContext, sdkPath);
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 61b9776..524dae5 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -612,6 +612,23 @@
   /// if the parameterName field is omitted.
   String? parameterType;
 
+  /// This field is omitted if getSuggestions was used rather than
+  /// getSuggestions2.
+  ///
+  /// This field is omitted if this suggestion corresponds to a locally
+  /// declared element.
+  ///
+  /// If this suggestion corresponds to an already imported element, then this
+  /// field is the URI of a library that provides this element, not the URI of
+  /// the library where the element is declared.
+  ///
+  /// If this suggestion corresponds to an element from a not yet imported
+  /// library, this field is the URI of a library that could be imported to
+  /// make this suggestion accessible in the file where completion was
+  /// requested, such as package:foo/bar.dart or
+  /// file:///home/me/workspace/foo/test/bar_test.dart.
+  String? libraryUri;
+
   /// True if the suggestion is for an element from a not yet imported library.
   /// This field is omitted if the element is declared locally, or is from
   /// library is already imported, so that the suggestion can be inserted as
@@ -642,6 +659,7 @@
       this.hasNamedParameters,
       this.parameterName,
       this.parameterType,
+      this.libraryUri,
       this.isNotImported});
 
   factory CompletionSuggestion.fromJson(
@@ -781,6 +799,11 @@
         parameterType = jsonDecoder.decodeString(
             jsonPath + '.parameterType', json['parameterType']);
       }
+      String? libraryUri;
+      if (json.containsKey('libraryUri')) {
+        libraryUri = jsonDecoder.decodeString(
+            jsonPath + '.libraryUri', json['libraryUri']);
+      }
       bool? isNotImported;
       if (json.containsKey('isNotImported')) {
         isNotImported = jsonDecoder.decodeBool(
@@ -804,6 +827,7 @@
           hasNamedParameters: hasNamedParameters,
           parameterName: parameterName,
           parameterType: parameterType,
+          libraryUri: libraryUri,
           isNotImported: isNotImported);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'CompletionSuggestion', json);
@@ -884,6 +908,10 @@
     if (parameterType != null) {
       result['parameterType'] = parameterType;
     }
+    var libraryUri = this.libraryUri;
+    if (libraryUri != null) {
+      result['libraryUri'] = libraryUri;
+    }
     var isNotImported = this.isNotImported;
     if (isNotImported != null) {
       result['isNotImported'] = isNotImported;
@@ -923,6 +951,7 @@
           hasNamedParameters == other.hasNamedParameters &&
           parameterName == other.parameterName &&
           parameterType == other.parameterType &&
+          libraryUri == other.libraryUri &&
           isNotImported == other.isNotImported;
     }
     return false;
@@ -953,6 +982,7 @@
         hasNamedParameters,
         parameterName,
         parameterType,
+        libraryUri,
         isNotImported,
       ]);
 }
@@ -1234,17 +1264,12 @@
   /// this field will not be defined.
   String? aliasedType;
 
-  /// If the element belongs to a library, the URI of the library. Otherwise,
-  /// this field will not be defined.
-  String? libraryUri;
-
   Element(this.kind, this.name, this.flags,
       {this.location,
       this.parameters,
       this.returnType,
       this.typeParameters,
-      this.aliasedType,
-      this.libraryUri});
+      this.aliasedType});
 
   factory Element.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -1294,18 +1319,12 @@
         aliasedType = jsonDecoder.decodeString(
             jsonPath + '.aliasedType', json['aliasedType']);
       }
-      String? libraryUri;
-      if (json.containsKey('libraryUri')) {
-        libraryUri = jsonDecoder.decodeString(
-            jsonPath + '.libraryUri', json['libraryUri']);
-      }
       return Element(kind, name, flags,
           location: location,
           parameters: parameters,
           returnType: returnType,
           typeParameters: typeParameters,
-          aliasedType: aliasedType,
-          libraryUri: libraryUri);
+          aliasedType: aliasedType);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'Element', json);
     }
@@ -1344,10 +1363,6 @@
     if (aliasedType != null) {
       result['aliasedType'] = aliasedType;
     }
-    var libraryUri = this.libraryUri;
-    if (libraryUri != null) {
-      result['libraryUri'] = libraryUri;
-    }
     return result;
   }
 
@@ -1364,8 +1379,7 @@
           parameters == other.parameters &&
           returnType == other.returnType &&
           typeParameters == other.typeParameters &&
-          aliasedType == other.aliasedType &&
-          libraryUri == other.libraryUri;
+          aliasedType == other.aliasedType;
     }
     return false;
   }
@@ -1380,7 +1394,6 @@
         returnType,
         typeParameters,
         aliasedType,
-        libraryUri,
       );
 }
 
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index cdb3f12..cfa4524 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -165,6 +165,7 @@
           'hasNamedParameters': isBool,
           'parameterName': isString,
           'parameterType': isString,
+          'libraryUri': isString,
           'isNotImported': isBool
         }));
 
@@ -237,8 +238,7 @@
       'parameters': isString,
       'returnType': isString,
       'typeParameters': isString,
-      'aliasedType': isString,
-      'libraryUri': isString
+      'aliasedType': isString
     }));
 
 /// ElementKind
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index 969a0ee..e284b4f 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -380,6 +380,29 @@
           omitted if the parameterName field is omitted.
         </p>
       </field>
+      <field name="libraryUri" experimental="true" optional="true">
+        <ref>String</ref>
+        <p>
+          This field  is omitted if <tt>getSuggestions</tt> was used rather
+          than <tt>getSuggestions2</tt>.
+        </p>
+        <p>
+          This field  is omitted if this suggestion corresponds to a locally
+          declared element.
+        </p>
+        <p>
+          If this suggestion corresponds to an already imported element,
+          then this field is the URI of a library that provides this element,
+          not the URI of the library where the element is declared.
+        </p>
+        <p>
+          If this suggestion corresponds to an element from a not yet
+          imported library, this field is the URI of a library that could be
+          imported to make this suggestion  accessible in the file where
+          completion was requested, such as <tt>package:foo/bar.dart</tt> or
+          <tt>file:///home/me/workspace/foo/test/bar_test.dart</tt>.
+        </p>
+      </field>
       <field name="isNotImported" optional="true" experimental="true">
         <ref>bool</ref>
         <p>
@@ -563,13 +586,6 @@
           Otherwise this field will not be defined.
         </p>
       </field>
-      <field name="libraryUri" optional="true" experimental="true">
-        <ref>String</ref>
-        <p>
-          If the element belongs to a library, the URI of the library.
-          Otherwise, this field will not be defined.
-        </p>
-      </field>
     </object>
   </type>
   <type name="ElementKind">
diff --git a/pkg/compiler/lib/src/common/elements.dart b/pkg/compiler/lib/src/common/elements.dart
index 734b23c..b33db18 100644
--- a/pkg/compiler/lib/src/common/elements.dart
+++ b/pkg/compiler/lib/src/common/elements.dart
@@ -16,826 +16,263 @@
 
 /// The common elements and types in Dart.
 abstract class CommonElements {
-  DartTypes get dartTypes;
+  final DartTypes dartTypes;
+  final ElementEnvironment _env;
+  ClassEntity _objectClass;
+  ClassEntity _boolClass;
+  ClassEntity _numClass;
+  ClassEntity _intClass;
+  ClassEntity _doubleClass;
+  ClassEntity _stringClass;
+  ClassEntity _functionClass;
+  ClassEntity _resourceClass;
+  ClassEntity _symbolClass;
+  ClassEntity _nullClass;
+  ClassEntity _typeClass;
+  ClassEntity _stackTraceClass;
+  ClassEntity _listClass;
+  ClassEntity _setClass;
+  ClassEntity _mapClass;
+  ClassEntity _unmodifiableSetClass;
+  ClassEntity _iterableClass;
+  ClassEntity _futureClass;
+  ClassEntity _streamClass;
+  LibraryEntity _coreLibrary;
+  LibraryEntity _asyncLibrary;
+  LibraryEntity _mirrorsLibrary;
+  LibraryEntity _typedDataLibrary;
+  LibraryEntity _jsHelperLibrary;
+  LibraryEntity _lateHelperLibrary;
+  LibraryEntity _foreignLibrary;
+  LibraryEntity _rtiLibrary;
+  LibraryEntity _interceptorsLibrary;
+  LibraryEntity _internalLibrary;
+  LibraryEntity _dartJsAnnotationsLibrary;
+  LibraryEntity _dartJsLibrary;
+  LibraryEntity _packageJsLibrary;
+  ClassEntity _typedDataClass;
+  ConstructorEntity _symbolConstructorTarget;
+  bool _computedSymbolConstructorDependencies = false;
+  ConstructorEntity _symbolConstructorImplementationTarget;
+  FunctionEntity _identicalFunction;
+  ClassEntity _mapLiteralClass;
+  ConstructorEntity _mapLiteralConstructor;
+  ConstructorEntity _mapLiteralConstructorEmpty;
+  FunctionEntity _mapLiteralUntypedMaker;
+  FunctionEntity _mapLiteralUntypedEmptyMaker;
+  ClassEntity _setLiteralClass;
+  ConstructorEntity _setLiteralConstructor;
+  ConstructorEntity _setLiteralConstructorEmpty;
+  FunctionEntity _setLiteralUntypedMaker;
+  FunctionEntity _setLiteralUntypedEmptyMaker;
+  FunctionEntity _objectNoSuchMethod;
+  FunctionEntity _syncStarIterableFactory;
+  FunctionEntity _asyncAwaitCompleterFactory;
+  FunctionEntity _asyncStarStreamControllerFactory;
+  ClassEntity _jsInterceptorClass;
+  ClassEntity _jsStringClass;
+  ClassEntity _jsArrayClass;
+  ClassEntity _jsNumberClass;
+  ClassEntity _jsIntClass;
+  ClassEntity _jsNumNotIntClass;
+  ClassEntity _jsNullClass;
+  ClassEntity _jsBoolClass;
+  ClassEntity _jsPlainJavaScriptObjectClass;
+  ClassEntity _jsUnknownJavaScriptObjectClass;
+  ClassEntity _jsJavaScriptFunctionClass;
+  ClassEntity _jsLegacyJavaScriptObjectClass;
+  ClassEntity _jsJavaScriptObjectClass;
+  ClassEntity _jsIndexableClass;
+  ClassEntity _jsMutableIndexableClass;
+  ClassEntity _jsMutableArrayClass;
+  ClassEntity _jsFixedArrayClass;
+  ClassEntity _jsExtendableArrayClass;
+  ClassEntity _jsUnmodifiableArrayClass;
+  ClassEntity _jsPositiveIntClass;
+  ClassEntity _jsUInt32Class;
+  ClassEntity _jsUInt31Class;
+  FunctionEntity _getNativeInterceptorMethod;
+  ConstructorEntity _jsArrayTypedConstructor;
+  ClassEntity _closureClass;
+  ClassEntity _closureClass0Args;
+  ClassEntity _closureClass2Args;
+  ClassEntity _boundClosureClass;
+  ClassEntity _typeLiteralClass;
+  ClassEntity _constMapLiteralClass;
+  ClassEntity _constSetLiteralClass;
+  ClassEntity _jsInvocationMirrorClass;
+  ClassEntity _requiredSentinelClass;
+  MemberEntity _invocationTypeArgumentGetter;
+  ClassEntity _jsIndexingBehaviorInterface;
+  ClassEntity _nativeAnnotationClass;
+  FunctionEntity _assertTest;
+  FunctionEntity _assertThrow;
+  FunctionEntity _assertHelper;
+  FunctionEntity _assertUnreachableMethod;
+  FunctionEntity _getIsolateAffinityTagMarker;
+  FunctionEntity _requiresPreambleMarker;
+  FunctionEntity _rawStartupMetrics;
+  FunctionEntity _setArrayType;
+  FunctionEntity _findType;
+  FunctionEntity _instanceType;
+  FunctionEntity _arrayInstanceType;
+  FunctionEntity _simpleInstanceType;
+  FunctionEntity _typeLiteralMaker;
+  FunctionEntity _checkTypeBound;
+  FieldEntity _rtiAsField;
+  FieldEntity _rtiIsField;
+  FieldEntity _rtiRestField;
+  FieldEntity _rtiPrecomputed1Field;
+  FunctionEntity _rtiEvalMethod;
+  FunctionEntity _rtiBindMethod;
+  FunctionEntity _rtiAddRulesMethod;
+  FunctionEntity _rtiAddErasedTypesMethod;
+  FunctionEntity _rtiAddTypeParameterVariancesMethod;
+  FunctionEntity _generalIsTestImplementation;
+  FunctionEntity _generalAsCheckImplementation;
+  FunctionEntity _generalNullableAsCheckImplementation;
+  FunctionEntity _specializedIsObject;
+  FunctionEntity _specializedAsObject;
+  FunctionEntity _generalNullableIsTestImplementation;
+  ClassEntity _symbolImplementationClass;
+  ClassEntity _externalNameClass;
+  ClassEntity _jsGetNameEnum;
+  FunctionEntity _jsAllowInterop1;
+  FunctionEntity _jsAllowInterop2;
+  FieldEntity _symbolImplementationField;
+  FunctionEntity _cachedCheckConcurrentModificationError;
+
+  CommonElements(this.dartTypes, this._env);
 
   /// The `Object` class defined in 'dart:core'.
-  ClassEntity get objectClass;
+  ClassEntity get objectClass =>
+      _objectClass ??= _findClass(coreLibrary, 'Object');
 
   /// The `bool` class defined in 'dart:core'.
-  ClassEntity get boolClass;
+  ClassEntity get boolClass => _boolClass ??= _findClass(coreLibrary, 'bool');
 
   /// The `num` class defined in 'dart:core'.
-  ClassEntity get numClass;
+  ClassEntity get numClass => _numClass ??= _findClass(coreLibrary, 'num');
 
   /// The `int` class defined in 'dart:core'.
-  ClassEntity get intClass;
+  ClassEntity get intClass => _intClass ??= _findClass(coreLibrary, 'int');
 
   /// The `double` class defined in 'dart:core'.
-  ClassEntity get doubleClass;
+  ClassEntity get doubleClass =>
+      _doubleClass ??= _findClass(coreLibrary, 'double');
 
   /// The `String` class defined in 'dart:core'.
-  ClassEntity get stringClass;
+  ClassEntity get stringClass =>
+      _stringClass ??= _findClass(coreLibrary, 'String');
 
   /// The `Function` class defined in 'dart:core'.
-  ClassEntity get functionClass;
+  ClassEntity get functionClass =>
+      _functionClass ??= _findClass(coreLibrary, 'Function');
 
   /// The `Resource` class defined in 'dart:core'.
-  ClassEntity get resourceClass;
+  ClassEntity get resourceClass =>
+      _resourceClass ??= _findClass(coreLibrary, 'Resource');
 
   /// The `Symbol` class defined in 'dart:core'.
-  ClassEntity get symbolClass;
+  ClassEntity get symbolClass =>
+      _symbolClass ??= _findClass(coreLibrary, 'Symbol');
 
   /// The `Null` class defined in 'dart:core'.
-  ClassEntity get nullClass;
+  ClassEntity get nullClass => _nullClass ??= _findClass(coreLibrary, 'Null');
 
   /// The `Type` class defined in 'dart:core'.
-  ClassEntity get typeClass;
+  ClassEntity get typeClass => _typeClass ??= _findClass(coreLibrary, 'Type');
 
   /// The `StackTrace` class defined in 'dart:core';
-  ClassEntity get stackTraceClass;
+  ClassEntity get stackTraceClass =>
+      _stackTraceClass ??= _findClass(coreLibrary, 'StackTrace');
 
   /// The `List` class defined in 'dart:core';
-  ClassEntity get listClass;
+  ClassEntity get listClass => _listClass ??= _findClass(coreLibrary, 'List');
 
   /// The `Set` class defined in 'dart:core';
-  ClassEntity get setClass;
+  ClassEntity get setClass => _setClass ??= _findClass(coreLibrary, 'Set');
 
   /// The `Map` class defined in 'dart:core';
-  ClassEntity get mapClass;
+  ClassEntity get mapClass => _mapClass ??= _findClass(coreLibrary, 'Map');
 
   /// The `Set` class defined in 'dart:core';
-  ClassEntity get unmodifiableSetClass;
+  ClassEntity get unmodifiableSetClass => _unmodifiableSetClass ??=
+      _findClass(_env.lookupLibrary(Uris.dart_collection), '_UnmodifiableSet');
 
   /// The `Iterable` class defined in 'dart:core';
-  ClassEntity get iterableClass;
+  ClassEntity get iterableClass =>
+      _iterableClass ??= _findClass(coreLibrary, 'Iterable');
 
   /// The `Future` class defined in 'async';.
-  ClassEntity get futureClass;
+  ClassEntity get futureClass =>
+      _futureClass ??= _findClass(asyncLibrary, 'Future');
 
   /// The `Stream` class defined in 'async';
-  ClassEntity get streamClass;
+  ClassEntity get streamClass =>
+      _streamClass ??= _findClass(asyncLibrary, 'Stream');
 
   /// The dart:core library.
-  LibraryEntity get coreLibrary;
+  LibraryEntity get coreLibrary =>
+      _coreLibrary ??= _env.lookupLibrary(Uris.dart_core, required: true);
 
   /// The dart:async library.
-  LibraryEntity get asyncLibrary;
+  LibraryEntity get asyncLibrary =>
+      _asyncLibrary ??= _env.lookupLibrary(Uris.dart_async);
 
   /// The dart:mirrors library.
-  LibraryEntity get mirrorsLibrary;
+  /// Null if the program doesn't access dart:mirrors.
+  LibraryEntity get mirrorsLibrary =>
+      _mirrorsLibrary ??= _env.lookupLibrary(Uris.dart_mirrors);
 
   /// The dart:typed_data library.
-  LibraryEntity get typedDataLibrary;
+  LibraryEntity get typedDataLibrary =>
+      _typedDataLibrary ??= _env.lookupLibrary(Uris.dart__native_typed_data);
 
   /// The dart:_js_helper library.
-  LibraryEntity get jsHelperLibrary;
+  LibraryEntity get jsHelperLibrary =>
+      _jsHelperLibrary ??= _env.lookupLibrary(Uris.dart__js_helper);
 
   /// The dart:_late_helper library
-  LibraryEntity get lateHelperLibrary;
+  LibraryEntity get lateHelperLibrary =>
+      _lateHelperLibrary ??= _env.lookupLibrary(Uris.dart__late_helper);
 
   /// The dart:_interceptors library.
-  LibraryEntity get interceptorsLibrary;
+  LibraryEntity get interceptorsLibrary =>
+      _interceptorsLibrary ??= _env.lookupLibrary(Uris.dart__interceptors);
 
   /// The dart:_foreign_helper library.
-  LibraryEntity get foreignLibrary;
+  LibraryEntity get foreignLibrary =>
+      _foreignLibrary ??= _env.lookupLibrary(Uris.dart__foreign_helper);
 
   /// The dart:_internal library.
-  LibraryEntity get rtiLibrary;
+  LibraryEntity get rtiLibrary =>
+      _rtiLibrary ??= _env.lookupLibrary(Uris.dart__rti, required: true);
 
   /// The dart:_internal library.
-  LibraryEntity get internalLibrary;
+  LibraryEntity get internalLibrary => _internalLibrary ??=
+      _env.lookupLibrary(Uris.dart__internal, required: true);
 
   /// The dart:js library.
-  LibraryEntity get dartJsLibrary;
+  LibraryEntity get dartJsLibrary =>
+      _dartJsLibrary ??= _env.lookupLibrary(Uris.dart_js);
 
   /// The package:js library.
-  LibraryEntity get packageJsLibrary;
+  LibraryEntity get packageJsLibrary =>
+      _packageJsLibrary ??= _env.lookupLibrary(Uris.package_js);
 
   /// The dart:_js_annotations library.
-  LibraryEntity get dartJsAnnotationsLibrary;
+  LibraryEntity get dartJsAnnotationsLibrary => _dartJsAnnotationsLibrary ??=
+      _env.lookupLibrary(Uris.dart__js_annotations);
 
   /// The `NativeTypedData` class from dart:typed_data.
-  ClassEntity get typedDataClass;
+  ClassEntity get typedDataClass =>
+      _typedDataClass ??= _findClass(typedDataLibrary, 'NativeTypedData');
 
   /// Constructor of the `Symbol` class in dart:internal.
   ///
   /// This getter will ensure that `Symbol` is resolved and lookup the
   /// constructor on demand.
-  ConstructorEntity get symbolConstructorTarget;
-
-  /// Whether [element] is the same as [symbolConstructor].
-  ///
-  /// Used to check for the constructor without computing it until it is likely
-  /// to be seen.
-  bool isSymbolConstructor(ConstructorEntity element);
-
-  /// The function `identical` in dart:core.
-  FunctionEntity get identicalFunction;
-
-  /// Whether [element] is the `Function.apply` method.
-  ///
-  /// This will not resolve the apply method if it hasn't been seen yet during
-  /// compilation.
-  bool isFunctionApplyMethod(MemberEntity element);
-
-  /// The `dynamic` type.
-  DynamicType get dynamicType;
-
-  /// The `Object` type defined in 'dart:core'.
-  InterfaceType get objectType;
-
-  /// The `bool` type defined in 'dart:core'.
-  InterfaceType get boolType;
-
-  /// The `num` type defined in 'dart:core'.
-  InterfaceType get numType;
-
-  /// The `int` type defined in 'dart:core'.
-  InterfaceType get intType;
-
-  /// The `double` type defined in 'dart:core'.
-  InterfaceType get doubleType;
-
-  /// The `String` type defined in 'dart:core'.
-  InterfaceType get stringType;
-
-  /// The `Symbol` type defined in 'dart:core'.
-  InterfaceType get symbolType;
-
-  /// The `Function` type defined in 'dart:core'.
-  InterfaceType get functionType;
-
-  /// The `Null` type defined in 'dart:core'.
-  InterfaceType get nullType;
-
-  /// The `Type` type defined in 'dart:core'.
-  InterfaceType get typeType;
-
-  InterfaceType get typeLiteralType;
-
-  /// The `StackTrace` type defined in 'dart:core';
-  InterfaceType get stackTraceType;
-
-  /// Returns an instance of the `List` type defined in 'dart:core' with
-  /// [elementType] as its type argument.
-  ///
-  /// If no type argument is provided, the canonical raw type is returned.
-  InterfaceType listType([DartType elementType]);
-
-  /// Returns an instance of the `Set` type defined in 'dart:core' with
-  /// [elementType] as its type argument.
-  ///
-  /// If no type argument is provided, the canonical raw type is returned.
-  InterfaceType setType([DartType elementType]);
-
-  /// Returns an instance of the `Map` type defined in 'dart:core' with
-  /// [keyType] and [valueType] as its type arguments.
-  ///
-  /// If no type arguments are provided, the canonical raw type is returned.
-  InterfaceType mapType([DartType keyType, DartType valueType]);
-
-  /// Returns an instance of the `Iterable` type defined in 'dart:core' with
-  /// [elementType] as its type argument.
-  ///
-  /// If no type argument is provided, the canonical raw type is returned.
-  InterfaceType iterableType([DartType elementType]);
-
-  /// Returns an instance of the `Future` type defined in 'dart:async' with
-  /// [elementType] as its type argument.
-  ///
-  /// If no type argument is provided, the canonical raw type is returned.
-  InterfaceType futureType([DartType elementType]);
-
-  /// Returns an instance of the `Stream` type defined in 'dart:async' with
-  /// [elementType] as its type argument.
-  ///
-  /// If no type argument is provided, the canonical raw type is returned.
-  InterfaceType streamType([DartType elementType]);
-
-  InterfaceType getConstantListTypeFor(InterfaceType sourceType);
-
-  InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
-      {bool onlyStringKeys = false});
-
-  InterfaceType getConstantSetTypeFor(InterfaceType sourceType);
-
-  FieldEntity get symbolField;
-
-  InterfaceType get symbolImplementationType;
-
-  // From dart:core
-  ClassEntity get mapLiteralClass;
-  ConstructorEntity get mapLiteralConstructor;
-  ConstructorEntity get mapLiteralConstructorEmpty;
-  FunctionEntity get mapLiteralUntypedMaker;
-  FunctionEntity get mapLiteralUntypedEmptyMaker;
-
-  ClassEntity get setLiteralClass;
-  ConstructorEntity get setLiteralConstructor;
-  ConstructorEntity get setLiteralConstructorEmpty;
-  FunctionEntity get setLiteralUntypedMaker;
-  FunctionEntity get setLiteralUntypedEmptyMaker;
-
-  FunctionEntity get objectNoSuchMethod;
-
-  bool isDefaultNoSuchMethodImplementation(FunctionEntity element);
-
-  // From dart:async
-  FunctionEntity get asyncHelperStartSync;
-  FunctionEntity get asyncHelperAwait;
-  FunctionEntity get asyncHelperReturn;
-  FunctionEntity get asyncHelperRethrow;
-
-  FunctionEntity get wrapBody;
-
-  FunctionEntity get yieldStar;
-
-  FunctionEntity get yieldSingle;
-
-  FunctionEntity get syncStarUncaughtError;
-
-  FunctionEntity get asyncStarHelper;
-
-  FunctionEntity get streamOfController;
-
-  FunctionEntity get endOfIteration;
-
-  ClassEntity get syncStarIterable;
-
-  ClassEntity get futureImplementation;
-
-  ClassEntity get controllerStream;
-
-  ClassEntity get streamIterator;
-
-  ConstructorEntity get streamIteratorConstructor;
-
-  FunctionEntity get syncStarIterableFactory;
-
-  FunctionEntity get asyncAwaitCompleterFactory;
-
-  FunctionEntity get asyncStarStreamControllerFactory;
-
-  ClassEntity get jsInterceptorClass;
-
-  ClassEntity get jsStringClass;
-
-  ClassEntity get jsArrayClass;
-
-  ClassEntity get jsNumberClass;
-
-  ClassEntity get jsIntClass;
-
-  ClassEntity get jsNumNotIntClass;
-
-  ClassEntity get jsNullClass;
-
-  ClassEntity get jsBoolClass;
-
-  ClassEntity get jsPlainJavaScriptObjectClass;
-
-  ClassEntity get jsUnknownJavaScriptObjectClass;
-
-  ClassEntity get jsJavaScriptFunctionClass;
-
-  InterfaceType get jsJavaScriptFunctionType;
-
-  ClassEntity get jsLegacyJavaScriptObjectClass;
-
-  ClassEntity get jsJavaScriptObjectClass;
-
-  ClassEntity get jsIndexableClass;
-
-  ClassEntity get jsMutableIndexableClass;
-
-  ClassEntity get jsMutableArrayClass;
-
-  ClassEntity get jsFixedArrayClass;
-
-  ClassEntity get jsExtendableArrayClass;
-
-  ClassEntity get jsUnmodifiableArrayClass;
-
-  ClassEntity get jsPositiveIntClass;
-
-  ClassEntity get jsUInt32Class;
-
-  ClassEntity get jsUInt31Class;
-
-  /// Returns `true` member is the 'findIndexForNativeSubclassType' method
-  /// declared in `dart:_interceptors`.
-  bool isFindIndexForNativeSubclassType(MemberEntity member);
-
-  FunctionEntity get getNativeInterceptorMethod;
-
-  ConstructorEntity get jsArrayTypedConstructor;
-
-  // From dart:_js_helper
-  // TODO(johnniwinther): Avoid the need for this (from [CheckedModeHelper]).
-  FunctionEntity findHelperFunction(String name);
-
-  ClassEntity get closureClass;
-  ClassEntity get closureClass0Args;
-  ClassEntity get closureClass2Args;
-
-  ClassEntity get boundClosureClass;
-
-  ClassEntity get typeLiteralClass;
-
-  ClassEntity get constMapLiteralClass;
-
-  ClassEntity get constSetLiteralClass;
-
-  ClassEntity get jsInvocationMirrorClass;
-
-  ClassEntity get requiredSentinelClass;
-
-  InterfaceType get requiredSentinelType;
-
-  MemberEntity get invocationTypeArgumentGetter;
-
-  /// Interface used to determine if an object has the JavaScript
-  /// indexing behavior. The interface is only visible to specific libraries.
-  ClassEntity get jsIndexingBehaviorInterface;
-
-  ClassEntity get stackTraceHelperClass;
-
-  ClassEntity get constantMapClass;
-  ClassEntity get constantStringMapClass;
-  ClassEntity get generalConstantMapClass;
-
-  ClassEntity get annotationCreatesClass;
-
-  ClassEntity get annotationReturnsClass;
-
-  ClassEntity get annotationJSNameClass;
-
-  /// The class for native annotations defined in dart:_js_helper.
-  ClassEntity get nativeAnnotationClass;
-
-  FunctionEntity get assertTest;
-
-  FunctionEntity get assertThrow;
-
-  FunctionEntity get assertHelper;
-
-  FunctionEntity get assertUnreachableMethod;
-
-  /// Holds the method "getIsolateAffinityTag" when dart:_js_helper has been
-  /// loaded.
-  FunctionEntity get getIsolateAffinityTagMarker;
-
-  /// Holds the method "requiresPreamble" in _js_helper.
-  FunctionEntity get requiresPreambleMarker;
-
-  /// Holds the method "_rawStartupMetrics" in _js_helper.
-  FunctionEntity get rawStartupMetrics;
-
-  FunctionEntity get loadLibraryWrapper;
-
-  FunctionEntity get loadDeferredLibrary;
-
-  FunctionEntity get boolConversionCheck;
-
-  FunctionEntity get traceHelper;
-
-  FunctionEntity get closureFromTearOff;
-
-  FunctionEntity get isJsIndexable;
-
-  FunctionEntity get throwIllegalArgumentException;
-
-  FunctionEntity get throwIndexOutOfRangeException;
-
-  FunctionEntity get exceptionUnwrapper;
-
-  FunctionEntity get throwUnsupportedError;
-
-  FunctionEntity get throwTypeError;
-
-  /// Recognizes the `checkConcurrentModificationError` helper without needing
-  /// it to be resolved.
-  bool isCheckConcurrentModificationError(MemberEntity member);
-
-  FunctionEntity get checkConcurrentModificationError;
-
-  FunctionEntity get throwConcurrentModificationError;
-
-  FunctionEntity get stringInterpolationHelper;
-
-  FunctionEntity get wrapExceptionHelper;
-
-  FunctionEntity get throwExpressionHelper;
-
-  FunctionEntity get closureConverter;
-
-  FunctionEntity get traceFromException;
-
-  FunctionEntity get checkDeferredIsLoaded;
-
-  FunctionEntity get throwNoSuchMethod;
-
-  FunctionEntity get createRuntimeType;
-
-  FunctionEntity get fallThroughError;
-
-  FunctionEntity get createInvocationMirror;
-
-  FunctionEntity get createUnmangledInvocationMirror;
-
-  FunctionEntity get cyclicThrowHelper;
-
-  FunctionEntity get defineProperty;
-
-  FunctionEntity get throwLateFieldADI;
-
-  bool isExtractTypeArguments(FunctionEntity member);
-
-  ClassEntity getInstantiationClass(int typeArgumentCount);
-
-  FunctionEntity getInstantiateFunction(int typeArgumentCount);
-
-  FunctionEntity get convertMainArgumentList;
-
-  // From dart:_rti
-
-  FunctionEntity get setArrayType;
-
-  FunctionEntity get findType;
-  FunctionEntity get instanceType;
-  FunctionEntity get arrayInstanceType;
-  FunctionEntity get simpleInstanceType;
-  FunctionEntity get typeLiteralMaker;
-  FunctionEntity get checkTypeBound;
-  FieldEntity get rtiAsField;
-  FieldEntity get rtiIsField;
-  FieldEntity get rtiRestField;
-  FieldEntity get rtiPrecomputed1Field;
-  FunctionEntity get rtiEvalMethod;
-  FunctionEntity get rtiBindMethod;
-  FunctionEntity get rtiAddRulesMethod;
-  FunctionEntity get rtiAddErasedTypesMethod;
-  FunctionEntity get rtiAddTypeParameterVariancesMethod;
-
-  FunctionEntity get installSpecializedIsTest;
-  FunctionEntity get installSpecializedAsCheck;
-  FunctionEntity get generalIsTestImplementation;
-  FunctionEntity get generalAsCheckImplementation;
-  FunctionEntity get generalNullableIsTestImplementation;
-  FunctionEntity get generalNullableAsCheckImplementation;
-
-  FunctionEntity get specializedIsObject;
-  FunctionEntity get specializedAsObject;
-  FunctionEntity get specializedIsTop;
-  FunctionEntity get specializedAsTop;
-  FunctionEntity get specializedIsBool;
-  FunctionEntity get specializedAsBool;
-  FunctionEntity get specializedAsBoolLegacy;
-  FunctionEntity get specializedAsBoolNullable;
-  FunctionEntity get specializedAsDouble;
-  FunctionEntity get specializedAsDoubleLegacy;
-  FunctionEntity get specializedAsDoubleNullable;
-  FunctionEntity get specializedIsInt;
-  FunctionEntity get specializedAsInt;
-  FunctionEntity get specializedAsIntLegacy;
-  FunctionEntity get specializedAsIntNullable;
-  FunctionEntity get specializedIsNum;
-  FunctionEntity get specializedAsNum;
-  FunctionEntity get specializedAsNumLegacy;
-  FunctionEntity get specializedAsNumNullable;
-  FunctionEntity get specializedIsString;
-  FunctionEntity get specializedAsString;
-  FunctionEntity get specializedAsStringLegacy;
-  FunctionEntity get specializedAsStringNullable;
-
-  FunctionEntity get instantiatedGenericFunctionTypeNewRti;
-  FunctionEntity get closureFunctionType;
-
-  // From dart:_internal
-
-  ClassEntity get symbolImplementationClass;
-
-  /// Used to annotate items that have the keyword "native".
-  ClassEntity get externalNameClass;
-
-  InterfaceType get externalNameType;
-
-  // From dart:_js_embedded_names
-
-  /// Holds the class for the [JsGetName] enum.
-  ClassEntity get jsGetNameEnum;
-
-  /// Returns `true` if [member] is a "foreign helper", that is, a member whose
-  /// semantics is defined synthetically and not through Dart code.
-  ///
-  /// Most foreign helpers are located in the `dart:_foreign_helper` library.
-  bool isForeignHelper(MemberEntity member);
-
-  /// Returns `true` if [member] is the `createJsSentinel` function defined in
-  /// dart:_foreign_helper.
-  bool isCreateJsSentinel(MemberEntity member);
-
-  /// Returns `true` if [member] is the `isJsSentinel` function defined in
-  /// dart:_foreign_helper.
-  bool isIsJsSentinel(MemberEntity member);
-
-  /// Returns `true` if [member] is the `_lateReadCheck` function defined in
-  /// dart:_internal.
-  bool isLateReadCheck(MemberEntity member);
-
-  /// Returns `true` if [member] is the `createSentinel` function defined in
-  /// dart:_internal.
-  bool isCreateSentinel(MemberEntity member);
-
-  ClassEntity getDefaultSuperclass(
-      ClassEntity cls, NativeBasicData nativeBasicData);
-
-  // From package:js
-  FunctionEntity get jsAllowInterop1;
-
-  // From dart:_js_annotations;
-  FunctionEntity get jsAllowInterop2;
-
-  /// Returns `true` if [function] is `allowInterop`.
-  ///
-  /// This function can come from either `package:js` or `dart:_js_annotations`.
-  bool isJsAllowInterop(FunctionEntity function);
-}
-
-abstract class KCommonElements implements CommonElements {
-  // From package:js
-  ClassEntity get jsAnnotationClass1;
-  ClassEntity get jsAnonymousClass1;
-
-  // From dart:_js_annotations
-  ClassEntity get jsAnnotationClass2;
-  ClassEntity get jsAnonymousClass2;
-
-  /// Returns `true` if [cls] is a @JS() annotation.
-  ///
-  /// The class can come from either `package:js` or `dart:_js_annotations`.
-  bool isJsAnnotationClass(ClassEntity cls);
-
-  /// Returns `true` if [cls] is an @anonymous annotation.
-  ///
-  /// The class can come from either `package:js` or `dart:_js_annotations`.
-  bool isJsAnonymousClass(ClassEntity cls);
-
-  ClassEntity get pragmaClass;
-  FieldEntity get pragmaClassNameField;
-  FieldEntity get pragmaClassOptionsField;
-
-  bool isCreateInvocationMirrorHelper(MemberEntity member);
-}
-
-abstract class JCommonElements implements CommonElements {
-  /// Returns `true` if [element] is the unnamed constructor of `List`.
-  ///
-  /// This will not resolve the constructor if it hasn't been seen yet during
-  /// compilation.
-  bool isUnnamedListConstructor(ConstructorEntity element);
-
-  /// Returns `true` if [element] is the named constructor of `List`,
-  /// e.g. `List.of`.
-  ///
-  /// This will not resolve the constructor if it hasn't been seen yet during
-  /// compilation.
-  bool isNamedListConstructor(String name, ConstructorEntity element);
-
-  /// Returns `true` if [element] is the named constructor of `JSArray`,
-  /// e.g. `JSArray.fixed`.
-  ///
-  /// This will not resolve the constructor if it hasn't been seen yet during
-  /// compilation.
-  bool isNamedJSArrayConstructor(String name, ConstructorEntity element);
-
-  bool isDefaultEqualityImplementation(MemberEntity element);
-
-  /// Returns `true` if [selector] applies to `JSIndexable.length`.
-  bool appliesToJsIndexableLength(Selector selector);
-
-  FunctionEntity get jsArrayRemoveLast;
-
-  FunctionEntity get jsArrayAdd;
-
-  bool isJsStringSplit(MemberEntity member);
-
-  /// Returns `true` if [selector] applies to `JSString.split` on [receiver]
-  /// in the given [world].
-  ///
-  /// Returns `false` if `JSString.split` is not available.
-  bool appliesToJsStringSplit(Selector selector, AbstractValue receiver,
-      AbstractValueDomain abstractValueDomain);
-
-  FunctionEntity get jsStringSplit;
-
-  FunctionEntity get jsStringToString;
-
-  FunctionEntity get jsStringOperatorAdd;
-
-  ClassEntity get jsConstClass;
-
-  /// Return `true` if [member] is the 'checkInt' function defined in
-  /// dart:_js_helpers.
-  bool isCheckInt(MemberEntity member);
-
-  /// Return `true` if [member] is the 'checkNum' function defined in
-  /// dart:_js_helpers.
-  bool isCheckNum(MemberEntity member);
-
-  /// Return `true` if [member] is the 'checkString' function defined in
-  /// dart:_js_helpers.
-  bool isCheckString(MemberEntity member);
-
-  bool isInstantiationClass(ClassEntity cls);
-
-  // From dart:_native_typed_data
-
-  ClassEntity get typedArrayOfIntClass;
-
-  ClassEntity get typedArrayOfDoubleClass;
-
-  /// Holds the class for the [JsBuiltins] enum.
-  ClassEntity get jsBuiltinEnum;
-
-  bool isForeign(MemberEntity element);
-
-  /// Returns `true` if the implementation of the 'operator ==' [function] is
-  /// known to handle `null` as argument.
-  bool operatorEqHandlesNullArgument(FunctionEntity function);
-}
-
-class CommonElementsImpl
-    implements CommonElements, KCommonElements, JCommonElements {
-  @override
-  final DartTypes dartTypes;
-  final ElementEnvironment _env;
-
-  CommonElementsImpl(this.dartTypes, this._env);
-
-  ClassEntity _objectClass;
-  @override
-  ClassEntity get objectClass =>
-      _objectClass ??= _findClass(coreLibrary, 'Object');
-
-  ClassEntity _boolClass;
-  @override
-  ClassEntity get boolClass => _boolClass ??= _findClass(coreLibrary, 'bool');
-
-  ClassEntity _numClass;
-  @override
-  ClassEntity get numClass => _numClass ??= _findClass(coreLibrary, 'num');
-
-  ClassEntity _intClass;
-  @override
-  ClassEntity get intClass => _intClass ??= _findClass(coreLibrary, 'int');
-
-  ClassEntity _doubleClass;
-  @override
-  ClassEntity get doubleClass =>
-      _doubleClass ??= _findClass(coreLibrary, 'double');
-
-  ClassEntity _stringClass;
-  @override
-  ClassEntity get stringClass =>
-      _stringClass ??= _findClass(coreLibrary, 'String');
-
-  ClassEntity _functionClass;
-  @override
-  ClassEntity get functionClass =>
-      _functionClass ??= _findClass(coreLibrary, 'Function');
-
-  ClassEntity _resourceClass;
-  @override
-  ClassEntity get resourceClass =>
-      _resourceClass ??= _findClass(coreLibrary, 'Resource');
-
-  ClassEntity _symbolClass;
-  @override
-  ClassEntity get symbolClass =>
-      _symbolClass ??= _findClass(coreLibrary, 'Symbol');
-
-  ClassEntity _nullClass;
-  @override
-  ClassEntity get nullClass => _nullClass ??= _findClass(coreLibrary, 'Null');
-
-  ClassEntity _typeClass;
-  @override
-  ClassEntity get typeClass => _typeClass ??= _findClass(coreLibrary, 'Type');
-
-  ClassEntity _stackTraceClass;
-  @override
-  ClassEntity get stackTraceClass =>
-      _stackTraceClass ??= _findClass(coreLibrary, 'StackTrace');
-
-  ClassEntity _listClass;
-  @override
-  ClassEntity get listClass => _listClass ??= _findClass(coreLibrary, 'List');
-
-  ClassEntity _setClass;
-  @override
-  ClassEntity get setClass => _setClass ??= _findClass(coreLibrary, 'Set');
-
-  ClassEntity _mapClass;
-  @override
-  ClassEntity get mapClass => _mapClass ??= _findClass(coreLibrary, 'Map');
-
-  ClassEntity _unmodifiableSetClass;
-  @override
-  ClassEntity get unmodifiableSetClass => _unmodifiableSetClass ??=
-      _findClass(_env.lookupLibrary(Uris.dart_collection), '_UnmodifiableSet');
-
-  ClassEntity _iterableClass;
-  @override
-  ClassEntity get iterableClass =>
-      _iterableClass ??= _findClass(coreLibrary, 'Iterable');
-
-  ClassEntity _futureClass;
-  @override
-  ClassEntity get futureClass =>
-      _futureClass ??= _findClass(asyncLibrary, 'Future');
-
-  ClassEntity _streamClass;
-  @override
-  ClassEntity get streamClass =>
-      _streamClass ??= _findClass(asyncLibrary, 'Stream');
-
-  LibraryEntity _coreLibrary;
-  @override
-  LibraryEntity get coreLibrary =>
-      _coreLibrary ??= _env.lookupLibrary(Uris.dart_core, required: true);
-
-  LibraryEntity _asyncLibrary;
-  @override
-  LibraryEntity get asyncLibrary =>
-      _asyncLibrary ??= _env.lookupLibrary(Uris.dart_async);
-
-  /// The dart:mirrors library.
-  ///
-  /// Null if the program doesn't access dart:mirrors.
-  LibraryEntity _mirrorsLibrary;
-  @override
-  LibraryEntity get mirrorsLibrary =>
-      _mirrorsLibrary ??= _env.lookupLibrary(Uris.dart_mirrors);
-
-  LibraryEntity _typedDataLibrary;
-  @override
-  LibraryEntity get typedDataLibrary =>
-      _typedDataLibrary ??= _env.lookupLibrary(Uris.dart__native_typed_data);
-
-  LibraryEntity _jsHelperLibrary;
-  @override
-  LibraryEntity get jsHelperLibrary =>
-      _jsHelperLibrary ??= _env.lookupLibrary(Uris.dart__js_helper);
-
-  LibraryEntity _lateHelperLibrary;
-  @override
-  LibraryEntity get lateHelperLibrary =>
-      _lateHelperLibrary ??= _env.lookupLibrary(Uris.dart__late_helper);
-
-  LibraryEntity _interceptorsLibrary;
-  @override
-  LibraryEntity get interceptorsLibrary =>
-      _interceptorsLibrary ??= _env.lookupLibrary(Uris.dart__interceptors);
-
-  LibraryEntity _foreignLibrary;
-  @override
-  LibraryEntity get foreignLibrary =>
-      _foreignLibrary ??= _env.lookupLibrary(Uris.dart__foreign_helper);
-
-  LibraryEntity _rtiLibrary;
-  @override
-  LibraryEntity get rtiLibrary =>
-      _rtiLibrary ??= _env.lookupLibrary(Uris.dart__rti, required: true);
-
-  /// Reference to the internal library to lookup functions to always inline.
-  LibraryEntity _internalLibrary;
-  @override
-  LibraryEntity get internalLibrary => _internalLibrary ??=
-      _env.lookupLibrary(Uris.dart__internal, required: true);
-
-  LibraryEntity _dartJsLibrary;
-  @override
-  LibraryEntity get dartJsLibrary =>
-      _dartJsLibrary ??= _env.lookupLibrary(Uris.dart_js);
-
-  LibraryEntity _packageJsLibrary;
-  @override
-  LibraryEntity get packageJsLibrary =>
-      _packageJsLibrary ??= _env.lookupLibrary(Uris.package_js);
-
-  LibraryEntity _dartJsAnnotationsLibrary;
-  @override
-  LibraryEntity get dartJsAnnotationsLibrary => _dartJsAnnotationsLibrary ??=
-      _env.lookupLibrary(Uris.dart__js_annotations);
-
-  ClassEntity _typedDataClass;
-  @override
-  ClassEntity get typedDataClass =>
-      _typedDataClass ??= _findClass(typedDataLibrary, 'NativeTypedData');
-
-  ConstructorEntity _symbolConstructorTarget;
-  @override
   ConstructorEntity get symbolConstructorTarget {
     // TODO(johnniwinther): Kernel does not include redirecting factories
     // so this cannot be found in kernel. Find a consistent way to handle
@@ -844,9 +281,6 @@
         _findConstructor(symbolImplementationClass, '');
   }
 
-  bool _computedSymbolConstructorDependencies = false;
-  ConstructorEntity _symbolConstructorImplementationTarget;
-
   void _ensureSymbolConstructorDependencies() {
     if (_computedSymbolConstructorDependencies) return;
     _computedSymbolConstructorDependencies = true;
@@ -870,7 +304,10 @@
         _findConstructor(symbolClass, '', required: false);
   }
 
-  @override
+  /// Whether [element] is the same as [symbolConstructor].
+  ///
+  /// Used to check for the constructor without computing it until it is likely
+  /// to be seen.
   bool isSymbolConstructor(ConstructorEntity element) {
     assert(element != null);
     _ensureSymbolConstructorDependencies();
@@ -878,80 +315,59 @@
         element == _symbolConstructorTarget;
   }
 
-  FunctionEntity _identicalFunction;
-  @override
+  /// The function `identical` in dart:core.
   FunctionEntity get identicalFunction =>
       _identicalFunction ??= _findLibraryMember(coreLibrary, 'identical');
 
-  @override
+  /// Whether [element] is the `Function.apply` method.
+  ///
+  /// This will not resolve the apply method if it hasn't been seen yet during
+  /// compilation.
   bool isFunctionApplyMethod(MemberEntity element) =>
       element.name == 'apply' && element.enclosingClass == functionClass;
 
-  /// Returns `true` if [element] is the unnamed constructor of `List`.
-  ///
-  /// This will not resolve the constructor if it hasn't been seen yet during
-  /// compilation.
-  @override
-  bool isUnnamedListConstructor(ConstructorEntity element) =>
-      (element.name == '' && element.enclosingClass == listClass) ||
-      (element.name == 'list' && element.enclosingClass == jsArrayClass);
-
-  /// Returns `true` if [element] is the 'filled' constructor of `List`.
-  ///
-  /// This will not resolve the constructor if it hasn't been seen yet during
-  /// compilation.
-  @override
-  bool isNamedListConstructor(String name, ConstructorEntity element) =>
-      element.name == name && element.enclosingClass == listClass;
-
-  /// Returns `true` if [element] is the [name]d constructor of `JSArray`.
-  ///
-  /// This will not resolve the constructor if it hasn't been seen yet during
-  /// compilation.
-  @override
-  bool isNamedJSArrayConstructor(String name, ConstructorEntity element) =>
-      element.name == name && element.enclosingClass == jsArrayClass;
-
-  @override
+  /// The `dynamic` type.
   DynamicType get dynamicType => _env.dynamicType;
 
-  @override
+  /// The `Object` type defined in 'dart:core'.
   InterfaceType get objectType => _getRawType(objectClass);
 
-  @override
+  /// The `bool` type defined in 'dart:core'.
   InterfaceType get boolType => _getRawType(boolClass);
 
-  @override
+  /// The `num` type defined in 'dart:core'.
   InterfaceType get numType => _getRawType(numClass);
 
-  @override
+  /// The `int` type defined in 'dart:core'.
   InterfaceType get intType => _getRawType(intClass);
 
-  @override
+  /// The `double` type defined in 'dart:core'.
   InterfaceType get doubleType => _getRawType(doubleClass);
 
-  @override
+  /// The `String` type defined in 'dart:core'.
   InterfaceType get stringType => _getRawType(stringClass);
 
-  @override
+  /// The `Symbol` type defined in 'dart:core'.
   InterfaceType get symbolType => _getRawType(symbolClass);
 
-  @override
+  /// The `Function` type defined in 'dart:core'.
   InterfaceType get functionType => _getRawType(functionClass);
 
-  @override
+  /// The `Null` type defined in 'dart:core'.
   InterfaceType get nullType => _getRawType(nullClass);
 
-  @override
+  /// The `Type` type defined in 'dart:core'.
   InterfaceType get typeType => _getRawType(typeClass);
 
-  @override
   InterfaceType get typeLiteralType => _getRawType(typeLiteralClass);
 
-  @override
+  /// The `StackTrace` type defined in 'dart:core';
   InterfaceType get stackTraceType => _getRawType(stackTraceClass);
 
-  @override
+  /// Returns an instance of the `List` type defined in 'dart:core' with
+  /// [elementType] as its type argument.
+  ///
+  /// If no type argument is provided, the canonical raw type is returned.
   InterfaceType listType([DartType elementType]) {
     if (elementType == null) {
       return _getRawType(listClass);
@@ -959,7 +375,10 @@
     return _createInterfaceType(listClass, [elementType]);
   }
 
-  @override
+  /// Returns an instance of the `Set` type defined in 'dart:core' with
+  /// [elementType] as its type argument.
+  ///
+  /// If no type argument is provided, the canonical raw type is returned.
   InterfaceType setType([DartType elementType]) {
     if (elementType == null) {
       return _getRawType(setClass);
@@ -967,7 +386,10 @@
     return _createInterfaceType(setClass, [elementType]);
   }
 
-  @override
+  /// Returns an instance of the `Map` type defined in 'dart:core' with
+  /// [keyType] and [valueType] as its type arguments.
+  ///
+  /// If no type arguments are provided, the canonical raw type is returned.
   InterfaceType mapType([DartType keyType, DartType valueType]) {
     if (keyType == null && valueType == null) {
       return _getRawType(mapClass);
@@ -979,7 +401,10 @@
     return _createInterfaceType(mapClass, [keyType, valueType]);
   }
 
-  @override
+  /// Returns an instance of the `Iterable` type defined in 'dart:core' with
+  /// [elementType] as its type argument.
+  ///
+  /// If no type argument is provided, the canonical raw type is returned.
   InterfaceType iterableType([DartType elementType]) {
     if (elementType == null) {
       return _getRawType(iterableClass);
@@ -987,7 +412,10 @@
     return _createInterfaceType(iterableClass, [elementType]);
   }
 
-  @override
+  /// Returns an instance of the `Future` type defined in 'dart:async' with
+  /// [elementType] as its type argument.
+  ///
+  /// If no type argument is provided, the canonical raw type is returned.
   InterfaceType futureType([DartType elementType]) {
     if (elementType == null) {
       return _getRawType(futureClass);
@@ -995,7 +423,10 @@
     return _createInterfaceType(futureClass, [elementType]);
   }
 
-  @override
+  /// Returns an instance of the `Stream` type defined in 'dart:async' with
+  /// [elementType] as its type argument.
+  ///
+  /// If no type argument is provided, the canonical raw type is returned.
   InterfaceType streamType([DartType elementType]) {
     if (elementType == null) {
       return _getRawType(streamClass);
@@ -1039,13 +470,11 @@
     return _env.createInterfaceType(cls, typeArguments);
   }
 
-  @override
   InterfaceType getConstantListTypeFor(InterfaceType sourceType) =>
       dartTypes.treatAsRawType(sourceType)
           ? _env.getRawType(jsArrayClass)
           : _env.createInterfaceType(jsArrayClass, sourceType.typeArguments);
 
-  @override
   InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
       {bool onlyStringKeys = false}) {
     ClassEntity classElement =
@@ -1057,33 +486,22 @@
     }
   }
 
-  @override
   InterfaceType getConstantSetTypeFor(InterfaceType sourceType) =>
       dartTypes.treatAsRawType(sourceType)
           ? _env.getRawType(constSetLiteralClass)
           : _env.createInterfaceType(
               constSetLiteralClass, sourceType.typeArguments);
 
-  @override
-  FieldEntity get symbolField => symbolImplementationField;
+  /// Returns the field that holds the internal name in the implementation class
+  /// for `Symbol`.
+  FieldEntity get symbolField => _symbolImplementationField ??=
+      _env.lookupLocalClassMember(symbolImplementationClass, '_name',
+          required: true);
 
-  @override
   InterfaceType get symbolImplementationType =>
       _env.getRawType(symbolImplementationClass);
 
-  @override
-  bool isDefaultEqualityImplementation(MemberEntity element) {
-    assert(element.name == '==');
-    ClassEntity classElement = element.enclosingClass;
-    return classElement == objectClass ||
-        classElement == jsInterceptorClass ||
-        classElement == jsNullClass;
-  }
-
   // From dart:core
-
-  ClassEntity _mapLiteralClass;
-  @override
   ClassEntity get mapLiteralClass {
     if (_mapLiteralClass == null) {
       _mapLiteralClass = _env.lookupClass(coreLibrary, 'LinkedHashMap');
@@ -1095,10 +513,6 @@
     return _mapLiteralClass;
   }
 
-  ConstructorEntity _mapLiteralConstructor;
-  ConstructorEntity _mapLiteralConstructorEmpty;
-  FunctionEntity _mapLiteralUntypedMaker;
-  FunctionEntity _mapLiteralUntypedEmptyMaker;
   void _ensureMapLiteralHelpers() {
     if (_mapLiteralConstructor != null) return;
 
@@ -1112,40 +526,29 @@
         _env.lookupLocalClassMember(mapLiteralClass, '_makeEmpty');
   }
 
-  @override
   ConstructorEntity get mapLiteralConstructor {
     _ensureMapLiteralHelpers();
     return _mapLiteralConstructor;
   }
 
-  @override
   ConstructorEntity get mapLiteralConstructorEmpty {
     _ensureMapLiteralHelpers();
     return _mapLiteralConstructorEmpty;
   }
 
-  @override
   FunctionEntity get mapLiteralUntypedMaker {
     _ensureMapLiteralHelpers();
     return _mapLiteralUntypedMaker;
   }
 
-  @override
   FunctionEntity get mapLiteralUntypedEmptyMaker {
     _ensureMapLiteralHelpers();
     return _mapLiteralUntypedEmptyMaker;
   }
 
-  ClassEntity _setLiteralClass;
-  @override
   ClassEntity get setLiteralClass => _setLiteralClass ??=
       _findClass(_env.lookupLibrary(Uris.dart_collection), 'LinkedHashSet');
 
-  ConstructorEntity _setLiteralConstructor;
-  ConstructorEntity _setLiteralConstructorEmpty;
-  FunctionEntity _setLiteralUntypedMaker;
-  FunctionEntity _setLiteralUntypedEmptyMaker;
-
   void _ensureSetLiteralHelpers() {
     if (_setLiteralConstructor != null) return;
 
@@ -1159,38 +562,31 @@
         _env.lookupLocalClassMember(setLiteralClass, '_makeEmpty');
   }
 
-  @override
   ConstructorEntity get setLiteralConstructor {
     _ensureSetLiteralHelpers();
     return _setLiteralConstructor;
   }
 
-  @override
   ConstructorEntity get setLiteralConstructorEmpty {
     _ensureSetLiteralHelpers();
     return _setLiteralConstructorEmpty;
   }
 
-  @override
   FunctionEntity get setLiteralUntypedMaker {
     _ensureSetLiteralHelpers();
     return _setLiteralUntypedMaker;
   }
 
-  @override
   FunctionEntity get setLiteralUntypedEmptyMaker {
     _ensureSetLiteralHelpers();
     return _setLiteralUntypedEmptyMaker;
   }
 
-  FunctionEntity _objectNoSuchMethod;
-  @override
   FunctionEntity get objectNoSuchMethod {
     return _objectNoSuchMethod ??=
         _env.lookupLocalClassMember(objectClass, Identifiers.noSuchMethod_);
   }
 
-  @override
   bool isDefaultNoSuchMethodImplementation(FunctionEntity element) {
     ClassEntity classElement = element.enclosingClass;
     return classElement == objectClass ||
@@ -1205,78 +601,59 @@
   FunctionEntity _findAsyncHelperFunction(String name) =>
       _findLibraryMember(asyncLibrary, name);
 
-  @override
   FunctionEntity get asyncHelperStartSync =>
       _findAsyncHelperFunction("_asyncStartSync");
-  @override
+
   FunctionEntity get asyncHelperAwait =>
       _findAsyncHelperFunction("_asyncAwait");
-  @override
+
   FunctionEntity get asyncHelperReturn =>
       _findAsyncHelperFunction("_asyncReturn");
-  @override
+
   FunctionEntity get asyncHelperRethrow =>
       _findAsyncHelperFunction("_asyncRethrow");
 
-  @override
   FunctionEntity get wrapBody =>
       _findAsyncHelperFunction("_wrapJsFunctionForAsync");
 
-  @override
   FunctionEntity get yieldStar => _env.lookupLocalClassMember(
       _findAsyncHelperClass("_IterationMarker"), "yieldStar");
 
-  @override
   FunctionEntity get yieldSingle => _env.lookupLocalClassMember(
       _findAsyncHelperClass("_IterationMarker"), "yieldSingle");
 
-  @override
   FunctionEntity get syncStarUncaughtError => _env.lookupLocalClassMember(
       _findAsyncHelperClass("_IterationMarker"), "uncaughtError");
 
-  @override
   FunctionEntity get asyncStarHelper =>
       _findAsyncHelperFunction("_asyncStarHelper");
 
-  @override
   FunctionEntity get streamOfController =>
       _findAsyncHelperFunction("_streamOfController");
 
-  @override
   FunctionEntity get endOfIteration => _env.lookupLocalClassMember(
       _findAsyncHelperClass("_IterationMarker"), "endOfIteration");
 
-  @override
   ClassEntity get syncStarIterable =>
       _findAsyncHelperClass("_SyncStarIterable");
 
-  @override
   ClassEntity get futureImplementation => _findAsyncHelperClass('_Future');
 
-  @override
   ClassEntity get controllerStream =>
       _findAsyncHelperClass("_ControllerStream");
 
-  @override
   ClassEntity get streamIterator => _findAsyncHelperClass("StreamIterator");
 
-  @override
   ConstructorEntity get streamIteratorConstructor =>
       _env.lookupConstructor(streamIterator, "");
 
-  FunctionEntity _syncStarIterableFactory;
-  @override
   FunctionEntity get syncStarIterableFactory => _syncStarIterableFactory ??=
       _findAsyncHelperFunction('_makeSyncStarIterable');
 
-  FunctionEntity _asyncAwaitCompleterFactory;
-  @override
   FunctionEntity get asyncAwaitCompleterFactory =>
       _asyncAwaitCompleterFactory ??=
           _findAsyncHelperFunction('_makeAsyncAwaitCompleter');
 
-  FunctionEntity _asyncStarStreamControllerFactory;
-  @override
   FunctionEntity get asyncStarStreamControllerFactory =>
       _asyncStarStreamControllerFactory ??=
           _findAsyncHelperFunction('_makeAsyncStarStreamController');
@@ -1288,256 +665,94 @@
   FunctionEntity _findInterceptorsFunction(String name) =>
       _findLibraryMember(interceptorsLibrary, name);
 
-  ClassEntity _jsInterceptorClass;
-  @override
   ClassEntity get jsInterceptorClass =>
       _jsInterceptorClass ??= _findInterceptorsClass('Interceptor');
 
-  ClassEntity _jsStringClass;
-  @override
   ClassEntity get jsStringClass =>
       _jsStringClass ??= _findInterceptorsClass('JSString');
 
-  ClassEntity _jsArrayClass;
-  @override
   ClassEntity get jsArrayClass =>
       _jsArrayClass ??= _findInterceptorsClass('JSArray');
 
-  ClassEntity _jsNumberClass;
-  @override
   ClassEntity get jsNumberClass =>
       _jsNumberClass ??= _findInterceptorsClass('JSNumber');
 
-  ClassEntity _jsIntClass;
-  @override
   ClassEntity get jsIntClass => _jsIntClass ??= _findInterceptorsClass('JSInt');
 
-  ClassEntity _jsNumNotIntClass;
-  @override
   ClassEntity get jsNumNotIntClass =>
       _jsNumNotIntClass ??= _findInterceptorsClass('JSNumNotInt');
 
-  ClassEntity _jsNullClass;
-  @override
   ClassEntity get jsNullClass =>
       _jsNullClass ??= _findInterceptorsClass('JSNull');
 
-  ClassEntity _jsBoolClass;
-  @override
   ClassEntity get jsBoolClass =>
       _jsBoolClass ??= _findInterceptorsClass('JSBool');
 
-  ClassEntity _jsPlainJavaScriptObjectClass;
-  @override
   ClassEntity get jsPlainJavaScriptObjectClass =>
       _jsPlainJavaScriptObjectClass ??=
           _findInterceptorsClass('PlainJavaScriptObject');
 
-  ClassEntity _jsUnknownJavaScriptObjectClass;
-  @override
   ClassEntity get jsUnknownJavaScriptObjectClass =>
       _jsUnknownJavaScriptObjectClass ??=
           _findInterceptorsClass('UnknownJavaScriptObject');
 
-  ClassEntity _jsJavaScriptFunctionClass;
-  @override
   ClassEntity get jsJavaScriptFunctionClass => _jsJavaScriptFunctionClass ??=
       _findInterceptorsClass('JavaScriptFunction');
 
-  @override
   InterfaceType get jsJavaScriptFunctionType =>
       _getRawType(jsJavaScriptFunctionClass);
 
-  ClassEntity _jsLegacyJavaScriptObjectClass;
-  @override
   ClassEntity get jsLegacyJavaScriptObjectClass =>
       _jsLegacyJavaScriptObjectClass ??=
           _findInterceptorsClass('LegacyJavaScriptObject');
 
-  ClassEntity _jsJavaScriptObjectClass;
-  @override
   ClassEntity get jsJavaScriptObjectClass =>
       _jsJavaScriptObjectClass ??= _findInterceptorsClass('JavaScriptObject');
 
-  ClassEntity _jsIndexableClass;
-  @override
   ClassEntity get jsIndexableClass =>
       _jsIndexableClass ??= _findInterceptorsClass('JSIndexable');
 
-  ClassEntity _jsMutableIndexableClass;
-  @override
   ClassEntity get jsMutableIndexableClass =>
       _jsMutableIndexableClass ??= _findInterceptorsClass('JSMutableIndexable');
 
-  ClassEntity _jsMutableArrayClass;
-  @override
   ClassEntity get jsMutableArrayClass =>
       _jsMutableArrayClass ??= _findInterceptorsClass('JSMutableArray');
 
-  ClassEntity _jsFixedArrayClass;
-  @override
   ClassEntity get jsFixedArrayClass =>
       _jsFixedArrayClass ??= _findInterceptorsClass('JSFixedArray');
 
-  ClassEntity _jsExtendableArrayClass;
-  @override
   ClassEntity get jsExtendableArrayClass =>
       _jsExtendableArrayClass ??= _findInterceptorsClass('JSExtendableArray');
 
-  ClassEntity _jsUnmodifiableArrayClass;
-  @override
   ClassEntity get jsUnmodifiableArrayClass => _jsUnmodifiableArrayClass ??=
       _findInterceptorsClass('JSUnmodifiableArray');
 
-  ClassEntity _jsPositiveIntClass;
-  @override
   ClassEntity get jsPositiveIntClass =>
       _jsPositiveIntClass ??= _findInterceptorsClass('JSPositiveInt');
 
-  ClassEntity _jsUInt32Class;
-  @override
   ClassEntity get jsUInt32Class =>
       _jsUInt32Class ??= _findInterceptorsClass('JSUInt32');
 
-  ClassEntity _jsUInt31Class;
-  @override
   ClassEntity get jsUInt31Class =>
       _jsUInt31Class ??= _findInterceptorsClass('JSUInt31');
 
-  @override
+  /// Returns `true` member is the 'findIndexForNativeSubclassType' method
+  /// declared in `dart:_interceptors`.
   bool isFindIndexForNativeSubclassType(MemberEntity member) {
     return member.name == 'findIndexForNativeSubclassType' &&
         member.isTopLevel &&
         member.library == interceptorsLibrary;
   }
 
-  FunctionEntity _getNativeInterceptorMethod;
-  @override
   FunctionEntity get getNativeInterceptorMethod =>
       _getNativeInterceptorMethod ??=
           _findInterceptorsFunction('getNativeInterceptor');
 
-  @override
-  bool appliesToJsIndexableLength(Selector selector) {
-    return selector.name == 'length' && (selector.isGetter || selector.isCall);
-  }
-
-  ConstructorEntity _jsArrayTypedConstructor;
-  @override
   ConstructorEntity get jsArrayTypedConstructor =>
       _jsArrayTypedConstructor ??= _findConstructor(jsArrayClass, 'typed');
 
-  FunctionEntity _jsArrayRemoveLast;
-  @override
-  FunctionEntity get jsArrayRemoveLast =>
-      _jsArrayRemoveLast ??= _findClassMember(jsArrayClass, 'removeLast');
-
-  FunctionEntity _jsArrayAdd;
-  @override
-  FunctionEntity get jsArrayAdd =>
-      _jsArrayAdd ??= _findClassMember(jsArrayClass, 'add');
-
-  bool _isJsStringClass(ClassEntity cls) {
-    return cls.name == 'JSString' && cls.library == interceptorsLibrary;
-  }
-
-  @override
-  bool isJsStringSplit(MemberEntity member) {
-    return member.name == 'split' &&
-        member.isInstanceMember &&
-        _isJsStringClass(member.enclosingClass);
-  }
-
-  @override
-  bool appliesToJsStringSplit(Selector selector, AbstractValue receiver,
-      AbstractValueDomain abstractValueDomain) {
-    if (_jsStringSplit == null) {
-      ClassEntity cls =
-          _findClass(interceptorsLibrary, 'JSString', required: false);
-      if (cls == null) return false;
-      _jsStringSplit = _findClassMember(cls, 'split', required: false);
-      if (_jsStringSplit == null) return false;
-    }
-    return selector.applies(_jsStringSplit) &&
-        (receiver == null ||
-            abstractValueDomain
-                .isTargetingMember(receiver, jsStringSplit, selector.memberName)
-                .isPotentiallyTrue);
-  }
-
-  FunctionEntity _jsStringSplit;
-  @override
-  FunctionEntity get jsStringSplit =>
-      _jsStringSplit ??= _findClassMember(jsStringClass, 'split');
-
-  FunctionEntity _jsStringToString;
-  @override
-  FunctionEntity get jsStringToString =>
-      _jsStringToString ??= _findClassMember(jsStringClass, 'toString');
-
-  FunctionEntity _jsStringOperatorAdd;
-  @override
-  FunctionEntity get jsStringOperatorAdd =>
-      _jsStringOperatorAdd ??= _findClassMember(jsStringClass, '+');
-
-  ClassEntity _jsConstClass;
-  @override
-  ClassEntity get jsConstClass =>
-      _jsConstClass ??= _findClass(foreignLibrary, 'JS_CONST');
-
-  // From dart:js
-  FunctionEntity _jsAllowInterop1;
-  @override
-  FunctionEntity get jsAllowInterop1 => _jsAllowInterop1 ??=
-      _findLibraryMember(dartJsLibrary, 'allowInterop', required: false);
-
-  // From dart:_js_annotations
-  FunctionEntity _jsAllowInterop2;
-  @override
-  FunctionEntity get jsAllowInterop2 => _jsAllowInterop2 ??= _findLibraryMember(
-      dartJsAnnotationsLibrary, 'allowInterop',
-      required: false);
-
-  @override
-  bool isJsAllowInterop(FunctionEntity function) {
-    return function == jsAllowInterop1 || function == jsAllowInterop2;
-  }
-
-  // From package:js
-  ClassEntity _jsAnnotationClass1;
-  @override
-  ClassEntity get jsAnnotationClass1 => _jsAnnotationClass1 ??=
-      _findClass(packageJsLibrary, 'JS', required: false);
-
-  // From dart:_js_annotations
-  ClassEntity _jsAnnotationClass2;
-  @override
-  ClassEntity get jsAnnotationClass2 => _jsAnnotationClass2 ??=
-      _findClass(dartJsAnnotationsLibrary, 'JS', required: false);
-
-  @override
-  bool isJsAnnotationClass(ClassEntity cls) {
-    return cls == jsAnnotationClass1 || cls == jsAnnotationClass2;
-  }
-
-  // From dart:js
-  ClassEntity _jsAnonymousClass1;
-  @override
-  ClassEntity get jsAnonymousClass1 => _jsAnonymousClass1 ??=
-      _findClass(packageJsLibrary, '_Anonymous', required: false);
-
-  // From dart:_js_annotations
-  ClassEntity _jsAnonymousClass2;
-  @override
-  ClassEntity get jsAnonymousClass2 => _jsAnonymousClass2 ??=
-      _findClass(dartJsAnnotationsLibrary, '_Anonymous', required: false);
-
-  @override
-  bool isJsAnonymousClass(ClassEntity cls) {
-    return cls == jsAnonymousClass1 || cls == jsAnonymousClass2;
-  }
-
-  @override
+  // From dart:_js_helper
+  // TODO(johnniwinther): Avoid the need for this (from [CheckedModeHelper]).
   FunctionEntity findHelperFunction(String name) => _findHelperFunction(name);
 
   FunctionEntity _findHelperFunction(String name) =>
@@ -1549,186 +764,125 @@
   FunctionEntity _findLateHelperFunction(String name) =>
       _findLibraryMember(lateHelperLibrary, name);
 
-  ClassEntity _closureClass;
-  @override
   ClassEntity get closureClass => _closureClass ??= _findHelperClass('Closure');
 
-  ClassEntity _closureClass0Args;
-  @override
   ClassEntity get closureClass0Args =>
       _closureClass0Args ??= _findHelperClass('Closure0Args');
 
-  ClassEntity _closureClass2Args;
-  @override
   ClassEntity get closureClass2Args =>
       _closureClass2Args ??= _findHelperClass('Closure2Args');
 
-  ClassEntity _boundClosureClass;
-  @override
   ClassEntity get boundClosureClass =>
       _boundClosureClass ??= _findHelperClass('BoundClosure');
 
-  ClassEntity _typeLiteralClass;
-  @override
   ClassEntity get typeLiteralClass =>
       _typeLiteralClass ??= _findRtiClass('_Type');
 
-  ClassEntity _constMapLiteralClass;
-  @override
   ClassEntity get constMapLiteralClass =>
       _constMapLiteralClass ??= _findHelperClass('ConstantMap');
 
   // TODO(fishythefish): Implement a `ConstantSet` class and update the backend
   // impacts + constant emitter accordingly.
-  ClassEntity _constSetLiteralClass;
-  @override
   ClassEntity get constSetLiteralClass =>
       _constSetLiteralClass ??= unmodifiableSetClass;
 
-  ClassEntity _pragmaClass;
-  @override
-  ClassEntity get pragmaClass =>
-      _pragmaClass ??= _findClass(coreLibrary, 'pragma');
-
-  FieldEntity _pragmaClassNameField;
-  @override
-  FieldEntity get pragmaClassNameField =>
-      _pragmaClassNameField ??= _findClassMember(pragmaClass, 'name');
-
-  FieldEntity _pragmaClassOptionsField;
-  @override
-  FieldEntity get pragmaClassOptionsField =>
-      _pragmaClassOptionsField ??= _findClassMember(pragmaClass, 'options');
-
-  ClassEntity _jsInvocationMirrorClass;
-  @override
   ClassEntity get jsInvocationMirrorClass =>
       _jsInvocationMirrorClass ??= _findHelperClass('JSInvocationMirror');
 
-  ClassEntity _requiredSentinelClass;
-  @override
   ClassEntity get requiredSentinelClass =>
       _requiredSentinelClass ??= _findHelperClass('_Required');
-  @override
+
   InterfaceType get requiredSentinelType => _getRawType(requiredSentinelClass);
 
-  MemberEntity _invocationTypeArgumentGetter;
-  @override
   MemberEntity get invocationTypeArgumentGetter =>
       _invocationTypeArgumentGetter ??=
           _findClassMember(jsInvocationMirrorClass, 'typeArguments');
 
-  ClassEntity _jsIndexingBehaviorInterface;
-  @override
+  /// Interface used to determine if an object has the JavaScript
+  /// indexing behavior. The interface is only visible to specific libraries.
   ClassEntity get jsIndexingBehaviorInterface =>
       _jsIndexingBehaviorInterface ??=
           _findHelperClass('JavaScriptIndexingBehavior');
 
-  @override
   ClassEntity get stackTraceHelperClass => _findHelperClass('_StackTrace');
 
-  @override
   ClassEntity get constantMapClass =>
       _findHelperClass(constant_system.JavaScriptMapConstant.DART_CLASS);
-  @override
+
   ClassEntity get constantStringMapClass =>
       _findHelperClass(constant_system.JavaScriptMapConstant.DART_STRING_CLASS);
-  @override
+
   ClassEntity get generalConstantMapClass => _findHelperClass(
       constant_system.JavaScriptMapConstant.DART_GENERAL_CLASS);
 
-  @override
   ClassEntity get annotationCreatesClass => _findHelperClass('Creates');
 
-  @override
   ClassEntity get annotationReturnsClass => _findHelperClass('Returns');
 
-  @override
   ClassEntity get annotationJSNameClass => _findHelperClass('JSName');
 
-  ClassEntity _nativeAnnotationClass;
-  @override
+  /// The class for native annotations defined in dart:_js_helper.
   ClassEntity get nativeAnnotationClass =>
       _nativeAnnotationClass ??= _findHelperClass('Native');
 
-  FunctionEntity _assertTest;
-  @override
   FunctionEntity get assertTest =>
       _assertTest ??= _findHelperFunction('assertTest');
 
-  FunctionEntity _assertThrow;
-  @override
   FunctionEntity get assertThrow =>
       _assertThrow ??= _findHelperFunction('assertThrow');
 
-  FunctionEntity _assertHelper;
-  @override
   FunctionEntity get assertHelper =>
       _assertHelper ??= _findHelperFunction('assertHelper');
 
-  FunctionEntity _assertUnreachableMethod;
-  @override
   FunctionEntity get assertUnreachableMethod =>
       _assertUnreachableMethod ??= _findHelperFunction('assertUnreachable');
 
-  FunctionEntity _getIsolateAffinityTagMarker;
-  @override
+  /// Holds the method "getIsolateAffinityTag" when dart:_js_helper has been
+  /// loaded.
   FunctionEntity get getIsolateAffinityTagMarker =>
       _getIsolateAffinityTagMarker ??=
           _findHelperFunction('getIsolateAffinityTag');
 
-  FunctionEntity _requiresPreambleMarker;
-  @override
+  /// Holds the method "requiresPreamble" in _js_helper.
   FunctionEntity get requiresPreambleMarker =>
       _requiresPreambleMarker ??= _findHelperFunction('requiresPreamble');
 
-  FunctionEntity _rawStartupMetrics;
-  @override
+  /// Holds the method "_rawStartupMetrics" in _js_helper.
   FunctionEntity get rawStartupMetrics =>
       _rawStartupMetrics ??= _findHelperFunction('rawStartupMetrics');
 
-  @override
   FunctionEntity get loadLibraryWrapper =>
       _findHelperFunction("_loadLibraryWrapper");
 
-  @override
   FunctionEntity get loadDeferredLibrary =>
       _findHelperFunction("loadDeferredLibrary");
 
-  @override
   FunctionEntity get boolConversionCheck =>
       _findHelperFunction('boolConversionCheck');
 
-  @override
   FunctionEntity get traceHelper => _findHelperFunction('traceHelper');
 
-  @override
   FunctionEntity get closureFromTearOff =>
       _findHelperFunction('closureFromTearOff');
 
-  @override
   FunctionEntity get isJsIndexable => _findHelperFunction('isJsIndexable');
 
-  @override
   FunctionEntity get throwIllegalArgumentException =>
       _findHelperFunction('iae');
 
-  @override
   FunctionEntity get throwIndexOutOfRangeException =>
       _findHelperFunction('ioore');
 
-  @override
   FunctionEntity get exceptionUnwrapper =>
       _findHelperFunction('unwrapException');
 
-  @override
   FunctionEntity get throwUnsupportedError =>
       _findHelperFunction('throwUnsupportedError');
 
-  @override
   FunctionEntity get throwTypeError => _findRtiFunction('throwTypeError');
 
-  @override
+  /// Recognizes the `checkConcurrentModificationError` helper without needing
+  /// it to be resolved.
   bool isCheckConcurrentModificationError(MemberEntity member) {
     return member.name == 'checkConcurrentModificationError' &&
         member.isFunction &&
@@ -1736,101 +890,52 @@
         member.library == jsHelperLibrary;
   }
 
-  FunctionEntity _cachedCheckConcurrentModificationError;
-  @override
   FunctionEntity get checkConcurrentModificationError =>
       _cachedCheckConcurrentModificationError ??=
           _findHelperFunction('checkConcurrentModificationError');
 
-  @override
   FunctionEntity get throwConcurrentModificationError =>
       _findHelperFunction('throwConcurrentModificationError');
 
-  @override
-  bool isCheckInt(MemberEntity member) {
-    return member.isFunction &&
-        member.isTopLevel &&
-        member.library == jsHelperLibrary &&
-        member.name == 'checkInt';
-  }
-
-  @override
-  bool isCheckNum(MemberEntity member) {
-    return member.isFunction &&
-        member.isTopLevel &&
-        member.library == jsHelperLibrary &&
-        member.name == 'checkNum';
-  }
-
-  @override
-  bool isCheckString(MemberEntity member) {
-    return member.isFunction &&
-        member.isTopLevel &&
-        member.library == jsHelperLibrary &&
-        member.name == 'checkString';
-  }
-
-  @override
   FunctionEntity get stringInterpolationHelper => _findHelperFunction('S');
 
-  @override
   FunctionEntity get wrapExceptionHelper =>
       _findHelperFunction('wrapException');
 
-  @override
   FunctionEntity get throwExpressionHelper =>
       _findHelperFunction('throwExpression');
 
-  @override
   FunctionEntity get closureConverter =>
       _findHelperFunction('convertDartClosureToJS');
 
-  @override
   FunctionEntity get traceFromException =>
       _findHelperFunction('getTraceFromException');
 
-  @override
   FunctionEntity get checkDeferredIsLoaded =>
       _findHelperFunction('checkDeferredIsLoaded');
 
-  @override
   FunctionEntity get throwNoSuchMethod =>
       _findHelperFunction('throwNoSuchMethod');
 
-  @override
   FunctionEntity get createRuntimeType => _findRtiFunction('createRuntimeType');
 
-  @override
   FunctionEntity get fallThroughError =>
       _findHelperFunction("getFallThroughError");
 
-  @override
   FunctionEntity get createInvocationMirror =>
       _findHelperFunction('createInvocationMirror');
 
-  @override
-  bool isCreateInvocationMirrorHelper(MemberEntity member) {
-    return member.isTopLevel &&
-        member.name == '_createInvocationMirror' &&
-        member.library == coreLibrary;
-  }
-
-  @override
   FunctionEntity get createUnmangledInvocationMirror =>
       _findHelperFunction('createUnmangledInvocationMirror');
 
-  @override
   FunctionEntity get cyclicThrowHelper =>
       _findHelperFunction("throwCyclicInit");
 
-  @override
   FunctionEntity get defineProperty => _findHelperFunction('defineProperty');
 
-  @override
   FunctionEntity get throwLateFieldADI =>
       _findLateHelperFunction('throwLateFieldADI');
 
-  @override
   bool isExtractTypeArguments(FunctionEntity member) {
     return member.name == 'extractTypeArguments' &&
         member.library == internalLibrary;
@@ -1847,26 +952,16 @@
     }
   }
 
-  @override
   ClassEntity getInstantiationClass(int typeArgumentCount) {
     _checkTypeArgumentCount(typeArgumentCount);
     return _findHelperClass('Instantiation$typeArgumentCount');
   }
 
-  @override
   FunctionEntity getInstantiateFunction(int typeArgumentCount) {
     _checkTypeArgumentCount(typeArgumentCount);
     return _findHelperFunction('instantiate$typeArgumentCount');
   }
 
-  @override
-  bool isInstantiationClass(ClassEntity cls) {
-    return cls.library == _jsHelperLibrary &&
-        cls.name != 'Instantiation' &&
-        cls.name.startsWith('Instantiation');
-  }
-
-  @override
   FunctionEntity get convertMainArgumentList =>
       _findHelperFunction('convertMainArgumentList');
 
@@ -1877,259 +972,159 @@
   FunctionEntity _findRtiFunction(String name) =>
       _findLibraryMember(rtiLibrary, name);
 
-  FunctionEntity _setArrayType;
-  @override
   FunctionEntity get setArrayType =>
       _setArrayType ??= _findRtiFunction('_setArrayType');
 
-  FunctionEntity _findType;
-  @override
   FunctionEntity get findType => _findType ??= _findRtiFunction('findType');
 
-  FunctionEntity _instanceType;
-  @override
   FunctionEntity get instanceType =>
       _instanceType ??= _findRtiFunction('instanceType');
 
-  FunctionEntity _arrayInstanceType;
-  @override
   FunctionEntity get arrayInstanceType =>
       _arrayInstanceType ??= _findRtiFunction('_arrayInstanceType');
 
-  FunctionEntity _simpleInstanceType;
-  @override
   FunctionEntity get simpleInstanceType =>
       _simpleInstanceType ??= _findRtiFunction('_instanceType');
 
-  FunctionEntity _typeLiteralMaker;
-  @override
   FunctionEntity get typeLiteralMaker =>
       _typeLiteralMaker ??= _findRtiFunction('typeLiteral');
 
-  FunctionEntity _checkTypeBound;
-  @override
   FunctionEntity get checkTypeBound =>
       _checkTypeBound ??= _findRtiFunction('checkTypeBound');
 
   ClassEntity get _rtiImplClass => _findClass(rtiLibrary, 'Rti');
+
   ClassEntity get _rtiUniverseClass => _findClass(rtiLibrary, '_Universe');
+
   FieldEntity _findRtiClassField(String name) =>
       _findClassMember(_rtiImplClass, name);
 
-  FieldEntity _rtiAsField;
-  @override
   FieldEntity get rtiAsField => _rtiAsField ??= _findRtiClassField('_as');
 
-  FieldEntity _rtiIsField;
-  @override
   FieldEntity get rtiIsField => _rtiIsField ??= _findRtiClassField('_is');
 
-  FieldEntity _rtiRestField;
-  @override
   FieldEntity get rtiRestField => _rtiRestField ??= _findRtiClassField('_rest');
 
-  FieldEntity _rtiPrecomputed1Field;
-  @override
   FieldEntity get rtiPrecomputed1Field =>
       _rtiPrecomputed1Field ??= _findRtiClassField('_precomputed1');
 
-  FunctionEntity _rtiEvalMethod;
-  @override
   FunctionEntity get rtiEvalMethod =>
       _rtiEvalMethod ??= _findClassMember(_rtiImplClass, '_eval');
 
-  FunctionEntity _rtiBindMethod;
-  @override
   FunctionEntity get rtiBindMethod =>
       _rtiBindMethod ??= _findClassMember(_rtiImplClass, '_bind');
 
-  FunctionEntity _rtiAddRulesMethod;
-  @override
   FunctionEntity get rtiAddRulesMethod =>
       _rtiAddRulesMethod ??= _findClassMember(_rtiUniverseClass, 'addRules');
 
-  FunctionEntity _rtiAddErasedTypesMethod;
-  @override
   FunctionEntity get rtiAddErasedTypesMethod => _rtiAddErasedTypesMethod ??=
       _findClassMember(_rtiUniverseClass, 'addErasedTypes');
 
-  FunctionEntity _rtiAddTypeParameterVariancesMethod;
-  @override
   FunctionEntity get rtiAddTypeParameterVariancesMethod =>
       _rtiAddTypeParameterVariancesMethod ??=
           _findClassMember(_rtiUniverseClass, 'addTypeParameterVariances');
 
-  @override
   FunctionEntity get installSpecializedIsTest =>
       _findRtiFunction('_installSpecializedIsTest');
 
-  @override
   FunctionEntity get installSpecializedAsCheck =>
       _findRtiFunction('_installSpecializedAsCheck');
 
-  FunctionEntity _generalIsTestImplementation;
-  @override
   FunctionEntity get generalIsTestImplementation =>
       _generalIsTestImplementation ??=
           _findRtiFunction('_generalIsTestImplementation');
 
-  FunctionEntity _generalNullableIsTestImplementation;
-  @override
   FunctionEntity get generalNullableIsTestImplementation =>
       _generalNullableIsTestImplementation ??=
           _findRtiFunction('_generalNullableIsTestImplementation');
 
-  FunctionEntity _generalAsCheckImplementation;
-  @override
   FunctionEntity get generalAsCheckImplementation =>
       _generalAsCheckImplementation ??=
           _findRtiFunction('_generalAsCheckImplementation');
 
-  FunctionEntity _generalNullableAsCheckImplementation;
-  @override
   FunctionEntity get generalNullableAsCheckImplementation =>
       _generalNullableAsCheckImplementation ??=
           _findRtiFunction('_generalNullableAsCheckImplementation');
 
-  FunctionEntity _specializedIsObject;
-  @override
   FunctionEntity get specializedIsObject =>
       _specializedIsObject ??= _findRtiFunction('_isObject');
 
-  FunctionEntity _specializedAsObject;
-  @override
   FunctionEntity get specializedAsObject =>
       _specializedAsObject ??= _findRtiFunction('_asObject');
 
-  @override
   FunctionEntity get specializedIsTop => _findRtiFunction('_isTop');
 
-  @override
   FunctionEntity get specializedAsTop => _findRtiFunction('_asTop');
 
-  @override
   FunctionEntity get specializedIsBool => _findRtiFunction('_isBool');
 
-  @override
   FunctionEntity get specializedAsBool => _findRtiFunction('_asBool');
 
-  @override
   FunctionEntity get specializedAsBoolLegacy => _findRtiFunction('_asBoolS');
 
-  @override
   FunctionEntity get specializedAsBoolNullable => _findRtiFunction('_asBoolQ');
 
-  @override
   FunctionEntity get specializedAsDouble => _findRtiFunction('_asDouble');
 
-  @override
   FunctionEntity get specializedAsDoubleLegacy =>
       _findRtiFunction('_asDoubleS');
 
-  @override
   FunctionEntity get specializedAsDoubleNullable =>
       _findRtiFunction('_asDoubleQ');
 
-  @override
   FunctionEntity get specializedIsInt => _findRtiFunction('_isInt');
 
-  @override
   FunctionEntity get specializedAsInt => _findRtiFunction('_asInt');
 
-  @override
   FunctionEntity get specializedAsIntLegacy => _findRtiFunction('_asIntS');
 
-  @override
   FunctionEntity get specializedAsIntNullable => _findRtiFunction('_asIntQ');
 
-  @override
   FunctionEntity get specializedIsNum => _findRtiFunction('_isNum');
 
-  @override
   FunctionEntity get specializedAsNum => _findRtiFunction('_asNum');
 
-  @override
   FunctionEntity get specializedAsNumLegacy => _findRtiFunction('_asNumS');
 
-  @override
   FunctionEntity get specializedAsNumNullable => _findRtiFunction('_asNumQ');
 
-  @override
   FunctionEntity get specializedIsString => _findRtiFunction('_isString');
 
-  @override
   FunctionEntity get specializedAsString => _findRtiFunction('_asString');
 
-  @override
   FunctionEntity get specializedAsStringLegacy =>
       _findRtiFunction('_asStringS');
 
-  @override
   FunctionEntity get specializedAsStringNullable =>
       _findRtiFunction('_asStringQ');
 
-  @override
   FunctionEntity get instantiatedGenericFunctionTypeNewRti =>
       _findRtiFunction('instantiatedGenericFunctionType');
 
-  @override
   FunctionEntity get closureFunctionType =>
       _findRtiFunction('closureFunctionType');
 
   // From dart:_internal
 
-  ClassEntity _symbolImplementationClass;
-  @override
   ClassEntity get symbolImplementationClass =>
       _symbolImplementationClass ??= _findClass(internalLibrary, 'Symbol');
 
-  ClassEntity _externalNameClass;
-  @override
+  /// Used to annotate items that have the keyword "native".
   ClassEntity get externalNameClass =>
       _externalNameClass ??= _findClass(internalLibrary, 'ExternalName');
-  @override
+
   InterfaceType get externalNameType => _getRawType(externalNameClass);
 
-  /// Returns the field that holds the internal name in the implementation class
-  /// for `Symbol`.
-  FieldEntity _symbolImplementationField;
-  FieldEntity get symbolImplementationField => _symbolImplementationField ??=
-      _env.lookupLocalClassMember(symbolImplementationClass, '_name',
-          required: true);
-
-  // From dart:_native_typed_data
-
-  ClassEntity _typedArrayOfIntClass;
-  @override
-  ClassEntity get typedArrayOfIntClass => _typedArrayOfIntClass ??= _findClass(
-      _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
-      'NativeTypedArrayOfInt');
-
-  ClassEntity _typedArrayOfDoubleClass;
-  @override
-  ClassEntity get typedArrayOfDoubleClass =>
-      _typedArrayOfDoubleClass ??= _findClass(
-          _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
-          'NativeTypedArrayOfDouble');
-
   // From dart:_js_embedded_names
 
-  ClassEntity _jsGetNameEnum;
-  @override
   ClassEntity get jsGetNameEnum => _jsGetNameEnum ??= _findClass(
       _env.lookupLibrary(Uris.dart__js_embedded_names, required: true),
       'JsGetName');
 
-  ClassEntity _jsBuiltinEnum;
-  @override
-  ClassEntity get jsBuiltinEnum => _jsBuiltinEnum ??= _findClass(
-      _env.lookupLibrary(Uris.dart__js_embedded_names, required: true),
-      'JsBuiltin');
-
-  @override
-  bool isForeign(MemberEntity element) => element.library == foreignLibrary;
-
-  @override
+  /// Returns `true` if [member] is a "foreign helper", that is, a member whose
+  /// semantics is defined synthetically and not through Dart code.
+  ///
+  /// Most foreign helpers are located in the `dart:_foreign_helper` library.
   bool isForeignHelper(MemberEntity member) {
     return member.library == foreignLibrary ||
         isCreateInvocationMirrorHelper(member);
@@ -2138,37 +1133,30 @@
   bool _isTopLevelFunctionNamed(String name, MemberEntity member) =>
       member.name == name && member.isFunction && member.isTopLevel;
 
-  @override
+  /// Returns `true` if [member] is the `createJsSentinel` function defined in
+  /// dart:_foreign_helper.
   bool isCreateJsSentinel(MemberEntity member) =>
       member.library == foreignLibrary &&
       _isTopLevelFunctionNamed('createJsSentinel', member);
 
-  @override
+  /// Returns `true` if [member] is the `isJsSentinel` function defined in
+  /// dart:_foreign_helper.
   bool isIsJsSentinel(MemberEntity member) =>
       member.library == foreignLibrary &&
       _isTopLevelFunctionNamed('isJsSentinel', member);
 
-  @override
+  /// Returns `true` if [member] is the `_lateReadCheck` function defined in
+  /// dart:_internal.
   bool isLateReadCheck(MemberEntity member) =>
       member.library == lateHelperLibrary &&
       _isTopLevelFunctionNamed('_lateReadCheck', member);
 
-  @override
+  /// Returns `true` if [member] is the `createSentinel` function defined in
+  /// dart:_internal.
   bool isCreateSentinel(MemberEntity member) =>
       member.library == internalLibrary &&
       _isTopLevelFunctionNamed('createSentinel', member);
 
-  @override
-  bool operatorEqHandlesNullArgument(FunctionEntity function) {
-    assert(function.name == '==',
-        failedAt(function, "Unexpected function $function."));
-    ClassEntity cls = function.enclosingClass;
-    return cls == objectClass ||
-        cls == jsInterceptorClass ||
-        cls == jsNullClass;
-  }
-
-  @override
   ClassEntity getDefaultSuperclass(
       ClassEntity cls, NativeBasicData nativeBasicData) {
     if (nativeBasicData.isJsInteropClass(cls)) {
@@ -2179,6 +1167,241 @@
         ? jsInterceptorClass
         : objectClass;
   }
+
+  // From package:js
+  FunctionEntity get jsAllowInterop1 => _jsAllowInterop1 ??=
+      _findLibraryMember(dartJsLibrary, 'allowInterop', required: false);
+
+  // From dart:_js_annotations;
+  FunctionEntity get jsAllowInterop2 => _jsAllowInterop2 ??= _findLibraryMember(
+      dartJsAnnotationsLibrary, 'allowInterop',
+      required: false);
+
+  /// Returns `true` if [function] is `allowInterop`.
+  ///
+  /// This function can come from either `package:js` or `dart:_js_annotations`.
+  bool isJsAllowInterop(FunctionEntity function) {
+    return function == jsAllowInterop1 || function == jsAllowInterop2;
+  }
+
+  bool isCreateInvocationMirrorHelper(MemberEntity member) {
+    return member.isTopLevel &&
+        member.name == '_createInvocationMirror' &&
+        member.library == coreLibrary;
+  }
+}
+
+class KCommonElements extends CommonElements {
+  ClassEntity _jsAnnotationClass1;
+  ClassEntity _jsAnonymousClass1;
+  ClassEntity _jsAnnotationClass2;
+  ClassEntity _jsAnonymousClass2;
+  ClassEntity _pragmaClass;
+  FieldEntity _pragmaClassNameField;
+  FieldEntity _pragmaClassOptionsField;
+
+  KCommonElements(DartTypes dartTypes, ElementEnvironment env)
+      : super(dartTypes, env);
+
+  // From package:js
+
+  ClassEntity get jsAnnotationClass1 => _jsAnnotationClass1 ??=
+      _findClass(packageJsLibrary, 'JS', required: false);
+
+  ClassEntity get jsAnonymousClass1 => _jsAnonymousClass1 ??=
+      _findClass(packageJsLibrary, '_Anonymous', required: false);
+
+  // From dart:_js_annotations
+
+  ClassEntity get jsAnnotationClass2 => _jsAnnotationClass2 ??=
+      _findClass(dartJsAnnotationsLibrary, 'JS', required: false);
+
+  ClassEntity get jsAnonymousClass2 => _jsAnonymousClass2 ??=
+      _findClass(dartJsAnnotationsLibrary, '_Anonymous', required: false);
+
+  /// Returns `true` if [cls] is a @JS() annotation.
+  ///
+  /// The class can come from either `package:js` or `dart:_js_annotations`.
+  bool isJsAnnotationClass(ClassEntity cls) {
+    return cls == jsAnnotationClass1 || cls == jsAnnotationClass2;
+  }
+
+  /// Returns `true` if [cls] is an @anonymous annotation.
+  ///
+  /// The class can come from either `package:js` or `dart:_js_annotations`.
+  bool isJsAnonymousClass(ClassEntity cls) {
+    return cls == jsAnonymousClass1 || cls == jsAnonymousClass2;
+  }
+
+  ClassEntity get pragmaClass =>
+      _pragmaClass ??= _findClass(coreLibrary, 'pragma');
+
+  FieldEntity get pragmaClassNameField =>
+      _pragmaClassNameField ??= _findClassMember(pragmaClass, 'name');
+
+  FieldEntity get pragmaClassOptionsField =>
+      _pragmaClassOptionsField ??= _findClassMember(pragmaClass, 'options');
+}
+
+class JCommonElements extends CommonElements {
+  FunctionEntity _jsArrayRemoveLast;
+  FunctionEntity _jsArrayAdd;
+  FunctionEntity _jsStringSplit;
+  FunctionEntity _jsStringToString;
+  FunctionEntity _jsStringOperatorAdd;
+  ClassEntity _jsConstClass;
+  ClassEntity _typedArrayOfIntClass;
+  ClassEntity _typedArrayOfDoubleClass;
+  ClassEntity _jsBuiltinEnum;
+
+  JCommonElements(DartTypes dartTypes, ElementEnvironment env)
+      : super(dartTypes, env);
+
+  /// Returns `true` if [element] is the unnamed constructor of `List`.
+  ///
+  /// This will not resolve the constructor if it hasn't been seen yet during
+  /// compilation.
+  bool isUnnamedListConstructor(ConstructorEntity element) =>
+      (element.name == '' && element.enclosingClass == listClass) ||
+      (element.name == 'list' && element.enclosingClass == jsArrayClass);
+
+  /// Returns `true` if [element] is the named constructor of `List`,
+  /// e.g. `List.of`.
+  ///
+  /// This will not resolve the constructor if it hasn't been seen yet during
+  /// compilation.
+  bool isNamedListConstructor(String name, ConstructorEntity element) =>
+      element.name == name && element.enclosingClass == listClass;
+
+  /// Returns `true` if [element] is the named constructor of `JSArray`,
+  /// e.g. `JSArray.fixed`.
+  ///
+  /// This will not resolve the constructor if it hasn't been seen yet during
+  /// compilation.
+  bool isNamedJSArrayConstructor(String name, ConstructorEntity element) =>
+      element.name == name && element.enclosingClass == jsArrayClass;
+
+  bool isDefaultEqualityImplementation(MemberEntity element) {
+    assert(element.name == '==');
+    ClassEntity classElement = element.enclosingClass;
+    return classElement == objectClass ||
+        classElement == jsInterceptorClass ||
+        classElement == jsNullClass;
+  }
+
+  /// Returns `true` if [selector] applies to `JSIndexable.length`.
+  bool appliesToJsIndexableLength(Selector selector) {
+    return selector.name == 'length' && (selector.isGetter || selector.isCall);
+  }
+
+  FunctionEntity get jsArrayRemoveLast =>
+      _jsArrayRemoveLast ??= _findClassMember(jsArrayClass, 'removeLast');
+
+  FunctionEntity get jsArrayAdd =>
+      _jsArrayAdd ??= _findClassMember(jsArrayClass, 'add');
+
+  bool _isJsStringClass(ClassEntity cls) {
+    return cls.name == 'JSString' && cls.library == interceptorsLibrary;
+  }
+
+  bool isJsStringSplit(MemberEntity member) {
+    return member.name == 'split' &&
+        member.isInstanceMember &&
+        _isJsStringClass(member.enclosingClass);
+  }
+
+  /// Returns `true` if [selector] applies to `JSString.split` on [receiver]
+  /// in the given [world].
+  ///
+  /// Returns `false` if `JSString.split` is not available.
+  bool appliesToJsStringSplit(Selector selector, AbstractValue receiver,
+      AbstractValueDomain abstractValueDomain) {
+    if (_jsStringSplit == null) {
+      ClassEntity cls =
+          _findClass(interceptorsLibrary, 'JSString', required: false);
+      if (cls == null) return false;
+      _jsStringSplit = _findClassMember(cls, 'split', required: false);
+      if (_jsStringSplit == null) return false;
+    }
+    return selector.applies(_jsStringSplit) &&
+        (receiver == null ||
+            abstractValueDomain
+                .isTargetingMember(receiver, jsStringSplit, selector.memberName)
+                .isPotentiallyTrue);
+  }
+
+  FunctionEntity get jsStringSplit =>
+      _jsStringSplit ??= _findClassMember(jsStringClass, 'split');
+
+  FunctionEntity get jsStringToString =>
+      _jsStringToString ??= _findClassMember(jsStringClass, 'toString');
+
+  FunctionEntity get jsStringOperatorAdd =>
+      _jsStringOperatorAdd ??= _findClassMember(jsStringClass, '+');
+
+  ClassEntity get jsConstClass =>
+      _jsConstClass ??= _findClass(foreignLibrary, 'JS_CONST');
+
+  /// Return `true` if [member] is the 'checkInt' function defined in
+  /// dart:_js_helpers.
+  bool isCheckInt(MemberEntity member) {
+    return member.isFunction &&
+        member.isTopLevel &&
+        member.library == jsHelperLibrary &&
+        member.name == 'checkInt';
+  }
+
+  /// Return `true` if [member] is the 'checkNum' function defined in
+  /// dart:_js_helpers.
+  bool isCheckNum(MemberEntity member) {
+    return member.isFunction &&
+        member.isTopLevel &&
+        member.library == jsHelperLibrary &&
+        member.name == 'checkNum';
+  }
+
+  /// Return `true` if [member] is the 'checkString' function defined in
+  /// dart:_js_helpers.
+  bool isCheckString(MemberEntity member) {
+    return member.isFunction &&
+        member.isTopLevel &&
+        member.library == jsHelperLibrary &&
+        member.name == 'checkString';
+  }
+
+  bool isInstantiationClass(ClassEntity cls) {
+    return cls.library == _jsHelperLibrary &&
+        cls.name != 'Instantiation' &&
+        cls.name.startsWith('Instantiation');
+  }
+
+  // From dart:_native_typed_data
+
+  ClassEntity get typedArrayOfIntClass => _typedArrayOfIntClass ??= _findClass(
+      _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
+      'NativeTypedArrayOfInt');
+
+  ClassEntity get typedArrayOfDoubleClass =>
+      _typedArrayOfDoubleClass ??= _findClass(
+          _env.lookupLibrary(Uris.dart__native_typed_data, required: true),
+          'NativeTypedArrayOfDouble');
+
+  ClassEntity get jsBuiltinEnum => _jsBuiltinEnum ??= _findClass(
+      _env.lookupLibrary(Uris.dart__js_embedded_names, required: true),
+      'JsBuiltin');
+
+  bool isForeign(MemberEntity element) => element.library == foreignLibrary;
+
+  /// Returns `true` if the implementation of the 'operator ==' [function] is
+  /// known to handle `null` as argument.
+  bool operatorEqHandlesNullArgument(FunctionEntity function) {
+    assert(function.name == '==',
+        failedAt(function, "Unexpected function $function."));
+    ClassEntity cls = function.enclosingClass;
+    return cls == objectClass ||
+        cls == jsInterceptorClass ||
+        cls == jsNullClass;
+  }
 }
 
 /// Interface for accessing libraries, classes and members.
@@ -2378,12 +1601,6 @@
   /// Returns the imports seen in [library]
   Iterable<ImportEntity> getImports(LibraryEntity library);
 
-  /// Returns the metadata constants declared on [library].
-  Iterable<ConstantValue> getLibraryMetadata(LibraryEntity library);
-
-  /// Returns the metadata constants declared on [cls].
-  Iterable<ConstantValue> getClassMetadata(ClassEntity cls);
-
   /// Returns the metadata constants declared on [member].
   Iterable<ConstantValue> getMemberMetadata(MemberEntity member,
       {bool includeParameterMetadata = false});
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 8e1bf87..9ca6a7c 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -76,7 +76,7 @@
   @override
   final DiagnosticReporter reporter;
   final Environment _environment;
-  CommonElementsImpl _commonElements;
+  JCommonElements _commonElements;
   JsElementEnvironment _elementEnvironment;
   DartTypeConverter _typeConverter;
   KernelDartTypes _types;
@@ -137,7 +137,7 @@
     _elementEnvironment = JsElementEnvironment(this);
     _typeConverter = DartTypeConverter(this);
     _types = KernelDartTypes(this, options);
-    _commonElements = CommonElementsImpl(_types, _elementEnvironment);
+    _commonElements = JCommonElements(_types, _elementEnvironment);
     _constantValuefier = ConstantValuefier(this);
 
     programEnv = _elementMap.env.convert();
@@ -297,7 +297,7 @@
     _elementEnvironment = JsElementEnvironment(this);
     _typeConverter = DartTypeConverter(this);
     _types = KernelDartTypes(this, options);
-    _commonElements = CommonElementsImpl(_types, _elementEnvironment);
+    _commonElements = JCommonElements(_types, _elementEnvironment);
     _constantValuefier = ConstantValuefier(this);
 
     source.registerComponentLookup(ComponentLookup(component));
@@ -510,7 +510,7 @@
   JsElementEnvironment get elementEnvironment => _elementEnvironment;
 
   @override
-  CommonElementsImpl get commonElements => _commonElements;
+  JCommonElements get commonElements => _commonElements;
 
   FunctionEntity get _mainFunction {
     return programEnv.mainMethod != null
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 2d8e7b6..7bd67d0 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -65,7 +65,7 @@
   @override
   final DiagnosticReporter reporter;
   final Environment _environment;
-  CommonElementsImpl _commonElements;
+  KCommonElements _commonElements;
   KernelElementEnvironment _elementEnvironment;
   DartTypeConverter _typeConverter;
   KernelDartTypes _types;
@@ -117,7 +117,7 @@
     _elementEnvironment = KernelElementEnvironment(this);
     _typeConverter = DartTypeConverter(this);
     _types = KernelDartTypes(this, options);
-    _commonElements = CommonElementsImpl(_types, _elementEnvironment);
+    _commonElements = KCommonElements(_types, _elementEnvironment);
     _constantValuefier = ConstantValuefier(this);
   }
 
@@ -128,7 +128,7 @@
   KernelElementEnvironment get elementEnvironment => _elementEnvironment;
 
   @override
-  CommonElementsImpl get commonElements => _commonElements;
+  KCommonElements get commonElements => _commonElements;
 
   FunctionEntity get _mainFunction {
     return env.mainMethod != null ? getMethodInternal(env.mainMethod) : null;
@@ -1874,13 +1874,6 @@
   }
 
   @override
-  Iterable<ConstantValue> getLibraryMetadata(covariant IndexedLibrary library) {
-    assert(elementMap.checkFamily(library));
-    KLibraryData libraryData = elementMap.libraries.getData(library);
-    return libraryData.getMetadata(elementMap);
-  }
-
-  @override
   Iterable<ImportEntity> getImports(covariant IndexedLibrary library) {
     assert(elementMap.checkFamily(library));
     KLibraryData libraryData = elementMap.libraries.getData(library);
@@ -1888,13 +1881,6 @@
   }
 
   @override
-  Iterable<ConstantValue> getClassMetadata(covariant IndexedClass cls) {
-    assert(elementMap.checkFamily(cls));
-    KClassData classData = elementMap.classes.getData(cls);
-    return classData.getMetadata(elementMap);
-  }
-
-  @override
   Iterable<ConstantValue> getMemberMetadata(covariant IndexedMember member,
       {bool includeParameterMetadata = false}) {
     // TODO(redemption): Support includeParameterMetadata.
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index 9df3e23..2d4c60f 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -216,7 +216,7 @@
     impactBuilder.registerFeature(Feature.SYNC_STAR);
     impactBuilder.registerStaticUse(StaticUse.staticInvoke(
         commonElements.syncStarIterableFactory,
-        const CallStructure.unnamed(1, 1),
+        CallStructure.unnamed(1, 1),
         <DartType>[elementMap.getDartType(elementType)]));
   }
 
@@ -225,7 +225,7 @@
     impactBuilder.registerFeature(Feature.ASYNC);
     impactBuilder.registerStaticUse(StaticUse.staticInvoke(
         commonElements.asyncAwaitCompleterFactory,
-        const CallStructure.unnamed(0, 1),
+        CallStructure.unnamed(0, 1),
         <DartType>[elementMap.getDartType(elementType)]));
   }
 
@@ -234,7 +234,7 @@
     impactBuilder.registerFeature(Feature.ASYNC_STAR);
     impactBuilder.registerStaticUse(StaticUse.staticInvoke(
         commonElements.asyncStarStreamControllerFactory,
-        const CallStructure.unnamed(1, 1),
+        CallStructure.unnamed(1, 1),
         <DartType>[elementMap.getDartType(elementType)]));
   }
 
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 37d2d3e..139b3a2 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -2391,15 +2391,34 @@
 
   @override
   void visitAsExpression(ir.AsExpression node) {
-    ir.Expression operand = node.operand;
+    // Recognize these special cases, where expression e has static type `T?`:
+    //
+    //     e as T
+    //     (e as dynamic) as T
+    //
+    // These patterns can only fail if `e` results in a `null` value.  The
+    // second pattern occurs when `e as dynamic` is used get an implicit
+    // downcast in order to make use of the different policies for explicit and
+    // implicit downcasts.
+    //
+    // The pattern match is syntactic which ensures the type bindings are
+    // consistent, i.e. from the same instance of a type variable scope.
+    ir.Expression operand = _skipCastsToDynamic(node.operand);
     operand.accept(this);
 
+    bool isNullRemovalPattern = false;
+
     StaticType operandType = _getStaticType(operand);
     DartType type = _elementMap.getDartType(node.type);
-    if (!node.isCovarianceCheck &&
-        _elementMap.types.isSubtype(operandType.type, type)) {
-      // Skip unneeded casts.
-      return;
+    if (!node.isCovarianceCheck) {
+      if (_elementMap.types.isSubtype(operandType.type, type)) {
+        // Skip unneeded casts.
+        return;
+      }
+      if (_elementMap.types
+          .isSubtype(operandType.type, _elementMap.types.nullableType(type))) {
+        isNullRemovalPattern = true;
+      }
     }
 
     SourceInformation sourceInformation =
@@ -2420,7 +2439,12 @@
           .getExplicitCastCheckPolicy(_currentFrame.member);
     }
 
-    if (policy.isEmitted) {
+    if (!policy.isEmitted) {
+      stack.add(expressionInstruction);
+      return;
+    }
+
+    void generateCheck() {
       HInstruction converted = _typeBuilder.buildAsCheck(
           expressionInstruction, localsHandler.substInContext(type),
           isTypeError: node.isTypeError, sourceInformation: sourceInformation);
@@ -2428,9 +2452,34 @@
         add(converted);
       }
       stack.add(converted);
-    } else {
-      stack.add(expressionInstruction);
     }
+
+    if (isNullRemovalPattern) {
+      // Generate a conditional to test only `null` values:
+      //
+      //     temp = e;
+      //     temp == null ? temp as T : temp
+      SsaBranchBuilder(this).handleConditional(
+          () {
+            push(HIdentity(
+                expressionInstruction,
+                graph.addConstantNull(closedWorld),
+                _abstractValueDomain.boolType));
+          },
+          generateCheck,
+          () {
+            stack.add(expressionInstruction);
+          });
+    } else {
+      generateCheck();
+    }
+  }
+
+  static ir.Expression _skipCastsToDynamic(ir.Expression node) {
+    if (node is ir.AsExpression && node.type is ir.DynamicType) {
+      return _skipCastsToDynamic(node.operand);
+    }
+    return node;
   }
 
   @override
diff --git a/pkg/compiler/lib/src/ssa/ssa.dart b/pkg/compiler/lib/src/ssa/ssa.dart
index 77182b9..4986815 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -220,7 +220,7 @@
 
     registry.registerStaticUse(StaticUse.staticInvoke(
         completerFactory,
-        const CallStructure.unnamed(0, 1),
+        CallStructure.unnamed(0, 1),
         [elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)]));
 
     return rewriter;
@@ -255,7 +255,7 @@
 
     registry.registerStaticUse(StaticUse.staticInvoke(
         commonElements.syncStarIterableFactory,
-        const CallStructure.unnamed(1, 1),
+        CallStructure.unnamed(1, 1),
         [elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)]));
 
     return rewriter;
@@ -293,7 +293,7 @@
 
     registry.registerStaticUse(StaticUse.staticInvoke(
         commonElements.asyncStarStreamControllerFactory,
-        const CallStructure.unnamed(1, 1),
+        CallStructure.unnamed(1, 1),
         [elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)]));
 
     return rewriter;
diff --git a/pkg/compiler/lib/src/universe/call_structure.dart b/pkg/compiler/lib/src/universe/call_structure.dart
index 234a3a9..1dc8cdd 100644
--- a/pkg/compiler/lib/src/universe/call_structure.dart
+++ b/pkg/compiler/lib/src/universe/call_structure.dart
@@ -11,7 +11,12 @@
 import 'selector.dart' show Selector;
 
 /// The structure of the arguments at a call-site.
-// TODO(johnniwinther): Should these be cached?
+///
+/// A call-site passes some number of arguments: some positional arguments
+/// followed by some named arguments. There may also be type arguments.
+///
+/// A CallStructure is unmodifiable.
+
 // TODO(johnniwinther): Should isGetter/isSetter be part of the call structure
 // instead of the selector?
 class CallStructure {
@@ -19,11 +24,23 @@
   /// data stream.
   static const String tag = 'call-structure';
 
-  static const CallStructure NO_ARGS = CallStructure.unnamed(0);
-  static const CallStructure ONE_ARG = CallStructure.unnamed(1);
-  static const CallStructure TWO_ARGS = CallStructure.unnamed(2);
-  static const CallStructure THREE_ARGS = CallStructure.unnamed(3);
-  static const CallStructure FOUR_ARGS = CallStructure.unnamed(4);
+  static const CallStructure NO_ARGS = CallStructure._(0);
+  static const CallStructure ONE_ARG = CallStructure._(1);
+  static const CallStructure TWO_ARGS = CallStructure._(2);
+
+  static const List<List<CallStructure>> _common = [
+    [NO_ARGS, CallStructure._(0, 1), CallStructure._(0, 2)],
+    [ONE_ARG, CallStructure._(1, 1), CallStructure._(1, 2)],
+    [TWO_ARGS, CallStructure._(2, 1), CallStructure._(2, 2)],
+    [CallStructure._(3), CallStructure._(3, 1), CallStructure._(3, 2)],
+    [CallStructure._(4), CallStructure._(4, 1), CallStructure._(4, 2)],
+    [CallStructure._(5), CallStructure._(5, 1), CallStructure._(5, 2)],
+    [CallStructure._(6)],
+    [CallStructure._(7)],
+    [CallStructure._(8)],
+    [CallStructure._(9)],
+    [CallStructure._(10)],
+  ];
 
   /// The number of type arguments of the call.
   final int typeArgumentCount;
@@ -37,14 +54,31 @@
   /// The number of positional argument of the call.
   int get positionalArgumentCount => argumentCount;
 
-  const CallStructure.unnamed(this.argumentCount, [this.typeArgumentCount = 0]);
+  const CallStructure._(this.argumentCount, [this.typeArgumentCount = 0]);
+
+  factory CallStructure.unnamed(int argumentCount,
+      [int typeArgumentCount = 0]) {
+    // This simple canonicalization of common call structures greatly reduces
+    // the number of allocations of CallStructure objects.
+    if (argumentCount < _common.length) {
+      final row = _common[argumentCount];
+      if (typeArgumentCount < row.length) {
+        final result = row[typeArgumentCount];
+        assert(result.argumentCount == argumentCount &&
+            result.typeArgumentCount == typeArgumentCount);
+        return result;
+      }
+    }
+    return CallStructure._(argumentCount, typeArgumentCount);
+  }
 
   factory CallStructure(int argumentCount,
       [List<String> namedArguments, int typeArgumentCount = 0]) {
     if (namedArguments == null || namedArguments.isEmpty) {
       return CallStructure.unnamed(argumentCount, typeArgumentCount);
     }
-    return NamedCallStructure(argumentCount, namedArguments, typeArgumentCount);
+    return _NamedCallStructure(
+        argumentCount, namedArguments, typeArgumentCount, null);
   }
 
   /// Deserializes a [CallStructure] object from [source].
@@ -127,7 +161,7 @@
     return this.argumentCount == other.argumentCount &&
         this.namedArgumentCount == other.namedArgumentCount &&
         this.typeArgumentCount == other.typeArgumentCount &&
-        sameNames(this.namedArguments, other.namedArguments);
+        _sameNames(this.namedArguments, other.namedArguments);
   }
 
   // TODO(johnniwinther): Cache hash code?
@@ -193,7 +227,8 @@
     }
   }
 
-  static bool sameNames(List<String> first, List<String> second) {
+  static bool _sameNames(List<String> first, List<String> second) {
+    assert(first.length == second.length);
     for (int i = 0; i < first.length; i++) {
       if (first[i] != second[i]) return false;
     }
@@ -201,20 +236,19 @@
   }
 }
 
-/// Call structure with named arguments.
-class NamedCallStructure extends CallStructure {
+/// Call structure with named arguments. This is an implementation detail of the
+/// CallStructure interface.
+class _NamedCallStructure extends CallStructure {
   @override
   final List<String> namedArguments;
-  final List<String> _orderedNamedArguments;
 
-  NamedCallStructure(
-      int argumentCount, List<String> namedArguments, int typeArgumentCount)
-      : this._(argumentCount, namedArguments, typeArgumentCount, []);
+  /// The list of ordered named arguments is computed lazily. Initially `null`.
+  List<String> /*?*/ _orderedNamedArguments;
 
-  NamedCallStructure._(int argumentCount, this.namedArguments,
+  _NamedCallStructure(int argumentCount, this.namedArguments,
       int typeArgumentCount, this._orderedNamedArguments)
       : assert(namedArguments.isNotEmpty),
-        super.unnamed(argumentCount, typeArgumentCount);
+        super._(argumentCount, typeArgumentCount);
 
   @override
   bool get isNamed => true;
@@ -229,24 +263,29 @@
   int get positionalArgumentCount => argumentCount - namedArgumentCount;
 
   @override
-  bool get isNormalized => namedArguments == _orderedNamedArguments;
+  bool get isNormalized =>
+      identical(namedArguments, getOrderedNamedArguments());
 
   @override
-  CallStructure toNormalized() => NamedCallStructure._(
-      argumentCount,
-      getOrderedNamedArguments(),
-      typeArgumentCount,
-      getOrderedNamedArguments());
+  CallStructure toNormalized() => isNormalized
+      ? this
+      : _NamedCallStructure(argumentCount, getOrderedNamedArguments(),
+          typeArgumentCount, getOrderedNamedArguments());
 
   @override
   List<String> getOrderedNamedArguments() {
-    if (!_orderedNamedArguments.isEmpty) return _orderedNamedArguments;
+    return _orderedNamedArguments ??= _getOrderedNamedArguments();
+  }
 
-    _orderedNamedArguments.addAll(namedArguments);
-    _orderedNamedArguments.sort((String first, String second) {
-      return first.compareTo(second);
-    });
-    return _orderedNamedArguments;
+  List<String> _getOrderedNamedArguments() {
+    List<String> ordered = List.of(namedArguments, growable: false);
+    ordered.sort((String first, String second) => first.compareTo(second));
+    // Use the same List if [namedArguments] is already ordered to indicate this
+    // _NamedCallStructure is normalized.
+    if (CallStructure._sameNames(ordered, namedArguments)) {
+      return namedArguments;
+    }
+    return ordered;
   }
 
   @override
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index 5235fe1..dddc39b 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -148,7 +148,7 @@
     } else if (element.isConstructor) {
       return Selector.callConstructor(name);
     } else {
-      throw failedAt(element, "Can't get selector from $element");
+      throw failedAt(element, "Cannot get selector from $element");
     }
   }
 
diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart
index e8ae525..af19b56 100644
--- a/pkg/dartdev/lib/src/analysis_server.dart
+++ b/pkg/dartdev/lib/src/analysis_server.dart
@@ -97,15 +97,16 @@
     ];
 
     _process = await startDartProcess(sdk, command);
+    final proc = _process!;
     // This callback hookup can't throw.
-    _process!.exitCode.whenComplete(() => _process = null);
+    proc.exitCode.whenComplete(() => _process = null);
 
-    final Stream<String> errorStream = _process!.stderr
+    final Stream<String> errorStream = proc.stderr
         .transform<String>(utf8.decoder)
         .transform<String>(const LineSplitter());
     errorStream.listen(log.stderr);
 
-    final Stream<String> inStream = _process!.stdout
+    final Stream<String> inStream = proc.stdout
         .transform<String>(utf8.decoder)
         .transform<String>(const LineSplitter());
     inStream.listen(_handleServerResponse);
diff --git a/pkg/dartdev/test/utils.dart b/pkg/dartdev/test/utils.dart
index 316c8bc..145d519 100644
--- a/pkg/dartdev/test/utils.dart
+++ b/pkg/dartdev/test/utils.dart
@@ -130,11 +130,12 @@
         ],
         workingDirectory: workingDir ?? dir.path,
         environment: {if (logAnalytics) '_DARTDEV_LOG_ANALYTICS': 'true'});
-    final stdoutContents = _process!.stdout.transform(utf8.decoder).join();
-    final stderrContents = _process!.stderr.transform(utf8.decoder).join();
-    final code = await _process!.exitCode;
+    final proc = _process!;
+    final stdoutContents = proc.stdout.transform(utf8.decoder).join();
+    final stderrContents = proc.stderr.transform(utf8.decoder).join();
+    final code = await proc.exitCode;
     return ProcessResult(
-      _process!.pid,
+      proc.pid,
       code,
       await stdoutContents,
       await stderrContents,
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index ae632ec..880d764 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -25,13 +25,14 @@
 export '../fasta/incremental_serializer.dart' show IncrementalSerializer;
 
 abstract class IncrementalKernelGenerator {
-  factory IncrementalKernelGenerator(CompilerOptions options, Uri entryPoint,
+  factory IncrementalKernelGenerator(
+      CompilerOptions options, List<Uri> entryPoints,
       [Uri? initializeFromDillUri,
       bool? outlineOnly,
       IncrementalSerializer? incrementalSerializer]) {
     return new IncrementalCompiler(
         new CompilerContext(
-            new ProcessedOptions(options: options, inputs: [entryPoint])),
+            new ProcessedOptions(options: options, inputs: entryPoints)),
         initializeFromDillUri,
         outlineOnly,
         incrementalSerializer);
@@ -42,11 +43,11 @@
   /// Notice that the component has to include the platform, and that no other
   /// platform will be loaded.
   factory IncrementalKernelGenerator.fromComponent(
-      CompilerOptions options, Uri entryPoint, Component? component,
+      CompilerOptions options, List<Uri> entryPoints, Component? component,
       [bool? outlineOnly, IncrementalSerializer? incrementalSerializer]) {
     return new IncrementalCompiler.fromComponent(
         new CompilerContext(
-            new ProcessedOptions(options: options, inputs: [entryPoint])),
+            new ProcessedOptions(options: options, inputs: entryPoints)),
         component,
         outlineOnly,
         incrementalSerializer);
@@ -63,10 +64,10 @@
   /// Notice that the component has to include the platform, and that no other
   /// platform will be loaded.
   factory IncrementalKernelGenerator.forExpressionCompilationOnly(
-      CompilerOptions options, Uri entryPoint, Component component) {
+      CompilerOptions options, List<Uri> entryPoints, Component component) {
     return new IncrementalCompiler.forExpressionCompilationOnly(
         new CompilerContext(
-            new ProcessedOptions(options: options, inputs: [entryPoint])),
+            new ProcessedOptions(options: options, inputs: entryPoints)),
         component);
   }
 
diff --git a/pkg/front_end/lib/src/api_prototype/kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
index ca6286c..39c7f32 100644
--- a/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
@@ -45,16 +45,19 @@
 /// The input [source] is expected to be a script with a main method, otherwise
 /// an error is reported.
 // TODO(sigmund): rename to kernelForScript?
-Future<CompilerResult?> kernelForProgram(
-    Uri source, CompilerOptions options) async {
-  return (await kernelForProgramInternal(source, options));
+Future<CompilerResult?> kernelForProgram(Uri source, CompilerOptions options,
+    {List<Uri> additionalSources: const <Uri>[]}) async {
+  return (await kernelForProgramInternal(source, options,
+      additionalSources: additionalSources));
 }
 
 Future<CompilerResult?> kernelForProgramInternal(
     Uri source, CompilerOptions options,
-    {bool retainDataForTesting: false, bool requireMain: true}) async {
-  ProcessedOptions pOptions =
-      new ProcessedOptions(options: options, inputs: [source]);
+    {List<Uri> additionalSources: const <Uri>[],
+    bool retainDataForTesting: false,
+    bool requireMain: true}) async {
+  ProcessedOptions pOptions = new ProcessedOptions(
+      options: options, inputs: [source, ...additionalSources]);
   return await CompilerContext.runWithOptions(pOptions, (context) async {
     CompilerResult result = await generateKernelInternal(
         includeHierarchyAndCoreTypes: true,
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_target.dart b/pkg/front_end/lib/src/fasta/dill/dill_target.dart
index b5b737e..1a0b447 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_target.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_target.dart
@@ -12,6 +12,8 @@
 
 import '../compiler_context.dart' show CompilerContext;
 
+import '../kernel/benchmarker.dart' show BenchmarkPhases, Benchmarker;
+
 import '../messages.dart' show FormattedMessage, LocatedMessage, Message;
 
 import '../ticker.dart' show Ticker;
@@ -40,7 +42,10 @@
   /// Shared with [CompilerContext].
   final Map<Uri, Source> uriToSource = CompilerContext.current.uriToSource;
 
-  DillTarget(this.ticker, this.uriTranslator, this.backendTarget)
+  final Benchmarker? benchmarker;
+
+  DillTarget(this.ticker, this.uriTranslator, this.backendTarget,
+      {this.benchmarker})
       // ignore: unnecessary_null_comparison
       : assert(ticker != null),
         // ignore: unnecessary_null_comparison
@@ -81,9 +86,12 @@
 
   void buildOutlines({bool suppressFinalizationErrors: false}) {
     if (loader.libraries.isNotEmpty) {
+      benchmarker?.enterPhase(BenchmarkPhases.dill_buildOutlines);
       loader.buildOutlines();
+      benchmarker?.enterPhase(BenchmarkPhases.dill_finalizeExports);
       loader.finalizeExports(
           suppressFinalizationErrors: suppressFinalizationErrors);
+      benchmarker?.enterPhase(BenchmarkPhases.unknown);
     }
     isLoaded = true;
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart b/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart
new file mode 100644
index 0000000..79df036
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart
@@ -0,0 +1,115 @@
+// 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.
+
+class Benchmarker {
+  final Stopwatch _totalStopwatch = new Stopwatch()..start();
+  final Stopwatch _phaseStopwatch = new Stopwatch()..start();
+  BenchmarkPhases _currentPhase = BenchmarkPhases.implicitInitialization;
+  List<PhaseTiming> _phaseTimings = [];
+
+  void enterPhase(BenchmarkPhases phase) {
+    if (_currentPhase == phase) return;
+    _phaseTimings.add(
+        new PhaseTiming(_currentPhase, _phaseStopwatch.elapsedMicroseconds));
+    _phaseStopwatch.reset();
+    _currentPhase = phase;
+  }
+
+  void stop() {
+    enterPhase(BenchmarkPhases.end);
+    _totalStopwatch.stop();
+  }
+
+  Map<String, Object?> toJson() {
+    // TODO: Merge unknown?
+    return <String, Object?>{
+      "totalTime": _totalStopwatch.elapsedMicroseconds,
+      "phases": _phaseTimings,
+    };
+  }
+}
+
+class PhaseTiming {
+  final BenchmarkPhases phase;
+  final int runtime;
+
+  PhaseTiming(this.phase, this.runtime);
+
+  Map<String, Object?> toJson() {
+    return <String, Object?>{
+      "phase": phase.name,
+      "runtime": runtime,
+    };
+  }
+}
+
+enum BenchmarkPhases {
+  implicitInitialization,
+  loadSDK,
+  loadAdditionalDills,
+
+  dill_buildOutlines,
+  dill_finalizeExports,
+
+  outline_kernelBuildOutlines,
+  outline_becomeCoreLibrary,
+  outline_resolveParts,
+  outline_computeMacroDeclarations,
+  outline_computeLibraryScopes,
+  outline_computeMacroApplications,
+  outline_setupTopAndBottomTypes,
+  outline_resolveTypes,
+  outline_computeVariances,
+  outline_computeDefaultTypes,
+  outline_applyTypeMacros,
+  outline_checkSemantics,
+  outline_finishTypeVariables,
+  outline_createTypeInferenceEngine,
+  outline_buildComponent,
+  outline_installDefaultSupertypes,
+  outline_installSyntheticConstructors,
+  outline_resolveConstructors,
+  outline_link,
+  outline_computeCoreTypes,
+  outline_buildClassHierarchy,
+  outline_checkSupertypes,
+  outline_applyDeclarationMacros,
+  outline_buildClassHierarchyMembers,
+  outline_computeHierarchy,
+  outline_computeShowHideElements,
+  outline_installTypedefTearOffs,
+  outline_performTopLevelInference,
+  outline_checkOverrides,
+  outline_checkAbstractMembers,
+  outline_addNoSuchMethodForwarders,
+  outline_checkMixins,
+  outline_buildOutlineExpressions,
+  outline_checkTypes,
+  outline_checkRedirectingFactories,
+  outline_finishSynthesizedParameters,
+  outline_checkMainMethods,
+  outline_installAllComponentProblems,
+
+  body_buildBodies,
+  body_finishSynthesizedParameters,
+
+  body_finishDeferredLoadTearoffs,
+  body_finishNoSuchMethodForwarders,
+  body_collectSourceClasses,
+  body_applyDefinitionMacros,
+  body_finishNativeMethods,
+  body_finishPatchMethods,
+  body_finishAllConstructors,
+  body_runBuildTransformations,
+  body_verify,
+  body_installAllComponentProblems,
+
+  printComponentText,
+  omitPlatform,
+  writeComponent,
+  // add more here
+  //
+  end,
+  unknown,
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index d01d2d8..6ac5ea0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -72,6 +72,7 @@
 import '../ticker.dart' show Ticker;
 import '../type_inference/type_schema.dart';
 import '../uri_translator.dart' show UriTranslator;
+import 'benchmarker.dart' show BenchmarkPhases, Benchmarker;
 import 'constant_evaluator.dart' as constants
     show
         EvaluationMode,
@@ -182,12 +183,15 @@
 
   final ProcessedOptions _options;
 
+  final Benchmarker? benchmarker;
+
   KernelTarget(this.fileSystem, this.includeComments, DillTarget dillTarget,
       this.uriTranslator)
       : dillTarget = dillTarget,
         backendTarget = dillTarget.backendTarget,
         _options = CompilerContext.current.options,
-        ticker = dillTarget.ticker {
+        ticker = dillTarget.ticker,
+        benchmarker = dillTarget.benchmarker {
     loader = createLoader();
   }
 
@@ -399,10 +403,20 @@
     _hasComputedNeededPrecompilations = true;
     if (loader.first == null) return null;
     return withCrashReporting<NeededPrecompilations?>(() async {
+      benchmarker?.enterPhase(BenchmarkPhases.outline_kernelBuildOutlines);
       await loader.buildOutlines();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_becomeCoreLibrary);
       loader.coreLibrary.becomeCoreLibrary();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_resolveParts);
       loader.resolveParts();
-      return loader.computeMacroDeclarations();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_computeMacroDeclarations);
+      NeededPrecompilations? result = loader.computeMacroDeclarations();
+
+      benchmarker?.enterPhase(BenchmarkPhases.unknown);
+      return result;
     }, () => loader.currentUriForCrashReporting);
   }
 
@@ -423,56 +437,135 @@
           throw new UnsupportedError('Macro precompilation is not supported.');
         }
       }
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_computeLibraryScopes);
       loader.computeLibraryScopes();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_computeMacroApplications);
       MacroApplications? macroApplications =
           await loader.computeMacroApplications();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_setupTopAndBottomTypes);
       setupTopAndBottomTypes();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_resolveTypes);
       loader.resolveTypes();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_computeVariances);
       loader.computeVariances();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_computeDefaultTypes);
       loader.computeDefaultTypes(
           dynamicType, nullType, bottomType, objectClassBuilder);
+
       if (macroApplications != null) {
+        benchmarker?.enterPhase(BenchmarkPhases.outline_applyTypeMacros);
         await macroApplications.applyTypeMacros();
       }
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_checkSemantics);
       List<SourceClassBuilder>? sourceClassBuilders =
           loader.checkSemantics(objectClassBuilder);
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_finishTypeVariables);
       loader.finishTypeVariables(objectClassBuilder, dynamicType);
+
+      benchmarker
+          ?.enterPhase(BenchmarkPhases.outline_createTypeInferenceEngine);
       loader.createTypeInferenceEngine();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_buildComponent);
       loader.buildComponent();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_installDefaultSupertypes);
       installDefaultSupertypes();
+
+      benchmarker
+          ?.enterPhase(BenchmarkPhases.outline_installSyntheticConstructors);
       installSyntheticConstructors(sourceClassBuilders);
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_resolveConstructors);
       loader.resolveConstructors();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_link);
       component =
           link(new List<Library>.of(loader.libraries), nameRoot: nameRoot);
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_computeCoreTypes);
       computeCoreTypes();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_buildClassHierarchy);
       loader.buildClassHierarchy(sourceClassBuilders, objectClassBuilder);
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_checkSupertypes);
       loader.checkSupertypes(sourceClassBuilders, enumClass);
+
       if (macroApplications != null) {
+        benchmarker?.enterPhase(BenchmarkPhases.outline_applyDeclarationMacros);
         await macroApplications
             .applyDeclarationsMacros(loader.hierarchyBuilder);
       }
+
+      benchmarker
+          ?.enterPhase(BenchmarkPhases.outline_buildClassHierarchyMembers);
       loader.buildClassHierarchyMembers(sourceClassBuilders);
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_computeHierarchy);
       loader.computeHierarchy();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_computeShowHideElements);
       loader.computeShowHideElements();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_installTypedefTearOffs);
       loader.installTypedefTearOffs();
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_performTopLevelInference);
       loader.performTopLevelInference(sourceClassBuilders);
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_checkOverrides);
       loader.checkOverrides(sourceClassBuilders);
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_checkAbstractMembers);
       loader.checkAbstractMembers(sourceClassBuilders);
+
+      benchmarker
+          ?.enterPhase(BenchmarkPhases.outline_addNoSuchMethodForwarders);
       loader.addNoSuchMethodForwarders(sourceClassBuilders);
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_checkMixins);
       loader.checkMixins(sourceClassBuilders);
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_buildOutlineExpressions);
       loader.buildOutlineExpressions(
           loader.hierarchy, synthesizedFunctionNodes);
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_checkTypes);
       loader.checkTypes();
+
+      benchmarker
+          ?.enterPhase(BenchmarkPhases.outline_checkRedirectingFactories);
       loader.checkRedirectingFactories(sourceClassBuilders);
+
+      benchmarker
+          ?.enterPhase(BenchmarkPhases.outline_finishSynthesizedParameters);
       finishSynthesizedParameters(forOutline: true);
+
+      benchmarker?.enterPhase(BenchmarkPhases.outline_checkMainMethods);
       loader.checkMainMethods();
+
+      benchmarker
+          ?.enterPhase(BenchmarkPhases.outline_installAllComponentProblems);
       installAllComponentProblems(loader.allComponentProblems);
       loader.allComponentProblems.clear();
+
+      benchmarker?.enterPhase(BenchmarkPhases.unknown);
+
       // For whatever reason sourceClassBuilders is kept alive for some amount
       // of time, meaning that all source library builders will be kept alive
       // (for whatever amount of time) even though we convert them to dill
       // library builders. To avoid it we null it out here.
       sourceClassBuilders = null;
+
       return new BuildResult(
           component: component, macroApplications: macroApplications);
     }, () => loader.currentUriForCrashReporting);
@@ -494,22 +587,50 @@
     }
     return withCrashReporting<BuildResult>(() async {
       ticker.logMs("Building component");
+
+      benchmarker?.enterPhase(BenchmarkPhases.body_buildBodies);
       await loader.buildBodies();
+
+      benchmarker?.enterPhase(BenchmarkPhases.body_finishSynthesizedParameters);
       finishSynthesizedParameters();
+
+      benchmarker?.enterPhase(BenchmarkPhases.body_finishDeferredLoadTearoffs);
       loader.finishDeferredLoadTearoffs();
+
+      benchmarker
+          ?.enterPhase(BenchmarkPhases.body_finishNoSuchMethodForwarders);
       loader.finishNoSuchMethodForwarders();
+
+      benchmarker?.enterPhase(BenchmarkPhases.body_collectSourceClasses);
       List<SourceClassBuilder>? sourceClasses = loader.collectSourceClasses();
+
       if (macroApplications != null) {
+        benchmarker?.enterPhase(BenchmarkPhases.body_applyDefinitionMacros);
         await macroApplications.applyDefinitionMacros();
       }
+
+      benchmarker?.enterPhase(BenchmarkPhases.body_finishNativeMethods);
       loader.finishNativeMethods();
+
+      benchmarker?.enterPhase(BenchmarkPhases.body_finishPatchMethods);
       loader.finishPatchMethods();
+
+      benchmarker?.enterPhase(BenchmarkPhases.body_finishAllConstructors);
       finishAllConstructors(sourceClasses);
+
+      benchmarker?.enterPhase(BenchmarkPhases.body_runBuildTransformations);
       runBuildTransformations();
 
-      if (verify) this.verify();
+      if (verify) {
+        benchmarker?.enterPhase(BenchmarkPhases.body_verify);
+        this.verify();
+      }
+
+      benchmarker?.enterPhase(BenchmarkPhases.body_installAllComponentProblems);
       installAllComponentProblems(loader.allComponentProblems);
 
+      benchmarker?.enterPhase(BenchmarkPhases.unknown);
+
       // For whatever reason sourceClasses is kept alive for some amount
       // of time, meaning that all source library builders will be kept alive
       // (for whatever amount of time) even though we convert them to dill
diff --git a/pkg/front_end/lib/src/fasta/kernel/macro.dart b/pkg/front_end/lib/src/fasta/kernel/macro.dart
index 995a036..bec7d02 100644
--- a/pkg/front_end/lib/src/fasta/kernel/macro.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/macro.dart
@@ -9,7 +9,7 @@
 import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart'
     as macro;
 import 'package:front_end/src/base/common.dart';
-import 'package:kernel/ast.dart' show DartType, DynamicType;
+import 'package:kernel/ast.dart' show DartType;
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/src/types.dart';
 import 'package:kernel/type_environment.dart' show SubtypeCheckMode;
@@ -20,6 +20,7 @@
 import '../builder/library_builder.dart';
 import '../builder/member_builder.dart';
 import '../builder/named_type_builder.dart';
+import '../builder/nullability_builder.dart';
 import '../builder/type_builder.dart';
 import '../identifiers.dart';
 import '../source/source_class_builder.dart';
@@ -166,7 +167,8 @@
     return new MacroApplications(macroExecutor, libraryData, dataForTesting);
   }
 
-  Map<SourceClassBuilder, macro.ClassDeclaration?> _classDeclarations = {};
+  Map<SourceClassBuilder, macro.ClassDeclaration> _classDeclarations = {};
+  Map<macro.ClassDeclaration, SourceClassBuilder> _classBuilders = {};
   Map<MemberBuilder, macro.Declaration?> _memberDeclarations = {};
 
   // TODO(johnniwinther): Support all members.
@@ -179,6 +181,10 @@
     return _classDeclarations[builder] ??= _createClassDeclaration(builder);
   }
 
+  SourceClassBuilder _getClassBuilder(macro.ClassDeclaration declaration) {
+    return _classBuilders[declaration]!;
+  }
+
   macro.Declaration _createMemberDeclaration(MemberBuilder memberBuilder) {
     if (memberBuilder is SourceProcedureBuilder) {
       return _createFunctionDeclaration(memberBuilder);
@@ -297,7 +303,7 @@
       ClassHierarchyBase classHierarchy) async {
     types = new Types(classHierarchy);
     typeResolver = new _TypeResolver(this);
-    classIntrospector = new _ClassIntrospector();
+    classIntrospector = new _ClassIntrospector(this);
     await _applyMacros(_applyDeclarationsMacros);
   }
 
@@ -344,7 +350,7 @@
   }
 
   macro.ClassDeclaration _createClassDeclaration(SourceClassBuilder builder) {
-    return new macro.ClassDeclarationImpl(
+    macro.ClassDeclaration declaration = new macro.ClassDeclarationImpl(
         id: macro.RemoteInstance.uniqueId,
         identifier: new macro.IdentifierImpl(
             id: macro.RemoteInstance.uniqueId, name: builder.name),
@@ -358,6 +364,8 @@
         mixins: [],
         // TODO(johnniwinther): Support superclass
         superclass: null);
+    _classBuilders[declaration] = builder;
+    return declaration;
   }
 
   List<List<macro.ParameterDeclarationImpl>> _createParameters(
@@ -372,25 +380,24 @@
       for (FormalParameterBuilder formal in formals) {
         macro.TypeAnnotationImpl type =
             computeTypeAnnotation(builder.library, formal.type);
-        // TODO(johnniwinther): Support default values.
         if (formal.isNamed) {
           namedParameters.add(new macro.ParameterDeclarationImpl(
-              id: macro.RemoteInstance.uniqueId,
-              identifier: new macro.IdentifierImpl(
-                  id: macro.RemoteInstance.uniqueId, name: formal.name),
-              isRequired: formal.isNamedRequired,
-              isNamed: true,
-              type: type,
-              defaultValue: null));
+            id: macro.RemoteInstance.uniqueId,
+            identifier: new macro.IdentifierImpl(
+                id: macro.RemoteInstance.uniqueId, name: formal.name),
+            isRequired: formal.isNamedRequired,
+            isNamed: true,
+            type: type,
+          ));
         } else {
           positionalParameters.add(new macro.ParameterDeclarationImpl(
-              id: macro.RemoteInstance.uniqueId,
-              identifier: new macro.IdentifierImpl(
-                  id: macro.RemoteInstance.uniqueId, name: formal.name),
-              isRequired: formal.isRequired,
-              isNamed: false,
-              type: type,
-              defaultValue: null));
+            id: macro.RemoteInstance.uniqueId,
+            identifier: new macro.IdentifierImpl(
+                id: macro.RemoteInstance.uniqueId, name: formal.name),
+            isRequired: formal.isRequired,
+            isNamed: false,
+            type: type,
+          ));
         }
       }
     }
@@ -518,8 +525,6 @@
           identifier: new macro.IdentifierImpl(
               id: macro.RemoteInstance.uniqueId, name: builder.name),
           definingClass: definingClass.identifier as macro.IdentifierImpl,
-          // TODO(johnniwinther): Support initializer.
-          initializer: null,
           isExternal: builder.isExternal,
           isFinal: builder.isFinal,
           isLate: builder.isLate,
@@ -529,8 +534,6 @@
           id: macro.RemoteInstance.uniqueId,
           identifier: new macro.IdentifierImpl(
               id: macro.RemoteInstance.uniqueId, name: builder.name),
-          // TODO(johnniwinther): Support initializer.
-          initializer: null,
           isExternal: builder.isExternal,
           isFinal: builder.isFinal,
           isLate: builder.isLate,
@@ -538,7 +541,7 @@
     }
   }
 
-  Map<TypeBuilder?, _NamedTypeAnnotationImpl> _typeAnnotationCache = {};
+  Map<TypeBuilder?, macro.TypeAnnotationImpl> _typeAnnotationCache = {};
 
   List<macro.TypeAnnotationImpl> computeTypeAnnotations(
       LibraryBuilder library, List<TypeBuilder>? typeBuilders) {
@@ -547,7 +550,7 @@
         (int index) => computeTypeAnnotation(library, typeBuilders[index]));
   }
 
-  _NamedTypeAnnotationImpl _computeTypeAnnotation(
+  macro.TypeAnnotationImpl _computeTypeAnnotation(
       LibraryBuilder libraryBuilder, TypeBuilder? typeBuilder) {
     if (typeBuilder != null) {
       if (typeBuilder is NamedTypeBuilder) {
@@ -556,21 +559,22 @@
             computeTypeAnnotations(libraryBuilder, typeBuilder.arguments);
         bool isNullable = typeBuilder.nullabilityBuilder.isNullable;
         if (name is String) {
-          return new _NamedTypeAnnotationImpl(
-              typeBuilder: typeBuilder,
-              libraryBuilder: libraryBuilder,
+          return new macro.NamedTypeAnnotationImpl(
               id: macro.RemoteInstance.uniqueId,
-              identifier: new macro.IdentifierImpl(
-                  id: macro.RemoteInstance.uniqueId, name: name),
+              identifier: new _IdentifierImpl(
+                  typeBuilder: typeBuilder,
+                  libraryBuilder: libraryBuilder,
+                  id: macro.RemoteInstance.uniqueId,
+                  name: name),
               typeArguments: typeArguments,
               isNullable: isNullable);
         } else if (name is QualifiedName) {
           assert(name.qualifier is String);
-          return new _NamedTypeAnnotationImpl(
-              typeBuilder: typeBuilder,
-              libraryBuilder: libraryBuilder,
+          return new macro.NamedTypeAnnotationImpl(
               id: macro.RemoteInstance.uniqueId,
-              identifier: new macro.IdentifierImpl(
+              identifier: new _IdentifierImpl(
+                  typeBuilder: typeBuilder,
+                  libraryBuilder: libraryBuilder,
                   id: macro.RemoteInstance.uniqueId,
                   // TODO: We probably shouldn't be including the qualifier
                   // here. Kernel should probably have its own implementation
@@ -582,9 +586,7 @@
         }
       }
     }
-    return new _NamedTypeAnnotationImpl(
-        typeBuilder: typeBuilder,
-        libraryBuilder: libraryBuilder,
+    return new macro.NamedTypeAnnotationImpl(
         id: macro.RemoteInstance.uniqueId,
         identifier: dynamicIdentifier,
         isNullable: false,
@@ -597,17 +599,51 @@
         _computeTypeAnnotation(libraryBuilder, typeBuilder);
   }
 
-  macro.StaticType resolveTypeAnnotation(
-      _NamedTypeAnnotationImpl typeAnnotation) {
-    TypeBuilder? typeBuilder = typeAnnotation.typeBuilder;
-    LibraryBuilder libraryBuilder = typeAnnotation.libraryBuilder;
-    DartType dartType;
-    if (typeBuilder != null) {
-      dartType = typeBuilder.build(libraryBuilder);
+  TypeBuilder _typeBuilderForAnnotation(
+      macro.TypeAnnotationCode typeAnnotation) {
+    NullabilityBuilder nullabilityBuilder;
+    if (typeAnnotation is macro.NullableTypeAnnotationCode) {
+      nullabilityBuilder = const NullabilityBuilder.nullable();
+      typeAnnotation = typeAnnotation.underlyingType;
     } else {
-      dartType = const DynamicType();
+      nullabilityBuilder = const NullabilityBuilder.omitted();
     }
-    return createStaticType(dartType);
+
+    if (typeAnnotation is macro.NamedTypeAnnotationCode) {
+      _IdentifierImpl typeIdentifier = typeAnnotation.name as _IdentifierImpl;
+      TypeBuilder? originalTypeBuilder = typeIdentifier.typeBuilder;
+      if (originalTypeBuilder == null) {
+        throw new StateError('No type builder for $typeIdentifier');
+      }
+      if (originalTypeBuilder is! NamedTypeBuilder) {
+        throw new StateError(
+            'Type $typeIdentifier was not a named type as expected!');
+      }
+      List<TypeBuilder> arguments = [
+        for (macro.TypeAnnotationCode argumentCode
+            in typeAnnotation.typeArguments)
+          _typeBuilderForAnnotation(argumentCode),
+      ];
+
+      return new NamedTypeBuilder.fromTypeDeclarationBuilder(
+          originalTypeBuilder.declaration!, nullabilityBuilder,
+          instanceTypeVariableAccess:
+              originalTypeBuilder.instanceTypeVariableAccess,
+          arguments: arguments);
+    }
+    // TODO: Implement support for function types.
+    throw new UnimplementedError(
+        'Unimplemented type annotation kind ${typeAnnotation.kind}');
+  }
+
+  macro.StaticType resolveTypeAnnotation(
+      macro.TypeAnnotationCode typeAnnotation) {
+    TypeBuilder typeBuilder = _typeBuilderForAnnotation(typeAnnotation);
+    // TODO: This should probably be passed in instead, possibly attached to the
+    // TypeResolver class?
+    LibraryBuilder libraryBuilder =
+        typeAnnotation.parts.whereType<_IdentifierImpl>().first.libraryBuilder;
+    return createStaticType(typeBuilder.build(libraryBuilder));
   }
 
   Map<DartType, _StaticTypeImpl> _staticTypeCache = {};
@@ -617,22 +653,16 @@
   }
 }
 
-class _NamedTypeAnnotationImpl extends macro.NamedTypeAnnotationImpl {
+class _IdentifierImpl extends macro.IdentifierImpl {
   final TypeBuilder? typeBuilder;
   final LibraryBuilder libraryBuilder;
 
-  _NamedTypeAnnotationImpl({
+  _IdentifierImpl({
     required this.typeBuilder,
     required this.libraryBuilder,
     required int id,
-    required bool isNullable,
-    required macro.IdentifierImpl identifier,
-    required List<macro.TypeAnnotationImpl> typeArguments,
-  }) : super(
-            id: id,
-            isNullable: isNullable,
-            identifier: identifier,
-            typeArguments: typeArguments);
+    required String name,
+  }) : super(id: id, name: name);
 }
 
 class _StaticTypeImpl extends macro.StaticType {
@@ -659,31 +689,49 @@
   _TypeResolver(this.macroApplications);
 
   @override
-  Future<macro.StaticType> instantiateCode(macro.ExpressionCode code) {
-    // TODO: implement instantiateCode
-    throw new UnimplementedError();
-  }
-
-  @override
-  Future<macro.StaticType> instantiateType(
-      covariant _NamedTypeAnnotationImpl typeAnnotation) {
+  Future<macro.StaticType> resolve(macro.TypeAnnotationCode typeAnnotation) {
     return new Future.value(
         macroApplications.resolveTypeAnnotation(typeAnnotation));
   }
 }
 
 class _ClassIntrospector implements macro.ClassIntrospector {
+  final MacroApplications macroApplications;
+
+  _ClassIntrospector(this.macroApplications);
+
   @override
   Future<List<macro.ConstructorDeclaration>> constructorsOf(
       macro.ClassDeclaration clazz) {
-    // TODO: implement constructorsOf
-    throw new UnimplementedError('_ClassIntrospector.constructorsOf');
+    ClassBuilder classBuilder = macroApplications._getClassBuilder(clazz);
+    List<macro.ConstructorDeclaration> result = [];
+    classBuilder.forEachConstructor((_, MemberBuilder memberBuilder) {
+      if (memberBuilder is DeclaredSourceConstructorBuilder) {
+        // TODO(johnniwinther): Should we support synthesized constructors?
+        result.add(macroApplications._getMemberDeclaration(memberBuilder)
+            as macro.ConstructorDeclaration);
+      }
+    });
+    classBuilder.forEach((_, Builder memberBuilder) {
+      if (memberBuilder is SourceFactoryBuilder) {
+        result.add(macroApplications._getMemberDeclaration(memberBuilder)
+            as macro.ConstructorDeclaration);
+      }
+    });
+    return new Future.value(result);
   }
 
   @override
   Future<List<macro.FieldDeclaration>> fieldsOf(macro.ClassDeclaration clazz) {
-    // TODO: implement fieldsOf
-    throw new UnimplementedError('_ClassIntrospector.fieldsOf');
+    ClassBuilder classBuilder = macroApplications._getClassBuilder(clazz);
+    List<macro.FieldDeclaration> result = [];
+    classBuilder.forEach((_, Builder memberBuilder) {
+      if (memberBuilder is SourceFieldBuilder) {
+        result.add(macroApplications._getMemberDeclaration(memberBuilder)
+            as macro.FieldDeclaration);
+      }
+    });
+    return new Future.value(result);
   }
 
   @override
@@ -696,8 +744,15 @@
   @override
   Future<List<macro.MethodDeclaration>> methodsOf(
       macro.ClassDeclaration clazz) {
-    // TODO: implement methodsOf
-    throw new UnimplementedError('_ClassIntrospector.methodsOf');
+    ClassBuilder classBuilder = macroApplications._getClassBuilder(clazz);
+    List<macro.MethodDeclaration> result = [];
+    classBuilder.forEach((_, Builder memberBuilder) {
+      if (memberBuilder is SourceProcedureBuilder) {
+        result.add(macroApplications._getMemberDeclaration(memberBuilder)
+            as macro.MethodDeclaration);
+      }
+    });
+    return new Future.value(result);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index e90cf3d..90ad778 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -2570,6 +2570,8 @@
 
 _completeOnAsyncReturn(_future, value, async_jump_var) {}
 
+_completeWithNoFutureOnAsyncReturn(_future, value, async_jump_var) {}
+
 _completeOnAsyncError(_future, e, st, async_jump_var) {}
 
 class _AsyncStarStreamController {
diff --git a/pkg/front_end/test/hot_reload_e2e_test.dart b/pkg/front_end/test/hot_reload_e2e_test.dart
index 69069c9..86ddcb0 100644
--- a/pkg/front_end/test/hot_reload_e2e_test.dart
+++ b/pkg/front_end/test/hot_reload_e2e_test.dart
@@ -309,7 +309,7 @@
     ..fileSystem = fs
     ..target = new VmTarget(new TargetFlags())
     ..environmentDefines = {};
-  return new IncrementalKernelGenerator(options, entryUri);
+  return new IncrementalKernelGenerator(options, [entryUri]);
 }
 
 Future<bool> rebuild(IncrementalKernelGenerator compiler, Uri outputUri) async {
diff --git a/pkg/front_end/test/incremental_bulk_compiler_full.dart b/pkg/front_end/test/incremental_bulk_compiler_full.dart
index 9edfd97..0856796 100644
--- a/pkg/front_end/test/incremental_bulk_compiler_full.dart
+++ b/pkg/front_end/test/incremental_bulk_compiler_full.dart
@@ -76,7 +76,7 @@
     late List<int> oneShotSerialized;
     try {
       IncrementalKernelGenerator compiler =
-          new IncrementalKernelGenerator(getOptions(), uri);
+          new IncrementalKernelGenerator(getOptions(), [uri]);
       oneShotSerialized =
           util.postProcess((await compiler.computeDelta()).component);
     } catch (e) {
@@ -89,7 +89,7 @@
     try {
       globalDebuggingNames = new NameSystem();
       if (context.compiler == null) {
-        context.compiler = new IncrementalKernelGenerator(getOptions(), uri);
+        context.compiler = new IncrementalKernelGenerator(getOptions(), [uri]);
       }
       IncrementalCompilerResult compilerResult = await context.compiler!
           .computeDelta(entryPoints: [uri], fullComponent: true);
@@ -106,7 +106,7 @@
     try {
       globalDebuggingNames = new NameSystem();
       if (context.compiler == null) {
-        context.compiler = new IncrementalKernelGenerator(getOptions(), uri);
+        context.compiler = new IncrementalKernelGenerator(getOptions(), [uri]);
       }
       IncrementalCompilerResult compilerResult = await context.compiler!
           .computeDelta(entryPoints: [uri], fullComponent: true);
diff --git a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
index 23e4ee1..a6dbe4e 100644
--- a/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
+++ b/pkg/front_end/test/macro_application/data/pkgs/macro/lib/macro.dart
@@ -28,9 +28,9 @@
     if (function.positionalParameters.isEmpty) {
       return;
     }
-    StaticType returnType = await builder.instantiateType(function.returnType);
+    StaticType returnType = await builder.resolve(function.returnType.code);
     StaticType parameterType =
-    await builder.instantiateType(function.positionalParameters.first.type);
+    await builder.resolve(function.positionalParameters.first.type.code);
     builder.augment(new FunctionBodyCode.fromString('''{
   print('isExactly=${await returnType.isExactly(parameterType)}');
   print('isSubtype=${await returnType.isSubtypeOf(parameterType)}');
@@ -90,9 +90,9 @@
     if (function.positionalParameters.isEmpty) {
       return;
     }
-    StaticType returnType = await builder.instantiateType(function.returnType);
+    StaticType returnType = await builder.resolve(function.returnType.code);
     StaticType parameterType =
-    await builder.instantiateType(function.positionalParameters.first.type);
+    await builder.resolve(function.positionalParameters.first.type.code);
     bool isExactly = await returnType.isExactly(parameterType);
     bool isSubtype = await returnType.isSubtypeOf(parameterType);
     String tag = '${isExactly ? 'e' : ''}${isSubtype ? 's' : ''}';
@@ -199,6 +199,59 @@
 
 macro
 
+class ClassDeclarationsMacro2 implements ClassDeclarationsMacro {
+  const ClassDeclarationsMacro2();
+
+  FutureOr<void> buildDeclarationsForClass(ClassDeclaration clazz,
+      ClassMemberDeclarationBuilder builder) async {
+    List<ConstructorDeclaration> constructors = await builder.constructorsOf(
+        clazz);
+    StringBuffer constructorsText = new StringBuffer();
+    String comma = '';
+    constructorsText.write('constructors=');
+    for (ConstructorDeclaration constructor in constructors) {
+      constructorsText.write(comma);
+      String name = constructor.identifier.name;
+      constructorsText.write("'$name'");
+      comma = ',';
+    }
+
+    List<FieldDeclaration> fields = await builder.fieldsOf(
+        clazz);
+    StringBuffer fieldsText = new StringBuffer();
+    comma = '';
+    fieldsText.write('fields=');
+    for (FieldDeclaration field in fields) {
+      fieldsText.write(comma);
+      String name = field.identifier.name;
+      fieldsText.write("'$name'");
+      comma = ',';
+    }
+
+    List<MethodDeclaration> methods = await builder.methodsOf(
+        clazz);
+    StringBuffer methodsText = new StringBuffer();
+    comma = '';
+    methodsText.write('methods=');
+    for (MethodDeclaration method in methods) {
+      methodsText.write(comma);
+      String name = method.identifier.name;
+      methodsText.write("'$name'");
+      comma = ',';
+    }
+
+    builder.declareInLibrary(new DeclarationCode.fromString('''
+void ${clazz.identifier.name}Introspection() {
+  print("$constructorsText");
+  print("$fieldsText");
+  print("$methodsText");
+}
+'''));
+  }
+}
+
+macro
+
 class ConstructorDeclarationsMacro1
     implements ConstructorDeclarationsMacro {
   const ConstructorDeclarationsMacro1();
diff --git a/pkg/front_end/test/macro_application/data/tests/declarations.dart b/pkg/front_end/test/macro_application/data/tests/declarations.dart
index cf13538..c4584d6 100644
--- a/pkg/front_end/test/macro_application/data/tests/declarations.dart
+++ b/pkg/front_end/test/macro_application/data/tests/declarations.dart
@@ -54,8 +54,15 @@
 
 /*class: Class1:
 void Class1GeneratedMethod_() {}
+
+void Class1Introspection() {
+  print("constructors=''");
+  print("fields='instanceField1','instanceField2','instanceField3'");
+  print("methods='instanceMethod1','instanceGetter1','[]','instanceSetter1'");
+}
 */
 @ClassDeclarationsMacro1()
+@ClassDeclarationsMacro2()
 class Class1 {
   /*member: Class1.:
 augment class Class1 {
@@ -126,8 +133,15 @@
 
 /*class: Class2:
 void Class2GeneratedMethod_a() {}
+
+void Class2Introspection() {
+  print("constructors=");
+  print("fields='instanceField1'");
+  print("methods='instanceMethod1'");
+}
 */
 @ClassDeclarationsMacro1()
+@ClassDeclarationsMacro2()
 abstract class Class2 {
   /*member: Class2.instanceMethod1:
 void Class2_instanceMethod1GeneratedMethod_a() {}
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 7ddc634..3423497 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -107,6 +107,7 @@
 belonging
 beloning
 benchmark
+benchmarker
 benchmarks
 bf
 bi
@@ -1286,6 +1287,7 @@
 tiki
 tilde
 till
+timings
 tiny
 tj
 tm
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index b71a7ff..1714002 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -64,6 +64,8 @@
 bbb
 bc
 bench
+benchmarker
+benchmarkers
 besides
 beta
 bigger
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect
index adcb97b..aaa0017 100644
--- a/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart.weak.transformed.expect
@@ -28,7 +28,7 @@
 static method Extension|asyncMethod(lowered final core::int* #this) → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -37,7 +37,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect
index 4e5d4b5..cda03dd 100644
--- a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.weak.transformed.expect
@@ -17,7 +17,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -38,7 +38,7 @@
         self::expect(87, let final core::Object* #t11 = CheckLibraryIsLoaded(prefix) in def::Extension|staticProperty = 87);
         self::expect(87, let final core::Object* #t12 = CheckLibraryIsLoaded(prefix) in def::Extension|staticMethod());
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect
index 299f5f6..52535cd 100644
--- a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -29,7 +29,7 @@
         self::expect(87, let final core::Object* #t7 = CheckLibraryIsLoaded(prefix) in def::topLevelProperty);
         self::expect(87, let final core::Object* #t8 = CheckLibraryIsLoaded(prefix) in def::topLevelMethod());
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
index 295921a..4b96489 100644
--- a/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
@@ -10,7 +10,7 @@
 static method asyncString() → asy::Future<core::String*>* /* originally async */ {
   final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
   core::bool* :is_sync = false;
-  FutureOr<core::String*>* :return_value;
+  core::String? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -22,7 +22,7 @@
         :return_value = "foo";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -181,7 +181,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -194,7 +194,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::asyncString(), :async_op_then, :async_op_error, :async_op) in null;
         core::String* str = _in::unsafeCast<core::String*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart b/pkg/front_end/testcases/general/async_function_returns_future_or.dart
new file mode 100644
index 0000000..8a4d911
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+main() async {
+  await returnsString();
+  await returnsFutureOrString();
+  await returnsAwaitFutureOrString();
+  await returnsFutureString();
+  await returnsAwaitFutureString();
+  await returnsObject();
+  await returnsFutureOrObject();
+  await returnsAwaitFutureOrObject();
+  await returnsFutureObject();
+  await returnsAwaitFutureObject();
+}
+
+Future<String> returnsString() async => 'a';
+Future<String> returnsFutureOrString() async => getFutureOr<String>('a');
+Future<String> returnsAwaitFutureOrString() async =>
+    await getFutureOr<String>('a');
+Future<String> returnsFutureString() async => getFuture<String>('a');
+FutureOr<String> returnsAwaitFutureString() async =>
+    await getFuture<String>('a');
+
+Future<Object> returnsObject() async => Object();
+Future<Object> returnsFutureOrObject() async => getFutureOr<Object>(Object());
+Future<Object> returnsAwaitFutureOrObject() async =>
+    await getFutureOr<Object>(Object());
+Future<Object> returnsFutureObject() async => getFuture<Object>(Object());
+FutureOr<Object> returnsAwaitFutureObject() async =>
+    await getFuture<Object>(Object());
+
+FutureOr<T> getFutureOr<T>(T v) async => v;
+Future<T> getFuture<T>(T v) async => v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline.expect
new file mode 100644
index 0000000..94a1eca
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+import 'dart:async';
+
+main() async {}
+Future<String> returnsString() async => 'a';
+Future<String> returnsFutureOrString() async => getFutureOr<String>('a');
+Future<String> returnsAwaitFutureOrString() async =>
+    await getFutureOr<String>('a');
+Future<String> returnsFutureString() async => getFuture<String>('a');
+FutureOr<String> returnsAwaitFutureString() async =>
+    await getFuture<String>('a');
+Future<Object> returnsObject() async => Object();
+Future<Object> returnsFutureOrObject() async => getFutureOr<Object>(Object());
+Future<Object> returnsAwaitFutureOrObject() async =>
+    await getFutureOr<Object>(Object());
+Future<Object> returnsFutureObject() async => getFuture<Object>(Object());
+FutureOr<Object> returnsAwaitFutureObject() async =>
+    await getFuture<Object>(Object());
+FutureOr<T> getFutureOr<T>(T v) async => v;
+Future<T> getFuture<T>(T v) async => v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..41cf593
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+import 'dart:async';
+
+Future<Object> returnsAwaitFutureOrObject() async =>
+    await getFutureOr<Object>(Object());
+Future<Object> returnsFutureObject() async => getFuture<Object>(Object());
+Future<Object> returnsFutureOrObject() async => getFutureOr<Object>(Object());
+Future<Object> returnsObject() async => Object();
+Future<String> returnsAwaitFutureOrString() async =>
+    await getFutureOr<String>('a');
+Future<String> returnsFutureOrString() async => getFutureOr<String>('a');
+Future<String> returnsFutureString() async => getFuture<String>('a');
+Future<String> returnsString() async => 'a';
+Future<T> getFuture<T>(T v) async => v;
+FutureOr<Object> returnsAwaitFutureObject() async =>
+    await getFuture<Object>(Object());
+FutureOr<String> returnsAwaitFutureString() async =>
+    await getFuture<String>('a');
+FutureOr<T> getFutureOr<T>(T v) async => v;
+main() async {}
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.expect
new file mode 100644
index 0000000..6f8e4d4
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.expect
@@ -0,0 +1,43 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method main() → dynamic async {
+  await self::returnsString();
+  await self::returnsFutureOrString();
+  await self::returnsAwaitFutureOrString();
+  await self::returnsFutureString();
+  await self::returnsAwaitFutureString();
+  await self::returnsObject();
+  await self::returnsFutureOrObject();
+  await self::returnsAwaitFutureOrObject();
+  await self::returnsFutureObject();
+  await self::returnsAwaitFutureObject();
+}
+static method returnsString() → asy::Future<core::String> async 
+  return "a";
+static method returnsFutureOrString() → asy::Future<core::String> async 
+  return self::getFutureOr<core::String>("a");
+static method returnsAwaitFutureOrString() → asy::Future<core::String> async 
+  return await self::getFutureOr<core::String>("a");
+static method returnsFutureString() → asy::Future<core::String> async 
+  return self::getFuture<core::String>("a");
+static method returnsAwaitFutureString() → FutureOr<core::String> async 
+  return await self::getFuture<core::String>("a");
+static method returnsObject() → asy::Future<core::Object> async 
+  return new core::Object::•();
+static method returnsFutureOrObject() → asy::Future<core::Object> async 
+  return self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> async 
+  return await self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsFutureObject() → asy::Future<core::Object> async 
+  return self::getFuture<core::Object>(new core::Object::•());
+static method returnsAwaitFutureObject() → FutureOr<core::Object> async 
+  return await self::getFuture<core::Object>(new core::Object::•());
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> async 
+  return v;
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> async 
+  return v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.modular.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.modular.expect
new file mode 100644
index 0000000..6f8e4d4
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.modular.expect
@@ -0,0 +1,43 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method main() → dynamic async {
+  await self::returnsString();
+  await self::returnsFutureOrString();
+  await self::returnsAwaitFutureOrString();
+  await self::returnsFutureString();
+  await self::returnsAwaitFutureString();
+  await self::returnsObject();
+  await self::returnsFutureOrObject();
+  await self::returnsAwaitFutureOrObject();
+  await self::returnsFutureObject();
+  await self::returnsAwaitFutureObject();
+}
+static method returnsString() → asy::Future<core::String> async 
+  return "a";
+static method returnsFutureOrString() → asy::Future<core::String> async 
+  return self::getFutureOr<core::String>("a");
+static method returnsAwaitFutureOrString() → asy::Future<core::String> async 
+  return await self::getFutureOr<core::String>("a");
+static method returnsFutureString() → asy::Future<core::String> async 
+  return self::getFuture<core::String>("a");
+static method returnsAwaitFutureString() → FutureOr<core::String> async 
+  return await self::getFuture<core::String>("a");
+static method returnsObject() → asy::Future<core::Object> async 
+  return new core::Object::•();
+static method returnsFutureOrObject() → asy::Future<core::Object> async 
+  return self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> async 
+  return await self::getFutureOr<core::Object>(new core::Object::•());
+static method returnsFutureObject() → asy::Future<core::Object> async 
+  return self::getFuture<core::Object>(new core::Object::•());
+static method returnsAwaitFutureObject() → FutureOr<core::Object> async 
+  return await self::getFuture<core::Object>(new core::Object::•());
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> async 
+  return v;
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> async 
+  return v;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.outline.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.outline.expect
new file mode 100644
index 0000000..98b26fc
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method main() → dynamic async 
+  ;
+static method returnsString() → asy::Future<core::String> async 
+  ;
+static method returnsFutureOrString() → asy::Future<core::String> async 
+  ;
+static method returnsAwaitFutureOrString() → asy::Future<core::String> async 
+  ;
+static method returnsFutureString() → asy::Future<core::String> async 
+  ;
+static method returnsAwaitFutureString() → FutureOr<core::String> async 
+  ;
+static method returnsObject() → asy::Future<core::Object> async 
+  ;
+static method returnsFutureOrObject() → asy::Future<core::Object> async 
+  ;
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> async 
+  ;
+static method returnsFutureObject() → asy::Future<core::Object> async 
+  ;
+static method returnsAwaitFutureObject() → FutureOr<core::Object> async 
+  ;
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> async 
+  ;
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> async 
+  ;
diff --git a/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.transformed.expect
new file mode 100644
index 0000000..3100e06
--- /dev/null
+++ b/pkg/front_end/testcases/general/async_function_returns_future_or.dart.weak.transformed.expect
@@ -0,0 +1,386 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+static method main() → dynamic /* originally async */ {
+  final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
+  core::bool* :is_sync = false;
+  dynamic :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        [yield] let dynamic #t1 = asy::_awaitHelper(self::returnsString(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::String>(:result);
+        [yield] let dynamic #t2 = asy::_awaitHelper(self::returnsFutureOrString(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::String>(:result);
+        [yield] let dynamic #t3 = asy::_awaitHelper(self::returnsAwaitFutureOrString(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::String>(:result);
+        [yield] let dynamic #t4 = asy::_awaitHelper(self::returnsFutureString(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::String>(:result);
+        [yield] let dynamic #t5 = asy::_awaitHelper(self::returnsAwaitFutureString(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::String>(:result);
+        [yield] let dynamic #t6 = asy::_awaitHelper(self::returnsObject(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::Object>(:result);
+        [yield] let dynamic #t7 = asy::_awaitHelper(self::returnsFutureOrObject(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::Object>(:result);
+        [yield] let dynamic #t8 = asy::_awaitHelper(self::returnsAwaitFutureOrObject(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::Object>(:result);
+        [yield] let dynamic #t9 = asy::_awaitHelper(self::returnsFutureObject(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::Object>(:result);
+        [yield] let dynamic #t10 = asy::_awaitHelper(self::returnsAwaitFutureObject(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::Object>(:result);
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsString() → asy::Future<core::String> /* originally async */ {
+  final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+  core::bool* :is_sync = false;
+  core::String? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        :return_value = "a";
+        break #L2;
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsFutureOrString() → asy::Future<core::String> /* originally async */ {
+  final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+  core::bool* :is_sync = false;
+  FutureOr<core::String>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        :return_value = self::getFutureOr<core::String>("a");
+        break #L3;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsAwaitFutureOrString() → asy::Future<core::String> /* originally async */ {
+  final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+  core::bool* :is_sync = false;
+  core::String? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L4:
+      {
+        [yield] let dynamic #t11 = asy::_awaitHelper(self::getFutureOr<core::String>("a"), :async_op_then, :async_op_error, :async_op) in null;
+        :return_value = _in::unsafeCast<core::String>(:result);
+        break #L4;
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsFutureString() → asy::Future<core::String> /* originally async */ {
+  final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+  core::bool* :is_sync = false;
+  FutureOr<core::String>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L5:
+      {
+        :return_value = self::getFuture<core::String>("a");
+        break #L5;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsAwaitFutureString() → FutureOr<core::String> /* originally async */ {
+  final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
+  core::bool* :is_sync = false;
+  core::String? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L6:
+      {
+        [yield] let dynamic #t12 = asy::_awaitHelper(self::getFuture<core::String>("a"), :async_op_then, :async_op_error, :async_op) in null;
+        :return_value = _in::unsafeCast<core::String>(:result);
+        break #L6;
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsObject() → asy::Future<core::Object> /* originally async */ {
+  final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+  core::bool* :is_sync = false;
+  FutureOr<core::Object>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L7:
+      {
+        :return_value = new core::Object::•();
+        break #L7;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsFutureOrObject() → asy::Future<core::Object> /* originally async */ {
+  final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+  core::bool* :is_sync = false;
+  FutureOr<core::Object>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L8:
+      {
+        :return_value = self::getFutureOr<core::Object>(new core::Object::•());
+        break #L8;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsAwaitFutureOrObject() → asy::Future<core::Object> /* originally async */ {
+  final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+  core::bool* :is_sync = false;
+  FutureOr<core::Object>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L9:
+      {
+        [yield] let dynamic #t13 = asy::_awaitHelper(self::getFutureOr<core::Object>(new core::Object::•()), :async_op_then, :async_op_error, :async_op) in null;
+        :return_value = _in::unsafeCast<core::Object>(:result);
+        break #L9;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsFutureObject() → asy::Future<core::Object> /* originally async */ {
+  final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+  core::bool* :is_sync = false;
+  FutureOr<core::Object>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L10:
+      {
+        :return_value = self::getFuture<core::Object>(new core::Object::•());
+        break #L10;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method returnsAwaitFutureObject() → FutureOr<core::Object> /* originally async */ {
+  final asy::_Future<core::Object> :async_future = new asy::_Future::•<core::Object>();
+  core::bool* :is_sync = false;
+  FutureOr<core::Object>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L11:
+      {
+        [yield] let dynamic #t14 = asy::_awaitHelper(self::getFuture<core::Object>(new core::Object::•()), :async_op_then, :async_op_error, :async_op) in null;
+        :return_value = _in::unsafeCast<core::Object>(:result);
+        break #L11;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method getFutureOr<T extends core::Object? = dynamic>(self::getFutureOr::T% v) → FutureOr<self::getFutureOr::T%> /* originally async */ {
+  final asy::_Future<self::getFutureOr::T%> :async_future = new asy::_Future::•<self::getFutureOr::T%>();
+  core::bool* :is_sync = false;
+  FutureOr<self::getFutureOr::T%>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L12:
+      {
+        :return_value = v;
+        break #L12;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method getFuture<T extends core::Object? = dynamic>(self::getFuture::T% v) → asy::Future<self::getFuture::T%> /* originally async */ {
+  final asy::_Future<self::getFuture::T%> :async_future = new asy::_Future::•<self::getFuture::T%>();
+  core::bool* :is_sync = false;
+  FutureOr<self::getFuture::T%>? :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L13:
+      {
+        :return_value = v;
+        break #L13;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
diff --git a/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect
index c05a8b5..7e77550 100644
--- a/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_method_with_invalid_type.dart.weak.transformed.expect
@@ -13,7 +13,7 @@
 static method foo() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -24,7 +24,7 @@
       {
         invalid-type x;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
index 758329d..ef502e2 100644
--- a/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
@@ -30,7 +30,7 @@
 static method main() → void /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -62,7 +62,7 @@
           throw "Expected '${expected}' but got '${actual}'";
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/await.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await.dart.weak.transformed.expect
index 6107389..7fd936b 100644
--- a/pkg/front_end/testcases/general/await.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -20,7 +20,7 @@
         [yield] let dynamic #t1 = asy::_awaitHelper("Hello, World!", :async_op_then, :async_op_error, :async_op) in null;
         core::print(_in::unsafeCast<core::String*>(:result));
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
index 087766ec..22900f0 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
@@ -59,7 +59,7 @@
 static method staticMembers() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -100,7 +100,7 @@
         core::num* e = _in::unsafeCast<core::int*>(:async_temporary_5).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
         self::expect(5, e);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -115,7 +115,7 @@
 static method topLevelMembers() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -151,7 +151,7 @@
         core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
         self::expect(5, e);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -166,7 +166,7 @@
 static method instanceMembers() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -203,7 +203,7 @@
         core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
         self::expect(5, e);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -218,7 +218,7 @@
 static method others() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -255,7 +255,7 @@
         core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*};
         self::expect(2, e);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -270,7 +270,7 @@
 static method conditionals() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -327,7 +327,7 @@
         on dynamic catch(final dynamic e) {
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -342,7 +342,7 @@
 static method asserts() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -400,7 +400,7 @@
           }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -415,7 +415,7 @@
 static method controlFlow() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -681,7 +681,7 @@
           }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -758,7 +758,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -785,7 +785,7 @@
           :result;
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect
index 0372529..3dce525 100644
--- a/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await_in_cascade.dart.weak.transformed.expect
@@ -13,7 +13,7 @@
   method m() → asy::Future<core::List<core::int*>*>* /* originally async */ {
     final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
     core::bool* :is_sync = false;
-    FutureOr<core::List<core::int*>*>* :return_value;
+    core::List<core::int*>? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -29,7 +29,7 @@
           :return_value = block {} =>#t1;
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -44,7 +44,7 @@
   method _m() → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -56,7 +56,7 @@
           :return_value = 42;
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -82,7 +82,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -95,7 +95,7 @@
         [yield] let dynamic #t3 = asy::_awaitHelper(new self::C::•().{self::C::m}(){() →* asy::Future<core::List<core::int*>*>*}, :async_op_then, :async_op_error, :async_op) in null;
         self::expect(42, _in::unsafeCast<core::List<core::int*>*>(:result).{core::Iterable::first}{core::int*});
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect b/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect
index 3d71e92..1345153 100644
--- a/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33196.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
 static method returnsString() → FutureOr<core::String*>* /* originally async */ {
   final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
   core::bool* :is_sync = false;
-  FutureOr<core::String*>* :return_value;
+  core::String? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -24,7 +24,7 @@
         :return_value = "oh no";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect b/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
index 85541c5..8f45939 100644
--- a/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
@@ -43,7 +43,7 @@
 static method f1() → asy::Future<core::List<core::Object*>*>* /* originally async */ {
   final asy::_Future<core::List<core::Object*>*>* :async_future = new asy::_Future::•<core::List<core::Object*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::List<core::Object*>*>* :return_value;
+  core::List<core::Object*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -55,7 +55,7 @@
         :return_value = core::_GrowableList::_literal1<core::Object*>(1);
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -72,7 +72,7 @@
 static method f3() → asy::Future<core::Object*>* /* originally async */ {
   final asy::_Future<core::Object*>* :async_future = new asy::_Future::•<core::Object*>();
   core::bool* :is_sync = false;
-  FutureOr<core::Object*>* :return_value;
+  core::Object? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -84,7 +84,7 @@
         :return_value = 3;
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -99,7 +99,7 @@
 static method foo() → asy::Future<self::X*>* /* originally async */ {
   final asy::_Future<self::X*>* :async_future = new asy::_Future::•<self::X*>();
   core::bool* :is_sync = false;
-  FutureOr<self::X*>* :return_value;
+  self::X? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -120,7 +120,7 @@
         :return_value = new self::X::•(_in::unsafeCast<self::Y*>(:async_temporary_0), _in::unsafeCast<core::Object*>(:result));
         break #L3;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -135,7 +135,7 @@
 static method main() → asy::Future<void>* /* originally async */ {
   final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>* :return_value;
+  void :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -148,7 +148,7 @@
         [yield] let dynamic #t4 = asy::_awaitHelper(self::foo(), :async_op_then, :async_op_error, :async_op) in null;
         core::print(_in::unsafeCast<self::X*>(:result));
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect b/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect
index 0a550d4..5c69330 100644
--- a/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/check_deferred_before_args2.dart.weak.transformed.expect
@@ -10,7 +10,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -24,7 +24,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(LoadLibrary(lib), :async_op_then, :async_op_error, :async_op) in null;
         def::m(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect
index 59854bd..e74ebe2 100644
--- a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.weak.transformed.expect
@@ -1946,7 +1946,7 @@
 static method testForElementErrors(core::Map<core::int*, core::int*>* map, core::List<core::int*>* list) → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -2481,7 +2481,7 @@
           #t293.{core::Map::[]=}{Invariant}("baz", null){(core::String*, core::int*) →* void};
         } =>#t293;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect
index d223493..cd22de9 100644
--- a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.weak.transformed.expect
@@ -19,7 +19,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -60,7 +60,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.expect b/pkg/front_end/testcases/general/external_import.dart.weak.expect
index 0d7662f..5e7e2df 100644
--- a/pkg/front_end/testcases/general/external_import.dart.weak.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.weak.expect
@@ -37,5 +37,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///external_import.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect b/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect
index 0d7662f..5e7e2df 100644
--- a/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.weak.modular.expect
@@ -37,5 +37,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///external_import.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect b/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect
index 0d7662f..5e7e2df 100644
--- a/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.weak.transformed.expect
@@ -37,5 +37,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///external_import.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect b/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect
index cae05ae..946e531 100644
--- a/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/flutter_issue64155.dart.weak.transformed.expect
@@ -116,7 +116,7 @@
   method test(covariant-by-class asy::Future<self::Response<core::String*>*>* fetch) → asy::Future<core::String*>* /* originally async */ {
     final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
     core::bool* :is_sync = false;
-    FutureOr<core::String*>* :return_value;
+    core::String? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -146,7 +146,7 @@
           :return_value = result;
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -185,7 +185,7 @@
   method test(covariant-by-class asy::Future<self::PagingResponse<core::String*>*>* fetch) → asy::Future<core::String*>* /* originally async */ {
     final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
     core::bool* :is_sync = false;
-    FutureOr<core::String*>* :return_value;
+    core::String? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -215,7 +215,7 @@
           :return_value = result;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect b/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect
index d6d5aa0..f0fb90b 100644
--- a/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/future_return.dart.weak.transformed.expect
@@ -45,7 +45,7 @@
 static method returnClass() → self::Class* /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -57,7 +57,7 @@
         :return_value = new self::Class::•();
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -72,7 +72,7 @@
 static method returnFutureClass() → asy::Future<self::Class*>* /* originally async */ {
   final asy::_Future<self::Class*>* :async_future = new asy::_Future::•<self::Class*>();
   core::bool* :is_sync = false;
-  FutureOr<self::Class*>* :return_value;
+  self::Class? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -84,7 +84,7 @@
         :return_value = new self::Class::•();
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -99,7 +99,7 @@
 static method returnFutureOrClass() → FutureOr<self::Class*>* /* originally async */ {
   final asy::_Future<self::Class*>* :async_future = new asy::_Future::•<self::Class*>();
   core::bool* :is_sync = false;
-  FutureOr<self::Class*>* :return_value;
+  self::Class? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -111,7 +111,7 @@
         :return_value = new self::Class::•();
         break #L3;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -369,7 +369,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -404,7 +404,7 @@
         [yield] let dynamic #t12 = asy::_awaitHelper(self::returnFutureOrClassFromFutureOrClass(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<self::Class*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect
index b9327a2..ae34a36 100644
--- a/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/issue38253c.dart.weak.transformed.expect
@@ -27,7 +27,7 @@
   function f2() → invalid-type /* originally async */ {
     final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -36,7 +36,7 @@
       try {
         #L1:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect
index ba98fca..be46445 100644
--- a/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/issue46956.dart.weak.transformed.expect
@@ -17,7 +17,7 @@
 static method test(self::A<core::String> a) → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
         final core::String? x = _in::unsafeCast<core::String?>(:result);
         self::bar(x);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect b/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect
index e545ab0..983f3d4 100644
--- a/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/no_such_method_forwarder.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
   method _foo() → void /* originally async */ {
     final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -25,7 +25,7 @@
           _in::unsafeCast<Null>(:result);
           core::print("hello");
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect b/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
index 3d879b8..3c53c2b 100644
--- a/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
   method foo(dynamic x) → asy::Future<void>* /* originally async */ {
     final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
     core::bool* :is_sync = false;
-    FutureOr<void>* :return_value;
+    void :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -20,7 +20,7 @@
       try {
         #L1:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -50,7 +50,7 @@
   method bar(dynamic x) → asy::Future<void>* /* originally async */ {
     final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
     core::bool* :is_sync = false;
-    FutureOr<void>* :return_value;
+    void :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
       try {
         #L2:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -85,7 +85,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -105,7 +105,7 @@
         :return_value = core::_GrowableList::_literal2<asy::Future<void>*>(_in::unsafeCast<asy::Future<void>*>(:async_temporary_1), _in::unsafeCast<self::B*>(:async_temporary_0).{self::B::bar}(_in::unsafeCast<Null>(:result)){(dynamic) →* asy::Future<void>*});
         break #L3;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect b/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect
index f6ea477..99d4140 100644
--- a/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/stream_future.dart.weak.transformed.expect
@@ -37,7 +37,7 @@
 static method returnFutureDynamic() → asy::Future<dynamic>* /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -49,7 +49,7 @@
         :return_value = new self::Class::•();
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -64,7 +64,7 @@
 static method returnFutureClass() → asy::Future<self::Class*>* /* originally async */ {
   final asy::_Future<self::Class*>* :async_future = new asy::_Future::•<self::Class*>();
   core::bool* :is_sync = false;
-  FutureOr<self::Class*>* :return_value;
+  self::Class? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -76,7 +76,7 @@
         :return_value = new self::Class::•();
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -169,7 +169,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -206,7 +206,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect
index e955e1e..1bb3512 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.1.expect
@@ -4,7 +4,7 @@
   static method whatever() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -19,7 +19,7 @@
           :return_value = "hello";
           break #L1;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -56,7 +56,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -70,7 +70,7 @@
           :result;
           dart.core::print(#C2);
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect
index 4f65073..6a2982c 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_3.yaml.world.2.expect
@@ -4,7 +4,7 @@
   static method whatever() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -19,7 +19,7 @@
           :return_value = "hello";
           break #L1;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -56,7 +56,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -71,7 +71,7 @@
           dart.core::print(#C2);
           dart.core::print("Done");
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect
index 5d54f1b..9d83b08 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.1.expect
@@ -22,7 +22,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -36,7 +36,7 @@
           :result;
           dart.core::print(#C2);
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -51,7 +51,7 @@
   static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -66,7 +66,7 @@
           :return_value = "hello";
           break #L2;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect
index d857553..d0bec69 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.2.expect
@@ -22,7 +22,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -36,7 +36,7 @@
           :result;
           dart.core::print(#C2);
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -51,7 +51,7 @@
   static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -66,7 +66,7 @@
           :return_value = "hello!!!";
           break #L2;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect
index 8da36e7..d9b9b9f 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_5.yaml.world.3.expect
@@ -22,7 +22,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -37,7 +37,7 @@
           dart.core::print(#C2);
           dart.core::print("Done!");
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
@@ -52,7 +52,7 @@
   static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
     dart.core::int* :await_jump_var = 0;
@@ -67,7 +67,7 @@
           :return_value = "hello!!!";
           break #L2;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
index cf7f401..8c98fe7 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
@@ -59,6 +59,7 @@
   ffi::DynamicLibrary,
   ffi::DynamicLibraryExtension,
   ffi::FfiNative,
+  ffi::Finalizable,
   ffi::Float,
   ffi::FloatArray,
   ffi::FloatPointer,
@@ -148,6 +149,7 @@
   ffi::DynamicLibrary,
   ffi::DynamicLibraryExtension,
   ffi::FfiNative,
+  ffi::Finalizable,
   ffi::Float,
   ffi::FloatArray,
   ffi::FloatPointer,
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
index cb6c619..820c44b 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
@@ -59,6 +59,7 @@
   ffi::DynamicLibrary,
   ffi::DynamicLibraryExtension,
   ffi::FfiNative,
+  ffi::Finalizable,
   ffi::Float,
   ffi::FloatArray,
   ffi::FloatPointer,
@@ -148,6 +149,7 @@
   ffi::DynamicLibrary,
   ffi::DynamicLibraryExtension,
   ffi::FfiNative,
+  ffi::Finalizable,
   ffi::Float,
   ffi::FloatArray,
   ffi::FloatPointer,
diff --git a/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect
index 919ede4..7072277 100644
--- a/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_await.dart.weak.transformed.expect
@@ -29,7 +29,7 @@
 static method test() → void /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
         function test0() → asy::Future<core::int*>* /* originally async */ {
           final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
           core::bool* :is_sync = false;
-          FutureOr<core::int*>* :return_value;
+          core::int? :return_value;
           (dynamic) →* dynamic :async_op_then;
           (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
           core::int* :await_jump_var = 0;
@@ -64,7 +64,7 @@
                 :return_value = x0;
                 break #L2;
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -340,7 +340,7 @@
         [yield] let dynamic #t10 = asy::_awaitHelper(x9, :async_op_then, :async_op_error, :async_op) in null;
         core::int* y9 = _in::unsafeCast<core::int*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect
index 02f5546..d131af3 100644
--- a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 static field () →* asy::Future<core::int*>* f = () → asy::Future<core::int*>* /* originally async */ {
   final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
   core::bool* :is_sync = false;
-  FutureOr<core::int*>* :return_value;
+  core::int? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -18,7 +18,7 @@
         :return_value = 0;
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect
index 946c0ba..33452c2 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
   () →* asy::Future<core::num*>* f = () → asy::Future<core::num*>* /* originally async */ {
     final asy::_Future<core::num*>* :async_future = new asy::_Future::•<core::num*>();
     core::bool* :is_sync = false;
-    FutureOr<core::num*>* :return_value;
+    core::num? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -29,7 +29,7 @@
             break #L1;
           }
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect
index 2f681c5..1ca076e 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -51,7 +51,7 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(f(){() →* asy::Future<Null>*}, :async_op_then, :async_op_error, :async_op) in null;
         core::String* s = _in::unsafeCast<Null>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect
index fbf4bc7..0b66184 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -57,7 +57,7 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(f(){() →* asy::Stream<Null>*}.{asy::Stream::first}{asy::Future<Null>*}, :async_op_then, :async_op_error, :async_op) in null;
         core::String* s = _in::unsafeCast<Null>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect
index 0b4c6aa..ef028bb 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
 static method main() → asy::Future<dynamic>* /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -25,7 +25,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(d as{TypeError,ForDynamic} core::int*)), :async_op_then, :async_op_error, :async_op) in null;
         core::List<core::int*>* l1 = _in::unsafeCast<core::List<core::int*>*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect
index acaf1c5..f7624fe 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.weak.transformed.expect
@@ -62,7 +62,7 @@
 static method f() → asy::Future<dynamic>* /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -226,7 +226,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -241,7 +241,7 @@
 static method main() → asy::Future<dynamic>* /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -318,7 +318,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect
index e4fd3e1..b47ff66 100644
--- a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -83,7 +83,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect
index ab96b76..6786a24 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   asy::Future<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   asy::Future<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect
index bffba5e..2f74e115 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   asy::Future<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   asy::Future<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect
index 37463d1..7decc2d 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   self::MyFuture<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   self::MyFuture<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect
index 90f1db4..6bc3b03 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   self::MyFuture<core::int*>* t3 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   self::MyFuture<core::int*>* t4 = f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect
index 39baeba..4971cd6 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   asy::Future<core::int*>* t3 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   asy::Future<core::int*>* t4 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect
index 6a2855eb..7cffed8 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -52,7 +52,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -67,7 +67,7 @@
   asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -81,7 +81,7 @@
           :return_value = _in::unsafeCast<core::int*>(:result);
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -96,7 +96,7 @@
   asy::Future<core::int*>* t3 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
           :return_value = 3;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
   asy::Future<core::int*>* t4 = f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
           :return_value = 3;
           break #L4;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
index 204dbee..be1084c 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
index 608046f..4327ac5 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
index e32c9fb..477a406 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
index 02b3b6b..0211604 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
index e0176fc..6759525 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
index 9fb5822..877ea634 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
index bf8be62..2716550 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -60,7 +60,7 @@
           :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect
index 3145f91..955a495 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.weak.transformed.expect
@@ -47,7 +47,7 @@
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::List<core::int*>*>* :return_value;
+  core::List<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
         :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect
index 0bdd40c..9c426f7 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::List<core::int*>*>* :return_value;
+  core::List<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -50,7 +50,7 @@
         :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect
index 925b980..09a8df9 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.weak.transformed.expect
@@ -47,7 +47,7 @@
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::List<core::int*>*>* :return_value;
+  core::List<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -59,7 +59,7 @@
         :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect
index e0915b4..35a7372 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::List<core::int*>*>* :return_value;
+  core::List<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -50,7 +50,7 @@
         :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect
index ced25c9..e617289 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.weak.transformed.expect
@@ -24,7 +24,7 @@
 static method foo() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -39,7 +39,7 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::wait<core::List<self::A*>*>(core::_GrowableList::_literal2<asy::Future<core::List<self::A*>*>*>(f1, f2)), :async_op_then, :async_op_error, :async_op) in null;
         core::List<core::List<self::A*>*>* merged = _in::unsafeCast<core::List<core::List<self::A*>*>>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect
index ebe5e12..241a603 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -25,7 +25,7 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(self::id<FutureOr<core::String*>*>(f), :async_op_then, :async_op_error, :async_op) in null;
         core::String* s = _in::unsafeCast<core::String*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect
index edb2427..3e7e7b1 100644
--- a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.weak.transformed.expect
@@ -34,7 +34,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -54,7 +54,7 @@
         core::List<self::A*>* list = result;
         list = result2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect
index 3715d17..9c54557 100644
--- a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.weak.transformed.expect
@@ -9,7 +9,7 @@
   function f1() → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -21,7 +21,7 @@
           :return_value = 42;
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -39,7 +39,7 @@
   function f3() → asy::Future<core::int*>* /* originally async */ {
     final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
     core::bool* :is_sync = false;
-    FutureOr<core::int*>* :return_value;
+    core::int? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -51,7 +51,7 @@
           :return_value = 42;
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect
index fef5b28..8eee676 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.weak.transformed.expect
@@ -58,7 +58,7 @@
   method foo(covariant-by-class self::Bar::T* t) → dynamic /* originally async */ {
     final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -97,7 +97,7 @@
               }
           }
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -127,7 +127,7 @@
   method foo(covariant-by-class self::Baz::S* t) → dynamic /* originally async */ {
     final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>* :return_value;
+    dynamic :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -167,7 +167,7 @@
               }
           }
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -244,7 +244,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -440,7 +440,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect
index aa020dd..dfc471b 100644
--- a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.weak.transformed.expect
@@ -30,7 +30,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -122,7 +122,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect
index 2ad99fc..356e2de 100644
--- a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.weak.transformed.expect
@@ -46,7 +46,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -201,7 +201,7 @@
             }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
index 079f495..5b963bf 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
@@ -139,7 +139,7 @@
 static method hest() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -178,7 +178,7 @@
         :return_value = "hest";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -193,7 +193,7 @@
 static method fisk() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -250,7 +250,7 @@
         function #f#set(core::Function f#param) → dynamic
           return #f = f#param;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
index c43553e..c376454 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
@@ -159,7 +159,7 @@
 static method hest() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -198,7 +198,7 @@
         :return_value = "hest";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -213,7 +213,7 @@
 static method fisk() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -294,7 +294,7 @@
           return #f = f#param;
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
index 4d771b3..e5c093e 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect
@@ -25,5 +25,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
index f3903c0..de205ad 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect
@@ -52,5 +52,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
index e179ab5..ec86fcc 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect
@@ -25,5 +25,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect
index e179ab5..ec86fcc 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect
@@ -25,5 +25,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
index 24cfa96..77e3dbf 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect
@@ -52,5 +52,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect
index dd7fa30..f82c29d 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect
@@ -33,5 +33,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect
index a16945b..d5ddd95 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect
@@ -84,5 +84,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect
index be09548..d33f1a0 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect
@@ -33,5 +33,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect
index be09548..d33f1a0 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect
@@ -33,5 +33,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect
index a83a86b..6a4db26 100644
--- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect
@@ -84,5 +84,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
-- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9)
+- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:140:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
index 4d55755..64a9400 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
@@ -76,7 +76,7 @@
   method test(covariant-by-class asy::Future<self::Response<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
     final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
     core::bool* :is_sync = false;
-    FutureOr<core::String>? :return_value;
+    core::String? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -106,7 +106,7 @@
           :return_value = result;
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -135,7 +135,7 @@
   method test(covariant-by-class asy::Future<self::PagingResponse<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
     final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
     core::bool* :is_sync = false;
-    FutureOr<core::String>? :return_value;
+    core::String? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
           :return_value = result;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
index 4d55755..64a9400 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
@@ -76,7 +76,7 @@
   method test(covariant-by-class asy::Future<self::Response<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
     final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
     core::bool* :is_sync = false;
-    FutureOr<core::String>? :return_value;
+    core::String? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -106,7 +106,7 @@
           :return_value = result;
           break #L2;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -135,7 +135,7 @@
   method test(covariant-by-class asy::Future<self::PagingResponse<core::String>> fetch) → asy::Future<core::String> /* originally async */ {
     final asy::_Future<core::String> :async_future = new asy::_Future::•<core::String>();
     core::bool* :is_sync = false;
-    FutureOr<core::String>? :return_value;
+    core::String? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
           :return_value = result;
           break #L3;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect
index 3864109..1ecce4a 100644
--- a/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41108.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -31,7 +31,7 @@
   List y = await l(); // should be a List?
            ^" in let core::List<dynamic>? #t2 = _in::unsafeCast<core::List<dynamic>?>(:result) in #t2 == null ?{core::List<dynamic>} #t2 as{TypeError,ForNonNullableByDefault} core::List<dynamic> : #t2{core::List<dynamic>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect
index 18ac50d..1a6d93f 100644
--- a/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41108.dart.weak.transformed.expect
@@ -15,7 +15,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -31,7 +31,7 @@
   List y = await l(); // should be a List?
            ^" in _in::unsafeCast<core::List<dynamic>?>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
index 9eb092b..ec795d3 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -20,7 +20,7 @@
         core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2 == null ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
         core::print(i);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
index 9eb092b..ec795d3 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -20,7 +20,7 @@
         core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2 == null ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
         core::print(i);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
index e3bb148..d45e990 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
@@ -85,7 +85,7 @@
   (core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
     core::bool* :is_sync = false;
-    FutureOr<Never>? :return_value;
+    Never? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -96,7 +96,7 @@
         {
           throw v;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -165,7 +165,7 @@
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
     core::bool* :is_sync = false;
-    FutureOr<Never>? :return_value;
+    Never? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -176,7 +176,7 @@
         {
           self::throwing();
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -219,7 +219,7 @@
 static method errors() → void /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -407,7 +407,7 @@
           return :async_future;
         };
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
index dbb0ff6..90dabf3 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
@@ -86,7 +86,7 @@
   (core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
     core::bool* :is_sync = false;
-    FutureOr<Never>? :return_value;
+    Never? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -97,7 +97,7 @@
         {
           throw v;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -166,7 +166,7 @@
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_Future<Never> :async_future = new asy::_Future::•<Never>();
     core::bool* :is_sync = false;
-    FutureOr<Never>? :return_value;
+    Never? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -177,7 +177,7 @@
         {
           let final Never #t5 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -220,7 +220,7 @@
 static method errors() → void /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -408,7 +408,7 @@
           return :async_future;
         };
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
index a53d4d3..ed3a3ca 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
@@ -63,7 +63,7 @@
 static method getFutureBool() → asy::Future<core::bool> /* originally async */ {
   final asy::_Future<core::bool> :async_future = new asy::_Future::•<core::bool>();
   core::bool* :is_sync = false;
-  FutureOr<core::bool>? :return_value;
+  core::bool? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -75,7 +75,7 @@
         :return_value = true;
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -186,7 +186,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -390,7 +390,7 @@
           return :async_future;
         })(){() → asy::Future<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
index a53d4d3..ed3a3ca 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
@@ -63,7 +63,7 @@
 static method getFutureBool() → asy::Future<core::bool> /* originally async */ {
   final asy::_Future<core::bool> :async_future = new asy::_Future::•<core::bool>();
   core::bool* :is_sync = false;
-  FutureOr<core::bool>? :return_value;
+  core::bool? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -75,7 +75,7 @@
         :return_value = true;
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -186,7 +186,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -390,7 +390,7 @@
           return :async_future;
         })(){() → asy::Future<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect
index f1dad02..8b27a53 100644
--- a/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437b.dart.strong.transformed.expect
@@ -145,7 +145,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -284,7 +284,7 @@
           return new core::_SyncIterable::•<core::bool>(:sync_op_gen);
         })(){() → core::Iterable<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect
index f1dad02..8b27a53 100644
--- a/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437b.dart.weak.transformed.expect
@@ -145,7 +145,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -284,7 +284,7 @@
           return new core::_SyncIterable::•<core::bool>(:sync_op_gen);
         })(){() → core::Iterable<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
index afdc269..995ecac 100644
--- a/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
@@ -225,7 +225,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -460,7 +460,7 @@
           return :controller_stream;
         })(){() → asy::Stream<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
index afdc269..995ecac 100644
--- a/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
@@ -225,7 +225,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -460,7 +460,7 @@
           return :controller_stream;
         })(){() → asy::Stream<core::bool>};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect
index 50a282e..ec6e4be 100644
--- a/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41602.dart.strong.transformed.expect
@@ -18,7 +18,7 @@
 static method returnFutureOfVoid() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -43,7 +43,7 @@
 static method returnVoidAsync() → void /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -52,7 +52,7 @@
     try {
       #L2:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -67,7 +67,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -82,7 +82,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::returnVoidAsync(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -97,7 +97,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -110,7 +110,7 @@
         [yield] let dynamic #t3 = asy::_awaitHelper(self::returnFutureOfVoid(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect
index 50a282e..ec6e4be 100644
--- a/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41602.dart.weak.transformed.expect
@@ -18,7 +18,7 @@
 static method returnFutureOfVoid() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -43,7 +43,7 @@
 static method returnVoidAsync() → void /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -52,7 +52,7 @@
     try {
       #L2:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -67,7 +67,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -82,7 +82,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::returnVoidAsync(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -97,7 +97,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -110,7 +110,7 @@
         [yield] let dynamic #t3 = asy::_awaitHelper(self::returnFutureOfVoid(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
index 5a264b1..b845eb9 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
@@ -37,7 +37,7 @@
   <S extends FutureOr<core::num>>(S, FutureOr<core::num>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num>>(S s, FutureOr<core::num>t) → asy::Future<core::num> /* originally async */ {
     final asy::_Future<core::num> :async_future = new asy::_Future::•<core::num>();
     core::bool* :is_sync = false;
-    FutureOr<core::num>? :return_value;
+    core::num? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -51,7 +51,7 @@
           :return_value = _in::unsafeCast<core::num>(:result).{core::num::+}(1){(core::num) → core::num};
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
index 5a264b1..b845eb9 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
@@ -37,7 +37,7 @@
   <S extends FutureOr<core::num>>(S, FutureOr<core::num>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num>>(S s, FutureOr<core::num>t) → asy::Future<core::num> /* originally async */ {
     final asy::_Future<core::num> :async_future = new asy::_Future::•<core::num>();
     core::bool* :is_sync = false;
-    FutureOr<core::num>? :return_value;
+    core::num? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -51,7 +51,7 @@
           :return_value = _in::unsafeCast<core::num>(:result).{core::num::+}(1){(core::num) → core::num};
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
index b810299..fe3f074 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
@@ -40,7 +40,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -85,7 +85,7 @@
           return :async_future;
         })(){() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>>} as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
index b810299..fe3f074 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
@@ -40,7 +40,7 @@
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -85,7 +85,7 @@
           return :async_future;
         })(){() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>>} as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
index 22760fa..ce05381 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -23,7 +23,7 @@
         (dynamic _) → asy::Future<core::int?> /* originally async */ {
           final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
           core::bool* :is_sync = false;
-          FutureOr<core::int?>? :return_value;
+          core::int? :return_value;
           (dynamic) → dynamic :async_op_then;
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
@@ -37,7 +37,7 @@
                   break #L2;
                 }
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -50,7 +50,7 @@
           return :async_future;
         };
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
index 22760fa..ce05381 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -23,7 +23,7 @@
         (dynamic _) → asy::Future<core::int?> /* originally async */ {
           final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
           core::bool* :is_sync = false;
-          FutureOr<core::int?>? :return_value;
+          core::int? :return_value;
           (dynamic) → dynamic :async_op_then;
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
@@ -37,7 +37,7 @@
                   break #L2;
                 }
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -50,7 +50,7 @@
           return :async_future;
         };
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect
index 122e031..83b083c 100644
--- a/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -32,7 +32,7 @@
           self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
         } =>#t2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect
index 122e031..83b083c 100644
--- a/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect
@@ -15,7 +15,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -32,7 +32,7 @@
           self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
         } =>#t2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
index 2885cb8..5d5407b 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
@@ -126,7 +126,7 @@
 static method hest() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
         :return_value = "hest";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -180,7 +180,7 @@
 static method fisk() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -231,7 +231,7 @@
           };
         late core::Function f = #f#initializer(){() → core::Function};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
index 2885cb8..5d5407b 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
@@ -126,7 +126,7 @@
 static method hest() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -165,7 +165,7 @@
         :return_value = "hest";
         break #L1;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -180,7 +180,7 @@
 static method fisk() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -231,7 +231,7 @@
           };
         late core::Function f = #f#initializer(){() → core::Function};
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
index 2a9f5d7..765a694 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
 static method allYield() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::allYield2(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -42,7 +42,7 @@
 static method allYield2() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
         [yield] let dynamic #t4 = asy::_awaitHelper(self::allYield3(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -72,7 +72,7 @@
 static method allYield3() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -86,7 +86,7 @@
         _in::unsafeCast<core::int>(:result);
         self::throwSync();
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -114,7 +114,7 @@
         asy::runZonedGuarded<asy::Future<Null>>(() → asy::Future<Null> /* originally async */ {
           final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
           core::bool* :is_sync = false;
-          FutureOr<Null>? :return_value;
+          Null :return_value;
           (dynamic) → dynamic :async_op_then;
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
@@ -128,7 +128,7 @@
                 _in::unsafeCast<void>(:result);
                 completer.{asy::Completer::complete}(null){([FutureOr<void>?]) → void};
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
index 2a9f5d7..765a694 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
 static method allYield() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -27,7 +27,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::allYield2(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -42,7 +42,7 @@
 static method allYield2() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
         [yield] let dynamic #t4 = asy::_awaitHelper(self::allYield3(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -72,7 +72,7 @@
 static method allYield3() → asy::Future<void> /* originally async */ {
   final asy::_Future<void> :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>? :return_value;
+  void :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -86,7 +86,7 @@
         _in::unsafeCast<core::int>(:result);
         self::throwSync();
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -114,7 +114,7 @@
         asy::runZonedGuarded<asy::Future<Null>>(() → asy::Future<Null> /* originally async */ {
           final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
           core::bool* :is_sync = false;
-          FutureOr<Null>? :return_value;
+          Null :return_value;
           (dynamic) → dynamic :async_op_then;
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
@@ -128,7 +128,7 @@
                 _in::unsafeCast<void>(:result);
                 completer.{asy::Completer::complete}(null){([FutureOr<void>?]) → void};
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
index d7034897..3686411 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
@@ -94,7 +94,7 @@
 static method returnAsync1() → asy::Future<dynamic> /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -103,7 +103,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -118,7 +118,7 @@
 static method returnAsync2() → FutureOr<dynamic> /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -127,7 +127,7 @@
     try {
       #L2:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -171,7 +171,7 @@
 static method returnAsync4() → FutureOr<core::int?> /* originally async */ {
   final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
   core::bool* :is_sync = false;
-  FutureOr<core::int?>? :return_value;
+  core::int? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -180,7 +180,7 @@
     try {
       #L4:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -195,7 +195,7 @@
 static method returnAsync5() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -204,7 +204,7 @@
     try {
       #L5:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -246,7 +246,7 @@
 static method returnAsync7() → asy::Future<core::int?> /* originally async */ {
   final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
   core::bool* :is_sync = false;
-  FutureOr<core::int?>? :return_value;
+  core::int? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -255,7 +255,7 @@
     try {
       #L7:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -362,7 +362,7 @@
   function returnAsync1() → asy::Future<dynamic> /* originally async */ {
     final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -371,7 +371,7 @@
       try {
         #L13:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -386,7 +386,7 @@
   function returnAsync2() → FutureOr<dynamic> /* originally async */ {
     final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -395,7 +395,7 @@
       try {
         #L14:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -439,7 +439,7 @@
   function returnAsync4() → FutureOr<core::int?> /* originally async */ {
     final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
     core::bool* :is_sync = false;
-    FutureOr<core::int?>? :return_value;
+    core::int? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -448,7 +448,7 @@
       try {
         #L16:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -463,7 +463,7 @@
   function returnAsync5() → asy::Future<Null> /* originally async */ {
     final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
     core::bool* :is_sync = false;
-    FutureOr<Null>? :return_value;
+    Null :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -472,7 +472,7 @@
       try {
         #L17:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -514,7 +514,7 @@
   function returnAsync7() → asy::Future<core::int?> /* originally async */ {
     final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
     core::bool* :is_sync = false;
-    FutureOr<core::int?>? :return_value;
+    core::int? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -523,7 +523,7 @@
       try {
         #L19:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
index 7f20e82..081a23c 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
@@ -95,7 +95,7 @@
 static method returnAsync1() → asy::Future<dynamic> /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -104,7 +104,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -119,7 +119,7 @@
 static method returnAsync2() → FutureOr<dynamic> /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -128,7 +128,7 @@
     try {
       #L2:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -172,7 +172,7 @@
 static method returnAsync4() → FutureOr<core::int?> /* originally async */ {
   final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
   core::bool* :is_sync = false;
-  FutureOr<core::int?>? :return_value;
+  core::int? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -181,7 +181,7 @@
     try {
       #L4:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -196,7 +196,7 @@
 static method returnAsync5() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -205,7 +205,7 @@
     try {
       #L5:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -247,7 +247,7 @@
 static method returnAsync7() → asy::Future<core::int?> /* originally async */ {
   final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
   core::bool* :is_sync = false;
-  FutureOr<core::int?>? :return_value;
+  core::int? :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -256,7 +256,7 @@
     try {
       #L7:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -366,7 +366,7 @@
   function returnAsync1() → asy::Future<dynamic> /* originally async */ {
     final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -375,7 +375,7 @@
       try {
         #L14:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -390,7 +390,7 @@
   function returnAsync2() → FutureOr<dynamic> /* originally async */ {
     final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
     core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -399,7 +399,7 @@
       try {
         #L15:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -443,7 +443,7 @@
   function returnAsync4() → FutureOr<core::int?> /* originally async */ {
     final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
     core::bool* :is_sync = false;
-    FutureOr<core::int?>? :return_value;
+    core::int? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -452,7 +452,7 @@
       try {
         #L17:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -467,7 +467,7 @@
   function returnAsync5() → asy::Future<Null> /* originally async */ {
     final asy::_Future<Null> :async_future = new asy::_Future::•<Null>();
     core::bool* :is_sync = false;
-    FutureOr<Null>? :return_value;
+    Null :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -476,7 +476,7 @@
       try {
         #L18:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -518,7 +518,7 @@
   function returnAsync7() → asy::Future<core::int?> /* originally async */ {
     final asy::_Future<core::int?> :async_future = new asy::_Future::•<core::int?>();
     core::bool* :is_sync = false;
-    FutureOr<core::int?>? :return_value;
+    core::int? :return_value;
     (dynamic) → dynamic :async_op_then;
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
@@ -527,7 +527,7 @@
       try {
         #L20:
         {}
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect
index 96460c4..160716b 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41602.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
 static method returnFutureOfVoid() → asy::Future<void>* /* originally async */ {
   final asy::_Future<void>* :async_future = new asy::_Future::•<void>();
   core::bool* :is_sync = false;
-  FutureOr<void>* :return_value;
+  void :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -16,7 +16,7 @@
     try {
       #L1:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -32,7 +32,7 @@
 static method returnVoidAsync() → void /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -41,7 +41,7 @@
     try {
       #L2:
       {}
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -56,7 +56,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -73,7 +73,7 @@
         [yield] let dynamic #t3 = asy::_awaitHelper(self::returnVoidAsync(), :async_op_then, :async_op_error, :async_op) in null;
         _in::unsafeCast<void>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
index dcba0f6..1f53e96 100644
--- a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
@@ -10,7 +10,7 @@
   return (typ::Request* r) → asy::Future<typ::Response*>* /* originally async */ {
     final asy::_Future<typ::Response*>* :async_future = new asy::_Future::•<typ::Response*>();
     core::bool* :is_sync = false;
-    FutureOr<typ::Response*>* :return_value;
+    typ::Response? :return_value;
     (dynamic) →* dynamic :async_op_then;
     (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
     core::int* :await_jump_var = 0;
@@ -22,7 +22,7 @@
           :return_value = new typ::Response::•();
           break #L1;
         }
-        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect
index 7670aed..b24cb95 100644
--- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.expect
@@ -42,5 +42,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///native_is_illegal.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect
index 7670aed..b24cb95 100644
--- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.modular.expect
@@ -42,5 +42,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///native_is_illegal.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect
index 7670aed..b24cb95 100644
--- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.weak.transformed.expect
@@ -42,5 +42,5 @@
 
 Constructor coverage from constants:
 org-dartlang-testcase:///native_is_illegal.dart:
-- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:109:9)
 - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect
index d3211c4..b4b664d 100644
--- a/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.weak.transformed.expect
@@ -116,7 +116,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -132,7 +132,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper(self::f3(), :async_op_then, :async_op_error, :async_op) in null;
         core::print(_in::unsafeCast<invalid-type>(:result));
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect
index 8e89457..63a99de 100644
--- a/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_37681.dart.weak.transformed.expect
@@ -22,7 +22,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -38,7 +38,7 @@
         function f_async() → core::int* /* originally async */ {
           final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
           core::bool* :is_sync = false;
-          FutureOr<dynamic>* :return_value;
+          dynamic :return_value;
           (dynamic) →* dynamic :async_op_then;
           (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
           core::int* :await_jump_var = 0;
@@ -50,7 +50,7 @@
                 :return_value = 42;
                 break #L2;
               }
-              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
               return;
             }
             on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -147,7 +147,7 @@
           }
         }
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect
index ee407a3..9262980 100644
--- a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>* :return_value;
+  dynamic :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -108,7 +108,7 @@
         [yield] let dynamic #t13 = asy::_awaitHelper(self::lhmfun2(), :async_op_then, :async_op_error, :async_op) in null;
         col::LinkedHashMap<core::int*, core::bool*>* flhm2 = _in::unsafeCast<col::LinkedHashMap<core::int*, core::bool*>*>(:result);
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -123,7 +123,7 @@
 static method mapfun() → asy::Future<core::Map<core::int*, core::bool*>*>* /* originally async */ {
   final asy::_Future<core::Map<core::int*, core::bool*>*>* :async_future = new asy::_Future::•<core::Map<core::int*, core::bool*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::Map<core::int*, core::bool*>*>* :return_value;
+  core::Map<core::int*, core::bool*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -135,7 +135,7 @@
         :return_value = <core::int*, core::bool*>{};
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -150,7 +150,7 @@
 static method setfun() → asy::Future<core::Set<core::int*>*>* /* originally async */ {
   final asy::_Future<core::Set<core::int*>*>* :async_future = new asy::_Future::•<core::Set<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::Set<core::int*>*>* :return_value;
+  core::Set<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -164,7 +164,7 @@
         } =>#t14;
         break #L3;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
@@ -179,7 +179,7 @@
 static method iterablefun() → asy::Future<core::Iterable<core::int*>*>* /* originally async */ {
   final asy::_Future<core::Iterable<core::int*>*>* :async_future = new asy::_Future::•<core::Iterable<core::int*>*>();
   core::bool* :is_sync = false;
-  FutureOr<core::Iterable<core::int*>*>* :return_value;
+  core::Iterable<core::int*>? :return_value;
   (dynamic) →* dynamic :async_op_then;
   (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
   core::int* :await_jump_var = 0;
@@ -193,7 +193,7 @@
         } =>#t15;
         break #L4;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
diff --git a/pkg/front_end/tool/_fasta/benchmark_visualiser.html b/pkg/front_end/tool/_fasta/benchmark_visualiser.html
new file mode 100644
index 0000000..f2e509b
--- /dev/null
+++ b/pkg/front_end/tool/_fasta/benchmark_visualiser.html
@@ -0,0 +1,78 @@
+<html>
+
+<head>
+  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
+  <script type="text/javascript">
+    google.charts.load('current', { 'packages': ['corechart'] });
+    google.charts.setOnLoadCallback(loaded);
+
+    function drawChart() {
+      var useLogarithmic = document.getElementById('chartLog').checked;
+      try {
+        var benchmarkdata = JSON.parse(document.getElementById('jsondata').value);
+      }
+      catch (e) {
+        document.getElementById('chart_div').innerHTML = "BAD JSON #0!" + e.message;
+        return;
+      }
+      var data = new google.visualization.DataTable();
+      data.addColumn('string', 'Phase');
+
+      var countBenchmarks = benchmarkdata.benchmarkers.length;
+      for (var i = 0; i < countBenchmarks; i++) {
+        data.addColumn('number', 'Run #' + (i + 1));
+      }
+
+      var phaseCount = benchmarkdata.benchmarkers[0].phases.length;
+      for (var i = 0; i < countBenchmarks; i++) {
+        if (benchmarkdata.benchmarkers[i].phases.length != phaseCount) {
+          document.getElementById('chart_div').innerHTML = "BAD JSON #1!";
+          return;
+        }
+      }
+
+      for (var j = 0; j < phaseCount; j++) {
+        var rowArray = [];
+        rowArray.push(benchmarkdata.benchmarkers[0].phases[j].phase);
+        for (var i = 0; i < countBenchmarks; i++) {
+          rowArray.push(benchmarkdata.benchmarkers[i].phases[j].runtime);
+          if (benchmarkdata.benchmarkers[i].phases[j].phase != rowArray[0]) {
+            document.getElementById('chart_div').innerHTML = "BAD JSON #2!";
+            return;
+          }
+        }
+        data.addRow(rowArray);
+      }
+
+      if (useLogarithmic) {
+        var options = {
+          vAxis: {
+            scaleType: 'log'
+          }
+        };
+      } else {
+        var options = {};
+      }
+
+      var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
+      chart.draw(data, options);
+    }
+
+    function loaded() {
+      document.getElementById('chartitbutton').disabled = false;
+    }
+  </script>
+</head>
+
+<body>
+  <textarea id="jsondata" rows="20" cols="80"></textarea>
+  <br />
+  <input type="checkbox" id="chartLog">
+  <label for="chartLog"> Use logarithmic scale</label>
+  <br />
+
+  <button id="chartitbutton" onclick="drawChart()" disabled>Chart it!</button>
+  <div id="chart_div" style="width:1200; height:900"></div>
+</body>
+
+</html>
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 24fad8f..822fced 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -4,16 +4,23 @@
 
 library fasta.tool.entry_points;
 
-import 'dart:convert' show LineSplitter, jsonDecode, jsonEncode, utf8;
+import 'dart:convert' show JsonEncoder, LineSplitter, jsonDecode, utf8;
 
 import 'dart:io' show File, Platform, exitCode, stderr, stdin, stdout;
 
+import 'dart:typed_data' show Uint8List;
+
 import 'package:_fe_analyzer_shared/src/util/relativize.dart'
     show isWindows, relativizeUri;
 
+import 'package:front_end/src/api_prototype/kernel_generator.dart';
+
 import 'package:front_end/src/fasta/fasta_codes.dart'
     show LocatedMessage, codeInternalProblemVerificationError;
 
+import 'package:front_end/src/fasta/kernel/benchmarker.dart'
+    show BenchmarkPhases, Benchmarker;
+
 import 'package:kernel/kernel.dart'
     show CanonicalName, Library, Component, Source, loadComponentFromBytes;
 
@@ -55,7 +62,11 @@
 
 import 'command_line.dart' show runProtectedFromAbort, withGlobalOptions;
 
-const bool summary = const bool.fromEnvironment("summary", defaultValue: false);
+const bool benchmark =
+    const bool.fromEnvironment("benchmark", defaultValue: false);
+
+const bool summary =
+    const bool.fromEnvironment("summary", defaultValue: false) || benchmark;
 
 const int iterations = const int.fromEnvironment("iterations", defaultValue: 1);
 
@@ -64,13 +75,20 @@
 
   // Timing results for each iteration
   List<double> elapsedTimes = <double>[];
+  List<Benchmarker> benchmarkers = <Benchmarker>[];
 
   for (int i = 0; i < iterations; i++) {
     if (i > 0) {
       print("\n\n=== Iteration ${i + 1} of $iterations");
     }
-    var stopwatch = new Stopwatch()..start();
-    await compile(arguments);
+    Stopwatch stopwatch = new Stopwatch()..start();
+    Benchmarker? benchmarker;
+    if (benchmark) {
+      benchmarker = new Benchmarker();
+      benchmarkers.add(benchmarker);
+    }
+    await compile(arguments, benchmarker: benchmarker);
+    benchmarker?.stop();
     stopwatch.stop();
 
     elapsedTimes.add(stopwatch.elapsedMilliseconds.toDouble());
@@ -80,20 +98,47 @@
     }
   }
 
-  if (summary) {
-    var json = jsonEncode(<String, dynamic>{'elapsedTimes': elapsedTimes});
-    print('\nSummary: $json');
-  }
+  summarize(elapsedTimes, benchmarkers);
 }
 
 Future<void> outlineEntryPoint(List<String> arguments) async {
   installAdditionalTargets();
 
+  // Timing results for each iteration
+  List<double> elapsedTimes = <double>[];
+  List<Benchmarker> benchmarkers = <Benchmarker>[];
+
   for (int i = 0; i < iterations; i++) {
     if (i > 0) {
-      print("\n");
+      print("\n\n=== Iteration ${i + 1} of $iterations");
     }
-    await outline(arguments);
+    Stopwatch stopwatch = new Stopwatch()..start();
+    Benchmarker? benchmarker;
+    if (benchmark) {
+      benchmarker = new Benchmarker();
+      benchmarkers.add(benchmarker);
+    }
+    await outline(arguments, benchmarker: benchmarker);
+    benchmarker?.stop();
+    stopwatch.stop();
+
+    elapsedTimes.add(stopwatch.elapsedMilliseconds.toDouble());
+  }
+
+  summarize(elapsedTimes, benchmarkers);
+}
+
+void summarize(List<double> elapsedTimes, List<Benchmarker> benchmarkers) {
+  if (summary) {
+    Map<String, dynamic> map = <String, dynamic>{
+      'elapsedTimes': elapsedTimes,
+      if (benchmarkers.isNotEmpty) 'benchmarkers': benchmarkers
+    };
+    JsonEncoder encoder = new JsonEncoder.withIndent("  ");
+    String json = encoder.convert(map);
+    print('\nSummary:\n\n$json\n');
+  } else {
+    assert(benchmarkers.isEmpty);
   }
 }
 
@@ -218,7 +263,8 @@
   });
 }
 
-Future<KernelTarget> outline(List<String> arguments) async {
+Future<KernelTarget> outline(List<String> arguments,
+    {Benchmarker? benchmarker}) async {
   return await runProtectedFromAbort<KernelTarget>(() async {
     return await withGlobalOptions("outline", arguments, true,
         (CompilerContext c, _) async {
@@ -228,12 +274,14 @@
       CompileTask task =
           new CompileTask(c, new Ticker(isVerbose: c.options.verbose));
       return await task.buildOutline(
-          output: c.options.output, omitPlatform: c.options.omitPlatform);
+          output: c.options.output,
+          omitPlatform: c.options.omitPlatform,
+          benchmarker: benchmarker);
     });
   });
 }
 
-Future<Uri> compile(List<String> arguments) async {
+Future<Uri> compile(List<String> arguments, {Benchmarker? benchmarker}) async {
   return await runProtectedFromAbort<Uri>(() async {
     return await withGlobalOptions("compile", arguments, true,
         (CompilerContext c, _) async {
@@ -242,7 +290,8 @@
       }
       CompileTask task =
           new CompileTask(c, new Ticker(isVerbose: c.options.verbose));
-      return await task.compile(omitPlatform: c.options.omitPlatform);
+      return await task.compile(
+          omitPlatform: c.options.omitPlatform, benchmarker: benchmarker);
     });
   });
 }
@@ -267,8 +316,10 @@
 
   CompileTask(this.c, this.ticker);
 
-  DillTarget createDillTarget(UriTranslator uriTranslator) {
-    return new DillTarget(ticker, uriTranslator, c.options.target);
+  DillTarget createDillTarget(UriTranslator uriTranslator,
+      {Benchmarker? benchmarker}) {
+    return new DillTarget(ticker, uriTranslator, c.options.target,
+        benchmarker: benchmarker);
   }
 
   KernelTarget createKernelTarget(
@@ -303,8 +354,10 @@
   Future<KernelTarget> buildOutline(
       {Uri? output,
       bool omitPlatform: false,
-      bool supportAdditionalDills: true}) async {
-    KernelTarget kernelTarget = await _createKernelTarget();
+      bool supportAdditionalDills: true,
+      Benchmarker? benchmarker}) async {
+    KernelTarget kernelTarget =
+        await _createKernelTarget(benchmarker: benchmarker);
     BuildResult buildResult = await _buildOutline(kernelTarget,
         output: output,
         omitPlatform: omitPlatform,
@@ -313,10 +366,11 @@
     return kernelTarget;
   }
 
-  Future<KernelTarget> _createKernelTarget() async {
+  Future<KernelTarget> _createKernelTarget({Benchmarker? benchmarker}) async {
     UriTranslator uriTranslator = await c.options.getUriTranslator();
     ticker.logMs("Read packages file");
-    DillTarget dillTarget = createDillTarget(uriTranslator);
+    DillTarget dillTarget =
+        createDillTarget(uriTranslator, benchmarker: benchmarker);
     return createKernelTarget(dillTarget, uriTranslator);
   }
 
@@ -325,19 +379,23 @@
       bool omitPlatform: false,
       bool supportAdditionalDills: true}) async {
     DillTarget dillTarget = kernelTarget.dillTarget;
+    Benchmarker? benchmarker = dillTarget.benchmarker;
 
     if (supportAdditionalDills) {
+      benchmarker?.enterPhase(BenchmarkPhases.loadSDK);
       Component? sdkSummary = await c.options.loadSdkSummary(null);
       if (sdkSummary != null) {
         dillTarget.loader.appendLibraries(sdkSummary);
       }
 
+      benchmarker?.enterPhase(BenchmarkPhases.loadAdditionalDills);
       CanonicalName nameRoot = sdkSummary?.root ?? new CanonicalName.root();
       for (Component additionalDill
           in await c.options.loadAdditionalDills(nameRoot)) {
         dillTarget.loader.appendLibraries(additionalDill);
       }
     } else {
+      benchmarker?.enterPhase(BenchmarkPhases.loadSDK);
       Component? sdkSummary = await c.options.loadSdkSummary(null);
       if (sdkSummary != null) {
         dillTarget.loader.appendLibraries(sdkSummary);
@@ -349,11 +407,13 @@
     BuildResult buildResult = await kernelTarget.buildOutlines();
     Component? outline = buildResult.component;
     if (c.options.debugDump && output != null) {
+      benchmarker?.enterPhase(BenchmarkPhases.printComponentText);
       printComponentText(outline,
           libraryFilter: kernelTarget.isSourceLibraryForDebugging);
     }
     if (output != null) {
       if (omitPlatform) {
+        benchmarker?.enterPhase(BenchmarkPhases.omitPlatform);
         outline!.computeCanonicalNames();
         Component userCode = new Component(
             nameRoot: outline.root,
@@ -368,16 +428,21 @@
         outline = userCode;
       }
 
+      benchmarker?.enterPhase(BenchmarkPhases.writeComponent);
       await writeComponentToFile(outline!, output);
       ticker.logMs("Wrote outline to ${output.toFilePath()}");
     }
+    benchmarker?.enterPhase(BenchmarkPhases.unknown);
     return buildResult;
   }
 
   Future<Uri> compile(
-      {bool omitPlatform: false, bool supportAdditionalDills: true}) async {
+      {bool omitPlatform: false,
+      bool supportAdditionalDills: true,
+      Benchmarker? benchmarker}) async {
     c.options.reportNullSafetyCompilationModeInfo();
-    KernelTarget kernelTarget = await _createKernelTarget();
+    KernelTarget kernelTarget =
+        await _createKernelTarget(benchmarker: benchmarker);
     BuildResult buildResult = await _buildOutline(kernelTarget,
         supportAdditionalDills: supportAdditionalDills);
     Uri uri = c.options.output!;
@@ -387,10 +452,12 @@
     buildResult.macroApplications?.close();
     Component component = buildResult.component!;
     if (c.options.debugDump) {
+      benchmarker?.enterPhase(BenchmarkPhases.printComponentText);
       printComponentText(component,
           libraryFilter: kernelTarget.isSourceLibraryForDebugging);
     }
     if (omitPlatform) {
+      benchmarker?.enterPhase(BenchmarkPhases.omitPlatform);
       component.computeCanonicalNames();
       Component userCode = new Component(
           nameRoot: component.root,
@@ -405,9 +472,11 @@
       component = userCode;
     }
     if (uri.scheme == "file") {
+      benchmarker?.enterPhase(BenchmarkPhases.writeComponent);
       await writeComponentToFile(component, uri);
       ticker.logMs("Wrote component to ${uri.toFilePath()}");
     }
+    benchmarker?.enterPhase(BenchmarkPhases.unknown);
     return uri;
   }
 }
@@ -415,8 +484,8 @@
 /// Load the [Component] from the given [uri] and append its libraries
 /// to the [dillTarget].
 Component _appendDillForUri(DillTarget dillTarget, Uri uri) {
-  var bytes = new File.fromUri(uri).readAsBytesSync();
-  var platformComponent = loadComponentFromBytes(bytes);
+  Uint8List bytes = new File.fromUri(uri).readAsBytesSync();
+  Component platformComponent = loadComponentFromBytes(bytes);
   dillTarget.loader.appendLibraries(platformComponent, byteCount: bytes.length);
   return platformComponent;
 }
@@ -439,7 +508,7 @@
     print("Compiling ${c.options.sdkRoot} to $fullOutput");
   }
 
-  var result =
+  CompilerResult result =
       await generateKernelInternal(buildSummary: true, buildComponent: true);
   // ignore: unnecessary_null_comparison
   if (result == null) {
diff --git a/pkg/front_end/tool/incremental_perf.dart b/pkg/front_end/tool/incremental_perf.dart
index 6b91a96..afb0e81 100644
--- a/pkg/front_end/tool/incremental_perf.dart
+++ b/pkg/front_end/tool/incremental_perf.dart
@@ -123,7 +123,7 @@
   final UriTranslator uriTranslator = await processedOptions.getUriTranslator();
 
   collector.start("Initial compilation");
-  var generator = new IncrementalKernelGenerator(compilerOptions, entryUri);
+  var generator = new IncrementalKernelGenerator(compilerOptions, [entryUri]);
 
   var compilerResult = await generator.computeDelta();
   var component = compilerResult.component;
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index d59f082..d68a4ec 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -89,6 +89,9 @@
       help: 'Path to output Ninja depfile. Only used in batch mode.')
   ..addOption('packages',
       help: '.packages file to use for compilation', defaultsTo: null)
+  ..addMultiOption('source',
+      help: 'List additional source files to include into compilation.',
+      defaultsTo: const <String>[])
   ..addOption('target',
       help: 'Target model that determines what core libraries are available',
       allowed: <String>[
@@ -363,6 +366,7 @@
   ProcessedOptions _processedOptions;
   FileSystem _fileSystem;
   Uri _mainSource;
+  List<Uri> _additionalSources;
   ArgResults _options;
 
   IncrementalCompiler _generator;
@@ -422,6 +426,8 @@
         options['filesystem-scheme'], options['filesystem-root'],
         allowHttp: options['enable-http-uris']);
     _mainSource = resolveInputUri(entryPoint);
+    _additionalSources =
+        (options['source'] as List<String>).map(resolveInputUri).toList();
     _kernelBinaryFilenameFull = _options['output-dill'] ?? '$entryPoint.dill';
     _kernelBinaryFilenameIncremental = _options['output-incremental-dill'] ??
         (_options['output-dill'] != null
@@ -575,6 +581,7 @@
       }
       results = await _runWithPrintRedirection(() => compileToKernel(
           _mainSource, compilerOptions,
+          additionalSources: _additionalSources,
           includePlatform: options['link-platform'],
           deleteToStringPackageUris: options['delete-tostring-package-uri'],
           aot: options['aot'],
@@ -809,8 +816,8 @@
     }
     errors.clear();
 
-    IncrementalCompilerResult deltaProgramResult =
-        await _generator.compile(entryPoint: _mainSource);
+    IncrementalCompilerResult deltaProgramResult = await _generator
+        .compile(entryPoints: [_mainSource, ..._additionalSources]);
     Component deltaProgram = deltaProgramResult.component;
     if (deltaProgram != null && transformer != null) {
       transformer.transform(deltaProgram);
@@ -1078,7 +1085,8 @@
   }
 
   IncrementalCompiler _createGenerator(Uri initializeFromDillUri) {
-    return IncrementalCompiler(_compilerOptions, _mainSource,
+    return IncrementalCompiler(
+        _compilerOptions, [_mainSource, ..._additionalSources],
         initializeFromDillUri: initializeFromDillUri,
         incrementalSerialization: incrementalSerialization);
   }
diff --git a/pkg/frontend_server/test/frontend_server_test.dart b/pkg/frontend_server/test/frontend_server_test.dart
index 35f6315..1d7e607 100644
--- a/pkg/frontend_server/test/frontend_server_test.dart
+++ b/pkg/frontend_server/test/frontend_server_test.dart
@@ -424,7 +424,7 @@
       when(generator.compile()).thenAnswer((_) =>
           Future<IncrementalCompilerResult>.value(
               IncrementalCompilerResult(Component())));
-      when(generator.compile(entryPoint: anyNamed("entryPoint"))).thenAnswer(
+      when(generator.compile(entryPoints: anyNamed("entryPoints"))).thenAnswer(
           (_) => Future<IncrementalCompilerResult>.value(
               IncrementalCompilerResult(Component())));
       final _MockedBinaryPrinterFactory printerFactory =
@@ -1653,6 +1653,68 @@
       expect(await starter(args), 0);
     });
 
+    test('compile multiple sources', () async {
+      final src1 = File('${tempDir.path}/src1.dart')
+        ..createSync()
+        ..writeAsStringSync("main() {}\n");
+      final src2 = File('${tempDir.path}/src2.dart')
+        ..createSync()
+        ..writeAsStringSync("entryPoint2() {}\n");
+      final src3 = File('${tempDir.path}/src3.dart')
+        ..createSync()
+        ..writeAsStringSync("entryPoint3() {}\n");
+      final packagesFile = File('${tempDir.path}/.packages')
+        ..createSync()
+        ..writeAsStringSync("\n");
+      final dillFile = File('${tempDir.path}/app.dill');
+      expect(dillFile.existsSync(), equals(false));
+      final List<String> args = <String>[
+        '--sdk-root=${sdkRoot.toFilePath()}',
+        '--incremental',
+        '--packages=${packagesFile.path}',
+        '--source=${src2.path}',
+        '--source=${src3.path}',
+        '--platform=${platformKernel.path}',
+        '--output-dill=${dillFile.path}'
+      ];
+
+      final StreamController<List<int>> inputStreamController =
+          StreamController<List<int>>();
+      final StreamController<List<int>> stdoutStreamController =
+          StreamController<List<int>>();
+      final IOSink ioSink = IOSink(stdoutStreamController.sink);
+      StreamController<Result> receivedResults = StreamController<Result>();
+
+      final outputParser = OutputParser(receivedResults);
+      stdoutStreamController.stream
+          .transform(utf8.decoder)
+          .transform(const LineSplitter())
+          .listen(outputParser.listener);
+
+      Future<int> result =
+          starter(args, input: inputStreamController.stream, output: ioSink);
+      inputStreamController.add('compile ${src1.uri}\n'.codeUnits);
+      receivedResults.stream.listen((Result compiledResult) {
+        CompilationResult result =
+            CompilationResult.parse(compiledResult.status);
+        expect(dillFile.existsSync(), equals(true));
+        expect(result.filename, dillFile.path);
+        expect(result.errorsCount, 0);
+
+        final component = loadComponentFromBinary(dillFile.path);
+        // Contains (at least) the 3 files we want.
+        final srcUris = {src1.uri, src2.uri, src3.uri};
+        expect(
+            component.libraries
+                .where((lib) => srcUris.contains(lib.fileUri))
+                .length,
+            srcUris.length);
+        inputStreamController.add('quit\n'.codeUnits);
+      });
+      expect(await result, 0);
+      inputStreamController.close();
+    });
+
     group('http uris', () {
       var host = 'localhost';
       File dillFile;
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index feaa794..4dc523e 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -164,6 +164,9 @@
   late final Procedure completeOnAsyncReturn =
       index.getTopLevelProcedure('dart:async', '_completeOnAsyncReturn');
 
+  late final Procedure completeWithNoFutureOnAsyncReturn = index
+      .getTopLevelProcedure('dart:async', '_completeWithNoFutureOnAsyncReturn');
+
   late final Procedure completeOnAsyncError =
       index.getTopLevelProcedure('dart:async', '_completeOnAsyncError');
 
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index ad89d1f..c0375c2 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -1347,6 +1347,18 @@
   VariableDeclaration? asyncFutureVariable;
   VariableDeclaration? isSyncVariable;
 
+  // In general an async functions such as
+  //
+  //     Future<X> foo() async { return <expr>; }
+  //
+  // can return as `<expr>` either X or Future<X>, i.e. it can return
+  // FutureOr<X>
+  //
+  // If we know it doesn't return any object of type `Future`, we can optimize
+  // the future completion process by avoiding some expensive `is Future<T>`
+  // type checks on the returned value.
+  late bool canReturnFuture;
+
   AsyncFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction,
       StatefulStaticTypeContext staticTypeContext)
       : super(helper, enclosingFunction, staticTypeContext);
@@ -1385,13 +1397,22 @@
         type: helper.coreTypes.boolLegacyRawType);
     statements.add(isSyncVariable!);
 
-    // asy::FutureOr<dynamic>* :return_value;
+    // asy::FutureOr<T>* :return_value;
     returnVariable = VariableDeclaration(ContinuationVariables.returnValue,
         type: returnType);
     statements.add(returnVariable!);
 
+    canReturnFuture = false;
+
     setupAsyncContinuations(statements);
 
+    // If we could prove the function doesn't return a `Future` we change the
+    // type of `:return_value`.
+    if (!canReturnFuture) {
+      returnVariable!.type =
+          valueType.withDeclaredNullability(Nullability.nullable);
+    }
+
     // :async_op();
     final startStatement = ExpressionStatement(LocalFunctionInvocation(
         nestedClosureVariable, Arguments([]),
@@ -1439,7 +1460,9 @@
     return Block(<Statement>[
       body,
       ExpressionStatement(StaticInvocation(
-          helper.completeOnAsyncReturn,
+          canReturnFuture
+              ? helper.completeOnAsyncReturn
+              : helper.completeWithNoFutureOnAsyncReturn,
           Arguments([
             VariableGet(asyncFutureVariable!),
             VariableGet(returnVariable!),
@@ -1452,14 +1475,47 @@
   @override
   TreeNode visitReturnStatement(
       ReturnStatement node, TreeNode? removalSentinel) {
-    var expr = node.expression == null
-        ? new NullLiteral()
+    final expression = node.expression;
+    if (expression != null && !canReturnFuture) {
+      final returnedType = staticTypeContext.getExpressionType(expression);
+      canReturnFuture = _canHoldFutureObject(returnedType);
+    }
+
+    final transformedExpression = node.expression == null
+        ? NullLiteral()
         : expressionRewriter!.rewrite(node.expression!, statements);
-    statements.add(new ExpressionStatement(
-        new VariableSet(returnVariable!, expr)..fileOffset = node.fileOffset));
-    statements.add(new BreakStatement(labeledBody!));
+    statements.add(ExpressionStatement(
+        VariableSet(returnVariable!, transformedExpression)
+          ..fileOffset = node.fileOffset));
+    statements.add(BreakStatement(labeledBody!));
     return removalSentinel ?? EmptyStatement();
   }
+
+  bool _canHoldFutureObject(DartType type) {
+    // Any supertype or subtype of `FutureOr` may hold a `Future` object.
+    final env = staticTypeContext.typeEnvironment;
+
+    if (type is TypeParameterType) {
+      type = type.parameter.defaultType;
+    }
+
+    if (type is FutureOrType) return true;
+
+    // Any supertype of Future (which includes Future/Object/dynamic) can hold
+    // Future objects.
+    if (env.isSubtypeOf(
+        helper.futureType, type, SubtypeCheckMode.ignoringNullabilities)) {
+      return true;
+    }
+
+    // Any subtype of Future (which includes Future/_Future and any user-defined
+    // implementations) can hold Future objects.
+    if (env.isSubtypeOf(
+        type, helper.futureType, SubtypeCheckMode.ignoringNullabilities)) {
+      return true;
+    }
+    return false;
+  }
 }
 
 class HelperNodes {
@@ -1476,6 +1532,7 @@
   final Procedure asyncThenWrapper;
   final Procedure awaitHelper;
   final Procedure completeOnAsyncReturn;
+  final Procedure completeWithNoFutureOnAsyncReturn;
   final Procedure completeOnAsyncError;
   final Library coreLibrary;
   final CoreTypes coreTypes;
@@ -1496,6 +1553,7 @@
   final Member syncIteratorYieldEachIterable;
   final Class boolClass;
   final Procedure unsafeCast;
+  final DartType futureType;
 
   bool productMode;
 
@@ -1513,6 +1571,7 @@
       this.asyncThenWrapper,
       this.awaitHelper,
       this.completeOnAsyncReturn,
+      this.completeWithNoFutureOnAsyncReturn,
       this.completeOnAsyncError,
       this.coreLibrary,
       this.coreTypes,
@@ -1533,7 +1592,9 @@
       this.syncIteratorYieldEachIterable,
       this.boolClass,
       this.productMode,
-      this.unsafeCast);
+      this.unsafeCast)
+      : futureType = InterfaceType(
+            futureClass, Nullability.nonNullable, [DynamicType()]);
 
   factory HelperNodes.fromCoreTypes(CoreTypes coreTypes, bool productMode) {
     return new HelperNodes._(
@@ -1550,6 +1611,7 @@
         coreTypes.asyncThenWrapperHelperProcedure,
         coreTypes.awaitHelperProcedure,
         coreTypes.completeOnAsyncReturn,
+        coreTypes.completeWithNoFutureOnAsyncReturn,
         coreTypes.completeOnAsyncError,
         coreTypes.coreLibrary,
         coreTypes,
diff --git a/pkg/vm/analysis_options.yaml b/pkg/vm/analysis_options.yaml
index 76886bd..4aaf9c5 100644
--- a/pkg/vm/analysis_options.yaml
+++ b/pkg/vm/analysis_options.yaml
@@ -4,5 +4,4 @@
 
 analyzer:
   exclude:
-    - testcases/**
     - tool/**
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 43240f8..8e3f752 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -324,16 +324,16 @@
     result.generator = new IncrementalCompiler.forExpressionCompilationOnly(
         component,
         result.options,
-        component.mainMethod!.enclosingLibrary.fileUri);
+        [component.mainMethod!.enclosingLibrary.fileUri]);
     return result;
   }
 
   @override
   Future<CompilerResult> compileInternal(Uri script) async {
-    final generator = this.generator ??= IncrementalCompiler(options, script);
+    final generator = this.generator ??= IncrementalCompiler(options, [script]);
     errorsPlain.clear();
     errorsColorized.clear();
-    final compilerResult = await generator.compile(entryPoint: script);
+    final compilerResult = await generator.compile(entryPoints: [script]);
     final component = compilerResult.component;
     return new CompilerResult(component, const {},
         compilerResult.classHierarchy, compilerResult.coreTypes);
@@ -367,7 +367,7 @@
     new BinaryPrinter(sink).writeComponentFile(fullComponent);
     sink.close();
 
-    clone.generator = new IncrementalCompiler(options, generator.entryPoint,
+    clone.generator = new IncrementalCompiler(options, generator.entryPoints,
         initializeFromDillUri: Uri.file(filename));
     return clone;
   }
diff --git a/pkg/vm/lib/incremental_compiler.dart b/pkg/vm/lib/incremental_compiler.dart
index 3794fbf..fdf6e5c 100644
--- a/pkg/vm/lib/incremental_compiler.dart
+++ b/pkg/vm/lib/incremental_compiler.dart
@@ -29,45 +29,44 @@
   bool initialized = false;
   bool fullComponent = false;
   Uri? initializeFromDillUri;
-  Uri _entryPoint;
+  List<Uri> _entryPoints;
   final bool forExpressionCompilationOnly;
 
-  Uri get entryPoint => _entryPoint;
+  List<Uri> get entryPoints => _entryPoints;
   IncrementalKernelGenerator get generator => _generator;
   IncrementalCompilerResult? get lastKnownGoodResult => _lastKnownGood;
 
-  IncrementalCompiler(this._compilerOptions, this._entryPoint,
+  IncrementalCompiler(this._compilerOptions, this._entryPoints,
       {this.initializeFromDillUri, bool incrementalSerialization: true})
       : forExpressionCompilationOnly = false {
     if (incrementalSerialization) {
       incrementalSerializer = new IncrementalSerializer();
     }
-    _generator = new IncrementalKernelGenerator(_compilerOptions, _entryPoint,
+    _generator = new IncrementalKernelGenerator(_compilerOptions, _entryPoints,
         initializeFromDillUri, false, incrementalSerializer);
     _pendingDeltas = <IncrementalCompilerResult>[];
   }
 
   IncrementalCompiler.forExpressionCompilationOnly(
-      Component component, this._compilerOptions, this._entryPoint)
+      Component component, this._compilerOptions, this._entryPoints)
       : forExpressionCompilationOnly = true {
     _generator = new IncrementalKernelGenerator.forExpressionCompilationOnly(
-        _compilerOptions, _entryPoint, component);
+        _compilerOptions, _entryPoints, component);
     _pendingDeltas = <IncrementalCompilerResult>[];
   }
 
   /// Recompiles invalidated files, produces incremental component.
   ///
-  /// If [entryPoint] is specified, that points to new entry point for the
-  /// compilation. Otherwise, previously set entryPoint is used.
-  Future<IncrementalCompilerResult> compile({Uri? entryPoint}) async {
+  /// If [entryPoints] is specified, that points to the new list of entry
+  /// points for the compilation. Otherwise, previously set entryPoints are
+  /// used.
+  Future<IncrementalCompilerResult> compile({List<Uri>? entryPoints}) async {
     final task = new TimelineTask();
     try {
       task.start("IncrementalCompiler.compile");
-      _entryPoint = entryPoint ?? _entryPoint;
-      List<Uri>? entryPoints;
-      if (entryPoint != null) entryPoints = [entryPoint];
+      _entryPoints = entryPoints ?? _entryPoints;
       IncrementalCompilerResult compilerResult = await _generator.computeDelta(
-          entryPoints: entryPoints, fullComponent: fullComponent);
+          entryPoints: _entryPoints, fullComponent: fullComponent);
       initialized = true;
       fullComponent = false;
       _pendingDeltas.add(compilerResult);
@@ -176,8 +175,8 @@
     _lastKnownGood?.component.relink();
 
     _generator = new IncrementalKernelGenerator.fromComponent(_compilerOptions,
-        _entryPoint, _lastKnownGood?.component, false, incrementalSerializer);
-    await _generator.computeDelta(entryPoints: [_entryPoint]);
+        _entryPoints, _lastKnownGood?.component, false, incrementalSerializer);
+    await _generator.computeDelta(entryPoints: _entryPoints);
   }
 
   /// This tells incremental compiler that it needs rescan [uri] file during
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 76a0f85..e77ba6b 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -97,6 +97,9 @@
           ' If multi-root file system is used, the input script and .packages file should be specified using URI.');
   args.addOption('filesystem-scheme',
       help: 'The URI scheme for the multi-root virtual filesystem.');
+  args.addMultiOption('source',
+      help: 'List additional source files to include into compilation.',
+      defaultsTo: const <String>[]);
   args.addOption('target',
       help: 'Target model that determines what core libraries are available',
       allowed: <String>['vm', 'flutter', 'flutter_runner', 'dart_runner'],
@@ -203,6 +206,7 @@
   final bool treeShakeWriteOnlyFields = options['tree-shake-write-only-fields'];
   final List<String>? experimentalFlags = options['enable-experiment'];
   final Map<String, String> environmentDefines = {};
+  final List<String> sources = options['source'];
 
   if (!parseCommandLineDefines(options['define'], environmentDefines, usage)) {
     return badUsageExitCode;
@@ -248,6 +252,8 @@
     mainUri = await convertToPackageUri(fileSystem, mainUri, packagesUri);
   }
 
+  final List<Uri> additionalSources = sources.map(resolveInputUri).toList();
+
   final verbosity = Verbosity.parseArgument(options['verbosity']);
   final errorPrinter = new ErrorPrinter(verbosity);
   final errorDetector =
@@ -285,6 +291,7 @@
   }
 
   final results = await compileToKernel(mainUri, compilerOptions,
+      additionalSources: additionalSources,
       includePlatform: additionalDills.isNotEmpty,
       deleteToStringPackageUris: options['delete-tostring-package-uri'],
       aot: aot,
@@ -354,7 +361,8 @@
 ///
 Future<KernelCompilationResults> compileToKernel(
     Uri source, CompilerOptions options,
-    {bool includePlatform: false,
+    {List<Uri> additionalSources: const <Uri>[],
+    bool includePlatform: false,
     List<String> deleteToStringPackageUris: const <String>[],
     bool aot: false,
     bool useGlobalTypeFlowAnalysis: false,
@@ -379,7 +387,8 @@
     compilerResult =
         await loadKernel(options.fileSystem, resolveInputUri(fromDillFile));
   } else {
-    compilerResult = await kernelForProgram(source, options);
+    compilerResult = await kernelForProgram(source, options,
+        additionalSources: additionalSources);
   }
   final Component? component = compilerResult?.component;
   Iterable<Uri>? compiledSources = component?.uriToSource.keys;
diff --git a/pkg/vm/lib/transformations/ffi/common.dart b/pkg/vm/lib/transformations/ffi/common.dart
index c23bddb..5c20ebf 100644
--- a/pkg/vm/lib/transformations/ffi/common.dart
+++ b/pkg/vm/lib/transformations/ffi/common.dart
@@ -252,6 +252,7 @@
   final Procedure asFunctionTearoff;
   final Procedure lookupFunctionTearoff;
   final Procedure getNativeFieldFunction;
+  final Class finalizableClass;
   final Procedure reachabilityFenceFunction;
   final Procedure checkAbiSpecificIntegerMappingFunction;
 
@@ -479,6 +480,7 @@
             LibraryIndex.tearoffPrefix + 'lookupFunction'),
         getNativeFieldFunction = index.getTopLevelProcedure(
             'dart:nativewrappers', '_getNativeField'),
+        finalizableClass = index.getClass('dart:ffi', 'Finalizable'),
         reachabilityFenceFunction =
             index.getTopLevelProcedure('dart:_internal', 'reachabilityFence'),
         checkAbiSpecificIntegerMappingFunction = index.getTopLevelProcedure(
diff --git a/pkg/vm/lib/transformations/ffi/finalizable.dart b/pkg/vm/lib/transformations/ffi/finalizable.dart
new file mode 100644
index 0000000..758465b
--- /dev/null
+++ b/pkg/vm/lib/transformations/ffi/finalizable.dart
@@ -0,0 +1,894 @@
+// 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:kernel/ast.dart';
+import 'package:kernel/kernel.dart';
+import 'package:kernel/type_environment.dart';
+
+/// Implements the `Finalizable` semantics.
+///
+/// Designed to be mixed in. Calls super.visitXXX() to visit all nodes (except
+/// the ones created by this transformation).
+///
+/// This transformation is not AST-node preserving. [Expression]s and
+/// [Statement]s can be replaced by other [Expression]s and [Statement]s
+/// respectively. This means one cannot do `visitX() { super.visitX() as X }`.
+mixin FinalizableTransformer on Transformer {
+  TypeEnvironment get env;
+  Procedure get reachabilityFenceFunction;
+  Class get finalizableClass;
+
+  StaticTypeContext? staticTypeContext;
+
+  _Scope? _currentScope;
+
+  bool thisIsFinalizable = false;
+
+  /// Traverses [f] in a newly created [_Scope].
+  ///
+  /// Any declarations added to this new scope will be fenced in
+  /// [appendFencesToStatement] and [appendFencesToExpression] if provided.
+  ///
+  /// Captures need to be precomputed (by [FindCaptures]) and can be passed in
+  /// through [precomputedCaptureScope].
+  ///
+  /// [declaresThis] is true if `this` in the scope is `Finalizable` and
+  /// defined.
+  T inScope<T>(
+    TreeNode node,
+    T Function() f, {
+    Statement? appendFencesToStatement,
+    Expression? appendFencesToExpression,
+    bool? declaresThis,
+    _Scope? precomputedCaptureScope,
+  }) {
+    final scope =
+        _Scope(node, parent: _currentScope, declaresThis: declaresThis);
+    if (precomputedCaptureScope != null) {
+      scope._capturesThis = precomputedCaptureScope._capturesThis;
+      scope._captures = precomputedCaptureScope._captures;
+    }
+    _currentScope = scope;
+    final result = f();
+    if (appendFencesToStatement != null) {
+      _appendReachabilityFences(
+          appendFencesToStatement, scope.toFenceThisScope);
+    }
+    if (appendFencesToExpression != null) {
+      appendFencesToExpression.replaceWith(_wrapReachabilityFences(
+          appendFencesToExpression, scope.toFenceThisScope));
+    }
+    assert(_currentScope == scope);
+    _currentScope = _currentScope!.parent;
+    return result;
+  }
+
+  Map<LocalFunction, _Scope> _precomputedCaptures = {};
+
+  _Scope? _precomputeCaptures(LocalFunction node) {
+    if (_currentScope!.allDeclarationsIsEmpty) {
+      // There's nothing we can capture.
+      return null;
+    }
+    final lookup = _precomputedCaptures[node];
+    if (lookup != null) {
+      return lookup;
+    }
+    final visitor =
+        FindCaptures(_currentScope!, thisIsFinalizable, _isFinalizable);
+    visitor.visitLocalFunction(node);
+    _precomputedCaptures = visitor.precomputedScopes;
+    return _precomputedCaptures[node]!;
+  }
+
+  @override
+  visitField(Field node) {
+    assert(staticTypeContext == null);
+    staticTypeContext = StaticTypeContext(node, env);
+    assert(_currentScope == null);
+    assert(thisIsFinalizable == false);
+    thisIsFinalizable = _thisIsFinalizableFromMember(node);
+    final result = inScope(
+      node,
+      () => super.visitField(node),
+      declaresThis: thisIsFinalizable,
+    );
+    thisIsFinalizable = false;
+    staticTypeContext = null;
+    return result;
+  }
+
+  @override
+  visitConstructor(Constructor node) {
+    assert(staticTypeContext == null);
+    staticTypeContext = StaticTypeContext(node, env);
+    assert(_currentScope == null);
+    assert(thisIsFinalizable == false);
+    thisIsFinalizable = _thisIsFinalizableFromMember(node);
+    final result = inScope(
+      node,
+      () => super.visitConstructor(node),
+      appendFencesToStatement: node.function.body,
+      declaresThis: thisIsFinalizable,
+    );
+    thisIsFinalizable = false;
+    staticTypeContext = null;
+    return result;
+  }
+
+  @override
+  visitProcedure(Procedure node) {
+    assert(staticTypeContext == null);
+    staticTypeContext = StaticTypeContext(node, env);
+    assert(_currentScope == null);
+    assert(thisIsFinalizable == false);
+    thisIsFinalizable = _thisIsFinalizableFromMember(node);
+    final result = inScope(
+      node,
+      () => super.visitProcedure(node),
+      appendFencesToStatement: node.function.body,
+      declaresThis: thisIsFinalizable,
+    );
+    thisIsFinalizable = false;
+    staticTypeContext = null;
+    return result;
+  }
+
+  @override
+  TreeNode visitBlock(Block node) {
+    return inScope(
+      node,
+      () => super.visitBlock(node),
+      appendFencesToStatement: node,
+    );
+  }
+
+  @override
+  TreeNode visitForInStatement(ForInStatement node) {
+    return inScope(
+      node,
+      () => super.visitForInStatement(node),
+      appendFencesToStatement: node.body,
+    );
+  }
+
+  @override
+  TreeNode visitForStatement(ForStatement node) {
+    return inScope(
+      node,
+      () => super.visitForStatement(node),
+      appendFencesToStatement: node.body,
+    );
+  }
+
+  @override
+  TreeNode visitLet(Let node) {
+    return inScope(
+      node,
+      () => super.visitLet(node),
+      appendFencesToExpression: node.body,
+    );
+  }
+
+  @override
+  TreeNode visitFunctionDeclaration(FunctionDeclaration node) {
+    return inScope(
+      node,
+      () => super.visitFunctionDeclaration(node),
+      appendFencesToStatement: node.function.body,
+      precomputedCaptureScope: _precomputeCaptures(node),
+    );
+  }
+
+  @override
+  TreeNode visitFunctionExpression(FunctionExpression node) {
+    return inScope(
+      node,
+      () => super.visitFunctionExpression(node),
+      appendFencesToStatement: node.function.body,
+      precomputedCaptureScope: _precomputeCaptures(node),
+    );
+  }
+
+  @override
+  TreeNode visitTryCatch(TryCatch node) {
+    return inScope(
+      node,
+      () => super.visitTryCatch(node),
+    );
+  }
+
+  @override
+  TreeNode visitCatch(Catch node) {
+    return inScope(
+      node,
+      () => super.visitCatch(node),
+    );
+  }
+
+  @override
+  TreeNode visitSwitchStatement(SwitchStatement node) {
+    return inScope(
+      node,
+      () => super.visitSwitchStatement(node),
+    );
+  }
+
+  @override
+  TreeNode visitVariableDeclaration(VariableDeclaration node) {
+    if (_currentScope == null) {
+      // Global variable.
+      return super.visitVariableDeclaration(node);
+    }
+    if (_isFinalizable(node.type)) {
+      _currentScope!.addDeclaration(node);
+    }
+    return super.visitVariableDeclaration(node);
+  }
+
+  @override
+  TreeNode visitVariableSet(VariableSet node) {
+    node = super.visitVariableSet(node) as VariableSet;
+    if (!_isFinalizable(node.variable.type)) {
+      return node;
+    }
+
+    final expression = node.value;
+
+    final newExpression = _wrapReachabilityFences(
+      expression,
+      [VariableGet(node.variable)],
+    );
+
+    node.value = newExpression;
+    newExpression.parent = node;
+
+    return node;
+  }
+
+  @override
+  TreeNode visitReturnStatement(ReturnStatement node) {
+    final declarations = _currentScope!.toFenceReturn;
+    node = super.visitReturnStatement(node) as ReturnStatement;
+    if (declarations.isEmpty) {
+      return node;
+    }
+
+    final expression = node.expression;
+    if (expression == null) {
+      final newStatement = Block([
+        ..._reachabilityFences(declarations),
+        node,
+      ]);
+      return newStatement;
+    }
+
+    final newExpression = _wrapReachabilityFences(expression, declarations);
+
+    node.expression = newExpression;
+    newExpression.parent = node;
+
+    return node;
+  }
+
+  /// The async transform runs after this transform. It transforms
+  /// [YieldStatement]s in async* functions into:
+  /// ```
+  /// _AsyncStarStreamController controller;
+  /// if(controller.add(...){
+  ///   return ...
+  /// } else {
+  ///   yield ...
+  /// }
+  /// ```
+  /// We don't want to run this transform after the async transform because that
+  /// introduces new scoping and control flow and it would create another
+  /// traversal over the AST.
+  /// So, we need to insert fences for yields as if they were returns in async*
+  /// functions.
+  ///
+  /// However, there is more. The body of async* and sync* functions is
+  /// transformed into a 'closure', which branches on the yield index and is
+  /// executed multiple times. The context of this closure is restored on
+  /// re-execution. These two things make it a continuation.
+  /// The [YieldStatement]s are compiled into returns from that closure.
+  /// When inlining the iterator machinery and eleminating dead code, the
+  /// compiler can see that we will never execute a re-entry if we just ask for
+  /// only the first value of a stream from a sync* function.
+  /// So, we need to insert fences for yields as if they were returns in sync*
+  /// functions as well.
+  @override
+  TreeNode visitYieldStatement(YieldStatement node) {
+    final declarations = _currentScope!.toFenceReturn;
+    node = super.visitYieldStatement(node) as YieldStatement;
+    if (declarations.isEmpty) {
+      return node;
+    }
+
+    final newExpression =
+        _wrapReachabilityFences(node.expression, declarations);
+
+    node.expression = newExpression;
+    newExpression.parent = node;
+
+    return node;
+  }
+
+  /// [AwaitExpression]s are transformed into [YieldStatement]s by the
+  /// async transform. See the comment on [visitYieldStatement].
+  @override
+  TreeNode visitAwaitExpression(AwaitExpression node) {
+    final declarations = _currentScope!.toFenceReturn;
+    node = super.visitAwaitExpression(node) as AwaitExpression;
+    if (declarations.isEmpty) {
+      return node;
+    }
+
+    final newExpression = _wrapReachabilityFences(node.operand, declarations);
+
+    node.operand = newExpression;
+    newExpression.parent = node;
+
+    return node;
+  }
+
+  @override
+  TreeNode visitThrow(Throw node) {
+    final declarations = _currentScope!.toFenceThrow(
+        staticTypeContext!.getExpressionType(node.expression), env);
+    node = super.visitThrow(node) as Throw;
+    if (declarations.isEmpty) {
+      return node;
+    }
+
+    final newExpression =
+        _wrapReachabilityFences(node.expression, declarations);
+
+    node.expression = newExpression;
+    newExpression.parent = node;
+
+    return node;
+  }
+
+  @override
+  TreeNode visitRethrow(Rethrow node) {
+    final declarations = _currentScope!.toFenceRethrow(
+      _currentScope!.rethrowType,
+      env,
+    );
+    node = super.visitRethrow(node) as Rethrow;
+    if (declarations.isEmpty) {
+      return node;
+    }
+
+    return BlockExpression(
+      Block(<Statement>[
+        ..._reachabilityFences(declarations),
+      ]),
+      node,
+    );
+  }
+
+  @override
+  TreeNode visitBreakStatement(BreakStatement node) {
+    final declarations = _currentScope!.toFenceBreak(node.target);
+
+    if (declarations.isEmpty) {
+      return node;
+    }
+
+    final newStatement = Block([
+      ..._reachabilityFences(declarations),
+      node,
+    ]);
+    return newStatement;
+  }
+
+  @override
+  TreeNode visitLabeledStatement(LabeledStatement node) {
+    _currentScope!._labels.add(node);
+    return super.visitLabeledStatement(node);
+  }
+
+  @override
+  TreeNode visitContinueSwitchStatement(ContinueSwitchStatement node) {
+    final switchStatement = node.target.parent as SwitchStatement;
+    final declarations = _currentScope!.toFenceSwitchContinue(switchStatement);
+
+    if (declarations.isEmpty) {
+      return node;
+    }
+
+    final newStatement = Block([
+      ..._reachabilityFences(declarations),
+      node,
+    ]);
+    return newStatement;
+  }
+
+  /// Cache for [isFinalizable].
+  ///
+  /// Speeds up the type checks by about a factor of 2 on Flutter Gallery.
+  Map<DartType, bool> _isFinalizableCache = {};
+
+  /// Whether [type] is something that subtypes `FutureOr<Finalizable?>?`.
+  bool _isFinalizable(DartType type) {
+    final cached = _isFinalizableCache[type];
+    if (cached != null) {
+      return cached;
+    }
+
+    final finalizableType = FutureOrType(
+        InterfaceType(finalizableClass, Nullability.nullable),
+        Nullability.nullable);
+    if (!env.isSubtypeOf(
+      type,
+      finalizableType,
+      SubtypeCheckMode.withNullabilities,
+    )) {
+      _isFinalizableCache[type] = false;
+      return false;
+    }
+
+    // Exclude never types.
+    final futureOfNeverType =
+        FutureOrType(NeverType.nullable(), Nullability.nullable);
+    final result = !env.isSubtypeOf(
+      type,
+      futureOfNeverType,
+      SubtypeCheckMode.ignoringNullabilities,
+    );
+    _isFinalizableCache[type] = result;
+    return result;
+  }
+
+  bool _thisIsFinalizableFromMember(Member member) {
+    final enclosingClass_ = member.enclosingClass;
+    if (enclosingClass_ == null) {
+      return false;
+    }
+    if (member.isAbstract) {
+      return false;
+    }
+    if (member.isExternal) {
+      return false;
+    }
+    if (member is Constructor && member.isSynthetic) {
+      return false;
+    }
+    if (member is Procedure && member.isStatic) {
+      return false;
+    }
+    return _isFinalizable(
+        InterfaceType(enclosingClass_, Nullability.nonNullable));
+  }
+
+  List<Statement> _reachabilityFences(List<Expression> declarations) =>
+      <Statement>[
+        for (var declaration in declarations)
+          ExpressionStatement(
+            StaticInvocation(
+              reachabilityFenceFunction,
+              Arguments(<Expression>[declaration]),
+            ),
+          ),
+      ];
+
+  /// Turns an [expression] into a block expression with reachability fences.
+  ///
+  /// ```
+  /// block {
+  /// final <expression type> #t1 = <expression>;
+  /// _in::reachabilityFence(finalizable0);
+  /// _in::reachabilityFence(finalizable1);
+  /// // ..
+  /// } =>#t1
+  /// ```
+  ///
+  /// Note that this modifies the parent of [expression].
+  Expression _wrapReachabilityFences(
+      Expression expression, List<Expression> declarations) {
+    final resultVariable = VariableDeclaration(
+        ':expressionValueWrappedFinalizable',
+        initializer: expression,
+        type: staticTypeContext!.getExpressionType(expression),
+        isFinal: true);
+    return BlockExpression(
+      Block(<Statement>[
+        resultVariable,
+        ..._reachabilityFences(declarations),
+      ]),
+      VariableGet(resultVariable),
+    );
+  }
+
+  Statement _appendReachabilityFences(
+      Statement statement, List<Expression> declarations) {
+    if (declarations.isEmpty) {
+      return statement;
+    }
+    Block block = () {
+      if (statement is Block) {
+        return statement;
+      }
+      final replacement = Block(<Statement>[]);
+      statement.replaceWith(replacement);
+      replacement.statements.add(statement);
+      return replacement;
+    }();
+    if (block.statements.isEmpty ||
+        (!block.statements.last.endsWithAbnormalControlFlow)) {
+      block.statements.addAll(_reachabilityFences(declarations));
+    }
+    return block;
+  }
+}
+
+/// A lightweight version of the above transform that precomputes scopes.
+///
+/// We need to precompute scopes and captures because a variable can be captured
+/// later in a closure than the first return.
+///
+/// We cannot use the precomputed scopes for their declarations, because we
+/// could see returns in a scope before a declaration.
+class FindCaptures extends RecursiveVisitor<void> {
+  final bool Function(DartType) _isFinalizable;
+
+  final bool thisIsFinalizable;
+
+  final Map<LocalFunction, _Scope> precomputedScopes = {};
+
+  _Scope _currentScope;
+
+  FindCaptures(this._currentScope, this.thisIsFinalizable, this._isFinalizable);
+
+  void inScope(LocalFunction node, void Function() f) {
+    final scope = _Scope(node, parent: _currentScope, declaresThis: false);
+    assert(precomputedScopes[node] == null);
+    precomputedScopes[node] = scope;
+    _currentScope = scope;
+    final result = f();
+    assert(_currentScope == scope);
+    _currentScope = _currentScope.parent!;
+    return result;
+  }
+
+  void visitLocalFunction(LocalFunction node) {
+    if (node is FunctionDeclaration) {
+      return visitFunctionDeclaration(node);
+    }
+    if (node is FunctionExpression) {
+      return visitFunctionExpression(node);
+    }
+    assert(false);
+  }
+
+  @override
+  void visitFunctionDeclaration(FunctionDeclaration node) {
+    inScope(
+      node,
+      () => super.visitFunctionDeclaration(node),
+    );
+  }
+
+  @override
+  void visitFunctionExpression(FunctionExpression node) {
+    inScope(
+      node,
+      () => super.visitFunctionExpression(node),
+    );
+  }
+
+  @override
+  void visitVariableDeclaration(VariableDeclaration node) {
+    if (_isFinalizable(node.type)) {
+      _currentScope.addDeclaration(node);
+    }
+    super.visitVariableDeclaration(node);
+  }
+
+  @override
+  void visitVariableGet(VariableGet node) {
+    super.visitVariableGet(node);
+    if (_isFinalizable(node.variable.type)) {
+      _currentScope.addCapture(node.variable);
+    }
+  }
+
+  @override
+  void visitVariableSet(VariableSet node) {
+    super.visitVariableSet(node);
+    if (_isFinalizable(node.variable.type)) {
+      _currentScope.addCapture(node.variable);
+    }
+  }
+
+  @override
+  void visitThisExpression(ThisExpression node) {
+    if (thisIsFinalizable) {
+      _currentScope.addCaptureThis();
+    }
+    super.visitThisExpression(node);
+  }
+}
+
+/// A scope contains all `Finalizable` declarations and captures.
+class _Scope {
+  /// Parent scope if any.
+  final _Scope? parent;
+
+  /// The [node] introducing this scope.
+  final TreeNode node;
+
+  /// The declarations in this scope.
+  ///
+  /// The list is mutable, because we populate it during visiting statements.
+  ///
+  /// We use a list rather than a set because declarations are unique and we'd
+  /// like to prevent arbitrary reorderings when generating code from this.
+  final List<VariableDeclaration> _declarations = [];
+
+  /// [ThisExpression] is not a [VariableDeclaration] and needs to be tracked
+  /// separately.
+  final bool declaresThis;
+
+  /// Labels defined in this scope.
+  ///
+  /// Used for seeing which declarations need to be fenced when encountering
+  /// a [BreakStatement];
+  final Set<LabeledStatement> _labels = {};
+
+  _Scope(this.node, {this.parent, bool? declaresThis})
+      : this.declaresThis = declaresThis ?? false,
+        this.allDeclarationsIsEmpty =
+            (parent?.allDeclarationsIsEmpty ?? true) &&
+                !(declaresThis ?? false);
+
+  void addDeclaration(VariableDeclaration declaration) {
+    _declarations.add(declaration);
+    allDeclarationsIsEmpty = false;
+  }
+
+  /// Whether [allDeclarations] is empty.
+  ///
+  /// Manually cached for performance.
+  bool allDeclarationsIsEmpty;
+
+  /// All declarations in this and parent scopes.
+  ///
+  /// Excluding `this`.
+  List<VariableDeclaration> get allDeclarations => [
+        ...?parent?.allDeclarations,
+        ..._declarations,
+      ];
+
+  bool get canCapture => node is LocalFunction;
+
+  /// Which of the ancestor scopes (or this) captures variables.
+  late final _Scope? capturingScope = () {
+    if (canCapture) {
+      return this;
+    }
+    return parent?.capturingScope;
+  }();
+
+  Map<VariableDeclaration, bool>? _captures;
+
+  Map<VariableDeclaration, bool> get captures {
+    if (_captures != null) {
+      return _captures!;
+    }
+
+    assert(canCapture);
+    _captures = {for (var d in parent!.allDeclarations) d: false};
+    return _captures!;
+  }
+
+  bool _capturesThis = false;
+
+  void addCapture(VariableDeclaration declaration) {
+    final capturingScope_ = capturingScope;
+    if (capturingScope_ == null) {
+      // We're not in a nested closure.
+      return;
+    }
+
+    final captures = capturingScope_.captures;
+    if (!captures.containsKey(declaration)) {
+      // This is a local variable, not a captured one.
+      return;
+    }
+    captures[declaration] = true;
+
+    capturingScope_.parent?.addCapture(declaration);
+  }
+
+  void addCaptureThis() {
+    final capturingScope_ = capturingScope;
+    if (capturingScope_ == null) {
+      // We're not in a nested closure.
+      return;
+    }
+
+    capturingScope_._capturesThis = true;
+
+    capturingScope_.parent?.addCaptureThis();
+  }
+
+  /// Get declarations in this scope.
+  List<Expression> get toFenceThisScope {
+    final captures = _captures;
+    return [
+      if (declaresThis || _capturesThis) ThisExpression(),
+      for (var d in _declarations) VariableGet(d),
+      if (captures != null)
+        for (var d in captures.entries.where((e) => e.value).map((e) => e.key))
+          VariableGet(d),
+    ];
+  }
+
+  /// Whether when a return is found, this is the last ancestor of which
+  /// declarations should be considered.
+  bool get scopesReturn {
+    assert(node is Block ||
+        node is Catch ||
+        node is ForInStatement ||
+        node is ForStatement ||
+        node is Let ||
+        node is LocalFunction ||
+        node is Member ||
+        node is SwitchStatement ||
+        node is TryCatch);
+    return node is Member || node is LocalFunction;
+  }
+
+  /// Get all declarations that should stay alive on a return.
+  ///
+  /// This include all declarations in scopes until we see a function scope.
+  List<Expression> get toFenceReturn {
+    return [
+      if (!scopesReturn) ...parent!.toFenceReturn,
+      ...toFenceThisScope,
+    ];
+  }
+
+  List<Expression> toFenceBreak(LabeledStatement label) {
+    if (_labels.contains(label)) {
+      return [];
+    }
+    return [
+      ...parent!.toFenceBreak(label),
+      ...toFenceThisScope,
+    ];
+  }
+
+  List<Expression> toFenceSwitchContinue(SwitchStatement switchStatement) {
+    if (node == switchStatement) {
+      return [];
+    }
+    return [
+      ...parent!.toFenceSwitchContinue(switchStatement),
+      ...toFenceThisScope,
+    ];
+  }
+
+  bool scopesThrow(DartType exceptionType, TypeEnvironment typeEnvironment) {
+    final node_ = node;
+    if (node_ is! TryCatch) {
+      return false;
+    }
+    final catches = node_.catches;
+    for (final catch_ in catches) {
+      if (typeEnvironment.isSubtypeOf(
+          exceptionType, catch_.guard, SubtypeCheckMode.withNullabilities)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  List<Expression> toFenceThrow(
+    DartType exceptionType,
+    TypeEnvironment typeEnvironment,
+  ) =>
+      [
+        if (!scopesThrow(exceptionType, typeEnvironment))
+          ...?parent?.toFenceThrow(exceptionType, typeEnvironment),
+        ...toFenceThisScope,
+      ];
+
+  DartType get rethrowType {
+    final node_ = node;
+    if (node_ is Catch) {
+      return node_.guard;
+    }
+    return parent!.rethrowType;
+  }
+
+  List<Expression> toFenceRethrow(
+      DartType exceptionType, TypeEnvironment typeEnvironment) {
+    return [
+      if (!scopesThrow(exceptionType, typeEnvironment))
+        ...?parent?.toFenceRethrow(exceptionType, typeEnvironment),
+      if (scopesThrow(exceptionType, typeEnvironment))
+        ...?parent?.toFenceThrow(exceptionType, typeEnvironment),
+      ...toFenceThisScope,
+    ];
+  }
+}
+
+extension on Statement {
+  /// Whether this statement ends with abnormal control flow.
+  ///
+  /// Used to avoid inserting definitely dead reachabilityFences.
+  ///
+  /// Recurses into [Block]s to  inspect their last statement.
+  ///
+  /// Examples:
+  ///
+  /// ```dart
+  /// {
+  ///   // ...
+  ///   return 5;
+  /// }
+  /// ```
+  ///
+  /// returns true.
+  ///
+  /// ```dart
+  /// {
+  ///   {
+  ///     break L2;
+  ///   }
+  /// }
+  /// ```
+  ///
+  /// returns true.
+  ///
+  /// ```dart
+  /// print(foo);
+  /// ```
+  ///
+  /// returns false.
+  ///
+  /// Does not take into consideration full control flow, rather this is best
+  /// effort:
+  ///
+  /// ```dart
+  /// {
+  ///   return 42;
+  ///   var unreachable = true;
+  /// }
+  /// ```
+  ///
+  /// returns false, even though inserting fences is superfluous.
+  ///
+  /// These extra fences are not unsound.
+  bool get endsWithAbnormalControlFlow {
+    if (this is ReturnStatement) {
+      return true;
+    }
+    if (this is BreakStatement) {
+      return true;
+    }
+    if (this is ContinueSwitchStatement) {
+      return true;
+    }
+    if (this is Throw) {
+      return true;
+    }
+    if (this is Rethrow) {
+      return true;
+    }
+    final this_ = this;
+    if (this_ is Block) {
+      final statements = this_.statements;
+      if (statements.isEmpty) {
+        return false;
+      }
+      return statements.last.endsWithAbnormalControlFlow;
+    }
+    return false;
+  }
+}
diff --git a/pkg/vm/lib/transformations/ffi/use_sites.dart b/pkg/vm/lib/transformations/ffi/use_sites.dart
index ba1a0b1..0a765e3 100644
--- a/pkg/vm/lib/transformations/ffi/use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi/use_sites.dart
@@ -20,6 +20,7 @@
 import 'package:kernel/ast.dart';
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/core_types.dart';
+import 'package:kernel/kernel.dart';
 import 'package:kernel/library_index.dart' show LibraryIndex;
 import 'package:kernel/reference_from_index.dart';
 import 'package:kernel/target/targets.dart' show DiagnosticReporter;
@@ -30,6 +31,7 @@
 import 'native_type_cfe.dart';
 import 'common.dart'
     show NativeType, FfiTransformer, nativeTypeSizes, WORD_SIZE, UNKNOWN;
+import 'finalizable.dart';
 
 /// Checks and replaces calls to dart:ffi compound fields and methods.
 void transformLibraries(
@@ -51,22 +53,20 @@
     // If dart:ffi is not loaded (for real): do not do the transformation.
     return;
   }
-  final transformer = new _FfiUseSiteTransformer(
+  final transformer = new _FfiUseSiteTransformer2(
       index, coreTypes, hierarchy, diagnosticReporter, referenceFromIndex);
   libraries.forEach(transformer.visitLibrary);
 }
 
-/// Checks and replaces calls to dart:ffi compound fields and methods.
-class _FfiUseSiteTransformer extends FfiTransformer {
-  StaticTypeContext? _staticTypeContext;
-
-  bool get isFfiLibrary => currentLibrary == ffiLibrary;
-
-  // Used to create private top-level fields with unique names for each
-  // callback.
-  int callbackCount = 0;
-
-  _FfiUseSiteTransformer(
+/// Combines [_FfiUseSiteTransformer] and [FinalizableTransformer] into a single
+/// traversal.
+///
+/// This transformation is not AST-node preserving. [Expression]s and
+/// [Statement]s can be replaced by other [Expression]s and [Statement]s
+/// respectively. This means one cannot do `visitX() { super.visitX() as X }`.
+class _FfiUseSiteTransformer2 extends FfiTransformer
+    with _FfiUseSiteTransformer, FinalizableTransformer {
+  _FfiUseSiteTransformer2(
       LibraryIndex index,
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
@@ -74,6 +74,26 @@
       ReferenceFromIndex? referenceFromIndex)
       : super(index, coreTypes, hierarchy, diagnosticReporter,
             referenceFromIndex);
+}
+
+/// Checks and replaces calls to dart:ffi compound fields and methods.
+///
+/// Designed to be mixed in. Calls super.visitXXX() to visit all nodes (except
+/// the ones created by this transformation).
+///
+/// This transformation is not AST-node preserving. [Expression]s and
+/// [Statement]s can be replaced by other [Expression]s and [Statement]s
+/// respectively. This means one cannot do `visitX() { super.visitX() as X }`.
+mixin _FfiUseSiteTransformer on FfiTransformer {
+  StaticTypeContext? get staticTypeContext;
+
+  bool _inFfiTearoff = false;
+
+  bool get isFfiLibrary => currentLibrary == ffiLibrary;
+
+  // Used to create private top-level fields with unique names for each
+  // callback.
+  int callbackCount = 0;
 
   @override
   TreeNode visitLibrary(Library node) {
@@ -95,42 +115,34 @@
   }
 
   @override
-  visitField(Field node) {
-    _staticTypeContext = new StaticTypeContext(node, env);
-    var result = super.visitField(node);
-    _staticTypeContext = null;
-    return result;
-  }
-
-  @override
-  visitConstructor(Constructor node) {
-    _staticTypeContext = new StaticTypeContext(node, env);
-    var result = super.visitConstructor(node);
-    _staticTypeContext = null;
-    return result;
-  }
-
-  @override
   visitProcedure(Procedure node) {
-    if (isFfiLibrary && node.isExtensionMember) {
-      if (node == allocationTearoff ||
-          node == asFunctionTearoff ||
-          node == lookupFunctionTearoff) {
-        // Skip static checks and transformation for the tearoffs.
-        return node;
-      }
-    }
-
-    _staticTypeContext = new StaticTypeContext(node, env);
+    assert(_inFfiTearoff == false);
+    _inFfiTearoff = (isFfiLibrary &&
+        node.isExtensionMember &&
+        (node == allocationTearoff ||
+            node == asFunctionTearoff ||
+            node == lookupFunctionTearoff));
     final result = super.visitProcedure(node);
-    _staticTypeContext = null;
+    _inFfiTearoff = false;
     return result;
   }
 
   @override
-  visitStaticInvocation(StaticInvocation node) {
-    super.visitStaticInvocation(node);
+  TreeNode visitStaticInvocation(StaticInvocation node) {
+    final modifiedExpression = _visitStaticInvocation(node);
+    if (node == modifiedExpression) {
+      return super.visitStaticInvocation(node);
+    }
+    // We've just created this node. We're likely not going to need to transform
+    // this node itself. Visit its sub exprssions.
+    return super.defaultExpression(modifiedExpression);
+  }
 
+  /// Replaces nodes if they match. Does not invoke any super visit.
+  Expression _visitStaticInvocation(StaticInvocation node) {
+    if (_inFfiTearoff) {
+      return node;
+    }
     final Member target = node.target;
     try {
       if (target == abiSpecificIntegerPointerGetValue ||
@@ -141,7 +153,7 @@
           target == abiSpecificIntegerArraySetElemAt) {
         final pointer = node.arguments.positional[0];
         final pointerType =
-            pointer.getStaticType(_staticTypeContext!) as InterfaceType;
+            pointer.getStaticType(staticTypeContext!) as InterfaceType;
         _ensureNativeTypeValid(pointerType, pointer,
             allowCompounds: true, allowInlineArray: true);
 
@@ -279,7 +291,7 @@
         final DartType nativeType = InterfaceType(
             nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
         final Expression func = node.arguments.positional[0];
-        final DartType dartType = func.getStaticType(_staticTypeContext!);
+        final DartType dartType = func.getStaticType(staticTypeContext!);
 
         _ensureIsStaticFunction(func);
 
@@ -345,7 +357,7 @@
           }
 
           final DartType returnType =
-              exceptionalReturn.getStaticType(_staticTypeContext!);
+              exceptionalReturn.getStaticType(staticTypeContext!);
 
           if (!env.isSubtypeOf(returnType, funcType.returnType,
               SubtypeCheckMode.ignoringNullabilities)) {
@@ -746,13 +758,25 @@
 
   @override
   visitInstanceInvocation(InstanceInvocation node) {
-    super.visitInstanceInvocation(node);
+    final modifiedExpression = _visitInstanceInvocation(node);
+    if (node == modifiedExpression) {
+      return super.visitInstanceInvocation(node);
+    }
+    // We've just created this node. We're likely not going to need to transform
+    // this node itself. Visit its sub exprssions.
+    return super.defaultExpression(modifiedExpression);
+  }
 
+  /// Replaces nodes if they match. Does not invoke any super visit.
+  Expression _visitInstanceInvocation(InstanceInvocation node) {
+    if (_inFfiTearoff) {
+      return node;
+    }
     final Member target = node.interfaceTarget;
     try {
       if (target == elementAtMethod) {
         final DartType pointerType =
-            node.receiver.getStaticType(_staticTypeContext!);
+            node.receiver.getStaticType(staticTypeContext!);
         final DartType nativeType = _pointerTypeGetTypeArg(pointerType)!;
 
         _ensureNativeTypeValid(nativeType, node, allowCompounds: true);
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 66cf72d..d44ca15 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -65,7 +65,8 @@
     });
 
     test('compile', () async {
-      IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
+      IncrementalCompiler compiler =
+          new IncrementalCompiler(options, [main.uri]);
       IncrementalCompilerResult compilerResult = await compiler.compile();
       Component component = compilerResult.component;
 
@@ -84,7 +85,7 @@
       CompilerOptions optionsExcludeSources = getFreshOptions()
         ..embedSourceText = false;
       IncrementalCompiler compiler =
-          new IncrementalCompiler(optionsExcludeSources, main.uri);
+          new IncrementalCompiler(optionsExcludeSources, [main.uri]);
       IncrementalCompilerResult compilerResult = await compiler.compile();
       Component component = compilerResult.component;
 
@@ -111,7 +112,7 @@
           message.plainTextFormatted.forEach(print);
         };
       IncrementalCompiler compiler =
-          new IncrementalCompiler(optionsAcceptErrors, main.uri);
+          new IncrementalCompiler(optionsAcceptErrors, [main.uri]);
       await compiler.compile();
       compiler.accept();
       {
@@ -362,7 +363,8 @@
       Directory dir = mytest.createTempSync();
       File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
       File libDill = File(p.join(dir.path, p.basename(lib.path + ".dill")));
-      IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
+      IncrementalCompiler compiler =
+          new IncrementalCompiler(options, [main.uri]);
       await compileAndSerialize(mainDill, libDill, compiler);
 
       var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
@@ -389,7 +391,8 @@
       Directory dir = mytest.createTempSync();
       File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
       File libDill = File(p.join(dir.path, p.basename(lib.path + ".dill")));
-      IncrementalCompiler compiler = new IncrementalCompiler(options, lib.uri);
+      IncrementalCompiler compiler =
+          new IncrementalCompiler(options, [lib.uri]);
       await compileAndSerialize(mainDill, libDill, compiler);
 
       var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
@@ -453,7 +456,8 @@
       Directory dir = mytest.createTempSync();
       File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
       File libDill = File(p.join(dir.path, p.basename(lib.path + ".dill")));
-      IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
+      IncrementalCompiler compiler =
+          new IncrementalCompiler(options, [main.uri]);
       await compileAndSerialize(mainDill, libDill, compiler);
 
       var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
@@ -481,7 +485,8 @@
       Directory dir = mytest.createTempSync();
       File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
       File libDill = File(p.join(dir.path, p.basename(lib.path + ".dill")));
-      IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
+      IncrementalCompiler compiler =
+          new IncrementalCompiler(options, [main.uri]);
       await compileAndSerialize(mainDill, libDill, compiler);
 
       var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
@@ -642,7 +647,8 @@
       // Note that it's called 'lib1' to match with expectations from coverage
       // collector helper in this file.
       File libDill = File(p.join(dir.path, p.basename(lib1.path + ".dill")));
-      IncrementalCompiler compiler = new IncrementalCompiler(options, lib1.uri);
+      IncrementalCompiler compiler =
+          new IncrementalCompiler(options, [lib1.uri]);
       IncrementalCompilerResult compilerResult = await compiler.compile();
       Component component = compilerResult.component;
       expect(component.libraries.length, equals(1));
@@ -672,7 +678,7 @@
       // Then compile lib, run and verify coverage (un-named constructor
       // covered, and the named constructor coveraged too).
       File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
-      compilerResult = await compiler.compile(entryPoint: main.uri);
+      compilerResult = await compiler.compile(entryPoints: [main.uri]);
       component = compilerResult.component;
       expect(component.libraries.length, equals(1));
       expect(component.libraries.single.fileUri, equals(main.uri));
@@ -730,7 +736,7 @@
       int newLineForUnnamedConstructor = 8;
       int newLineForNamedConstructor = 9;
       compiler.invalidate(lib1.uri);
-      compilerResult = await compiler.compile(entryPoint: lib1.uri);
+      compilerResult = await compiler.compile(entryPoints: [lib1.uri]);
       component = compilerResult.component;
       expect(component.libraries.length, equals(1));
       expect(component.libraries.single.fileUri, equals(lib1.uri));
@@ -848,7 +854,8 @@
       File mainDill = File(p.join(dir.path, p.basename(main.path + ".dill")));
       File lib1Dill = File(p.join(dir.path, p.basename(lib1.path + ".dill")));
       File lib2Dill = File(p.join(dir.path, p.basename(lib2.path + ".dill")));
-      IncrementalCompiler compiler = new IncrementalCompiler(options, main.uri);
+      IncrementalCompiler compiler =
+          new IncrementalCompiler(options, [main.uri]);
       await compileAndSerialize(mainDill, lib1Dill, lib2Dill, compiler);
 
       var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
@@ -926,7 +933,8 @@
       fileBaz.writeAsStringSync("import 'dart:isolate';\n"
           "openReceivePortSoWeWontDie() { new RawReceivePort(); }\n");
 
-      IncrementalCompiler compiler = new IncrementalCompiler(options, file.uri);
+      IncrementalCompiler compiler =
+          new IncrementalCompiler(options, [file.uri]);
       IncrementalCompilerResult compilerResult = await compiler.compile();
       Component component = compilerResult.component;
 
@@ -1046,10 +1054,10 @@
       CompilerOptions optionsModified = getFreshOptions()
         ..packagesFileUri = packageUri;
       IncrementalCompiler compiler =
-          new IncrementalCompiler(optionsModified, packageEntry);
+          new IncrementalCompiler(optionsModified, [packageEntry]);
       {
         IncrementalCompilerResult compilerResult =
-            await compiler.compile(entryPoint: packageEntry);
+            await compiler.compile(entryPoints: [packageEntry]);
         Component component = compilerResult.component;
         File outputFile = new File('${mytest.path}/foo.dart.dill');
         await _writeProgramToFile(component, outputFile);
@@ -1075,7 +1083,7 @@
       compiler.invalidate(barUri);
       {
         IncrementalCompilerResult compilerResult =
-            await compiler.compile(entryPoint: packageEntry);
+            await compiler.compile(entryPoints: [packageEntry]);
         Component component = compilerResult.component;
         File outputFile = new File('${mytest.path}/foo1.dart.dill');
         await _writeProgramToFile(component, outputFile);
@@ -1124,12 +1132,12 @@
           ExperimentalFlag.alternativeInvalidationStrategy] = true;
 
       final IncrementalCompiler compiler =
-          new IncrementalCompiler(optionsModified, fooUri);
+          new IncrementalCompiler(optionsModified, [fooUri]);
       Library fooLib;
       Library barLib;
       {
         final IncrementalCompilerResult compilerResult =
-            await compiler.compile(entryPoint: fooUri);
+            await compiler.compile(entryPoints: [fooUri]);
         final Component component = compilerResult.component;
         expect(component.libraries.length, equals(2));
         fooLib = component.libraries.firstWhere((lib) => lib.fileUri == fooUri);
@@ -1168,7 +1176,7 @@
       compiler.invalidate(barUri);
       {
         final IncrementalCompilerResult compilerResult =
-            await compiler.compile(entryPoint: fooUri);
+            await compiler.compile(entryPoints: [fooUri]);
         final Component component = compilerResult.component;
         final Library? fooLib2 = component.libraries
             .firstWhereOrNull((lib) => lib.fileUri == fooUri);
@@ -1345,7 +1353,7 @@
         int extra() { return 22; }
       """);
       IncrementalCompiler compiler =
-          new IncrementalCompiler(options, mainFile.uri);
+          new IncrementalCompiler(options, [mainFile.uri]);
       IncrementalCompilerResult compilerResult = await compiler.compile();
       Component component = compilerResult.component;
       File mainDill = new File.fromUri(mainFile.uri.resolve("main.dill"));
@@ -1419,7 +1427,7 @@
         }
       """);
       IncrementalCompiler compiler =
-          new IncrementalCompiler(options, mainFile.uri);
+          new IncrementalCompiler(options, [mainFile.uri]);
       IncrementalCompilerResult compilerResult = await compiler.compile();
       Component component = compilerResult.component;
       File mainDill = new File.fromUri(mainFile.uri.resolve("main.dill"));
@@ -1595,7 +1603,7 @@
         CompilerOptions optionsModified = getFreshOptions()
           ..packagesFileUri = packagesFile.uri;
         IncrementalCompiler compiler =
-            new IncrementalCompiler(optionsModified, mainUri);
+            new IncrementalCompiler(optionsModified, [mainUri]);
 
         IncrementalCompilerResult compilerResult = await compiler.compile();
         Component component = compilerResult.component;
diff --git a/pkg/vm/test/kernel_front_end_test.dart b/pkg/vm/test/kernel_front_end_test.dart
index effa84d..037a610c 100644
--- a/pkg/vm/test/kernel_front_end_test.dart
+++ b/pkg/vm/test/kernel_front_end_test.dart
@@ -6,6 +6,8 @@
 
 import 'package:front_end/src/api_unstable/vm.dart'
     show computePlatformBinariesLocation;
+import 'package:kernel/ast.dart' show Component;
+import 'package:kernel/kernel.dart' show loadComponentFromBinary;
 import 'package:test/test.dart';
 import 'package:vm/kernel_front_end.dart';
 
@@ -26,6 +28,15 @@
   expect(compilerExitCode, successExitCode);
 }
 
+bool containsLibrary(Component component, String name) {
+  for (final lib in component.libraries) {
+    if (lib.importUri.pathSegments.last == name) {
+      return true;
+    }
+  }
+  return false;
+}
+
 main() {
   late Directory tempDir;
   setUp(() {
@@ -128,4 +139,28 @@
       'test-filesystem-scheme:///$mainScript',
     ]);
   }, timeout: Timeout.none);
+
+  test('multiple-sources', () async {
+    final src1 = File('${tempDir.path}/src1.dart');
+    final src2 = File('${tempDir.path}/src2.dart');
+    src1.writeAsStringSync("main() {}");
+    src2.writeAsStringSync("entryPoint() {}");
+    await testCompile([
+      '--platform',
+      platformPath(),
+      '--no-link-platform',
+      // Need to specify --packages as front-end refuses to infer
+      // its location when compiling multiple sources.
+      '--packages',
+      '$sdkDir/$packageConfigFile',
+      '--source',
+      src2.path,
+      '--output',
+      outputDill(),
+      src1.path,
+    ]);
+    final component = loadComponentFromBinary(outputDill());
+    expect(containsLibrary(component, 'src1.dart'), equals(true));
+    expect(containsLibrary(component, 'src2.dart'), equals(true));
+  }, timeout: Timeout.none);
 }
diff --git a/pkg/vm/test/transformations/ffi_test.dart b/pkg/vm/test/transformations/ffi_test.dart
index cda6097..8d4f639 100644
--- a/pkg/vm/test/transformations/ffi_test.dart
+++ b/pkg/vm/test/transformations/ffi_test.dart
@@ -48,14 +48,21 @@
   compareResultWithExpectationsFile(source, actual);
 }
 
-main() {
+void main(List<String> args) {
+  assert(args.length == 0 || args.length == 1);
+  String? filter;
+  if (args.length > 0) {
+    filter = args.first;
+  }
+
   group('ffi-transformations', () {
     final testCasesDir = Directory(pkgVmDir + '/testcases/transformations/ffi');
 
     for (var entry in testCasesDir
         .listSync(recursive: true, followLinks: false)
         .reversed) {
-      if (entry.path.endsWith(".dart")) {
+      if (entry.path.endsWith(".dart") &&
+          (filter == null || entry.path.contains(filter))) {
         test(entry.path, () => runTestCase(entry.uri));
       }
     }
diff --git a/pkg/vm/testcases/transformations/analysis_options.yaml b/pkg/vm/testcases/transformations/analysis_options.yaml
new file mode 100644
index 0000000..2db5dae
--- /dev/null
+++ b/pkg/vm/testcases/transformations/analysis_options.yaml
@@ -0,0 +1,10 @@
+# Copyright (c) 2017, 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.
+
+analyzer:
+  exclude:
+    - deferred_loading/**
+    - to_string_transformer/**
+    - type_flow/**
+    - unreachable_code_elimination/**
diff --git a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
index 328e71f..e063504 100644
--- a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
+++ b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
@@ -48,7 +48,7 @@
   static method j() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
     dart.core::int :await_jump_var = 0;
@@ -59,7 +59,7 @@
         {
           dart.core::print("J");
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
@@ -79,7 +79,7 @@
   static method h() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
     dart.core::int :await_jump_var = 0;
@@ -90,7 +90,7 @@
         {
           dart.core::print("H");
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
@@ -147,7 +147,7 @@
   static method g() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
     dart.core::int :await_jump_var = 0;
@@ -158,7 +158,7 @@
         {
           dart.core::print("G");
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
@@ -395,7 +395,7 @@
   static method main() → dynamic /* originally async */ {
     final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
     dart.core::bool* :is_sync = false;
-    FutureOr<dynamic>? :return_value;
+    dynamic :return_value;
     (dynamic) → dynamic :async_op_then;
     (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
     dart.core::int :await_jump_var = 0;
@@ -410,7 +410,7 @@
           [yield] let dynamic #t14 = dart.async::_awaitHelper(b::b(), :async_op_then, :async_op_error, :async_op) in null;
           :result;
         }
-        dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
       }
       on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
diff --git a/pkg/vm/testcases/transformations/ffi/compound_copies.dart b/pkg/vm/testcases/transformations/ffi/compound_copies.dart
index 4717b9b..534f880 100644
--- a/pkg/vm/testcases/transformations/ffi/compound_copies.dart
+++ b/pkg/vm/testcases/transformations/ffi/compound_copies.dart
@@ -1,7 +1,5 @@
 import 'dart:ffi';
 
-import 'package:ffi/ffi.dart';
-
 class Coordinate extends Struct {
   @Int64()
   external int x;
diff --git a/pkg/vm/testcases/transformations/ffi/compound_copies.dart.expect b/pkg/vm/testcases/transformations/ffi/compound_copies.dart.expect
index b1fe1cf..e7341fe 100644
--- a/pkg/vm/testcases/transformations/ffi/compound_copies.dart.expect
+++ b/pkg/vm/testcases/transformations/ffi/compound_copies.dart.expect
@@ -6,7 +6,6 @@
 import "dart:_internal" as _in;
 
 import "dart:ffi";
-import "package:ffi/ffi.dart";
 
 @#C6
 class Coordinate extends ffi::Struct {
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_async.dart b/pkg/vm/testcases/transformations/ffi/finalizable_async.dart
new file mode 100644
index 0000000..d2448ed
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_async.dart
@@ -0,0 +1,40 @@
+// 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.16
+
+// ignore_for_file: unused_local_variable
+
+import 'dart:ffi';
+
+Future<int> doSomething() async => 3;
+
+class MyFinalizable implements Finalizable {
+  Future<int> use() async {
+    return doSomething();
+  }
+
+  Future<int> use2() async {
+    return await doSomething();
+  }
+
+  Future<int> use3() {
+    return doSomething();
+  }
+}
+
+Future<int> useFinalizableAsync(Finalizable finalizable) async {
+  await Future.sync(() => 6);
+  final finalizable2 = MyFinalizable();
+  await Future.sync(() => 5);
+  final finalizable3 = MyFinalizable();
+  await Future.sync(() => 4);
+  return doSomething();
+}
+
+void main() async {
+  final finalizable = MyFinalizable();
+  final asyncResult = useFinalizableAsync(finalizable);
+  print(await asyncResult);
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_async.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_async.dart.expect
new file mode 100644
index 0000000..f72ce42
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_async.dart.expect
@@ -0,0 +1,199 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+  synthetic constructor •() → self::MyFinalizable
+    : super core::Object::•()
+    ;
+  method use() → 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 {
+        #L1:
+        {
+          :return_value = block {
+            final asy::Future<core::int> :expressionValueWrappedFinalizable = self::doSomething();
+            _in::reachabilityFence(this);
+          } =>:expressionValueWrappedFinalizable;
+          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(){() → dynamic};
+    :is_sync = true;
+    return :async_future;
+  }
+  method use2() → asy::Future<core::int> /* originally async */ {
+    final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+    core::bool* :is_sync = false;
+    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;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L2:
+        {
+          [yield] let dynamic #t1 = asy::_awaitHelper( block {
+            final asy::Future<core::int> :expressionValueWrappedFinalizable = self::doSomething();
+            _in::reachabilityFence(this);
+          } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+          final core::int :expressionValueWrappedFinalizable = _in::unsafeCast<core::int>(:result);
+          :return_value = block {
+            _in::reachabilityFence(this);
+          } =>:expressionValueWrappedFinalizable;
+          break #L2;
+        }
+        asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+        return;
+      }
+      on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+        asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+      }
+    :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+    :async_op(){() → dynamic};
+    :is_sync = true;
+    return :async_future;
+  }
+  method use3() → asy::Future<core::int> {
+    return block {
+      final asy::Future<core::int> :expressionValueWrappedFinalizable = self::doSomething();
+      _in::reachabilityFence(this);
+    } =>:expressionValueWrappedFinalizable;
+  }
+}
+static method doSomething() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  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 {
+      #L3:
+      {
+        :return_value = 3;
+        break #L3;
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
+static method useFinalizableAsync(ffi::Finalizable finalizable) → 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;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L4:
+      {
+        [yield] let dynamic #t2 = asy::_awaitHelper( block {
+          final asy::Future<core::int> :expressionValueWrappedFinalizable = asy::Future::sync<core::int>(() → core::int => 6);
+          _in::reachabilityFence(finalizable);
+        } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        final self::MyFinalizable finalizable2 = new self::MyFinalizable::•();
+        [yield] let dynamic #t3 = asy::_awaitHelper( block {
+          final asy::Future<core::int> :expressionValueWrappedFinalizable = asy::Future::sync<core::int>(() → core::int => 5);
+          _in::reachabilityFence(finalizable);
+          _in::reachabilityFence(finalizable2);
+        } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        final self::MyFinalizable finalizable3 = new self::MyFinalizable::•();
+        [yield] let dynamic #t4 = asy::_awaitHelper( block {
+          final asy::Future<core::int> :expressionValueWrappedFinalizable = asy::Future::sync<core::int>(() → core::int => 4);
+          _in::reachabilityFence(finalizable);
+          _in::reachabilityFence(finalizable2);
+          _in::reachabilityFence(finalizable3);
+        } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        :return_value = block {
+          final asy::Future<core::int> :expressionValueWrappedFinalizable = self::doSomething();
+          _in::reachabilityFence(finalizable);
+          _in::reachabilityFence(finalizable2);
+          _in::reachabilityFence(finalizable3);
+        } =>:expressionValueWrappedFinalizable;
+        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(){() → dynamic};
+  :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;
+  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 {
+      #L5:
+      {
+        final self::MyFinalizable finalizable = new self::MyFinalizable::•();
+        final asy::Future<core::int> asyncResult = self::useFinalizableAsync(finalizable);
+        [yield] let dynamic #t5 = asy::_awaitHelper( block {
+          final asy::Future<core::int> :expressionValueWrappedFinalizable = asyncResult;
+          _in::reachabilityFence(finalizable);
+        } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+        core::print(_in::unsafeCast<core::int>(:result));
+        _in::reachabilityFence(finalizable);
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart b/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart
new file mode 100644
index 0000000..6e73ab3
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart
@@ -0,0 +1,33 @@
+// 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.16
+
+// ignore_for_file: unused_local_variable
+
+import 'dart:ffi';
+
+class MyFinalizable implements Finalizable {}
+
+int doSomething() => 3;
+
+Stream<int> useFinalizableAsyncStar(Finalizable finalizable) async* {
+  final finalizable2 = MyFinalizable();
+  yield doSomething();
+  final finalizable3 = MyFinalizable();
+  await Future.sync(() => 3);
+  final finalizable4 = MyFinalizable();
+  if (DateTime.now().millisecondsSinceEpoch == 4) {
+    return;
+  }
+  yield 5;
+}
+
+void main() async {
+  final finalizable = MyFinalizable();
+  final asyncStarResult = useFinalizableAsyncStar(finalizable);
+  await for (final element in asyncStarResult) {
+    print(element);
+  }
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart.expect
new file mode 100644
index 0000000..01a6c61
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_async_star.dart.expect
@@ -0,0 +1,141 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+  synthetic constructor •() → self::MyFinalizable
+    : super core::Object::•()
+    ;
+}
+static method doSomething() → core::int
+  return 3;
+static method useFinalizableAsyncStar(ffi::Finalizable finalizable) → asy::Stream<core::int> /* originally async* */ {
+  asy::_AsyncStarStreamController<core::int>? :controller;
+  dynamic :controller_stream;
+  (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;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try
+      try {
+        #L1:
+        {
+          final self::MyFinalizable finalizable2 = new self::MyFinalizable::•();
+          if([@vm.call-site-attributes.metadata=receiverType:dart.async::_AsyncStarStreamController<dart.core::int>?] :controller.{asy::_AsyncStarStreamController::add}( block {
+            final core::int :expressionValueWrappedFinalizable = self::doSomething();
+            _in::reachabilityFence(finalizable);
+            _in::reachabilityFence(finalizable2);
+          } =>:expressionValueWrappedFinalizable){(core::int) → core::bool})
+            return null;
+          else
+            [yield] null;
+          final self::MyFinalizable finalizable3 = new self::MyFinalizable::•();
+          [yield] let dynamic #t1 = asy::_awaitHelper( block {
+            final asy::Future<core::int> :expressionValueWrappedFinalizable = asy::Future::sync<core::int>(() → core::int => 3);
+            _in::reachabilityFence(finalizable);
+            _in::reachabilityFence(finalizable2);
+            _in::reachabilityFence(finalizable3);
+          } =>:expressionValueWrappedFinalizable, :async_op_then, :async_op_error, :async_op) in null;
+          _in::unsafeCast<core::int>(:result);
+          final self::MyFinalizable finalizable4 = new self::MyFinalizable::•();
+          if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 4) {
+            {
+              _in::reachabilityFence(finalizable);
+              _in::reachabilityFence(finalizable2);
+              _in::reachabilityFence(finalizable3);
+              _in::reachabilityFence(finalizable4);
+              break #L1;
+            }
+          }
+          if([@vm.call-site-attributes.metadata=receiverType:dart.async::_AsyncStarStreamController<dart.core::int>?] :controller.{asy::_AsyncStarStreamController::add}( block {
+            final core::int :expressionValueWrappedFinalizable = 5;
+            _in::reachabilityFence(finalizable);
+            _in::reachabilityFence(finalizable2);
+            _in::reachabilityFence(finalizable3);
+            _in::reachabilityFence(finalizable4);
+          } =>:expressionValueWrappedFinalizable){(core::int) → core::bool})
+            return null;
+          else
+            [yield] null;
+          _in::reachabilityFence(finalizable2);
+          _in::reachabilityFence(finalizable3);
+          _in::reachabilityFence(finalizable4);
+          _in::reachabilityFence(finalizable);
+        }
+        return;
+      }
+      on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+        :controller.{asy::_AsyncStarStreamController::addError}(exception, stack_trace){(core::Object, core::StackTrace) → void};
+      }
+    finally {
+      :controller.{asy::_AsyncStarStreamController::close}(){() → dynamic};
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :controller = new asy::_AsyncStarStreamController::•<core::int>(:async_op);
+  :controller_stream = :controller.{asy::_AsyncStarStreamController::stream}{asy::Stream<core::int>};
+  return :controller_stream;
+}
+static method main() → void /* originally async */ {
+  final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
+  core::bool* :is_sync = false;
+  dynamic :return_value;
+  (dynamic) → dynamic :async_op_then;
+  (core::Object, core::StackTrace) → dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        final self::MyFinalizable finalizable = new self::MyFinalizable::•();
+        final asy::Stream<core::int> asyncStarResult = self::useFinalizableAsyncStar(finalizable);
+        {
+          asy::Stream<core::int> :stream = asyncStarResult;
+          asy::_StreamIterator<core::int>? :for-iterator = new asy::_StreamIterator::•<core::int>(:stream);
+          try
+            #L3:
+            while (true) {
+              dynamic #t2 = asy::_asyncStarMoveNextHelper(:stream);
+              [yield] let dynamic #t3 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(){() → asy::Future<core::bool>}, :async_op_then, :async_op_error, :async_op) in null;
+              if(_in::unsafeCast<core::bool>(:result)) {
+                final core::int element = :for-iterator.{asy::_StreamIterator::current}{core::int};
+                {
+                  core::print(element);
+                }
+              }
+              else
+                break #L3;
+            }
+          finally
+            if(!(:for-iterator.{asy::_StreamIterator::_subscription}{asy::StreamSubscription<core::int>?} == null)) {
+              [yield] let dynamic #t4 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(){() → asy::Future<dynamic>}, :async_op_then, :async_op_error, :async_op) in null;
+              :result;
+            }
+        }
+        _in::reachabilityFence(finalizable);
+      }
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+      asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+    }
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_op(){() → dynamic};
+  :is_sync = true;
+  return :async_future;
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart b/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart
new file mode 100644
index 0000000..1735d18
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart
@@ -0,0 +1,42 @@
+// 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.16
+
+import 'dart:ffi';
+
+int doSomething() => 3;
+
+class MyFinalizable implements Finalizable {
+  int use() {
+    return doSomething();
+  }
+}
+
+/// Should be transformed into:
+///
+/// ```
+/// int useFinalizableSync(Finalizable finalizable) {
+///   final result = doSomething();
+///   _reachabilityFence(finalizable);
+///   return result;
+/// }
+/// ```
+int useFinalizableSync(Finalizable finalizable) {
+  return doSomething();
+}
+
+/// Should be transformed into:
+///
+/// ```
+/// void main() {
+///   final finalizable = MyFinalizable();
+///   print(useFinalizableSync(finalizable));
+///   _reachabilityFence(finalizable);
+/// }
+/// ```
+void main() {
+  final finalizable = MyFinalizable();
+  print(useFinalizableSync(finalizable));
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart.expect
new file mode 100644
index 0000000..45da19f
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync.dart.expect
@@ -0,0 +1,32 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+  synthetic constructor •() → self::MyFinalizable
+    : super core::Object::•()
+    ;
+  method use() → core::int {
+    return block {
+      final core::int :expressionValueWrappedFinalizable = self::doSomething();
+      _in::reachabilityFence(this);
+    } =>:expressionValueWrappedFinalizable;
+  }
+}
+static method doSomething() → core::int
+  return 3;
+static method useFinalizableSync(ffi::Finalizable finalizable) → core::int {
+  return block {
+    final core::int :expressionValueWrappedFinalizable = self::doSomething();
+    _in::reachabilityFence(finalizable);
+  } =>:expressionValueWrappedFinalizable;
+}
+static method main() → void {
+  final self::MyFinalizable finalizable = new self::MyFinalizable::•();
+  core::print(self::useFinalizableSync(finalizable));
+  _in::reachabilityFence(finalizable);
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart b/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart
new file mode 100644
index 0000000..b435be9
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart
@@ -0,0 +1,227 @@
+// 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.16
+
+// ignore_for_file: unused_local_variable
+
+import 'dart:ffi';
+
+class MyFinalizable implements Finalizable {
+  int internalValue = 4;
+}
+
+void main() {
+  final finalizable = MyFinalizable();
+  {
+    final finalizable2 = MyFinalizable();
+    // Should generate: _reachabilityFence(finalizable2);
+  }
+  if (DateTime.now().millisecondsSinceEpoch == 42) {
+    // Should generate: _reachabilityFence(finalizable1);
+    return;
+  } else {
+    try {
+      final finalizable3 = MyFinalizable();
+      {
+        // Should not generate anything.
+      }
+      // Should generate: _reachabilityFence(finalizable3);
+    } on Exception {
+      final finalizable4 = MyFinalizable();
+      // Should generate: _reachabilityFence(finalizable4);
+    } finally {
+      final finalizable5 = MyFinalizable();
+      // Should generate: _reachabilityFence(finalizable5);
+    }
+    try {
+      final finalizable13 = MyFinalizable();
+      try {
+        final finalizable14 = MyFinalizable();
+        if (DateTime.now().millisecondsSinceEpoch == 100) {
+          // Caught in try.
+          // Should generate: _reachabilityFence(finalizable14);
+          throw Exception('foo');
+        }
+        if (DateTime.now().millisecondsSinceEpoch == 101) {
+          // Not caught in try.
+          // Should generate: _reachabilityFence(finalizable1);
+          // Should generate: _reachabilityFence(finalizable13);
+          // Should generate: _reachabilityFence(finalizable14);
+          throw Error();
+        }
+      } on Exception catch (e) {
+        print(e);
+        // Caught in surrounding try.
+        // Should generate: _reachabilityFence(finalizable13);
+        rethrow;
+      } finally {
+        if (DateTime.now().millisecondsSinceEpoch == 1000) {
+          // Caught in surrounding try.
+          // Should generate: _reachabilityFence(finalizable13);
+          throw Exception('bar');
+        }
+      }
+      // Should generate: _reachabilityFence(finalizable13);
+    } on Exception catch (e) {
+      print(e);
+    }
+  }
+  switch (DateTime.now().millisecondsSinceEpoch) {
+    case 1:
+    case 2:
+      final finalizable6 = MyFinalizable();
+      // Should generate: _reachabilityFence(finalizable1);
+      // Should generate: _reachabilityFence(finalizable6);
+      return;
+    Foo:
+    case 3:
+      final finalizable7 = MyFinalizable();
+      // Should generate: _reachabilityFence(finalizable7);
+      break;
+    Bar:
+    case 4:
+      final finalizable70 = MyFinalizable();
+      switch (DateTime.now().millisecondsSinceEpoch) {
+        case 5:
+          final finalizable71 = MyFinalizable();
+          if (DateTime.now().millisecondsSinceEpoch == 44) {
+            // Should generate: _reachabilityFence(finalizable70);
+            // Should generate: _reachabilityFence(finalizable71);
+            continue Bar;
+          }
+          // Should generate: _reachabilityFence(finalizable71);
+          break;
+      }
+      // Should generate: _reachabilityFence(finalizable70);
+      continue Foo;
+    default:
+      final finalizable8 = MyFinalizable();
+    // Should generate: _reachabilityFence(finalizable8);
+  }
+  labelI:
+  labelI3:
+  for (int i = 0; i < 10; i++) {
+    final finalizable9 = MyFinalizable();
+    labelJ:
+    for (int j = 0; j < 10; j++) {
+      final finalizable10 = MyFinalizable();
+      if (DateTime.now().millisecondsSinceEpoch == 42) {
+        // Should generate: _reachabilityFence(finalizable9);
+        // Should generate: _reachabilityFence(finalizable10);
+        break labelI3;
+      }
+      if (DateTime.now().millisecondsSinceEpoch == 1337) {
+        // Should generate: _reachabilityFence(finalizable9);
+        // Should generate: _reachabilityFence(finalizable10);
+        break labelI;
+      }
+      if (DateTime.now().millisecondsSinceEpoch == 1) {
+        // Should generate: _reachabilityFence(finalizable9);
+        continue labelJ;
+      }
+      if (DateTime.now().millisecondsSinceEpoch == 3) {
+        // Should generate: _reachabilityFence(finalizable9);
+        // Should generate: _reachabilityFence(finalizable10);
+        continue labelI;
+      }
+      // Should generate: _reachabilityFence(finalizable10);
+    }
+    // Should generate: _reachabilityFence(finalizable9);
+  }
+  label1:
+  {
+    final finalizable11 = MyFinalizable();
+    label2:
+    {
+      final finalizable12 = MyFinalizable();
+      if (DateTime.now().millisecondsSinceEpoch == 1) {
+        // Should generate: _reachabilityFence(finalizable11);
+        // Should generate: _reachabilityFence(finalizable12);
+        break label1;
+      }
+      if (DateTime.now().millisecondsSinceEpoch == 3) {
+        // Should generate: _reachabilityFence(finalizable12);
+        break label2;
+      }
+      // Should generate: _reachabilityFence(finalizable12);
+    }
+    // Should generate: _reachabilityFence(finalizable11);
+  }
+  for (int i = 0; i < 10; i++) {
+    final finalizable15 = MyFinalizable();
+    // Should generate: _reachabilityFence(finalizable15);
+  }
+  int i = 0;
+  while (i < 10) {
+    final finalizable16 = MyFinalizable();
+    i++;
+    // Should generate: _reachabilityFence(finalizable16);
+  }
+  for (final finalizable17
+      in Iterable<Finalizable>.generate(5, (int index) => MyFinalizable())) {
+    // Should generate: _reachabilityFence(finalizable17);
+  }
+  i = 0;
+  for (Finalizable finalizable18 = MyFinalizable(); i < 10; i++) {
+    // Should generate: _reachabilityFence(finalizable18);
+  }
+  // Should generate: _reachabilityFence(finalizable1);
+}
+
+int doSomething(int a) => a;
+
+void Function() createClosure() {
+  final finalizable20 = MyFinalizable();
+  return () {
+    if (DateTime.now().millisecondsSinceEpoch == 42) {
+      return;
+      // Should generate: _reachabilityFence(finalizable20);
+    }
+    doSomething(finalizable20.internalValue);
+    // Should generate: _reachabilityFence(finalizable20);
+  };
+  // Should generate: _reachabilityFence(finalizable20);
+}
+
+void Function() Function() Function() createNestedClosure() {
+  final finalizable40 = MyFinalizable();
+  return () {
+    final finalizable41 = MyFinalizable();
+    return () {
+      final finalizable42 = MyFinalizable();
+      return () {
+        doSomething(finalizable40.internalValue);
+        doSomething(finalizable41.internalValue);
+        doSomething(finalizable42.internalValue);
+        // Should generate: _reachabilityFence(finalizable40);
+        // Should generate: _reachabilityFence(finalizable41);
+        // Should generate: _reachabilityFence(finalizable42);
+      };
+      // Should generate: _reachabilityFence(finalizable40);
+      // Should generate: _reachabilityFence(finalizable41);
+      // Should generate: _reachabilityFence(finalizable42);
+    };
+    // Should generate: _reachabilityFence(finalizable40);
+    // Should generate: _reachabilityFence(finalizable41);
+  };
+  // Should generate: _reachabilityFence(finalizable40);
+}
+
+void Function() createBadClosure() {
+  final finalizable21 = MyFinalizable();
+  final internalValue = finalizable21.internalValue;
+  return () {
+    doSomething(internalValue);
+    // Should not generate: _reachabilityFence(finalizable21);
+  };
+  // Should generate: _reachabilityFence(finalizable21);
+}
+
+void reassignment() {
+  var finalizable30 = MyFinalizable();
+  doSomething(4);
+  // Should generate: _reachabilityFence(finalizable30);
+  finalizable30 = MyFinalizable();
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart.expect
new file mode 100644
index 0000000..987ce3e
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync2.dart.expect
@@ -0,0 +1,300 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+  field core::int internalValue = 4;
+  synthetic constructor •() → self::MyFinalizable
+    : super core::Object::•()
+    ;
+}
+static method main() → void {
+  final self::MyFinalizable finalizable = new self::MyFinalizable::•();
+  {
+    final self::MyFinalizable finalizable2 = new self::MyFinalizable::•();
+    _in::reachabilityFence(finalizable2);
+  }
+  if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+    {
+      _in::reachabilityFence(finalizable);
+      return;
+    }
+  }
+  else {
+    try
+      try {
+        final self::MyFinalizable finalizable3 = new self::MyFinalizable::•();
+        {}
+        _in::reachabilityFence(finalizable3);
+      }
+      on core::Exception catch(no-exception-var) {
+        final self::MyFinalizable finalizable4 = new self::MyFinalizable::•();
+        _in::reachabilityFence(finalizable4);
+      }
+    finally {
+      final self::MyFinalizable finalizable5 = new self::MyFinalizable::•();
+      _in::reachabilityFence(finalizable5);
+    }
+    try {
+      final self::MyFinalizable finalizable13 = new self::MyFinalizable::•();
+      try
+        try {
+          final self::MyFinalizable finalizable14 = new self::MyFinalizable::•();
+          if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 100) {
+            throw block {
+              final core::Exception :expressionValueWrappedFinalizable = core::Exception::•("foo");
+              _in::reachabilityFence(finalizable14);
+            } =>:expressionValueWrappedFinalizable;
+          }
+          if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 101) {
+            throw block {
+              final core::Error :expressionValueWrappedFinalizable = new core::Error::•();
+              _in::reachabilityFence(finalizable);
+              _in::reachabilityFence(finalizable13);
+              _in::reachabilityFence(finalizable14);
+            } =>:expressionValueWrappedFinalizable;
+          }
+          _in::reachabilityFence(finalizable14);
+        }
+        on core::Exception catch(final core::Exception e) {
+          core::print(e);
+          block {
+            _in::reachabilityFence(finalizable13);
+          } =>rethrow;
+        }
+      finally {
+        if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 1000) {
+          throw block {
+            final core::Exception :expressionValueWrappedFinalizable = core::Exception::•("bar");
+            _in::reachabilityFence(finalizable13);
+          } =>:expressionValueWrappedFinalizable;
+        }
+      }
+      _in::reachabilityFence(finalizable13);
+    }
+    on core::Exception catch(final core::Exception e) {
+      core::print(e);
+    }
+  }
+  #L1:
+  switch(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int}) {
+    #L2:
+    case #C1:
+    case #C2:
+      {
+        final self::MyFinalizable finalizable6 = new self::MyFinalizable::•();
+        {
+          _in::reachabilityFence(finalizable);
+          _in::reachabilityFence(finalizable6);
+          return;
+        }
+      }
+    #L3:
+    case #C3:
+      {
+        final self::MyFinalizable finalizable7 = new self::MyFinalizable::•();
+        {
+          _in::reachabilityFence(finalizable7);
+          break #L1;
+        }
+      }
+    #L4:
+    case #C4:
+      {
+        final self::MyFinalizable finalizable70 = new self::MyFinalizable::•();
+        #L5:
+        switch(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int}) {
+          #L6:
+          case #C5:
+            {
+              final self::MyFinalizable finalizable71 = new self::MyFinalizable::•();
+              if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 44) {
+                {
+                  _in::reachabilityFence(finalizable70);
+                  _in::reachabilityFence(finalizable71);
+                  continue #L4;
+                }
+              }
+              {
+                _in::reachabilityFence(finalizable71);
+                break #L5;
+              }
+            }
+        }
+        {
+          _in::reachabilityFence(finalizable70);
+          continue #L3;
+        }
+      }
+    #L7:
+    default:
+      {
+        final self::MyFinalizable finalizable8 = new self::MyFinalizable::•();
+        _in::reachabilityFence(finalizable8);
+      }
+  }
+  #L8:
+  for (core::int i = 0; i.{core::num::<}(10){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int})
+    #L9:
+    {
+      final self::MyFinalizable finalizable9 = new self::MyFinalizable::•();
+      for (core::int j = 0; j.{core::num::<}(10){(core::num) → core::bool}; j = j.{core::num::+}(1){(core::num) → core::int})
+        #L10:
+        {
+          final self::MyFinalizable finalizable10 = new self::MyFinalizable::•();
+          if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+            {
+              _in::reachabilityFence(finalizable9);
+              _in::reachabilityFence(finalizable10);
+              break #L8;
+            }
+          }
+          if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 1337) {
+            {
+              _in::reachabilityFence(finalizable9);
+              _in::reachabilityFence(finalizable10);
+              break #L8;
+            }
+          }
+          if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 1) {
+            {
+              _in::reachabilityFence(finalizable10);
+              break #L10;
+            }
+          }
+          if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 3) {
+            {
+              _in::reachabilityFence(finalizable9);
+              _in::reachabilityFence(finalizable10);
+              break #L9;
+            }
+          }
+          _in::reachabilityFence(finalizable10);
+        }
+      _in::reachabilityFence(finalizable9);
+    }
+  #L11:
+  {
+    final self::MyFinalizable finalizable11 = new self::MyFinalizable::•();
+    #L12:
+    {
+      final self::MyFinalizable finalizable12 = new self::MyFinalizable::•();
+      if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 1) {
+        {
+          _in::reachabilityFence(finalizable11);
+          _in::reachabilityFence(finalizable12);
+          break #L11;
+        }
+      }
+      if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 3) {
+        {
+          _in::reachabilityFence(finalizable12);
+          break #L12;
+        }
+      }
+      _in::reachabilityFence(finalizable12);
+    }
+    _in::reachabilityFence(finalizable11);
+  }
+  for (core::int i = 0; i.{core::num::<}(10){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int}) {
+    final self::MyFinalizable finalizable15 = new self::MyFinalizable::•();
+    _in::reachabilityFence(finalizable15);
+  }
+  core::int i = 0;
+  while (i.{core::num::<}(10){(core::num) → core::bool}) {
+    final self::MyFinalizable finalizable16 = new self::MyFinalizable::•();
+    i = i.{core::num::+}(1){(core::num) → core::int};
+    _in::reachabilityFence(finalizable16);
+  }
+  {
+    core::Iterator<ffi::Finalizable> :sync-for-iterator = core::Iterable::generate<ffi::Finalizable>(5, (core::int index) → self::MyFinalizable => new self::MyFinalizable::•()).{core::Iterable::iterator}{core::Iterator<ffi::Finalizable>};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
+      final ffi::Finalizable finalizable17 = :sync-for-iterator.{core::Iterator::current}{ffi::Finalizable};
+      {
+        _in::reachabilityFence(finalizable17);
+      }
+    }
+  }
+  i = 0;
+  for (ffi::Finalizable finalizable18 = new self::MyFinalizable::•(); i.{core::num::<}(10){(core::num) → core::bool}; i = i.{core::num::+}(1){(core::num) → core::int}) {
+    _in::reachabilityFence(finalizable18);
+  }
+  _in::reachabilityFence(finalizable);
+}
+static method doSomething(core::int a) → core::int
+  return a;
+static method createClosure() → () → void {
+  final self::MyFinalizable finalizable20 = new self::MyFinalizable::•();
+  return block {
+    final () → void :expressionValueWrappedFinalizable = () → void {
+      if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+        {
+          _in::reachabilityFence(finalizable20);
+          return;
+        }
+      }
+      self::doSomething(finalizable20.{self::MyFinalizable::internalValue}{core::int});
+      _in::reachabilityFence(finalizable20);
+    };
+    _in::reachabilityFence(finalizable20);
+  } =>:expressionValueWrappedFinalizable;
+}
+static method createNestedClosure() → () → () → () → void {
+  final self::MyFinalizable finalizable40 = new self::MyFinalizable::•();
+  return block {
+    final () → () → () → void :expressionValueWrappedFinalizable = () → () → () → void {
+      final self::MyFinalizable finalizable41 = new self::MyFinalizable::•();
+      return block {
+        final () → () → void :expressionValueWrappedFinalizable = () → () → void {
+          final self::MyFinalizable finalizable42 = new self::MyFinalizable::•();
+          return block {
+            final () → void :expressionValueWrappedFinalizable = () → void {
+              self::doSomething(finalizable40.{self::MyFinalizable::internalValue}{core::int});
+              self::doSomething(finalizable41.{self::MyFinalizable::internalValue}{core::int});
+              self::doSomething(finalizable42.{self::MyFinalizable::internalValue}{core::int});
+              _in::reachabilityFence(finalizable40);
+              _in::reachabilityFence(finalizable41);
+              _in::reachabilityFence(finalizable42);
+            };
+            _in::reachabilityFence(finalizable40);
+            _in::reachabilityFence(finalizable41);
+            _in::reachabilityFence(finalizable42);
+          } =>:expressionValueWrappedFinalizable;
+        };
+        _in::reachabilityFence(finalizable40);
+        _in::reachabilityFence(finalizable41);
+      } =>:expressionValueWrappedFinalizable;
+    };
+    _in::reachabilityFence(finalizable40);
+  } =>:expressionValueWrappedFinalizable;
+}
+static method createBadClosure() → () → void {
+  final self::MyFinalizable finalizable21 = new self::MyFinalizable::•();
+  final core::int internalValue = finalizable21.{self::MyFinalizable::internalValue}{core::int};
+  return block {
+    final () → void :expressionValueWrappedFinalizable = () → void {
+      self::doSomething(internalValue);
+    };
+    _in::reachabilityFence(finalizable21);
+  } =>:expressionValueWrappedFinalizable;
+}
+static method reassignment() → void {
+  self::MyFinalizable finalizable30 = new self::MyFinalizable::•();
+  self::doSomething(4);
+  finalizable30 = block {
+    final self::MyFinalizable :expressionValueWrappedFinalizable = new self::MyFinalizable::•();
+    _in::reachabilityFence(finalizable30);
+  } =>:expressionValueWrappedFinalizable;
+  _in::reachabilityFence(finalizable30);
+}
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 3
+  #C4 = 4
+  #C5 = 5
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart b/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart
new file mode 100644
index 0000000..bc83bbe
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart
@@ -0,0 +1,53 @@
+// 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.16
+
+// ignore_for_file: unused_local_variable
+
+import 'dart:ffi';
+
+class MyFinalizable implements Finalizable {
+  int _internalValue = 4;
+
+  int Function() capturingThis() {
+    return () {
+      final result = this._internalValue;
+      // Should generate: _reachabilityFence(this)
+      return result;
+    };
+    // Should generate: _reachabilityFence(this)
+  }
+
+  int Function() capturingThis2() {
+    return () {
+      return this._internalValue;
+      // Should generate: _reachabilityFence(this)
+    };
+    // Should generate: _reachabilityFence(this)
+  }
+
+  int Function() capturingThis3() {
+    return () {
+      return _internalValue;
+      // Should generate: _reachabilityFence(this)
+    };
+    // Should generate: _reachabilityFence(this)
+  }
+
+  /// Tests that captures later in the body also cause fences earlier in the body.
+  int Function() capturingThis4() {
+    return () {
+      if (DateTime.now().millisecondsSinceEpoch == 42) {
+        // Should generate: _reachabilityFence(this)
+        return 3;
+      }
+      return _internalValue;
+      // Should generate: _reachabilityFence(this)
+    };
+    // Should generate: _reachabilityFence(this)
+  }
+}
+
+void main() {}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart.expect
new file mode 100644
index 0000000..c251fa6
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync3.dart.expect
@@ -0,0 +1,66 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+  field core::int _internalValue = 4;
+  synthetic constructor •() → self::MyFinalizable
+    : super core::Object::•()
+    ;
+  method capturingThis() → () → core::int {
+    return block {
+      final () → core::int :expressionValueWrappedFinalizable = () → core::int {
+        final core::int result = this.{self::MyFinalizable::_internalValue}{core::int};
+        return block {
+          final core::int :expressionValueWrappedFinalizable = result;
+          _in::reachabilityFence(this);
+        } =>:expressionValueWrappedFinalizable;
+      };
+      _in::reachabilityFence(this);
+    } =>:expressionValueWrappedFinalizable;
+  }
+  method capturingThis2() → () → core::int {
+    return block {
+      final () → core::int :expressionValueWrappedFinalizable = () → core::int {
+        return block {
+          final core::int :expressionValueWrappedFinalizable = this.{self::MyFinalizable::_internalValue}{core::int};
+          _in::reachabilityFence(this);
+        } =>:expressionValueWrappedFinalizable;
+      };
+      _in::reachabilityFence(this);
+    } =>:expressionValueWrappedFinalizable;
+  }
+  method capturingThis3() → () → core::int {
+    return block {
+      final () → core::int :expressionValueWrappedFinalizable = () → core::int {
+        return block {
+          final core::int :expressionValueWrappedFinalizable = this.{self::MyFinalizable::_internalValue}{core::int};
+          _in::reachabilityFence(this);
+        } =>:expressionValueWrappedFinalizable;
+      };
+      _in::reachabilityFence(this);
+    } =>:expressionValueWrappedFinalizable;
+  }
+  method capturingThis4() → () → core::int {
+    return block {
+      final () → core::int :expressionValueWrappedFinalizable = () → core::int {
+        if(new core::DateTime::now().{core::DateTime::millisecondsSinceEpoch}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+          return block {
+            final core::int :expressionValueWrappedFinalizable = 3;
+            _in::reachabilityFence(this);
+          } =>:expressionValueWrappedFinalizable;
+        }
+        return block {
+          final core::int :expressionValueWrappedFinalizable = this.{self::MyFinalizable::_internalValue}{core::int};
+          _in::reachabilityFence(this);
+        } =>:expressionValueWrappedFinalizable;
+      };
+      _in::reachabilityFence(this);
+    } =>:expressionValueWrappedFinalizable;
+  }
+}
+static method main() → void {}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart b/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart
new file mode 100644
index 0000000..535486f
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.16
+
+// ignore_for_file: unused_local_variable
+
+import 'dart:ffi';
+
+class MyFinalizable implements Finalizable {}
+
+int doSomething() => 3;
+
+Iterable<int> useFinalizableSyncStar(Finalizable finalizable) sync* {
+  // _in::reachabilityFence(finalizable);
+  yield doSomething();
+  final finalizable2 = MyFinalizable();
+  // _in::reachabilityFence(finalizable);
+  // _in::reachabilityFence(finalizable2);
+  yield 5;
+  final finalizable3 = MyFinalizable();
+  // _in::reachabilityFence(finalizable);
+  // _in::reachabilityFence(finalizable2);
+  // _in::reachabilityFence(finalizable3);
+  yield 10;
+  // _in::reachabilityFence(finalizable);
+  // _in::reachabilityFence(finalizable2);
+  // _in::reachabilityFence(finalizable3);
+}
+
+void main() {
+  final finalizable = MyFinalizable();
+  for (final element in useFinalizableSyncStar(finalizable)) {
+    print(element);
+  }
+}
diff --git a/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart.expect b/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart.expect
new file mode 100644
index 0000000..fc74d17
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/finalizable_sync_star.dart.expect
@@ -0,0 +1,71 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+
+class MyFinalizable extends core::Object implements ffi::Finalizable {
+  synthetic constructor •() → self::MyFinalizable
+    : super core::Object::•()
+    ;
+}
+static method doSomething() → core::int
+  return 3;
+static method useFinalizableSyncStar(ffi::Finalizable finalizable) → core::Iterable<core::int> /* originally sync* */ {
+  function :sync_op_gen() → (core::_SyncIterator<dynamic>?, dynamic, dynamic) → core::bool* {
+    core::int :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    ffi::Finalizable finalizable = finalizable;
+    function :sync_op(core::_SyncIterator<dynamic>? :iterator, dynamic :exception, dynamic :stack_trace) → core::bool* yielding {
+      {
+        {
+          [@vm.call-site-attributes.metadata=receiverType:dart.core::_SyncIterator<dynamic>?] :iterator.{core::_SyncIterator::_current} = block {
+            final core::int :expressionValueWrappedFinalizable = self::doSomething();
+            _in::reachabilityFence(finalizable);
+          } =>:expressionValueWrappedFinalizable;
+          [yield] true;
+        }
+        final self::MyFinalizable finalizable2 = new self::MyFinalizable::•();
+        {
+          [@vm.call-site-attributes.metadata=receiverType:dart.core::_SyncIterator<dynamic>?] :iterator.{core::_SyncIterator::_current} = block {
+            final core::int :expressionValueWrappedFinalizable = 5;
+            _in::reachabilityFence(finalizable);
+            _in::reachabilityFence(finalizable2);
+          } =>:expressionValueWrappedFinalizable;
+          [yield] true;
+        }
+        final self::MyFinalizable finalizable3 = new self::MyFinalizable::•();
+        {
+          [@vm.call-site-attributes.metadata=receiverType:dart.core::_SyncIterator<dynamic>?] :iterator.{core::_SyncIterator::_current} = block {
+            final core::int :expressionValueWrappedFinalizable = 10;
+            _in::reachabilityFence(finalizable);
+            _in::reachabilityFence(finalizable2);
+            _in::reachabilityFence(finalizable3);
+          } =>:expressionValueWrappedFinalizable;
+          [yield] true;
+        }
+        _in::reachabilityFence(finalizable2);
+        _in::reachabilityFence(finalizable3);
+        _in::reachabilityFence(finalizable);
+      }
+      return false;
+    }
+    return :sync_op;
+  }
+  return new core::_SyncIterable::•<core::int>(:sync_op_gen);
+}
+static method main() → void {
+  final self::MyFinalizable finalizable = new self::MyFinalizable::•();
+  {
+    core::Iterator<core::int> :sync-for-iterator = self::useFinalizableSyncStar(finalizable).{core::Iterable::iterator}{core::Iterator<core::int>};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
+      final core::int element = :sync-for-iterator.{core::Iterator::current}{core::int};
+      {
+        core::print(element);
+      }
+    }
+  }
+  _in::reachabilityFence(finalizable);
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
index fc5a260..0f8f453 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
@@ -45,7 +45,7 @@
 static method baz() → asy::Future<dynamic> /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -57,7 +57,7 @@
         :return_value = new self::B::•();
         break #L2;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
@@ -72,7 +72,7 @@
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
   core::bool* :is_sync = false;
-  FutureOr<dynamic>? :return_value;
+  dynamic :return_value;
   (dynamic) → dynamic :async_op_then;
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
@@ -88,7 +88,7 @@
         [yield] let dynamic #t2 = asy::_awaitHelper([@vm.direct-call.metadata=#lib::A.bar??] [@vm.inferred-type.metadata=dart.async::_Future<dynamic> (receiver not int)] :async_temporary_0{dynamic}.bar(:result), :async_op_then, :async_op_error, :async_op) in null;
         :result;
       }
-      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
     }
     on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
index 9c9d0a4..950e802 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
@@ -22,6 +22,6 @@
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3395,getterSelectorId:3396]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3399,getterSelectorId:3400]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
     return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
index c4d4faf..5ccaefa 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
@@ -51,6 +51,6 @@
   synthetic constructor •() → self::ConstClass
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3399,getterSelectorId:3400]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3403,getterSelectorId:3404]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
     return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
 }
diff --git a/pkg/vm_service/java/src/org/dartlang/vm/service/element/Element.java b/pkg/vm_service/java/src/org/dartlang/vm/service/element/Element.java
index cdee4bd..7fc05db 100644
--- a/pkg/vm_service/java/src/org/dartlang/vm/service/element/Element.java
+++ b/pkg/vm_service/java/src/org/dartlang/vm/service/element/Element.java
@@ -92,7 +92,8 @@
     int size = array.size();
     List<String> result = new ArrayList<>();
     for (int index = 0; index < size; ++index) {
-      result.add(array.get(index).getAsString());
+      final JsonElement elem = array.get(index);
+      result.add(elem == JsonNull.INSTANCE ? null : elem.getAsString());
     }
     return result;
   }
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 4905a0d..f22ff9d 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -3420,7 +3420,7 @@
 }
 
 /// A `Code` object represents compiled code in the Dart VM.
-class Code extends ObjRef implements CodeRef {
+class Code extends Obj implements CodeRef {
   static Code? parse(Map<String, dynamic>? json) =>
       json == null ? null : Code._fromJson(json);
 
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 99c5e18..dc91e52 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -14,6 +14,7 @@
 
 dev_dependencies:
   async: ^2.5.0
+  expect: any
   markdown: ^4.0.0-nullsafety.0
   mockito: ^5.0.0-nullsafety.1
   path: ^1.8.0
diff --git a/pkg/vm_service/test/causal_async_stack_contents_test.dart b/pkg/vm_service/test/causal_async_stack_contents_test.dart
new file mode 100644
index 0000000..b634f10
--- /dev/null
+++ b/pkg/vm_service/test/causal_async_stack_contents_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2017, 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.
+//
+// VMOptions=--lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const LINE_C = 20;
+const LINE_A = 26;
+const LINE_B = 32;
+
+foobar() {
+  debugger();
+  print('foobar'); // LINE_C.
+}
+
+helper() async {
+  await 0; // force async gap
+  debugger();
+  print('helper'); // LINE_A.
+  foobar();
+}
+
+testMain() {
+  debugger();
+  helper(); // LINE_B.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // No causal frames because we are in a completely synchronous stack.
+    expect(stack.asyncCausalFrames, isNull);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // Has causal frames (we are inside an async function)
+    expect(stack.asyncCausalFrames, isNotNull);
+    expect(
+      stack.asyncCausalFrames![0].function!.owner.name,
+      contains('helper'),
+    );
+    // "helper" is not await'ed.
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // Has causal frames (we are inside a function called by an async function)
+    expect(stack.asyncCausalFrames, isNotNull);
+    final asyncStack = stack.asyncCausalFrames!;
+    expect(asyncStack[0].function!.name, contains('foobar'));
+    expect(asyncStack[1].function!.owner.name, contains('helper'));
+    // "helper" is not await'ed.
+  },
+];
+
+main(args) => runIsolateTestsSynchronous(
+      args,
+      tests,
+      'causal_async_stack_contents_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: extraDebuggingArgs,
+    );
diff --git a/pkg/vm_service/test/causal_async_stack_presence_test.dart b/pkg/vm_service/test/causal_async_stack_presence_test.dart
new file mode 100644
index 0000000..48bf16e
--- /dev/null
+++ b/pkg/vm_service/test/causal_async_stack_presence_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2017, 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.
+//
+// VMOptions=--lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const LINE_C = 19;
+const LINE_A = 25;
+const LINE_B = 31;
+
+foobar() {
+  debugger();
+  print('foobar'); // LINE_C.
+}
+
+helper() async {
+  await 0; // Yield. The rest will run async.
+  debugger();
+  print('helper'); // LINE_A.
+  foobar();
+}
+
+testMain() {
+  debugger();
+  helper(); // LINE_B.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // No causal frames because we are in a completely synchronous stack.
+    // Async function hasn't yielded yet.
+    expect(stack.asyncCausalFrames, isNull);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // Async function has yielded once, so it's now running async.
+    expect(stack.asyncCausalFrames, isNotNull);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // Has causal frames (we are inside a function called by an async function)
+    expect(stack.asyncCausalFrames, isNotNull);
+  },
+];
+
+main(args) => runIsolateTestsSynchronous(
+      args,
+      tests,
+      'causal_async_stack_presence_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: extraDebuggingArgs,
+    );
diff --git a/pkg/vm_service/test/causal_async_star_stack_contents_test.dart b/pkg/vm_service/test/causal_async_star_stack_contents_test.dart
new file mode 100644
index 0000000..4795850
--- /dev/null
+++ b/pkg/vm_service/test/causal_async_star_stack_contents_test.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2017, 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.
+//
+// VMOptions=--lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const LINE_A = 29;
+const LINE_B = 21;
+const LINE_C = 23;
+
+foobar() async* {
+  await 0; // force async gap
+  debugger();
+  yield 1; // LINE_B.
+  debugger();
+  yield 2; // LINE_C.
+}
+
+helper() async {
+  await 0; // force async gap
+  debugger();
+  print('helper'); // LINE_A.
+  await for (var i in foobar()) {
+    print('helper $i');
+  }
+}
+
+testMain() {
+  helper();
+}
+
+final tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // No causal frames because we are in a completely synchronous stack.
+    expect(stack.asyncCausalFrames, isNotNull);
+    final asyncStack = stack.asyncCausalFrames!;
+    expect(asyncStack.length, greaterThanOrEqualTo(1));
+    expect(asyncStack[0].function!.owner.name, contains('helper'));
+    // helper isn't awaited.
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // Has causal frames (we are inside an async function)
+    expect(stack.asyncCausalFrames, isNotNull);
+    final asyncStack = stack.asyncCausalFrames!;
+    expect(asyncStack.length, greaterThanOrEqualTo(3));
+    expect(asyncStack[0].function!.owner.name, contains('foobar'));
+    expect(asyncStack[1].kind, equals(FrameKind.kAsyncSuspensionMarker));
+    expect(asyncStack[2].function!.owner.name, contains('helper'));
+    expect(asyncStack[3].kind, equals(FrameKind.kAsyncSuspensionMarker));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // Has causal frames (we are inside a function called by an async function)
+    expect(stack.asyncCausalFrames, isNotNull);
+    final asyncStack = stack.asyncCausalFrames!;
+    expect(asyncStack.length, greaterThanOrEqualTo(4));
+    final script = await service.getObject(
+        isolateRef.id!, asyncStack[0].location!.script!.id!) as Script;
+    expect(asyncStack[0].function!.owner.name, contains('foobar'));
+    expect(
+      script.getLineNumberFromTokenPos(asyncStack[0].location!.tokenPos!),
+      LINE_C,
+    );
+    expect(asyncStack[1].kind, equals(FrameKind.kAsyncSuspensionMarker));
+    expect(asyncStack[2].function!.owner.name, contains('helper'));
+    expect(
+      script.getLineNumberFromTokenPos(asyncStack[2].location!.tokenPos!),
+      30,
+    );
+    expect(asyncStack[3].kind, equals(FrameKind.kAsyncSuspensionMarker));
+  },
+];
+
+main(args) => runIsolateTestsSynchronous(
+      args,
+      tests,
+      'causal_async_star_stack_contents_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: extraDebuggingArgs,
+    );
diff --git a/pkg/vm_service/test/causal_async_star_stack_presence_test.dart b/pkg/vm_service/test/causal_async_star_stack_presence_test.dart
new file mode 100644
index 0000000..5ba0a7d
--- /dev/null
+++ b/pkg/vm_service/test/causal_async_star_stack_presence_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2017, 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.
+//
+// VMOptions=--lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const LINE_A = 26;
+const LINE_B = 19;
+const LINE_C = 21;
+
+foobar() async* {
+  debugger();
+  yield 1; // LINE_B.
+  debugger();
+  yield 2; // LINE_C.
+}
+
+helper() async {
+  debugger();
+  print('helper'); // LINE_A.
+  await for (var i in foobar()) {
+    print('helper $i');
+  }
+}
+
+testMain() {
+  helper();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // No causal frames because we are in a completely synchronous stack.
+    expect(stack.asyncCausalFrames, isNull);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // Has causal frames (we are inside an async function)
+    expect(stack.asyncCausalFrames, isNotNull);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  (VmService service, IsolateRef isolateRef) async {
+    Stack stack = await service.getStack(isolateRef.id!);
+    // Has causal frames (we are inside a function called by an async function)
+    expect(stack.asyncCausalFrames, isNotNull);
+  },
+];
+
+main(args) => runIsolateTestsSynchronous(
+      args,
+      tests,
+      'causal_async_star_stack_presence_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: extraDebuggingArgs,
+    );
diff --git a/pkg/vm_service/test/code_test.dart b/pkg/vm_service/test/code_test.dart
new file mode 100644
index 0000000..3803827
--- /dev/null
+++ b/pkg/vm_service/test/code_test.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2015, 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 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'common/test_helper.dart';
+
+int counter = 0;
+
+void funcB() {
+  counter++; // line 13
+  if (counter % 100000000 == 0) {
+    print(counter);
+  }
+}
+
+void funcA() {
+  funcB();
+}
+
+void testFunction() {
+  while (true) {
+    funcA();
+  }
+}
+
+var tests = <IsolateTest>[
+// Go to breakpoint at line 13.
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final rootLib =
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+    // Set up a listener to wait for breakpoint events.
+    final completer = Completer<void>();
+
+    late final StreamSubscription subscription;
+    subscription = service.onDebugEvent.listen((event) async {
+      if (event.kind == EventKind.kPauseBreakpoint) {
+        print('Breakpoint reached');
+        await service.streamCancel(EventStreams.kDebug);
+        await subscription.cancel();
+        completer.complete();
+      }
+    });
+    await service.streamListen(EventStreams.kDebug);
+
+    // Add the breakpoint.
+    final script = rootLib.scripts![0];
+    final line = 13;
+    await service.addBreakpoint(isolateId, script.id!, line);
+    await completer.future; // Wait for breakpoint reached.
+  },
+
+// Inspect code objects for top two frames.
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    Stack stack = await service.getStack(isolateId);
+    // Make sure we are in the right place.
+    expect(stack.frames!.length, greaterThanOrEqualTo(3));
+    final frame0 = stack.frames![0];
+    final frame1 = stack.frames![1];
+    expect(frame0.function!.name, equals('funcB'));
+    expect(frame1.function!.name, equals('funcA'));
+    final codeId0 = frame0.code!.id!;
+    final codeId1 = frame1.code!.id!;
+
+    // Load code from frame 0.
+    Code code = await service.getObject(isolateId, codeId0) as Code;
+    expect(code.name, contains('funcB'));
+    expect(code.json!['_disassembly'], isNotNull);
+    expect(code.json!['_disassembly'].length, greaterThan(0));
+
+    // Load code from frame 0.
+    code = await service.getObject(isolateId, codeId1) as Code;
+    expect(code.type, equals('Code'));
+    expect(code.name, contains('funcA'));
+    expect(code.json!['_disassembly'], isNotNull);
+    expect(code.json!['_disassembly'].length, greaterThan(0));
+  },
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'code_test.dart',
+      testeeConcurrent: testFunction,
+    );
diff --git a/pkg/vm_service/test/column_breakpoint_test.dart b/pkg/vm_service/test/column_breakpoint_test.dart
new file mode 100644
index 0000000..8989f0d
--- /dev/null
+++ b/pkg/vm_service/test/column_breakpoint_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2019, 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 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+code() {
+  var b = [1, 2].map((i) => i == 0).toList();
+  print(b.length);
+}
+
+const int LINE = 9;
+const int COLUMN = 29;
+const String shortFile = "column_breakpoint_test.dart";
+const String breakpointFile =
+    "package:observatory_test_package/column_breakpoint_test.dart";
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$shortFile:${LINE + 0}:23", // on 'i == 0'
+  "$shortFile:${LINE + 0}:23", // iterate twice
+  "$shortFile:${LINE + 1}:3" //on 'b.length'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLineColumn(LINE, COLUMN), // on 'i == 0'
+  setBreakpointAtLineColumn(LINE + 1, 9), // on 'b.length'
+  resumeProgramRecordingStops(stops, false),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(
+    args,
+    tests,
+    'column_breakpoint_test.dart',
+    testeeConcurrent: code,
+    pause_on_start: true,
+    pause_on_exit: true,
+  );
+}
diff --git a/pkg/vm_service/test/common/service_test_common.dart b/pkg/vm_service/test/common/service_test_common.dart
index 6e84d16..268060a 100644
--- a/pkg/vm_service/test/common/service_test_common.dart
+++ b/pkg/vm_service/test/common/service_test_common.dart
@@ -142,6 +142,25 @@
   };
 }
 
+IsolateTest setBreakpointAtLineColumn(int line, int column) {
+  return (VmService service, IsolateRef isolateRef) async {
+    print("Setting breakpoint for line $line column $column");
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final lib =
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+    ScriptRef script = lib.scripts!.firstWhere((s) => s.uri == lib.uri);
+    Breakpoint bpt = await service.addBreakpoint(
+      isolateId,
+      script.id!,
+      line,
+      column: column,
+    );
+    print("Breakpoint is $bpt");
+    expect(bpt, isNotNull);
+  };
+}
+
 IsolateTest stoppedAtLine(int line) {
   return (VmService service, IsolateRef isolateRef) async {
     print("Checking we are at line $line");
@@ -211,6 +230,34 @@
   }
 }
 
+Future<void> resumeAndAwaitEvent(
+  VmService service,
+  IsolateRef isolateRef,
+  String streamId,
+  Function(Event) onEvent,
+) async {
+  final completer = Completer<void>();
+  late final StreamSubscription sub;
+  sub = service.onEvent(streamId).listen((event) async {
+    await onEvent(event);
+    await sub.cancel();
+    await service.streamCancel(streamId);
+    completer.complete();
+  });
+
+  await service.streamListen(streamId);
+  await service.resume(isolateRef.id!);
+  return completer.future;
+}
+
+IsolateTest resumeIsolateAndAwaitEvent(
+  String streamId,
+  Function(Event) onEvent,
+) {
+  return (VmService service, IsolateRef isolate) async =>
+      resumeAndAwaitEvent(service, isolate, streamId, onEvent);
+}
+
 Future<void> stepOver(VmService service, IsolateRef isolateRef) async {
   await service.streamListen(EventStreams.kDebug);
   await _subscribeDebugStream(service);
@@ -242,14 +289,13 @@
     subscription = service.onDebugEvent.listen((event) async {
       if (event.kind == EventKind.kPauseBreakpoint) {
         final stack = await service.getStack(isolateRef.id!);
-        final frames = stack.frames!;
-        expect(frames.length, greaterThanOrEqualTo(2));
+        expect(stack.frames!.length, greaterThanOrEqualTo(2));
 
         String brokeAt =
-            await _locationToString(service, isolateRef, frames[0]);
+            await _locationToString(service, isolateRef, stack.frames![0]);
         if (includeCaller) {
           brokeAt =
-              '$brokeAt (${await _locationToString(service, isolateRef, frames[1])})';
+              '$brokeAt (${await _locationToString(service, isolateRef, stack.frames![1])})';
         }
         recordStops.add(brokeAt);
         await service.resume(isolateRef.id!);
diff --git a/pkg/vm_service/test/common/test_helper.dart b/pkg/vm_service/test/common/test_helper.dart
index 62ced95..a5001d0 100644
--- a/pkg/vm_service/test/common/test_helper.dart
+++ b/pkg/vm_service/test/common/test_helper.dart
@@ -351,6 +351,8 @@
 
     await service.streamListen(EventStreams.kIsolate);
 
+    await service.streamListen(EventStreams.kIsolate);
+
     // The isolate may have started before we subscribed.
     vm = await service.getVM();
     if (vmIsolates.isNotEmpty) {
diff --git a/pkg/vm_service/test/contexts_test.dart b/pkg/vm_service/test/contexts_test.dart
new file mode 100644
index 0000000..4047e7a
--- /dev/null
+++ b/pkg/vm_service/test/contexts_test.dart
@@ -0,0 +1,151 @@
+// Copyright (c) 2014, 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:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+// Make sure these variables are not removed by the tree shaker.
+@pragma("vm:entry-point")
+var cleanBlock;
+@pragma("vm:entry-point")
+var copyingBlock;
+@pragma("vm:entry-point")
+var fullBlock;
+@pragma("vm:entry-point")
+var fullBlockWithChain;
+
+Function genCleanBlock() {
+  block(x) => x;
+  return block;
+}
+
+Function genCopyingBlock() {
+  final x = 'I could be copied into the block';
+  block() => x;
+  return block;
+}
+
+Function genFullBlock() {
+  var x = 42; // I must captured in a context.
+  block() => x;
+  x++;
+  return block;
+}
+
+Function genFullBlockWithChain() {
+  var x = 420; // I must captured in a context.
+  outerBlock() {
+    var y = 4200;
+    innerBlock() => x + y;
+    y++;
+    return innerBlock;
+  }
+
+  x++;
+  return outerBlock();
+}
+
+void script() {
+  cleanBlock = genCleanBlock();
+  copyingBlock = genCopyingBlock();
+  fullBlock = genFullBlock();
+  fullBlockWithChain = genFullBlockWithChain();
+}
+
+var tests = <IsolateTest>[
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final lib =
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+    final field = await service.getObject(
+      isolateId,
+      lib.variables!.singleWhere((v) => v.name == 'cleanBlock').id!,
+    ) as Field;
+
+    Instance block =
+        await service.getObject(isolateId, field.staticValue!.id!) as Instance;
+    expect(block.closureFunction, isNotNull);
+    expect(block.closureContext, isNull);
+  },
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final lib =
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+    final field = await service.getObject(
+      isolateId,
+      lib.variables!.singleWhere((v) => v.name == 'copyingBlock').id!,
+    ) as Field;
+    Instance block =
+        await service.getObject(isolateId, field.staticValue!.id!) as Instance;
+
+    expect(block.closureContext, isNotNull);
+    expect(block.closureContext!.length, equals(1));
+    final ctxt = await service.getObject(isolateId, block.closureContext!.id!)
+        as Context;
+    expect(ctxt.variables!.single.value.kind, InstanceKind.kString);
+    expect(
+      ctxt.variables!.single.value.valueAsString,
+      'I could be copied into the block',
+    );
+    expect(ctxt.parent, isNull);
+  },
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final lib =
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+    final field = await service.getObject(
+      isolateId,
+      lib.variables!.singleWhere((v) => v.name == 'fullBlock').id!,
+    ) as Field;
+    Instance block =
+        await service.getObject(isolateId, field.staticValue!.id!) as Instance;
+
+    expect(block.closureContext, isNotNull);
+    expect(block.closureContext!.length, equals(1));
+    final ctxt = await service.getObject(isolateId, block.closureContext!.id!)
+        as Context;
+
+    expect(ctxt.variables!.single.value.kind, InstanceKind.kInt);
+    expect(ctxt.variables!.single.value.valueAsString, '43');
+    expect(ctxt.parent, isNull);
+  },
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final lib =
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+    final field = await service.getObject(
+      isolateId,
+      lib.variables!.singleWhere((v) => v.name == 'fullBlockWithChain').id!,
+    ) as Field;
+    final block =
+        await service.getObject(isolateId, field.staticValue!.id!) as Instance;
+
+    expect(block.closureContext, isNotNull);
+    expect(block.closureContext!.length, equals(1));
+    final ctxt = await service.getObject(isolateId, block.closureContext!.id!)
+        as Context;
+    expect(ctxt.variables!.single.value.kind, InstanceKind.kInt);
+    expect(ctxt.variables!.single.value.valueAsString, '4201');
+    expect(ctxt.parent!.length, 1);
+
+    final outerCtxt =
+        await service.getObject(isolateId, ctxt.parent!.id!) as Context;
+    expect(outerCtxt.variables!.single.value.kind, InstanceKind.kInt);
+    expect(outerCtxt.variables!.single.value.valueAsString, '421');
+    expect(outerCtxt.parent, isNull);
+  },
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+      'contexts_test.dart',
+      testeeBefore: script,
+    );
diff --git a/pkg/vm_service/test/coverage_const_field_async_closure_test.dart b/pkg/vm_service/test/coverage_const_field_async_closure_test.dart
new file mode 100644
index 0000000..8a7430d
--- /dev/null
+++ b/pkg/vm_service/test/coverage_const_field_async_closure_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2019, 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:developer';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const int LINE_A = 17; // LINE_A - 4
+const int LINE_B = 25; // LINE_A - 3
+
+class Bar {
+  static const String field = "field"; // LINE_A
+}
+
+Future<String> fooAsync(int x) async {
+  if (x == 42) {
+    return '*' * x;
+  }
+  return List.generate(x, (_) => 'xyzzy').join(' ');
+} // LINE_B
+
+Future<void> testFunction() async {
+  await Future.delayed(Duration(milliseconds: 500));
+  // ignore: unawaited_futures
+  fooAsync(42).then((_) {});
+  debugger();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final stack = await service.getStack(isolateId);
+
+    // Make sure we are in the right place.
+    expect(stack.frames!.length, greaterThanOrEqualTo(1));
+    // Async closure of testFunction
+    expect(stack.frames![0].function!.name, 'async_op');
+
+    final rootLib =
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+    final script = await service.getObject(
+        isolateId, rootLib.scripts!.first.id!) as Script;
+
+    final report = await service.getSourceReport(
+      isolateId,
+      ['Coverage'],
+      scriptId: script.id!,
+      forceCompile: true,
+    );
+    int match = 0;
+    for (var range in report.ranges!) {
+      for (int i in range.coverage!.hits!) {
+        int? line = script.getLineNumberFromTokenPos(i);
+        if (line == null) {
+          throw FormatException('token ${i} was missing source location');
+        }
+        // Check LINE.
+        if (line == LINE_A || line == LINE_A - 3 || line == LINE_A - 4) {
+          match = match + 1;
+        }
+        // _clearAsyncThreadStackTrace should have an invalid token position.
+        expect(line, isNot(LINE_B));
+      }
+    }
+    // Neither LINE nor Bar.field should be added into coverage.
+    expect(match, 0);
+  },
+  resumeIsolate
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'coverage_const_field_async_closure_test.dart',
+      testeeConcurrent: testFunction,
+    );
diff --git a/pkg/vm_service/test/coverage_leaf_function_test.dart b/pkg/vm_service/test/coverage_leaf_function_test.dart
index 36b9a88..95ec6f8 100644
--- a/pkg/vm_service/test/coverage_leaf_function_test.dart
+++ b/pkg/vm_service/test/coverage_leaf_function_test.dart
@@ -3,8 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:developer';
+
 import 'package:test/test.dart';
 import 'package:vm_service/vm_service.dart';
+
 import 'common/service_test_common.dart';
 import 'common/test_helper.dart';
 
@@ -38,7 +40,7 @@
     expect(stack.frames!.length, greaterThanOrEqualTo(1));
     expect(stack.frames![0].function!.name, 'testFunction');
 
-    final Library root =
+    final root =
         await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
     FuncRef funcRef =
         root.functions!.singleWhere((f) => f.name == 'leafFunction');
@@ -69,12 +71,12 @@
   coverageTest(
     {
       'scriptIndex': 0,
-      'startPos': 397,
-      'endPos': 447,
+      'startPos': 399,
+      'endPos': 449,
       'compiled': true,
       'coverage': {
         'hits': [],
-        'misses': [397]
+        'misses': [399]
       }
     },
     reportLines: false,
@@ -82,12 +84,12 @@
   coverageTest(
     {
       'scriptIndex': 0,
-      'startPos': 397,
-      'endPos': 447,
+      'startPos': 399,
+      'endPos': 449,
       'compiled': true,
       'coverage': {
         'hits': [],
-        'misses': [11]
+        'misses': [13]
       }
     },
     reportLines: true,
@@ -97,11 +99,11 @@
   coverageTest(
     {
       'scriptIndex': 0,
-      'startPos': 397,
-      'endPos': 447,
+      'startPos': 399,
+      'endPos': 449,
       'compiled': true,
       'coverage': {
-        'hits': [397],
+        'hits': [399],
         'misses': []
       }
     },
@@ -110,11 +112,11 @@
   coverageTest(
     {
       'scriptIndex': 0,
-      'startPos': 397,
-      'endPos': 447,
+      'startPos': 399,
+      'endPos': 449,
       'compiled': true,
       'coverage': {
-        'hits': [11],
+        'hits': [13],
         'misses': []
       }
     },
diff --git a/pkg/vm_service/test/coverage_optimized_function_test.dart b/pkg/vm_service/test/coverage_optimized_function_test.dart
new file mode 100644
index 0000000..129fddc7
--- /dev/null
+++ b/pkg/vm_service/test/coverage_optimized_function_test.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2017, 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.
+// VMOptions=--no_background_compilation --optimization_counter_threshold=10
+
+import 'dart:developer';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+String optimizedFunction() {
+  return 5.toString() + 3.toString();
+}
+
+void testFunction() {
+  for (var i = 0; i < 20; i++) {
+    optimizedFunction();
+  }
+  debugger();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final stack = await service.getStack(isolateId);
+
+    // Make sure we are in the right place.
+    expect(stack.frames!.length, greaterThanOrEqualTo(1));
+    expect(stack.frames![0].function!.name, 'testFunction');
+
+    final root =
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+    final func = await service.getObject(
+      isolateId,
+      root.functions!.singleWhere((f) => f.name == 'optimizedFunction').id!,
+    ) as Func;
+
+    final report = await service.getSourceReport(
+      isolateId,
+      ['Coverage'],
+      scriptId: func.location!.script!.id!,
+      tokenPos: func.location!.tokenPos,
+      endTokenPos: func.location!.endTokenPos,
+      forceCompile: true,
+    );
+    expect(report.ranges!.length, 1);
+    final range = report.ranges![0];
+    expect(range.scriptIndex, 0);
+    expect(range.startPos, 476);
+    expect(range.endPos, 543);
+    expect(range.compiled, true);
+    final coverage = range.coverage!;
+    expect(coverage.hits, const [476, 516, 527, 531]);
+    expect(coverage.misses, isEmpty);
+    expect(report.scripts!.length, 1);
+    expect(
+      report.scripts![0].uri,
+      endsWith('coverage_optimized_function_test.dart'),
+    );
+  },
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'coverage_optimized_function_test.dart',
+      testeeConcurrent: testFunction,
+    );
diff --git a/pkg/vm_service/test/debugger_inspect_test.dart b/pkg/vm_service/test/debugger_inspect_test.dart
new file mode 100644
index 0000000..ab85371
--- /dev/null
+++ b/pkg/vm_service/test/debugger_inspect_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2015, 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 'dart:developer';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+class Point {
+  int x, y;
+  Point(this.x, this.y);
+}
+
+void testeeDo() {
+  inspect(Point(3, 4));
+}
+
+final tests = <IsolateTest>[
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+
+    final completer = Completer();
+    late StreamSubscription sub;
+    sub = service.onDebugEvent.listen((event) async {
+      if (event.kind == EventKind.kInspect) {
+        expect(event.inspectee!.classRef!.name, 'Point');
+        await sub.cancel();
+        await service.streamCancel(EventStreams.kDebug);
+        completer.complete();
+      }
+    });
+
+    await service.streamListen(EventStreams.kDebug);
+
+    // Start listening for events first.
+    await service.evaluate(
+      isolateRef.id!,
+      isolate.rootLib!.id!,
+      'testeeDo()',
+    );
+    await completer.future;
+  },
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'debugger_inspect_test.dart',
+    );
diff --git a/pkg/vm_service/test/debugging_inlined_finally_test.dart b/pkg/vm_service/test/debugging_inlined_finally_test.dart
new file mode 100644
index 0000000..c6ebeda
--- /dev/null
+++ b/pkg/vm_service/test/debugging_inlined_finally_test.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2015, 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:developer';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const int LINE_A = 25;
+const int LINE_B = 28;
+const int LINE_C = 31;
+
+testFunction() {
+  debugger();
+  var a;
+  try {
+    var b;
+    try {
+      for (int i = 0; i < 10; i++) {
+        var x = () => i + a + b;
+        return x; // LINE_A
+      }
+    } finally {
+      b = 10; // LINE_B
+    }
+  } finally {
+    a = 1; // LINE_C
+  }
+}
+
+testMain() {
+  var f = testFunction();
+  expect(f(), equals(11));
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  // Add breakpoint
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    Isolate isolate = await service.getIsolate(isolateId);
+    final rootLib =
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+
+    final script =
+        await service.getObject(isolateId, rootLib.scripts![0].id!) as Script;
+
+    // Add 3 breakpoints.
+    {
+      final bpt = await service.addBreakpoint(isolateId, script.id!, LINE_A);
+      expect(bpt.location!.script.id!, script.id);
+      final tmpScript =
+          await service.getObject(isolateId, script.id!) as Script;
+      expect(
+        tmpScript.getLineNumberFromTokenPos(bpt.location!.tokenPos),
+        LINE_A,
+      );
+      isolate = await service.getIsolate(isolateId);
+      expect(isolate.breakpoints!.length, 1);
+    }
+
+    {
+      final bpt = await service.addBreakpoint(isolateId, script.id!, LINE_B);
+      expect(bpt.location!.script.id, script.id);
+      final tmpScript =
+          await service.getObject(isolateId, script.id!) as Script;
+      expect(
+        tmpScript.getLineNumberFromTokenPos(bpt.location!.tokenPos),
+        LINE_B,
+      );
+      isolate = await service.getIsolate(isolateId);
+      expect(isolate.breakpoints!.length, 2);
+    }
+
+    {
+      final bpt = await service.addBreakpoint(isolateId, script.id!, LINE_C);
+      expect(bpt.location!.script.id, script.id!);
+      final tmpScript =
+          await service.getObject(isolateId, script.id!) as Script;
+      expect(
+        tmpScript.getLineNumberFromTokenPos(bpt.location!.tokenPos),
+        LINE_C,
+      );
+      isolate = await service.getIsolate(isolateId);
+      expect(isolate.breakpoints!.length, 3);
+    }
+    // Wait for breakpoint events.
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  // We are at the breakpoint on line LINE_A.
+  (VmService service, IsolateRef isolateRef) async {
+    final stack = await service.getStack(isolateRef.id!);
+    expect(stack.frames!.length, greaterThanOrEqualTo(1));
+
+    final script = await service.getObject(
+        isolateRef.id!, stack.frames![0].location!.script!.id!) as Script;
+    expect(
+      script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
+      LINE_A,
+    );
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  // We are at the breakpoint on line LINE_B.
+  (VmService service, IsolateRef isolateRef) async {
+    final stack = await service.getStack(isolateRef.id!);
+    expect(stack.frames!.length, greaterThanOrEqualTo(1));
+
+    final script = await service.getObject(
+        isolateRef.id!, stack.frames![0].location!.script!.id!) as Script;
+    expect(
+      script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
+      LINE_B,
+    );
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  // We are at the breakpoint on line LINE_C.
+  (VmService service, IsolateRef isolateRef) async {
+    final stack = await service.getStack(isolateRef.id!);
+    expect(stack.frames!.length, greaterThanOrEqualTo(1));
+
+    final script = await service.getObject(
+        isolateRef.id!, stack.frames![0].location!.script!.id!) as Script;
+    expect(
+      script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
+      LINE_C,
+    );
+  },
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+      'debugging_inlined_finally_test.dart',
+      testeeConcurrent: testMain,
+    );
diff --git a/pkg/vm_service/test/developer_extension_test.dart b/pkg/vm_service/test/developer_extension_test.dart
new file mode 100644
index 0000000..baa5115
--- /dev/null
+++ b/pkg/vm_service/test/developer_extension_test.dart
@@ -0,0 +1,137 @@
+// Copyright (c) 2015, 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 'dart:convert';
+import 'dart:developer';
+// ignore: import_of_legacy_library_into_null_safe
+import 'package:expect/expect.dart';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+Future<ServiceExtensionResponse> Handler(String method, Map paremeters) {
+  print('Invoked extension: $method');
+  switch (method) {
+    case 'ext..delay':
+      var c = Completer<ServiceExtensionResponse>();
+      Timer(Duration(seconds: 1), () {
+        c.complete(ServiceExtensionResponse.result(jsonEncode({
+          'type': '_delayedType',
+          'method': method,
+          'parameters': paremeters,
+        })));
+      });
+      return c.future;
+    case 'ext..error':
+      return Future<ServiceExtensionResponse>.value(
+          ServiceExtensionResponse.error(
+              ServiceExtensionResponse.extensionErrorMin, 'My error detail.'));
+    case 'ext..exception':
+      throw "I always throw!";
+    case 'ext..success':
+      return Future<ServiceExtensionResponse>.value(
+          ServiceExtensionResponse.result(jsonEncode({
+        'type': '_extensionType',
+        'method': method,
+        'parameters': paremeters,
+      })));
+  }
+  throw "Unknown extension: $method";
+}
+
+void test() {
+  registerExtension('ext..delay', Handler);
+  debugger();
+  postEvent('ALPHA', {'cat': 'dog'});
+  debugger();
+  registerExtension('ext..error', Handler);
+  registerExtension('ext..exception', Handler);
+  registerExtension('ext..success', Handler);
+  bool exceptionThrown = false;
+  try {
+    registerExtension('ext..delay', Handler);
+  } catch (e) {
+    exceptionThrown = true;
+  }
+  // This check is running in the target process so we can't used package:test.
+  Expect.equals(exceptionThrown, true);
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (VmService service, IsolateRef isolateRef) async {
+    final isolate = await service.getIsolate(isolateRef.id!);
+    // Note: extensions other than those is this test might already be
+    // registered by core libraries.
+    expect(isolate.extensionRPCs, contains('ext..delay'));
+    expect(isolate.extensionRPCs, isNot(contains('ext..error')));
+    expect(isolate.extensionRPCs, isNot(contains('ext..exception')));
+    expect(isolate.extensionRPCs, isNot(contains('ext..success')));
+  },
+  resumeIsolateAndAwaitEvent(EventStreams.kExtension, (event) {
+    expect(event.kind, EventKind.kExtension);
+    expect(event.extensionKind, 'ALPHA');
+    expect(event.extensionData!.data['cat'], equals('dog'));
+  }),
+  hasStoppedAtBreakpoint,
+  resumeIsolateAndAwaitEvent(EventStreams.kIsolate, (event) {
+    // Check that we received an event when '__error' was registered.
+    expect(event.kind, equals(EventKind.kServiceExtensionAdded));
+    expect(event.extensionRPC, 'ext..error');
+  }),
+  // Initial.
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    var result = await service.callServiceExtension(
+      'ext..delay',
+      isolateId: isolateId,
+    );
+
+    expect(result.json!['type'], '_delayedType');
+    expect(result.json!['method'], equals('ext..delay'));
+    expect(result.json!['parameters']['isolateId'], isNotNull);
+
+    try {
+      await service.callServiceExtension(
+        'ext..error',
+        isolateId: isolateId,
+      );
+    } on RPCError catch (e) {
+      expect(e.code, ServiceExtensionResponse.extensionErrorMin);
+      expect(e.details, 'My error detail.');
+    }
+
+    try {
+      await service.callServiceExtension(
+        'ext..exception',
+        isolateId: isolateId,
+      );
+    } on RPCError catch (e) {
+      expect(e.code, ServiceExtensionResponse.extensionError);
+      expect(e.details!.startsWith('I always throw!\n'), isTrue);
+    }
+
+    result = await service.callServiceExtension(
+      'ext..success',
+      isolateId: isolateId,
+      args: {
+        'apple': 'banana',
+      },
+    );
+    expect(result.json!['type'], '_extensionType');
+    expect(result.json!['method'], 'ext..success');
+    expect(result.json!['parameters']['isolateId'], isNotNull);
+    expect(result.json!['parameters']['apple'], 'banana');
+  },
+];
+
+main([args = const <String>[]]) async => runIsolateTests(
+      args,
+      tests,
+      'developer_extension_test.dart',
+      testeeConcurrent: test,
+    );
diff --git a/pkg/vm_service/test/developer_service_get_isolate_id_test.dart b/pkg/vm_service/test/developer_service_get_isolate_id_test.dart
new file mode 100644
index 0000000..d60780c
--- /dev/null
+++ b/pkg/vm_service/test/developer_service_get_isolate_id_test.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2016, 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 'dart:developer';
+import 'dart:isolate' as iso;
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+// testee state.
+late String selfId;
+late iso.Isolate childIsolate;
+late String childId;
+
+void spawnEntry(int i) {
+  debugger();
+}
+
+Future testeeMain() async {
+  debugger();
+  // Spawn an isolate.
+  childIsolate = await iso.Isolate.spawn(spawnEntry, 0);
+  // Assign the id for this isolate and it's child to strings so they can
+  // be read by the tester.
+  selfId = Service.getIsolateID(iso.Isolate.current)!;
+  childId = Service.getIsolateID(childIsolate)!;
+  debugger();
+}
+
+@pragma("vm:entry-point")
+getSelfId() => selfId;
+
+@pragma("vm:entry-point")
+getChildId() => childId;
+
+// tester state:
+late IsolateRef initialIsolate;
+late IsolateRef localChildIsolate;
+
+var tests = <VMTest>[
+  (VmService service) async {
+    final vm = await service.getVM();
+    // Sanity check.
+    expect(vm.isolates!.length, 1);
+    initialIsolate = vm.isolates![0];
+    await hasStoppedAtBreakpoint(service, initialIsolate);
+    // Resume.
+    await service.resume(initialIsolate.id!);
+  },
+  (VmService service) async {
+    // Initial isolate has paused at second debugger call.
+    await hasStoppedAtBreakpoint(service, initialIsolate);
+  },
+  (VmService service) async {
+    final vm = await service.getVM();
+
+    // Grab the child isolate.
+    localChildIsolate =
+        vm.isolates!.firstWhere((IsolateRef i) => i != initialIsolate);
+    expect(localChildIsolate, isNotNull);
+
+    // Reload the initial isolate.
+    initialIsolate = await service.getIsolate(initialIsolate.id!);
+
+    // Grab the root library.
+    Library rootLib = await service.getObject(
+      initialIsolate.id!,
+      (initialIsolate as Isolate).rootLib!.id!,
+    ) as Library;
+
+    // Grab self id.
+    final localSelfId = await service.invoke(
+      initialIsolate.id!,
+      rootLib.id!,
+      'getSelfId',
+      [],
+    ) as InstanceRef;
+
+    // Check that the id reported from dart:loper matches the id reported
+    // from the service protocol.
+    expect(localSelfId.kind, InstanceKind.kString);
+    expect(initialIsolate.id, localSelfId.valueAsString);
+
+    // Grab the child isolate's id.
+    final localChildId =
+        await service.invoke(initialIsolate.id!, rootLib.id!, 'getChildId', [])
+            as InstanceRef;
+
+    // Check that the id reported from dart:loper matches the id reported
+    // from the service protocol.
+    expect(localChildId.kind, InstanceKind.kString);
+    expect(localChildIsolate.id, localChildId.valueAsString);
+  }
+];
+
+main(args) async => runVMTests(
+      args,
+      tests,
+      'developer_service_get_isolate_id_test.dart',
+      testeeConcurrent: testeeMain,
+    );
diff --git a/pkg/vm_service/test/echo_test.dart b/pkg/vm_service/test/echo_test.dart
new file mode 100644
index 0000000..d21a524
--- /dev/null
+++ b/pkg/vm_service/test/echo_test.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2014, 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 'package:test/test.dart';
+import 'package:vm_service/src/vm_service.dart';
+import 'common/test_helper.dart';
+
+class EchoResponse extends Response {
+  static EchoResponse? parse(Map<String, dynamic>? json) =>
+      json == null ? null : EchoResponse._fromJson(json);
+
+  EchoResponse._fromJson(Map<String, dynamic> json) : text = json['text'];
+
+  @override
+  String get type => '_EchoResponse';
+  final String text;
+}
+
+var tests = <IsolateTest>[
+  (VmService service, IsolateRef isolateRef) async {
+    addTypeFactory('_EchoResponse', EchoResponse.parse);
+  },
+  (VmService service, IsolateRef isolateRef) async {
+    // Echo from VM target.
+    final result = await service.callMethod('_echo', args: {
+      'text': 'hello',
+    });
+    expect(result, isA<EchoResponse>());
+    expect((result as EchoResponse).text, 'hello');
+  },
+  (VmService service, IsolateRef isolateRef) async {
+    // Echo from Isolate target.
+    final result =
+        await service.callMethod('_echo', isolateId: isolateRef.id!, args: {
+      'text': 'hello',
+    });
+    expect(result, isA<EchoResponse>());
+    expect((result as EchoResponse).text, 'hello');
+  },
+  (VmService service, IsolateRef isolateRef) async {
+    final completer = Completer<void>();
+    late final StreamSubscription sub;
+    sub = service.onEvent('_Echo').listen((event) async {
+      expect(event.kind, '_Echo');
+      expect(event.data!.lengthInBytes, 3);
+      expect(event.data!.getUint8(0), 0);
+      expect(event.data!.getUint8(1), 128);
+      expect(event.data!.getUint8(2), 255);
+      await sub.cancel();
+      await service.streamCancel('_Echo');
+      completer.complete();
+    });
+
+    await service.streamListen('_Echo');
+    await service.callMethod(
+      '_triggerEchoEvent',
+      isolateId: isolateRef.id!,
+      args: {
+        'text': 'hello',
+      },
+    );
+    await completer.future;
+  },
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+      'echo_test.dart',
+    );
diff --git a/pkg/vm_service/test/eval_internal_class_test.dart b/pkg/vm_service/test/eval_internal_class_test.dart
new file mode 100644
index 0000000..9ddeb00
--- /dev/null
+++ b/pkg/vm_service/test/eval_internal_class_test.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2016, 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:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+var tests = <IsolateTest>[
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final rootLib = await service.getObject(
+      isolateId,
+      isolate.rootLib!.id!,
+    ) as Library;
+    Class classLibrary = await service.getObject(
+      isolateId,
+      rootLib.classRef!.id!,
+    ) as Class;
+
+    {
+      bool caughtExceptions = false;
+      try {
+        dynamic result = await service.evaluate(
+          isolateId,
+          classLibrary.id!,
+          '3 + 4',
+        );
+        print(result);
+      } on RPCError catch (e) {
+        expect(e.toString(), contains('can be evaluated only'));
+        caughtExceptions = true;
+      }
+      expect(caughtExceptions, isTrue);
+    }
+
+    final classClass = await service.getObject(
+      isolateId,
+      classLibrary.classRef!.id!,
+    ) as Class;
+    {
+      bool caughtExceptions = false;
+      try {
+        dynamic result = await service.evaluate(
+          isolateId,
+          classClass.id!,
+          '3 + 4',
+        );
+        print(result);
+      } on RPCError catch (e) {
+        expect(e.toString(), contains('can be evaluated only'));
+        caughtExceptions = true;
+      }
+      expect(caughtExceptions, isTrue);
+    }
+    final classArray = await service.getObject(
+      isolateId,
+      (await service.evaluate(
+        isolateId,
+        rootLib.id!,
+        "List<dynamic>.filled(2, null)",
+      ) as InstanceRef)
+          .classRef!
+          .id!,
+    ) as Class;
+    dynamic result = await service.evaluate(
+      isolateId,
+      classArray.id!,
+      '3 + 4',
+    );
+    expect(result is InstanceRef, isTrue);
+    expect(result.valueAsString, '7');
+  },
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'eval_internal_class_test.dart',
+    );
diff --git a/pkg/vm_service/test/eval_regression_flutter20255_test.dart b/pkg/vm_service/test/eval_regression_flutter20255_test.dart
new file mode 100644
index 0000000..6d3b963
--- /dev/null
+++ b/pkg/vm_service/test/eval_regression_flutter20255_test.dart
@@ -0,0 +1,108 @@
+// Copyright (c) 2018, 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 'dart:developer';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+class Base<T> {
+  String field;
+
+  Base(this.field);
+  String foo() => 'Base-$field';
+}
+
+class Sub<T> extends Base<T> {
+  String field;
+
+  Sub(this.field) : super(field);
+  String foo() {
+    debugger();
+    return 'Sub-$field';
+  }
+}
+
+class ISub<T> implements Base<T> {
+  String field;
+
+  ISub(this.field);
+  String foo() => 'ISub-$field';
+}
+
+class Box<T> {
+  late T value;
+
+  @pragma('vm:never-inline')
+  void setValue(T value) {
+    this.value = value;
+  }
+}
+
+final objects = <Base>[Base<int>('b'), Sub<double>('a'), ISub<bool>('c')];
+
+String triggerTypeTestingStubGeneration() {
+  final Box<Object> box = Box<Base>();
+  for (int i = 0; i < 1000000; ++i) {
+    box.setValue(objects.last);
+  }
+  return 'tts-generated';
+}
+
+void testFunction() {
+  // Triggers the debugger, which will evaluate an expression in the context of
+  // [Sub<double>], which will make a subclass of [Base<T>].
+  print(objects[1].foo());
+
+  triggerTypeTestingStubGeneration();
+
+  // Triggers the debugger, which will evaluate an expression in the context of
+  // [Sub<double>], which will make a subclass of [Base<T>].
+  print(objects[1].foo());
+}
+
+Future triggerEvaluation(VmService service, IsolateRef isolateRef) async {
+  Stack stack = await service.getStack(isolateRef.id!);
+
+  // Make sure we are in the right place.
+  expect(stack.frames!.length, greaterThanOrEqualTo(2));
+  expect(stack.frames![0].function!.name, 'foo');
+  expect(stack.frames![0].function!.owner.name, 'Sub');
+
+  // Trigger an evaluation, which will create a subclass of Base<T>.
+  final dynamic result = await service.evaluateInFrame(
+    isolateRef.id!,
+    0,
+    'this.field + " world \$T"',
+  );
+  expect(result.valueAsString, 'a world double');
+
+  // Trigger an optimization of a type testing stub (and usage of it).
+  final dynamic result2 = await service.evaluateInFrame(
+    isolateRef.id!,
+    0,
+    'triggerTypeTestingStubGeneration()',
+  );
+  expect(result2.valueAsString, 'tts-generated');
+}
+
+final testSteps = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  triggerEvaluation,
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  triggerEvaluation,
+  resumeIsolate,
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      testSteps,
+      'eval_regression_flutter20255_test.dart',
+      testeeConcurrent: testFunction,
+    );
diff --git a/pkg/vm_service/test/eval_skip_breakpoint.dart b/pkg/vm_service/test/eval_skip_breakpoint.dart
new file mode 100644
index 0000000..cdb4d5c
--- /dev/null
+++ b/pkg/vm_service/test/eval_skip_breakpoint.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2019, 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.
+// VMOptions=--verbose_debug
+
+import 'dart:developer';
+
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const int LINE_A = 22;
+const int LINE_B = 17;
+
+bar() {
+  print('bar');
+}
+
+testMain() {
+  debugger();
+  bar();
+  print("Done");
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  // Add breakpoint
+  setBreakpointAtLine(LINE_B),
+  // Evaluate 'bar()'
+  (VmService service, IsolateRef isolateRef) async {
+    final isolate = await service.getIsolate(isolateRef.id!);
+    await service.evaluate(
+      isolateRef.id!,
+      isolate.rootLib!.id!,
+      'bar()',
+      disableBreakpoints: true,
+    );
+  },
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'eval_skip_breakpoint.dart',
+      testeeConcurrent: testMain,
+    );
diff --git a/pkg/vm_service/test/evaluate_activation_in_method_class_other.dart b/pkg/vm_service/test/evaluate_activation_in_method_class_other.dart
new file mode 100644
index 0000000..000ba5e
--- /dev/null
+++ b/pkg/vm_service/test/evaluate_activation_in_method_class_other.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, 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:developer';
+
+var topLevel = "OtherLibrary";
+
+class Superclass2 {
+  var _instVar = 'Superclass2';
+  var instVar = 'Superclass2';
+  method() => 'Superclass2';
+  static staticMethod() => 'Superclass2';
+  suppress_warning() => _instVar;
+}
+
+class Superclass1 extends Superclass2 {
+  var _instVar = 'Superclass1';
+  var instVar = 'Superclass1';
+  method() => 'Superclass1';
+  static staticMethod() => 'Superclass1';
+
+  test() {
+    var _local = 'Superclass1';
+    debugger();
+    // Suppress unused variable warning.
+    print(_local);
+  }
+}
diff --git a/pkg/vm_service/test/evaluate_activation_in_method_class_test.dart b/pkg/vm_service/test/evaluate_activation_in_method_class_test.dart
new file mode 100644
index 0000000..0e1cc1d
--- /dev/null
+++ b/pkg/vm_service/test/evaluate_activation_in_method_class_test.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2016, 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.
+
+// Tests that expressions evaluated in a frame see the same scope as the
+// frame's method.
+
+import 'dart:async';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+import 'evaluate_activation_in_method_class_other.dart';
+
+var topLevel = "TestLibrary";
+
+class Subclass extends Superclass1 {
+  var _instVar = 'Subclass';
+  var instVar = 'Subclass';
+  method() => 'Subclass';
+  static staticMethod() => 'Subclass';
+  suppress_warning() => _instVar;
+}
+
+testeeDo() {
+  var obj = Subclass();
+  obj.test();
+}
+
+Future testerDo(VmService service, IsolateRef isolateRef) async {
+  await hasStoppedAtBreakpoint(service, isolateRef);
+  final isolateId = isolateRef.id!;
+
+  // Make sure we are in the right place.
+  var stack = await service.getStack(isolateId);
+  var topFrame = 0;
+  expect(
+    stack.frames![topFrame].function!.name,
+    equals('test'),
+  );
+  expect(
+    stack.frames![topFrame].function!.owner.name,
+    equals('Superclass1'),
+  );
+
+  InstanceRef result;
+
+  result = await service.evaluateInFrame(isolateId, topFrame, '_local')
+      as InstanceRef;
+  print(result);
+  expect(result.valueAsString, equals('Superclass1'));
+
+  result = await service.evaluateInFrame(isolateId, topFrame, '_instVar')
+      as InstanceRef;
+  print(result);
+  expect(result.valueAsString, equals('Superclass1'));
+
+  result = await service.evaluateInFrame(isolateId, topFrame, 'instVar')
+      as InstanceRef;
+  print(result);
+  expect(result.valueAsString, equals('Subclass'));
+
+  result = await service.evaluateInFrame(isolateId, topFrame, 'method()')
+      as InstanceRef;
+  print(result);
+  expect(result.valueAsString, equals('Subclass'));
+
+  result = await service.evaluateInFrame(isolateId, topFrame, 'super._instVar')
+      as InstanceRef;
+  print(result);
+  expect(result.valueAsString, equals('Superclass2'));
+
+  result = await service.evaluateInFrame(isolateId, topFrame, 'super.instVar')
+      as InstanceRef;
+  print(result);
+  expect(result.valueAsString, equals('Superclass2'));
+
+  result = await service.evaluateInFrame(isolateId, topFrame, 'super.method()')
+      as InstanceRef;
+  print(result);
+  expect(result.valueAsString, equals('Superclass2'));
+
+  result = await service.evaluateInFrame(isolateId, topFrame, 'staticMethod()')
+      as InstanceRef;
+  print(result);
+  expect(result.valueAsString, equals('Superclass1'));
+
+  // function.Owner verus function.Origin
+  // The mixin of Superclass is in _other.dart and the mixin
+  // application is in _test.dart.
+  result = await service.evaluateInFrame(isolateId, topFrame, 'topLevel')
+      as InstanceRef;
+  print(result);
+  expect(result.valueAsString, equals('OtherLibrary'));
+}
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      [testerDo],
+      'evaluate_activation_in_method_class_test.dart',
+      testeeConcurrent: testeeDo,
+    );
diff --git a/pkg/vm_service/tool/java/generate_java.dart b/pkg/vm_service/tool/java/generate_java.dart
index c80a481..0f61371 100644
--- a/pkg/vm_service/tool/java/generate_java.dart
+++ b/pkg/vm_service/tool/java/generate_java.dart
@@ -259,11 +259,14 @@
 
     String? h3Name;
 
+    // TODO(helin24): This code does not capture documentation with more than
+    //  one paragraph or lists. It may help to check generate_dart to fix this.
     for (int i = 0; i < nodes.length; i++) {
       Node node = nodes[i];
 
       if (isPre(node) && h3Name != null) {
-        String definition = textForCode(node);
+        String definition = textForCode(node)
+            .replaceAll('(string|Null)', 'string'); // this is terrible.
         String? docs;
 
         if (i + 1 < nodes.length && isPara(nodes[i + 1])) {
@@ -638,7 +641,8 @@
   }
 
   /// TODO: Hacked enum arg type determination
-  bool get isEnumType => name == 'step' || name == 'mode';
+  bool get isEnumType =>
+      name == 'step' || name == 'mode' || name == 'exceptionPauseMode';
 }
 
 class MethodParser extends Parser {
diff --git a/pkg/vm_service/tool/java/version.properties b/pkg/vm_service/tool/java/version.properties
new file mode 100644
index 0000000..1c8ad22
--- /dev/null
+++ b/pkg/vm_service/tool/java/version.properties
@@ -0,0 +1 @@
+version=3.56
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index cb64707..0e97fbb 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -888,7 +888,9 @@
   ASSERT(!function_.IsNull());
   auto isolate_group = IsolateGroup::Current();
   if (function_.ptr() ==
-      isolate_group->object_store()->complete_on_async_return()) {
+          isolate_group->object_store()->complete_on_async_return() ||
+      function_.ptr() == isolate_group->object_store()
+                             ->complete_with_no_future_on_async_return()) {
     // We are completing an async function's completer.
     return true;
   }
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 8ce45e3..81c5977 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -210,6 +210,15 @@
   return result.ptr();
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+static void DisableDebuggingAndInlining(const Function& function) {
+  if (FLAG_async_debugger) {
+    function.set_is_debuggable(false);
+    function.set_is_inlinable(false);
+  }
+}
+#endif  // DART_PRECOMPILED_RUNTIME
+
 void ObjectStore::InitKnownObjects() {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
@@ -251,11 +260,16 @@
                                      function_name, 0, 3, Object::null_array());
   ASSERT(!function.IsNull());
   set_complete_on_async_return(function);
-  if (FLAG_async_debugger) {
-    // Disable debugging and inlining the _CompleteOnAsyncReturn function.
-    function.set_is_debuggable(false);
-    function.set_is_inlinable(false);
-  }
+  DisableDebuggingAndInlining(function);
+
+  function_name =
+      async_lib.PrivateName(Symbols::_CompleteWithNoFutureOnAsyncReturn());
+  ASSERT(!function_name.IsNull());
+  function = Resolver::ResolveStatic(async_lib, Object::null_string(),
+                                     function_name, 0, 3, Object::null_array());
+  ASSERT(!function.IsNull());
+  set_complete_with_no_future_on_async_return(function);
+  DisableDebuggingAndInlining(function);
 
   function_name = async_lib.PrivateName(Symbols::_CompleteOnAsyncError());
   ASSERT(!function_name.IsNull());
@@ -263,11 +277,7 @@
                                      function_name, 0, 4, Object::null_array());
   ASSERT(!function.IsNull());
   set_complete_on_async_error(function);
-  if (FLAG_async_debugger) {
-    // Disable debugging and inlining the _CompleteOnAsyncError function.
-    function.set_is_debuggable(false);
-    function.set_is_inlinable(false);
-  }
+  DisableDebuggingAndInlining(function);
 
   cls =
       async_lib.LookupClassAllowPrivate(Symbols::_AsyncStarStreamController());
@@ -283,8 +293,7 @@
       if (function.IsNull()) {
         break;
       }
-      function.set_is_debuggable(false);
-      function.set_is_inlinable(false);
+      DisableDebuggingAndInlining(function);
     }
   }
 
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 3d77c61..896c01b 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -159,6 +159,7 @@
   RW(Function, simple_instance_of_false_function)                              \
   RW(Function, async_star_move_next_helper)                                    \
   RW(Function, complete_on_async_return)                                       \
+  RW(Function, complete_with_no_future_on_async_return)                        \
   RW(Function, complete_on_async_error)                                        \
   RW(Class, async_star_stream_controller)                                      \
   ARW_RELAXED(Smi, future_timeout_future_index)                                \
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index ed6e095..368f70b 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1903,7 +1903,7 @@
 _@Code_ is a reference to a _Code_ object.
 
 ```
-class Code extends @Object {
+class Code extends Object {
   // A name for this code object.
   string name;
 
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 5c8db08..6c9758a 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -288,6 +288,7 @@
   V(_CombinatorMirror, "_CombinatorMirror")                                    \
   V(_CompileTimeError, "_CompileTimeError")                                    \
   V(_CompleteOnAsyncReturn, "_completeOnAsyncReturn")                          \
+  V(_CompleteWithNoFutureOnAsyncReturn, "_completeWithNoFutureOnAsyncReturn")  \
   V(_ControllerSubscription, "_ControllerSubscription")                        \
   V(_CompleteOnAsyncError, "_completeOnAsyncError")                            \
   V(_DeletedEnumPrefix, "Deleted enum value from ")                            \
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
index f4ab556..ca3bd4f 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
@@ -62,3 +62,6 @@
 
 @patch
 bool isSentinel(dynamic value) => throw UnsupportedError('isSentinel');
+
+@patch
+T unsafeCast<T>(dynamic v) => v;
diff --git a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
index 9bf6da6..ef27959 100644
--- a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
@@ -73,3 +73,7 @@
 @patch
 @pragma('dart2js:tryInline')
 bool isSentinel(dynamic value) => isJsSentinel(value);
+
+@patch
+@pragma('dart2js:tryInline')
+T unsafeCast<T>(dynamic v) => v;
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index 363ae71..ee371e7 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -257,7 +257,20 @@
   // allow then and error handlers to be attached.
   // async_jump_var=0 is prior to first await, =1 is first await.
   if (!is_sync || value is Future) {
-    _future._asyncComplete(value);
+    _future._asyncCompleteUnchecked(value);
+  } else {
+    _future._completeWithValue(value);
+  }
+}
+
+@pragma("vm:entry-point", "call")
+void _completeWithNoFutureOnAsyncReturn(
+    _Future _future, Object? value, bool is_sync) {
+  // The first awaited expression is invoked sync. so complete is async. to
+  // allow then and error handlers to be attached.
+  // async_jump_var=0 is prior to first await, =1 is first await.
+  if (!is_sync) {
+    _future._asyncCompleteUncheckedNoFuture(value);
   } else {
     _future._completeWithValue(value);
   }
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index b8141d6..3d7a3cd8f 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -156,13 +156,9 @@
   return newStack;
 }
 
-// This function can be used to skip implicit or explicit checked down casts in
-// the parts of the core library implementation where we know by construction the
-// type of a value.
-//
-// Important: this is unsafe and must be used with care.
+@patch
 @pragma("vm:external-name", "Internal_unsafeCast")
-external T unsafeCast<T>(Object? v);
+external T unsafeCast<T>(dynamic v);
 
 // This function can be used to keep an object alive till that point.
 @pragma("vm:recognized", "other")
diff --git a/sdk/lib/_internal/vm/lib/timer_impl.dart b/sdk/lib/_internal/vm/lib/timer_impl.dart
index ac1939d..32f43d0 100644
--- a/sdk/lib/_internal/vm/lib/timer_impl.dart
+++ b/sdk/lib/_internal/vm/lib/timer_impl.dart
@@ -452,8 +452,9 @@
     if (_receivePort == null) {
       assert(_receivePort == null);
       assert(_sendPort == null);
-      _receivePort = RawReceivePort(_handleMessage, 'Timer');
-      _sendPort = _receivePort!.sendPort;
+      final port = RawReceivePort(_handleMessage, 'Timer');
+      _receivePort = port;
+      _sendPort = port.sendPort;
       _scheduledWakeupTime = 0;
     } else {
       (_receivePort as _RawReceivePortImpl)._setActive(true);
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index 0b16dae..ca05fc6 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -114,7 +114,8 @@
         printToZone,
         printToConsole,
         Since,
-        typeAcceptsNull;
+        typeAcceptsNull,
+        unsafeCast;
 
 part 'async_error.dart';
 part 'broadcast_stream_controller.dart';
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 4d13cc8..1b7176e 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -4,15 +4,6 @@
 
 part of dart.async;
 
-/// The onValue and onError handlers return either a value or a future
-typedef FutureOr<T> _FutureOnValue<S, T>(S value);
-
-/// Test used by [Future.catchError] to handle skip some errors.
-typedef bool _FutureErrorTest(Object error);
-
-/// Used by [WhenFuture].
-typedef dynamic _FutureAction();
-
 abstract class _Completer<T> implements Completer<T> {
   final _Future<T> future = new _Future<T>();
 
@@ -106,7 +97,7 @@
         state = (errorCallback == null) ? stateThen : stateThenOnerror;
 
   _FutureListener.thenAwait(
-      this.result, _FutureOnValue<S, T> onValue, Function errorCallback)
+      this.result, FutureOr<T> Function(S) onValue, Function errorCallback)
       : callback = onValue,
         errorCallback = errorCallback,
         state = stateThenOnerror;
@@ -127,19 +118,19 @@
 
   FutureOr<T> Function(S) get _onValue {
     assert(handlesValue);
-    return callback as dynamic;
+    return unsafeCast<FutureOr<T> Function(S)>(callback);
   }
 
   Function? get _onError => errorCallback;
 
-  _FutureErrorTest get _errorTest {
+  bool Function(Object) get _errorTest {
     assert(hasErrorTest);
-    return callback as dynamic;
+    return unsafeCast<bool Function(Object)>(callback);
   }
 
-  _FutureAction get _whenCompleteAction {
+  dynamic Function() get _whenCompleteAction {
     assert(handlesComplete);
-    return callback as dynamic;
+    return unsafeCast<dynamic Function()>(callback);
   }
 
   /// Whether this listener has an error callback.
@@ -607,6 +598,37 @@
     _asyncCompleteWithValue(value as dynamic); // Value promoted to T.
   }
 
+  /// Internal helper function used by the implementation of `async` functions.
+  ///
+  /// Like [_asyncComplete], but avoids type checks that are guaranteed to
+  /// succeed by the way the function is called.
+  /// Should be used judiciously.
+  void _asyncCompleteUnchecked(/*FutureOr<T>*/ dynamic value) {
+    assert((value as FutureOr<T>) == value);
+    final typedValue = unsafeCast<FutureOr<T>>(value);
+
+    // Doing just "is Future" is not sufficient.
+    // If `T` is Object` and `value` is `Future<Object?>.value(null)`,
+    // then value is a `Future`, but not a `Future<T>`, and going through the
+    // `_chainFuture` branch would end up assigning `null` to `Object`.
+    if (typedValue is Future<T>) {
+      _chainFuture(typedValue);
+      return;
+    }
+    _asyncCompleteWithValue(unsafeCast<T>(typedValue));
+  }
+
+  /// Internal helper function used to implement `async` functions.
+  ///
+  /// Like [_asyncCompleteUnchecked], but avoids a `is Future<T>` check due to
+  /// having a static guarantee on the callsite that the [value] cannot be a
+  /// [Future].
+  /// Should be used judiciously.
+  void _asyncCompleteUncheckedNoFuture(/*T*/ dynamic value) {
+    assert((value as T) == value);
+    _asyncCompleteWithValue(unsafeCast<T>(value));
+  }
+
   void _asyncCompleteWithValue(T value) {
     _setPendingComplete();
     _zone.scheduleMicrotask(() {
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index 9a7afe2..968c555 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -18,6 +18,7 @@
 part 'abi.dart';
 part 'abi_specific.dart';
 part 'native_type.dart';
+part 'native_finalizer.dart';
 part 'allocation.dart';
 part 'annotations.dart';
 part 'c_type.dart';
diff --git a/sdk/lib/ffi/ffi_sources.gni b/sdk/lib/ffi/ffi_sources.gni
index 4197369..c530899 100644
--- a/sdk/lib/ffi/ffi_sources.gni
+++ b/sdk/lib/ffi/ffi_sources.gni
@@ -12,6 +12,7 @@
   "annotations.dart",
   "c_type.dart",
   "dynamic_library.dart",
+  "native_finalizer.dart",
   "native_type.dart",
   "struct.dart",
   "union.dart",
diff --git a/sdk/lib/ffi/native_finalizer.dart b/sdk/lib/ffi/native_finalizer.dart
new file mode 100644
index 0000000..49fc667
--- /dev/null
+++ b/sdk/lib/ffi/native_finalizer.dart
@@ -0,0 +1,223 @@
+// 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.
+
+part of dart.ffi;
+
+/// Marker interface for objects which should not be finalized too soon.
+///
+/// Any local variable with a static type that _includes `Finalizable`_
+/// is guaranteed to be alive until execution exits the code block where
+/// the variable is in scope.
+///
+/// A type _includes `Finalizable`_ if either
+/// * the type is a non-`Never` subtype of `Finalizable`, or
+/// * the type is `T?` or `FutureOr<T>` where `T` includes `Finalizable`.
+///
+/// In other words, while an object is referenced by such a variable,
+/// it is guaranteed to *not* be considered unreachable,
+/// and the variable itself is considered alive for the entire duration
+/// of its scope, even after it is last referenced.
+///
+/// _Without this marker interface on the variable's type, a variable's
+/// value might be garbage collected before the surrounding scope has
+/// been completely executed, as long as the variable is definitely not
+/// referenced again. That can, in turn, trigger a `NativeFinalizer`
+/// to perform a callback. When the variable's type includes [Finalizable],
+/// The `NativeFinalizer` callback is prevented from running until
+/// the current code using that variable is complete._
+///
+/// For example, `finalizable` is kept alive during the execution of
+/// `someNativeCall`:
+///
+/// ```dart
+/// void myFunction() {
+///   final finalizable = MyFinalizable(Pointer.fromAddress(0));
+///   someNativeCall(finalizable.nativeResource);
+/// }
+///
+/// void someNativeCall(Pointer nativeResource) {
+///   // ..
+/// }
+///
+/// class MyFinalizable implements Finalizable {
+///   final Pointer nativeResource;
+///
+///   MyFinalizable(this.nativeResource);
+/// }
+/// ```
+///
+/// Methods on a class implementing `Finalizable` keep the `this` object alive
+/// for the duration of the method execution. _The `this` value is treated
+/// like a local variable._
+///
+/// For example, `this` is kept alive during the execution of `someNativeCall`
+/// in `myFunction`:
+///
+/// ```dart
+/// class MyFinalizable implements Finalizable {
+///   final Pointer nativeResource;
+///
+///   MyFinalizable(this.nativeResource);
+///
+///   void myFunction() {
+///     someNativeCall(nativeResource);
+///   }
+/// }
+///
+/// void someNativeCall(Pointer nativeResource) {
+///   // ..
+/// }
+/// ```
+///
+/// It is good practise to implement logic involving finalizables as methods
+/// on the class that implements [Finalizable].
+///
+/// If a closure is created inside the block scope declaring the variable, and
+/// that closure contains any reference to the variable, the variable stays
+/// alive as long as the closure object does, or as long as the body of such a
+/// closure is executing.
+///
+/// For example, `finalizable` is kept alive by the closure object and until the
+/// end of the closure body:
+///
+/// ```dart
+/// void doSomething() {
+///   final resourceAction = myFunction();
+///   resourceAction(); // `finalizable` is alive until this call returns.
+/// }
+///
+/// void Function() myFunction() {
+///   final finalizable = MyFinalizable(Pointer.fromAddress(0));
+///   return () {
+///     someNativeCall(finalizable.nativeResource);
+///   };
+/// }
+///
+/// void someNativeCall(Pointer nativeResource) {
+///   // ..
+/// }
+///
+/// class MyFinalizable implements Finalizable {
+///   final Pointer nativeResource;
+///
+///   MyFinalizable(this.nativeResource);
+/// }
+/// ```
+///
+/// Only captured variables are kept alive by closures, not all variables.
+///
+/// For example, `finalizable` is not kept alive by the returned closure object:
+///
+/// ```dart
+/// void Function() myFunction() {
+///   final finalizable = MyFinalizable(Pointer.fromAddress(0));
+///   final nativeResource = finalizable.nativeResource;
+///   return () {
+///     someNativeCall(nativeResource);
+///   };
+/// }
+///
+/// void someNativeCall(Pointer nativeResource) {
+///   // ..
+/// }
+///
+/// class MyFinalizable implements Finalizable {
+///   final Pointer nativeResource;
+///
+///   MyFinalizable(this.nativeResource);
+/// }
+/// ```
+///
+/// It's likely an error if a resource extracted from a finalizable object
+/// escapes the scope of the finalizable variable it's taken from.
+///
+/// The behavior of `Finalizable` variables applies to asynchronous
+/// functions too. Such variables are kept alive as long as any
+/// code may still execute inside the scope that declared the variable,
+/// or in a closure capturing the variable,
+/// even if there are asynchronous delays during that execution.
+///
+/// For example, `finalizable` is kept alive during the `await someAsyncCall()`:
+///
+/// ```dart
+/// Future<void> myFunction() async {
+///   final finalizable = MyFinalizable();
+///   await someAsyncCall();
+/// }
+///
+/// Future<void> someAsyncCall() async {
+///   // ..
+/// }
+///
+/// class MyFinalizable implements Finalizable {
+///   // ..
+/// }
+/// ```
+///
+/// Also in asynchronous code it's likely an error if a resource extracted from
+/// a finalizable object escapes the scope of the finalizable variable it's
+/// taken from. If you have to extract a resource from a `Finalizable`, you
+/// should ensure the scope in which Finalizable is defined outlives the
+/// resource by `await`ing any asynchronous code that uses the resource.
+///
+/// For example, `this` is kept alive until `resource` is not used anymore in
+/// `useAsync1`, but not in `useAsync2` and `useAsync3`:
+///
+/// ```dart
+/// class MyFinalizable {
+///   final Pointer<Int8> resource;
+///
+///   MyFinalizable(this.resource);
+///
+///   Future<int> useAsync1() async {
+///     return await useResource(resource);
+///   }
+///
+///   Future<int> useAsync2() async {
+///     return useResource(resource);
+///   }
+///
+///   Future<int> useAsync3() {
+///     return useResource(resource);
+///   }
+/// }
+///
+/// /// Does not use [resource] after the returned future completes.
+/// Future<int> useResource(Pointer<Int8> resource) async {
+///   return resource.value;
+/// }
+/// ```
+///
+/// _It is possible for an asynchronous function to *stall* at an
+/// `await`, such that the runtime system can see that there is no possible
+/// way for that `await` to complete. In that case, no code after the
+/// `await` will ever execute, including `finally` blocks, and the
+/// variable may be considered dead along with everything else._
+///
+/// If you're not going to keep a variable alive yourself, make sure to pass the
+/// finalizable object to other functions instead of just its resource.
+///
+/// For example, `finalizable` is not kept alive by `myFunction` after it has
+/// run to the end of its scope, while `someAsyncCall` could still continue
+/// execution. However, `finalizable` is kept alive by `someAsyncCall` itself:
+///
+/// ```dart
+/// void myFunction() {
+///   final finalizable = MyFinalizable();
+///   someAsyncCall(finalizable);
+/// }
+///
+/// Future<void> someAsyncCall(MyFinalizable finalizable) async {
+///   // ..
+/// }
+///
+/// class MyFinalizable implements Finalizable {
+///   // ..
+/// }
+/// ```
+// TODO(http://dartbug.com/44395): Add implicit await to Dart implementation.
+// This will fix `useAsync2` above.
+abstract class Finalizable {
+  factory Finalizable._() => throw UnsupportedError("");
+}
diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart
index 5d38bd8..a7a7eda 100644
--- a/sdk/lib/internal/internal.dart
+++ b/sdk/lib/internal/internal.dart
@@ -35,6 +35,23 @@
 // execution mode.
 external bool typeAcceptsNull<T>();
 
+/// Unsafely treats [value] as type [T].
+///
+/// An unsafe cast allows casting any value to any type,
+/// without any runtime type checks.
+///
+/// Can be used internally in platform library implementations of
+/// data structures, where a value is known to have a type different
+/// from its static type (like knowing that a string is definitely
+/// a "_OneByteString" or that the value stored into a heterogenous
+/// list is really a value of the surrounding map).
+///
+/// Must only be used for casts which would definitely *succeed*
+/// as a normal cast.
+///
+/// Should only be used for performance in performance critical code.
+external T unsafeCast<T>(dynamic value);
+
 // Powers of 10 up to 10^22 are representable as doubles.
 // Powers of 10 above that are only approximate due to lack of precission.
 // Used by double-parsing.
diff --git a/tools/VERSION b/tools/VERSION
index 8a18778..2811149 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 85
+PRERELEASE 86
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 740881b..f1dcf06 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -2264,17 +2264,6 @@
           ]
         },
         {
-          "name": "ddc weak modular tests",
-          "script": "out/ReleaseX64/dart-sdk/bin/dart",
-          "testRunner": true,
-          "arguments": [
-            "pkg/dev_compiler/test/modular_suite_nnbd.dart",
-            "-ndartdevk-weak-${system}-release-chrome",
-            "--verbose",
-            "--use-sdk"
-          ]
-        },
-        {
           "name": "ddc nnbd weak tests",
           "arguments": [
             "-ndartdevk-weak-linux-release-chrome",
@@ -2284,7 +2273,7 @@
             "dartdevc",
             "web"
           ],
-          "shards": 5,
+          "shards": 2,
           "fileset": "web_platform_nnbd"
         },
         {
@@ -2297,6 +2286,26 @@
           "fileset": "web_platform_nnbd"
         },
         {
+          "name": "ddc nnbd strong co19 tests",
+          "arguments": [
+            "-ndartdevk-strong-linux-release-chrome",
+            "co19"
+          ],
+          "shards": 3,
+          "fileset": "web_platform_nnbd"
+        },
+        {
+          "name": "ddc weak modular tests",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "testRunner": true,
+          "arguments": [
+            "pkg/dev_compiler/test/modular_suite_nnbd.dart",
+            "-ndartdevk-weak-${system}-release-chrome",
+            "--verbose",
+            "--use-sdk"
+          ]
+        },
+        {
           "name": "ddc nnbd strong tests",
           "arguments": [
             "-ndartdevk-strong-linux-release-chrome",
@@ -2306,13 +2315,6 @@
             "dartdevc",
             "web"
           ]
-        },
-        {
-          "name": "ddc nnbd strong co19 tests",
-          "arguments": [
-            "-ndartdevk-strong-linux-release-chrome",
-            "co19"
-          ]
         }
       ]
     },
@@ -4183,4 +4185,4 @@
     "macos": "buildtools/mac-x64/clang/bin/llvm-symbolizer",
     "windows": "buildtools/win-x64/clang/bin/llvm-symbolizer.exe"
   }
-}
\ No newline at end of file
+}