Version 2.17.0-17.0.dev

Merge commit '2a31ee5530c698329a643ec1f30217a05ff21c55' into 'dev'
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 74bf73c..9a507f4 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart
@@ -30,7 +30,7 @@
   /// 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> resolve(TypeAnnotation typeAnnotation);
+  Future<StaticType> resolve(covariant TypeAnnotation typeAnnotation);
 }
 
 /// The api used to introspect on a [ClassDeclaration].
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 09c2de9..c0f8a9f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart
@@ -49,10 +49,10 @@
 /// compared to other static types.
 abstract class StaticType {
   /// Returns true if this is a subtype of [other].
-  Future<bool> isSubtypeOf(StaticType other);
+  Future<bool> isSubtypeOf(covariant StaticType other);
 
   /// Returns true if this is an identical type to [other].
-  Future<bool> isExactly(StaticType other);
+  Future<bool> isExactly(covariant StaticType other);
 }
 
 /// A subtype of [StaticType] representing types that can be resolved by name
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
index 332144f..158363f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart
@@ -27,6 +27,7 @@
 import 'dart:isolate';
 
 import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor_shared/response_impls.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor_shared/serialization.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor_shared/protocol.dart';
@@ -39,27 +40,33 @@
 ///
 /// Supports the client side of the macro expansion protocol.
 void main(_, SendPort sendPort) {
+  /// Local function that sends requests and returns responses using [sendPort].
+  Future<Response> sendRequest(Request request) => _sendRequest(request, sendPort);
+
   withSerializationMode(SerializationMode.client, () {
     ReceivePort receivePort = new ReceivePort();
     sendPort.send(receivePort.sendPort);
+
     receivePort.listen((message) async {
       var deserializer = JsonDeserializer(message as Iterable<Object?>)
           ..moveNext();
+      int zoneId = deserializer.expectNum();
+      deserializer..moveNext();
       var type = MessageType.values[deserializer.expectNum()];
       var serializer = JsonSerializer();
       switch (type) {
         case MessageType.instantiateMacroRequest:
-          var request = InstantiateMacroRequest.deserialize(deserializer);
+          var request = new InstantiateMacroRequest.deserialize(deserializer, zoneId);
           (await _instantiateMacro(request)).serialize(serializer);
           break;
         case MessageType.executeDefinitionsPhaseRequest:
-          var request = ExecuteDefinitionsPhaseRequest.deserialize(
-              deserializer,
-              ClientTypeResolver(),
-              ClientClassIntrospector(),
-              ClientTypeDeclarationsResolver());
-          (await _executeDefinitionsPhase(request)).serialize(serializer);
+          var request = new ExecuteDefinitionsPhaseRequest.deserialize(deserializer, zoneId);
+          (await _executeDefinitionsPhase(request, sendRequest)).serialize(serializer);
           break;
+        case MessageType.response:
+          var response = new SerializableResponse.deserialize(deserializer, zoneId);
+          _responseCompleters.remove(response.requestId)!.complete(response);
+          return;
         default:
           throw new StateError('Unhandled event type \$type');
       }
@@ -102,31 +109,46 @@
         response: identifier,
         requestId: request.id,
         serializationZoneId: request.serializationZoneId);
-  } catch (e) {
+  } catch (e, s) {
     return new SerializableResponse(
       responseType: MessageType.error,
       error: e.toString(),
+      stackTrace: s.toString(),
       requestId: request.id,
       serializationZoneId: request.serializationZoneId);
   }
 }
 
 Future<SerializableResponse> _executeDefinitionsPhase(
-    ExecuteDefinitionsPhaseRequest request) async {
+    ExecuteDefinitionsPhaseRequest request,
+    Future<Response> Function(Request request) sendRequest) async {
   try {
     Macro? instance = _macroInstances[request.macro];
     if (instance == null) {
       throw new StateError('Unrecognized macro instance \${request.macro}\\n'
           'Known instances: \$_macroInstances)');
     }
+    var typeResolver = ClientTypeResolver(
+        sendRequest,
+        remoteInstance: request.typeResolver,
+        serializationZoneId: request.serializationZoneId);
+    var typeDeclarationResolver = ClientTypeDeclarationResolver(
+        sendRequest,
+        remoteInstance: request.typeDeclarationResolver,
+        serializationZoneId: request.serializationZoneId);
+    var classIntrospector = ClientClassIntrospector(
+        sendRequest,
+        remoteInstance: request.classIntrospector,
+        serializationZoneId: request.serializationZoneId);
+
     Declaration declaration = request.declaration;
     if (instance is FunctionDefinitionMacro &&
         declaration is FunctionDeclarationImpl) {
       FunctionDefinitionBuilderImpl builder = new FunctionDefinitionBuilderImpl(
           declaration,
-          request.typeResolver,
-          request.typeDeclarationResolver,
-          request.classIntrospector);
+          typeResolver,
+          typeDeclarationResolver,
+          classIntrospector);
       await instance.buildDefinitionForFunction(declaration, builder);
       return new SerializableResponse(
           responseType: MessageType.macroExecutionResult,
@@ -137,12 +159,28 @@
       throw new UnsupportedError(
           ('Only FunctionDefinitionMacros are supported currently'));
     }
-  } catch (e) {
+  } catch (e, s) {
     return new SerializableResponse(
       responseType: MessageType.error,
       error: e.toString(),
+      stackTrace: s.toString(),
       requestId: request.id,
       serializationZoneId: request.serializationZoneId);
   }
 }
+
+/// Holds on to response completers by request id.
+final _responseCompleters = <int, Completer<Response>>{};
+
+/// Serializes [request], sends it to [sendPort], and sets up a [Completer] in
+/// [_responseCompleters] to handle the response.
+Future<Response> _sendRequest(Request request, SendPort sendPort) {
+  Completer<Response> completer = Completer();
+  _responseCompleters[request.id] = completer;
+  JsonSerializer serializer = JsonSerializer();
+  serializer.addNum(request.serializationZoneId);
+  request.serialize(serializer);
+  sendPort.send(serializer.result);
+  return completer.future;
+}
 ''';
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 68d0f94..3f9e55c 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
@@ -6,6 +6,8 @@
 /// the isolate or process doing the work of macro loading and execution.
 library _fe_analyzer_shared.src.macros.executor_shared.protocol;
 
+import 'package:meta/meta.dart';
+
 import '../executor.dart';
 import '../api.dart';
 import '../executor_shared/response_impls.dart';
@@ -22,13 +24,16 @@
   Request({int? id, required this.serializationZoneId})
       : this.id = id ?? _next++;
 
-  Request.deserialize(Deserializer deserializer)
-      : serializationZoneId = (deserializer..moveNext()).expectNum(),
-        id = (deserializer..moveNext()).expectNum();
+  /// The [serializationZoneId] is a part of the header and needs to be parsed
+  /// before deserializing objects, and then passed in here.
+  Request.deserialize(Deserializer deserializer, this.serializationZoneId)
+      : id = (deserializer..moveNext()).expectNum();
 
-  void serialize(Serializer serializer) => serializer
-    ..addNum(serializationZoneId)
-    ..addNum(id);
+  /// The [serializationZoneId] needs to be separately serialized before the
+  /// rest of the object. This is not done by the instances themselves but by
+  /// the macro implementations.
+  @mustCallSuper
+  void serialize(Serializer serializer) => serializer.addNum(id);
 
   static int _next = 0;
 }
@@ -38,10 +43,15 @@
 class Response {
   final Object? response;
   final Object? error;
+  final String? stackTrace;
   final int requestId;
 
-  Response({this.response, this.error, required this.requestId})
-      : assert(response != null || error != null),
+  Response({
+    this.response,
+    this.error,
+    this.stackTrace,
+    required this.requestId,
+  })  : assert(response != null || error != null),
         assert(response == null || error == null);
 }
 
@@ -50,11 +60,13 @@
   final Serializable? response;
   final MessageType responseType;
   final String? error;
+  final String? stackTrace;
   final int requestId;
   final int serializationZoneId;
 
   SerializableResponse({
     this.error,
+    this.stackTrace,
     required this.requestId,
     this.response,
     required this.responseType,
@@ -70,10 +82,13 @@
     MessageType responseType = MessageType.values[deserializer.expectNum()];
     Serializable? response;
     String? error;
+    String? stackTrace;
     switch (responseType) {
       case MessageType.error:
         deserializer.moveNext();
         error = deserializer.expectString();
+        deserializer.moveNext();
+        stackTrace = deserializer.expectNullableString();
         break;
       case MessageType.macroClassIdentifier:
         response = new MacroClassIdentifierImpl.deserialize(deserializer);
@@ -84,6 +99,12 @@
       case MessageType.macroExecutionResult:
         response = new MacroExecutionResultImpl.deserialize(deserializer);
         break;
+      case MessageType.staticType:
+        response = RemoteInstance.deserialize(deserializer);
+        break;
+      case MessageType.boolean:
+        response = new BooleanValue.deserialize(deserializer);
+        break;
       default:
         throw new StateError('Unexpected response type $responseType');
     }
@@ -92,6 +113,7 @@
         responseType: responseType,
         response: response,
         error: error,
+        stackTrace: stackTrace,
         requestId: (deserializer..moveNext()).expectNum(),
         serializationZoneId: serializationZoneId);
   }
@@ -99,16 +121,30 @@
   void serialize(Serializer serializer) {
     serializer
       ..addNum(serializationZoneId)
+      ..addNum(MessageType.response.index)
       ..addNum(responseType.index);
     if (response != null) {
       response!.serialize(serializer);
     } else if (error != null) {
       serializer.addString(error!.toString());
+      serializer.addNullableString(stackTrace);
     }
     serializer.addNum(requestId);
   }
 }
 
+class BooleanValue implements Serializable {
+  final bool value;
+
+  BooleanValue(this.value);
+
+  BooleanValue.deserialize(Deserializer deserializer)
+      : value = (deserializer..moveNext()).expectBool();
+
+  @override
+  void serialize(Serializer serializer) => serializer..addBool(value);
+}
+
 /// A request to load a macro in this isolate.
 class LoadMacroRequest extends Request {
   final Uri library;
@@ -117,10 +153,11 @@
   LoadMacroRequest(this.library, this.name, {required int serializationZoneId})
       : super(serializationZoneId: serializationZoneId);
 
-  LoadMacroRequest.deserialize(Deserializer deserializer)
+  LoadMacroRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
       : library = Uri.parse((deserializer..moveNext()).expectString()),
         name = (deserializer..moveNext()).expectString(),
-        super.deserialize(deserializer);
+        super.deserialize(deserializer, serializationZoneId);
 
   @override
   void serialize(Serializer serializer) {
@@ -142,11 +179,12 @@
       {required int serializationZoneId})
       : super(serializationZoneId: serializationZoneId);
 
-  InstantiateMacroRequest.deserialize(Deserializer deserializer)
+  InstantiateMacroRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
       : macroClass = new MacroClassIdentifierImpl.deserialize(deserializer),
         constructorName = (deserializer..moveNext()).expectString(),
         arguments = new Arguments.deserialize(deserializer),
-        super.deserialize(deserializer);
+        super.deserialize(deserializer, serializationZoneId);
 
   @override
   void serialize(Serializer serializer) {
@@ -164,14 +202,9 @@
   final MacroInstanceIdentifier macro;
   final DeclarationImpl declaration;
 
-  /// Client/Server specific implementation, not serialized.
-  final TypeResolver typeResolver;
-
-  /// Client/Server specific implementation, not serialized.
-  final ClassIntrospector classIntrospector;
-
-  /// Client/Server specific implementation, not serialized.
-  final TypeDeclarationResolver typeDeclarationResolver;
+  final RemoteInstanceImpl typeResolver;
+  final RemoteInstanceImpl classIntrospector;
+  final RemoteInstanceImpl typeDeclarationResolver;
 
   ExecuteDefinitionsPhaseRequest(this.macro, this.declaration,
       this.typeResolver, this.classIntrospector, this.typeDeclarationResolver,
@@ -180,51 +213,175 @@
 
   /// When deserializing we have already consumed the message type, so we don't
   /// consume it again.
-  ExecuteDefinitionsPhaseRequest.deserialize(Deserializer deserializer,
-      this.typeResolver, this.classIntrospector, this.typeDeclarationResolver)
+  ExecuteDefinitionsPhaseRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
       : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
         declaration = RemoteInstance.deserialize(deserializer),
-        super.deserialize(deserializer);
+        typeResolver = RemoteInstance.deserialize(deserializer),
+        classIntrospector = RemoteInstance.deserialize(deserializer),
+        typeDeclarationResolver = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
 
   void serialize(Serializer serializer) {
     serializer.addNum(MessageType.executeDefinitionsPhaseRequest.index);
     macro.serialize(serializer);
     declaration.serialize(serializer);
+    typeResolver.serialize(serializer);
+    classIntrospector.serialize(serializer);
+    typeDeclarationResolver.serialize(serializer);
+
     super.serialize(serializer);
   }
 }
 
 /// A request to reflect on a type annotation
-class ReflectTypeRequest extends Request {
+class ResolveTypeRequest extends Request {
   final TypeAnnotationImpl typeAnnotation;
+  final RemoteInstanceImpl typeResolver;
 
-  ReflectTypeRequest(this.typeAnnotation, {required int serializationZoneId})
+  ResolveTypeRequest(this.typeAnnotation, this.typeResolver,
+      {required int serializationZoneId})
       : super(serializationZoneId: serializationZoneId);
 
   /// When deserializing we have already consumed the message type, so we don't
   /// consume it again.
-  ReflectTypeRequest.deserialize(Deserializer deserializer)
+  ResolveTypeRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
       : typeAnnotation = RemoteInstance.deserialize(deserializer),
-        super.deserialize(deserializer);
+        typeResolver = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
 
   void serialize(Serializer serializer) {
-    serializer.addNum(MessageType.reflectTypeRequest.index);
+    serializer.addNum(MessageType.resolveTypeRequest.index);
     typeAnnotation.serialize(serializer);
+    typeResolver.serialize(serializer);
     super.serialize(serializer);
   }
 }
 
-/// TODO: Implement this
+/// A request to check if a type is exactly another type.
+class IsExactlyTypeRequest extends Request {
+  final RemoteInstanceImpl leftType;
+  final RemoteInstanceImpl rightType;
+
+  IsExactlyTypeRequest(this.leftType, this.rightType,
+      {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  /// When deserializing we have already consumed the message type, so we don't
+  /// consume it again.
+  IsExactlyTypeRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
+      : leftType = RemoteInstance.deserialize(deserializer),
+        rightType = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
+
+  void serialize(Serializer serializer) {
+    serializer.addNum(MessageType.isExactlyTypeRequest.index);
+    leftType.serialize(serializer);
+    rightType.serialize(serializer);
+    super.serialize(serializer);
+  }
+}
+
+/// A request to check if a type is exactly another type.
+class IsSubtypeOfRequest extends Request {
+  final ClientStaticTypeImpl leftType;
+  final ClientStaticTypeImpl rightType;
+
+  IsSubtypeOfRequest(this.leftType, this.rightType,
+      {required int serializationZoneId})
+      : super(serializationZoneId: serializationZoneId);
+
+  /// When deserializing we have already consumed the message type, so we don't
+  /// consume it again.
+  IsSubtypeOfRequest.deserialize(
+      Deserializer deserializer, int serializationZoneId)
+      : leftType = RemoteInstance.deserialize(deserializer),
+        rightType = RemoteInstance.deserialize(deserializer),
+        super.deserialize(deserializer, serializationZoneId);
+
+  void serialize(Serializer serializer) {
+    serializer.addNum(MessageType.isSubtypeOfRequest.index);
+    leftType.remoteInstance.serialize(serializer);
+    rightType.remoteInstance.serialize(serializer);
+    super.serialize(serializer);
+  }
+}
+
+/// Client side implementation of a [TypeResolver], which creates a
+/// [ResolveTypeRequest] and passes it to a given [sendRequest] function which
+/// can return the [Response].
 class ClientTypeResolver implements TypeResolver {
+  /// The actual remote instance of this type resolver.
+  final RemoteInstanceImpl remoteInstance;
+
+  /// The ID of the zone in which to find the original type resolver.
+  final int serializationZoneId;
+
+  /// A function that can send a request and return a response using an
+  /// arbitrary communication channel.
+  final Future<Response> Function(Request request) _sendRequest;
+
+  ClientTypeResolver(this._sendRequest,
+      {required this.remoteInstance, required this.serializationZoneId});
+
   @override
-  Future<StaticType> resolve(TypeAnnotation typeAnnotation) {
-    // TODO: implement resolve
-    throw new UnimplementedError();
+  Future<StaticType> resolve(TypeAnnotationImpl typeAnnotation) async {
+    ResolveTypeRequest request = new ResolveTypeRequest(
+        typeAnnotation, remoteInstance,
+        serializationZoneId: serializationZoneId);
+    RemoteInstanceImpl remoteType =
+        _handleResponse(await _sendRequest(request));
+    return new ClientStaticTypeImpl(_sendRequest,
+        remoteInstance: remoteType, serializationZoneId: serializationZoneId);
+  }
+}
+
+class ClientStaticTypeImpl implements StaticType {
+  /// The actual remote instance of this static type.
+  final RemoteInstanceImpl remoteInstance;
+
+  final int serializationZoneId;
+
+  /// A function that can send a request and return a response using an
+  /// arbitrary communication channel.
+  final Future<Response> Function(Request request) sendRequest;
+
+  ClientStaticTypeImpl(this.sendRequest,
+      {required this.remoteInstance, required this.serializationZoneId});
+
+  @override
+  Future<bool> isExactly(ClientStaticTypeImpl other) async {
+    IsExactlyTypeRequest request = new IsExactlyTypeRequest(
+        this.remoteInstance, other.remoteInstance,
+        serializationZoneId: serializationZoneId);
+    return _handleResponse<BooleanValue>(await sendRequest(request)).value;
+  }
+
+  @override
+  Future<bool> isSubtypeOf(ClientStaticTypeImpl other) async {
+    IsSubtypeOfRequest request = new IsSubtypeOfRequest(this, other,
+        serializationZoneId: serializationZoneId);
+    return _handleResponse<BooleanValue>(await sendRequest(request)).value;
   }
 }
 
 /// TODO: Implement this
 class ClientClassIntrospector implements ClassIntrospector {
+  /// The actual remote instance of this type resolver.
+  final RemoteInstanceImpl remoteInstance;
+
+  /// The ID of the zone in which to find the original type resolver.
+  final int serializationZoneId;
+
+  /// A function that can send a request and return a response using an
+  /// arbitrary communication channel.
+  final Future<Response> Function(Request request) sendRequest;
+
+  ClientClassIntrospector(this.sendRequest,
+      {required this.remoteInstance, required this.serializationZoneId});
+
   @override
   Future<List<ConstructorDeclaration>> constructorsOf(ClassDeclaration clazz) {
     // TODO: implement constructorsOf
@@ -263,7 +420,20 @@
 }
 
 /// TODO: Implement this
-class ClientTypeDeclarationsResolver implements TypeDeclarationResolver {
+class ClientTypeDeclarationResolver implements TypeDeclarationResolver {
+  /// The actual remote instance of this type resolver.
+  final RemoteInstanceImpl remoteInstance;
+
+  /// The ID of the zone in which to find the original type resolver.
+  final int serializationZoneId;
+
+  /// A function that can send a request and return a response using an
+  /// arbitrary communication channel.
+  final Future<Response> Function(Request request) sendRequest;
+
+  ClientTypeDeclarationResolver(this.sendRequest,
+      {required this.remoteInstance, required this.serializationZoneId});
+
   @override
   Future<TypeDeclaration> declarationOf(NamedStaticType annotation) {
     // TODO: implement declarationOf
@@ -271,13 +441,39 @@
   }
 }
 
+/// An exception that occurred remotely, the exception object and stack trace
+/// are serialized as [String]s and both included in the [toString] output.
+class RemoteException implements Exception {
+  final String error;
+  final String? stackTrace;
+
+  RemoteException(this.error, [this.stackTrace]);
+
+  String toString() =>
+      'RemoteException: $error${stackTrace == null ? '' : '\n\n$stackTrace'}';
+}
+
+/// Either returns the actual response from [response], casted to [T], or throws
+/// a [RemoteException] with the given error and stack trace.
+T _handleResponse<T>(Response response) {
+  if (response.response != null) {
+    return response.response as T;
+  }
+  throw new RemoteException(response.error!.toString(), response.stackTrace);
+}
+
 enum MessageType {
+  boolean,
   error,
   executeDefinitionsPhaseRequest,
   instantiateMacroRequest,
+  isExactlyTypeRequest,
+  isSubtypeOfRequest,
   loadMacroRequest,
-  reflectTypeRequest,
+  resolveTypeRequest,
   macroClassIdentifier,
   macroInstanceIdentifier,
   macroExecutionResult,
+  response,
+  staticType,
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart
index 5dcd1f8..59c26fd 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/executor_shared/remote_instance.dart
@@ -70,6 +70,20 @@
   }
 }
 
+/// A remote instance which is just a pointer to some server side instance of
+/// a generic object.
+///
+/// The wrapped object is not serialized.
+class RemoteInstanceImpl extends RemoteInstance {
+  /// Always null on the client side, has an actual instance on the server side.
+  final Object? instance;
+
+  @override
+  RemoteInstanceKind get kind => RemoteInstanceKind.instance;
+
+  RemoteInstanceImpl({required int id, this.instance}) : super(id);
+}
+
 // The kinds of instances.
 enum RemoteInstanceKind {
   classDeclaration,
@@ -83,4 +97,6 @@
   typeAliasDeclaration,
   typeParameterDeclaration,
   variableDeclaration,
+  // A generic instance that is just a pointer to some server side instance.
+  instance,
 }
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 1fafb40..c950279 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
@@ -11,23 +11,29 @@
       case SerializationMode.client:
         moveNext();
         RemoteInstanceKind kind = RemoteInstanceKind.values[expectNum()];
-        moveNext();
         switch (kind) {
           case RemoteInstanceKind.namedTypeAnnotation:
+            moveNext();
             return _expectNamedTypeAnnotation(id) as T;
           case RemoteInstanceKind.functionTypeAnnotation:
+            moveNext();
             return _expectFunctionTypeAnnotation(id) as T;
           case RemoteInstanceKind.functionDeclaration:
+            moveNext();
             return _expectFunctionDeclaration(id) as T;
           case RemoteInstanceKind.parameterDeclaration:
+            moveNext();
             return _expectParameterDeclaration(id) as T;
           case RemoteInstanceKind.typeParameterDeclaration:
+            moveNext();
             return _expectTypeParameterDeclaration(id) as T;
+          case RemoteInstanceKind.instance:
+            return new RemoteInstanceImpl(id: id) as T;
           default:
             throw new UnsupportedError('Unsupported remote object kind: $kind');
         }
       case SerializationMode.server:
-        return RemoteInstance.cached(id);
+        return RemoteInstance.cached(id) as T;
     }
   }
 
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
index 24c7d80..f5a7287 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart
@@ -9,6 +9,7 @@
 import 'isolate_mirrors_impl.dart';
 import '../executor_shared/introspection_impls.dart';
 import '../executor_shared/protocol.dart';
+import '../executor_shared/remote_instance.dart';
 import '../executor.dart';
 import '../api.dart';
 
@@ -106,8 +107,15 @@
           TypeResolver typeResolver,
           ClassIntrospector classIntrospector,
           TypeDeclarationResolver typeDeclarationResolver) =>
-      _sendRequest(new ExecuteDefinitionsPhaseRequest(macro, declaration,
-          typeResolver, classIntrospector, typeDeclarationResolver,
+      _sendRequest(new ExecuteDefinitionsPhaseRequest(
+          macro,
+          declaration,
+          new RemoteInstanceImpl(
+              instance: typeResolver, id: RemoteInstance.uniqueId),
+          new RemoteInstanceImpl(
+              instance: classIntrospector, id: RemoteInstance.uniqueId),
+          new RemoteInstanceImpl(
+              instance: typeDeclarationResolver, id: RemoteInstance.uniqueId),
           // Serialization zones are not necessary in this executor.
           serializationZoneId: -1));
 
diff --git a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart
index fe7e32e..4673d17 100644
--- a/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/macros/isolate_mirrors_executor/isolate_mirrors_impl.dart
@@ -89,9 +89,9 @@
         declaration is FunctionDeclarationImpl) {
       FunctionDefinitionBuilderImpl builder = new FunctionDefinitionBuilderImpl(
           declaration,
-          request.typeResolver,
-          request.typeDeclarationResolver,
-          request.classIntrospector);
+          request.typeResolver.instance as TypeResolver,
+          request.typeDeclarationResolver.instance as TypeDeclarationResolver,
+          request.classIntrospector.instance as ClassIntrospector);
       await instance.buildDefinitionForFunction(declaration, builder);
       return new Response(response: builder.result, requestId: request.id);
     } else {
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 4b564b6..b2b3b49 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
@@ -5,6 +5,8 @@
 import 'dart:async';
 import 'dart:isolate';
 
+import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
+
 import '../api.dart';
 import '../executor_shared/introspection_impls.dart';
 import '../executor_shared/protocol.dart';
@@ -103,7 +105,7 @@
 
 class _SingleIsolatedMacroExecutor extends MacroExecutor {
   /// The stream on which we receive responses.
-  final Stream<Response> responseStream;
+  final Stream<Object> messageStream;
 
   /// The send port where we should send requests.
   final SendPort sendPort;
@@ -126,16 +128,85 @@
 
   _SingleIsolatedMacroExecutor(
       {required this.onClose,
-      required this.responseStream,
+      required this.messageStream,
       required this.sendPort}) {
-    responseStream.listen((event) {
-      Completer<Response>? completer =
-          responseCompleters.remove(event.requestId);
-      if (completer == null) {
-        throw new StateError(
-            'Got a response for an unrecognized request id ${event.requestId}');
-      }
-      completer.complete(event);
+    messageStream.listen((message) {
+      withSerializationMode(SerializationMode.server, () {
+        JsonDeserializer deserializer =
+            new JsonDeserializer(message as List<Object?>);
+        // Every object starts with a zone ID which dictates the zone in which
+        // we should deserialize the message.
+        deserializer.moveNext();
+        int zoneId = deserializer.expectNum();
+        Zone zone = serializationZones[zoneId]!;
+        zone.run(() async {
+          deserializer.moveNext();
+          MessageType messageType =
+              MessageType.values[deserializer.expectNum()];
+          switch (messageType) {
+            case MessageType.response:
+              SerializableResponse response =
+                  new SerializableResponse.deserialize(deserializer, zoneId);
+              Completer<Response>? completer =
+                  responseCompleters.remove(response.requestId);
+              if (completer == null) {
+                throw new StateError(
+                    'Got a response for an unrecognized request id '
+                    '${response.requestId}');
+              }
+              completer.complete(response);
+              break;
+            case MessageType.resolveTypeRequest:
+              ResolveTypeRequest request =
+                  new ResolveTypeRequest.deserialize(deserializer, zoneId);
+              SerializableResponse response = new SerializableResponse(
+                  response: new RemoteInstanceImpl(
+                      id: RemoteInstance.uniqueId,
+                      instance:
+                          await (request.typeResolver.instance as TypeResolver)
+                              .resolve(request.typeAnnotation)),
+                  requestId: request.id,
+                  responseType: MessageType.staticType,
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            case MessageType.isExactlyTypeRequest:
+              IsExactlyTypeRequest request =
+                  new IsExactlyTypeRequest.deserialize(deserializer, zoneId);
+              StaticType leftType = request.leftType.instance as StaticType;
+              StaticType rightType = request.leftType.instance as StaticType;
+              SerializableResponse response = new SerializableResponse(
+                  response:
+                      new BooleanValue(await leftType.isExactly(rightType)),
+                  requestId: request.id,
+                  responseType: MessageType.boolean,
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            case MessageType.isSubtypeOfRequest:
+              IsExactlyTypeRequest request =
+                  new IsExactlyTypeRequest.deserialize(deserializer, zoneId);
+              StaticType leftType = request.leftType.instance as StaticType;
+              StaticType rightType = request.leftType.instance as StaticType;
+              SerializableResponse response = new SerializableResponse(
+                  response:
+                      new BooleanValue(await leftType.isSubtypeOf(rightType)),
+                  requestId: request.id,
+                  responseType: MessageType.boolean,
+                  serializationZoneId: zoneId);
+              JsonSerializer serializer = new JsonSerializer();
+              response.serialize(serializer);
+              sendPort.send(serializer.result);
+              break;
+            default:
+              throw new StateError('Unexpected message type $messageType');
+          }
+        });
+      });
     });
   }
 
@@ -145,31 +216,22 @@
     Isolate isolate =
         await Isolate.spawnUri(precompiledKernelUri, [], receivePort.sendPort);
     Completer<SendPort> sendPortCompleter = new Completer();
-    StreamController<Response> responseStreamController =
+    StreamController<Object> messageStreamController =
         new StreamController(sync: true);
     receivePort.listen((message) {
       if (!sendPortCompleter.isCompleted) {
         sendPortCompleter.complete(message as SendPort);
       } else {
-        JsonDeserializer deserializer =
-            new JsonDeserializer(message as List<Object?>);
-        // Ever object starts with a zone ID which dictates the zone in which we
-        // should deserialize the message.
-        deserializer.moveNext();
-        int zoneId = deserializer.expectNum();
-        Zone zone = serializationZones[zoneId]!;
-        SerializableResponse response = zone.run(
-            () => new SerializableResponse.deserialize(deserializer, zoneId));
-        responseStreamController.add(response);
+        messageStreamController.add(message);
       }
-    }).onDone(responseStreamController.close);
+    }).onDone(messageStreamController.close);
 
     return new _SingleIsolatedMacroExecutor(
         onClose: () {
           receivePort.close();
           isolate.kill();
         },
-        responseStream: responseStreamController.stream,
+        messageStream: messageStreamController.stream,
         sendPort: await sendPortCompleter.future);
   }
 
@@ -199,8 +261,15 @@
           TypeResolver typeResolver,
           ClassIntrospector classIntrospector,
           TypeDeclarationResolver typeDeclarationResolver) =>
-      _sendRequest((zoneId) => new ExecuteDefinitionsPhaseRequest(macro,
-          declaration, typeResolver, classIntrospector, typeDeclarationResolver,
+      _sendRequest((zoneId) => new ExecuteDefinitionsPhaseRequest(
+          macro,
+          declaration,
+          new RemoteInstanceImpl(
+              instance: typeResolver, id: RemoteInstance.uniqueId),
+          new RemoteInstanceImpl(
+              instance: classIntrospector, id: RemoteInstance.uniqueId),
+          new RemoteInstanceImpl(
+              instance: typeDeclarationResolver, id: RemoteInstance.uniqueId),
           serializationZoneId: zoneId));
 
   @override
@@ -225,14 +294,16 @@
           {Uri? precompiledKernelUri}) =>
       throw new StateError('Unreachable');
 
-  /// Sends a [request] and handles the response, casting it to the expected
-  /// type or throwing the error provided.
+  /// Creates a [Request] with a given serialization zone ID, and handles the
+  /// response, casting it to the expected type or throwing the error provided.
   Future<T> _sendRequest<T>(Request Function(int) requestFactory) =>
       withSerializationMode(SerializationMode.server, () async {
         int zoneId = _nextSerializationZoneId++;
         serializationZones[zoneId] = Zone.current;
         Request request = requestFactory(zoneId);
         JsonSerializer serializer = new JsonSerializer();
+        // It is our responsibility to add the zone ID header.
+        serializer.addNum(zoneId);
         request.serialize(serializer);
         sendPort.send(serializer.result);
         Completer<Response> completer = new Completer<Response>();
@@ -241,7 +312,8 @@
           Response response = await completer.future;
           T? result = response.response as T?;
           if (result != null) return result;
-          throw response.error!;
+          throw new RemoteException(
+              response.error!.toString(), response.stackTrace);
         } finally {
           // Clean up the zone after the request is done.
           serializationZones.remove(zoneId);
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 aae2ad0..c1f7c1d 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
@@ -4,16 +4,16 @@
 
 import 'dart:io';
 
-import 'package:_fe_analyzer_shared/src/macros/api.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor_shared/remote_instance.dart';
 import 'package:_fe_analyzer_shared/src/macros/isolate_mirrors_executor/isolate_mirrors_executor.dart'
     as mirrorExecutor;
 
-import 'package:test/fake.dart';
 import 'package:test/test.dart';
 
+import '../util.dart';
+
 void main() {
   late MacroExecutor executor;
   late File simpleMacroFile;
@@ -55,6 +55,11 @@
     expect(instanceId, isNotNull,
         reason: 'Can create an instance with named arguments.');
 
+    var returnType = NamedTypeAnnotationImpl(
+        id: RemoteInstance.uniqueId,
+        name: 'String',
+        isNullable: false,
+        typeArguments: const []);
     var definitionResult = await executor.executeDefinitionsPhase(
         instanceId,
         FunctionDeclarationImpl(
@@ -66,16 +71,13 @@
           name: 'foo',
           namedParameters: [],
           positionalParameters: [],
-          returnType: NamedTypeAnnotationImpl(
-              id: RemoteInstance.uniqueId,
-              name: 'String',
-              isNullable: false,
-              typeArguments: const []),
+          returnType: returnType,
           typeParameters: [],
         ),
-        _FakeTypeResolver(),
-        _FakeClassIntrospector(),
-        _FakeTypeDeclarationResolver());
+        TestTypeResolver(
+            {returnType: TestStaticType('dart:core', 'String', [])}),
+        FakeClassIntrospector(),
+        FakeTypeDeclarationResolver());
     expect(definitionResult.augmentations, hasLength(1));
     expect(definitionResult.augmentations.first.debugString().toString(),
         equalsIgnoringWhitespace('''
@@ -85,27 +87,3 @@
             }'''));
   });
 }
-
-class _FakeClassIntrospector with Fake implements ClassIntrospector {}
-
-class _FakeTypeResolver with Fake implements TypeResolver {}
-
-class _FakeTypeDeclarationResolver
-    with Fake
-    implements TypeDeclarationResolver {}
-
-extension _ on Code {
-  StringBuffer debugString([StringBuffer? buffer]) {
-    buffer ??= StringBuffer();
-    for (var part in parts) {
-      if (part is Code) {
-        part.debugString(buffer);
-      } else if (part is TypeAnnotation) {
-        part.code.debugString(buffer);
-      } else {
-        buffer.write(part.toString());
-      }
-    }
-    return buffer;
-  }
-}
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 c4cac8b..1bdb14f 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
@@ -5,7 +5,6 @@
 import 'dart:io';
 import 'dart:isolate';
 
-import 'package:_fe_analyzer_shared/src/macros/api.dart';
 import 'package:_fe_analyzer_shared/src/macros/bootstrap.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor_shared/introspection_impls.dart';
@@ -13,9 +12,10 @@
 import 'package:_fe_analyzer_shared/src/macros/isolated_executor/isolated_executor.dart'
     as isolatedExecutor;
 
-import 'package:test/fake.dart';
 import 'package:test/test.dart';
 
+import '../util.dart';
+
 void main() {
   late MacroExecutor executor;
   late Directory tmpDir;
@@ -40,7 +40,7 @@
     executor.close();
   });
 
-  test('can load macros and create instances', () async {
+  test('can load and run macros', () async {
     var macroUri = simpleMacroFile.absolute.uri;
     var macroName = 'SimpleMacro';
 
@@ -78,6 +78,11 @@
     expect(instanceId, isNotNull,
         reason: 'Can create an instance with named arguments.');
 
+    var returnType = NamedTypeAnnotationImpl(
+        id: RemoteInstance.uniqueId,
+        name: 'String',
+        isNullable: false,
+        typeArguments: const []);
     var definitionResult = await executor.executeDefinitionsPhase(
         instanceId,
         FunctionDeclarationImpl(
@@ -89,16 +94,13 @@
           name: 'foo',
           namedParameters: [],
           positionalParameters: [],
-          returnType: NamedTypeAnnotationImpl(
-              id: RemoteInstance.uniqueId,
-              name: 'String',
-              isNullable: false,
-              typeArguments: const []),
+          returnType: returnType,
           typeParameters: [],
         ),
-        _FakeTypeResolver(),
-        _FakeClassIntrospector(),
-        _FakeTypeDeclarationResolver());
+        TestTypeResolver(
+            {returnType: TestStaticType('dart:core', 'String', [])}),
+        FakeClassIntrospector(),
+        FakeTypeDeclarationResolver());
     expect(definitionResult.augmentations, hasLength(1));
     expect(definitionResult.augmentations.first.debugString().toString(),
         equalsIgnoringWhitespace('''
@@ -108,27 +110,3 @@
             }'''));
   });
 }
-
-class _FakeClassIntrospector with Fake implements ClassIntrospector {}
-
-class _FakeTypeResolver with Fake implements TypeResolver {}
-
-class _FakeTypeDeclarationResolver
-    with Fake
-    implements TypeDeclarationResolver {}
-
-extension _ on Code {
-  StringBuffer debugString([StringBuffer? buffer]) {
-    buffer ??= StringBuffer();
-    for (var part in parts) {
-      if (part is Code) {
-        part.debugString(buffer);
-      } else if (part is TypeAnnotation) {
-        part.code.debugString(buffer);
-      } else {
-        buffer.write(part.toString());
-      }
-    }
-    return buffer;
-  }
-}
diff --git a/pkg/_fe_analyzer_shared/test/macros/simple_macro.dart b/pkg/_fe_analyzer_shared/test/macros/simple_macro.dart
index b95da0b..ff31b12 100644
--- a/pkg/_fe_analyzer_shared/test/macros/simple_macro.dart
+++ b/pkg/_fe_analyzer_shared/test/macros/simple_macro.dart
@@ -18,13 +18,23 @@
 
   @override
   FutureOr<void> buildDefinitionForFunction(
-      FunctionDeclaration method, FunctionDefinitionBuilder builder) {
+      FunctionDeclaration method, FunctionDefinitionBuilder builder) async {
     if (method.namedParameters
         .followedBy(method.positionalParameters)
         .isNotEmpty) {
       throw ArgumentError(
           'This macro can only be run on functions with no arguments!');
     }
+
+    // Test the type resolver and static type interfaces
+    var staticReturnType = await builder.resolve(method.returnType);
+    if (!(await staticReturnType.isExactly(staticReturnType))) {
+      throw StateError('The return type should be exactly equal to itself!');
+    }
+    if (!(await staticReturnType.isSubtypeOf(staticReturnType))) {
+      throw StateError('The return type should be a subtype of itself!');
+    }
+
     builder.augment(FunctionBodyCode.fromString('''{
       print('x: $x, y: $y');
       return augment super();
diff --git a/pkg/_fe_analyzer_shared/test/macros/util.dart b/pkg/_fe_analyzer_shared/test/macros/util.dart
new file mode 100644
index 0000000..179f50b
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/macros/util.dart
@@ -0,0 +1,60 @@
+// 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:_fe_analyzer_shared/src/macros/api.dart';
+
+import 'package:test/fake.dart';
+
+class FakeClassIntrospector with Fake implements ClassIntrospector {}
+
+class FakeTypeDeclarationResolver with Fake implements TypeDeclarationResolver {
+}
+
+class TestTypeResolver implements TypeResolver {
+  final Map<TypeAnnotation, StaticType> staticTypes;
+
+  TestTypeResolver(this.staticTypes);
+
+  @override
+  Future<StaticType> resolve(covariant TypeAnnotation typeAnnotation) async {
+    return staticTypes[typeAnnotation]!;
+  }
+}
+
+// Doesn't handle generics etc but thats ok for now
+class TestStaticType implements StaticType {
+  final String library;
+  final String name;
+  final List<TestStaticType> superTypes;
+
+  TestStaticType(this.library, this.name, this.superTypes);
+
+  @override
+  Future<bool> isExactly(TestStaticType other) async => _isExactly(other);
+
+  @override
+  Future<bool> isSubtypeOf(TestStaticType other) async =>
+      _isExactly(other) ||
+      superTypes.any((superType) => superType._isExactly(other));
+
+  bool _isExactly(TestStaticType other) =>
+      identical(other, this) ||
+      (library == other.library && name == other.name);
+}
+
+extension DebugCodeString on Code {
+  StringBuffer debugString([StringBuffer? buffer]) {
+    buffer ??= StringBuffer();
+    for (var part in parts) {
+      if (part is Code) {
+        part.debugString(buffer);
+      } else if (part is TypeAnnotation) {
+        part.code.debugString(buffer);
+      } else {
+        buffer.write(part.toString());
+      }
+    }
+    return buffer;
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index f5454a5..05653ef 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -7,7 +7,6 @@
 import 'package:kernel/ast.dart'
     show
         Class,
-        Constructor,
         DartType,
         DynamicType,
         FutureOrType,
@@ -32,11 +31,8 @@
 import 'library_builder.dart';
 import 'member_builder.dart';
 import 'metadata_builder.dart';
-import 'named_type_builder.dart';
 import 'nullability_builder.dart';
-import 'type_alias_builder.dart';
 import 'type_builder.dart';
-import 'type_declaration_builder.dart';
 import 'type_variable_builder.dart';
 
 abstract class ClassBuilder implements DeclarationBuilder {
@@ -59,8 +55,6 @@
 
   ConstructorScopeBuilder get constructorScopeBuilder;
 
-  abstract ClassBuilder? actualOrigin;
-
   @override
   Uri get fileUri;
 
@@ -78,10 +72,6 @@
 
   abstract TypeBuilder? mixedInTypeBuilder;
 
-  /// Registers a constructor redirection for this class and returns true if
-  /// this redirection gives rise to a cycle that has not been reported before.
-  bool checkConstructorCyclic(String source, String target);
-
   MemberBuilder? findConstructorOrFactory(
       String name, int charOffset, Uri uri, LibraryBuilder accessingLibrary);
 
@@ -95,8 +85,6 @@
   @override
   ClassBuilder get origin;
 
-  Class get actualCls;
-
   abstract bool isNullClass;
 
   @override
@@ -135,12 +123,6 @@
   Member? lookupInstanceMember(ClassHierarchy hierarchy, Name name,
       {bool isSetter: false, bool isSuper: false});
 
-  /// Looks up the constructor by [name] on the class built by this class
-  /// builder.
-  ///
-  /// If [isSuper] is `true`, constructors in the superclass are searched.
-  Constructor? lookupConstructor(Name name, {bool isSuper: false});
-
   /// Calls [f] for each constructor declared in this class.
   ///
   /// If [includeInjectedConstructors] is `true`, constructors only declared in
@@ -169,11 +151,6 @@
   @override
   final ConstructorScopeBuilder constructorScopeBuilder;
 
-  Map<String, ConstructorRedirection>? _redirectingConstructors;
-
-  @override
-  ClassBuilder? actualOrigin;
-
   @override
   bool isNullClass = false;
 
@@ -224,35 +201,6 @@
       (modifiers & declaresConstConstructorMask) != 0;
 
   @override
-  void forEachConstructor(void Function(String, MemberBuilder) f,
-      {bool includeInjectedConstructors: false}) {
-    if (isPatch) {
-      actualOrigin!.forEachConstructor(f,
-          includeInjectedConstructors: includeInjectedConstructors);
-    } else {
-      constructors.forEach(f);
-    }
-  }
-
-  /// Registers a constructor redirection for this class and returns true if
-  /// this redirection gives rise to a cycle that has not been reported before.
-  @override
-  bool checkConstructorCyclic(String source, String target) {
-    ConstructorRedirection? redirect = new ConstructorRedirection(target);
-    _redirectingConstructors ??= <String, ConstructorRedirection>{};
-    _redirectingConstructors![source] = redirect;
-    while (redirect != null) {
-      if (redirect.cycleReported) return false;
-      if (redirect.target == source) {
-        redirect.cycleReported = true;
-        return true;
-      }
-      redirect = _redirectingConstructors![redirect.target];
-    }
-    return false;
-  }
-
-  @override
   Builder? findStaticBuilder(
       String name, int charOffset, Uri fileUri, LibraryBuilder accessingLibrary,
       {bool isSetter: false}) {
@@ -329,9 +277,6 @@
   }
 
   @override
-  ClassBuilder get origin => actualOrigin ?? this;
-
-  @override
   InterfaceType get thisType {
     return _thisType ??= new InterfaceType(cls, library.nonNullable,
         getAsTypeArguments(cls.typeParameters, library.library));
@@ -477,63 +422,6 @@
     }
     return target;
   }
-
-  @override
-  Constructor? lookupConstructor(Name name, {bool isSuper: false}) {
-    if (name.text == "new") {
-      name = new Name("", name.library);
-    }
-
-    Class? instanceClass = cls;
-    if (isSuper) {
-      instanceClass = instanceClass.superclass;
-    }
-    if (instanceClass != null) {
-      for (Constructor constructor in instanceClass.constructors) {
-        if (constructor.name == name) {
-          return constructor;
-        }
-      }
-    }
-
-    /// Performs a similar lookup to [lookupConstructor], but using a slower
-    /// implementation.
-    Constructor? lookupConstructorWithPatches(Name name, bool isSuper) {
-      ClassBuilder? builder = this.origin;
-
-      ClassBuilder? getSuperclass(ClassBuilder builder) {
-        // This way of computing the superclass is slower than using the kernel
-        // objects directly.
-        TypeBuilder? supertype = builder.supertypeBuilder;
-        if (supertype is NamedTypeBuilder) {
-          TypeDeclarationBuilder? builder = supertype.declaration;
-          if (builder is ClassBuilder) return builder;
-          if (builder is TypeAliasBuilder) {
-            TypeDeclarationBuilder? declarationBuilder =
-                builder.unaliasDeclaration(supertype.arguments,
-                    isUsedAsClass: true,
-                    usedAsClassCharOffset: supertype.charOffset,
-                    usedAsClassFileUri: supertype.fileUri);
-            if (declarationBuilder is ClassBuilder) return declarationBuilder;
-          }
-        }
-        return null;
-      }
-
-      if (isSuper) {
-        builder = getSuperclass(builder)?.origin;
-      }
-      if (builder != null) {
-        Class cls = builder.cls;
-        for (Constructor constructor in cls.constructors) {
-          if (constructor.name == name) return constructor;
-        }
-      }
-      return null;
-    }
-
-    return lookupConstructorWithPatches(name, isSuper);
-  }
 }
 
 class ConstructorRedirection {
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
index 9ccfd18..18b8478 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
@@ -47,6 +47,9 @@
             cls.fileOffset);
 
   @override
+  DillClassBuilder get origin => this;
+
+  @override
   DillLibraryBuilder get library => super.library as DillLibraryBuilder;
 
   @override
@@ -77,9 +80,6 @@
     return supertype;
   }
 
-  @override
-  Class get actualCls => cls;
-
   void addField(Field field) {
     DillFieldBuilder builder = new DillFieldBuilder(field, this);
     String name = field.name.text;
@@ -171,6 +171,12 @@
     return super.interfaceBuilders;
   }
 
+  @override
+  void forEachConstructor(void Function(String, MemberBuilder) f,
+      {bool includeInjectedConstructors: false}) {
+    constructors.forEach(f);
+  }
+
   void clearCachedValues() {
     supertypeBuilder = null;
     interfaceBuilders = null;
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 197632f..fe74b48 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -85,6 +85,7 @@
 import '../scope.dart';
 import '../source/diet_parser.dart';
 import '../source/scope_listener.dart' show JumpTargetKind, ScopeListener;
+import '../source/source_class_builder.dart';
 import '../source/source_constructor_builder.dart';
 import '../source/source_enum_builder.dart';
 import '../source/source_factory_builder.dart';
@@ -139,8 +140,13 @@
   /// if any.
   final DeclarationBuilder? declarationBuilder;
 
-  /// The class or mixin declaration in which [member] is declared, if any.
-  final ClassBuilder? classBuilder;
+  /// The source class or mixin declaration in which [member] is declared, if
+  /// any.
+  ///
+  /// If [member] is a synthesized member for expression evaluation the
+  /// enclosing declaration might be a [DillClassBuilder]. This can be accessed
+  /// through [declarationBuilder].
+  final SourceClassBuilder? sourceClassBuilder;
 
   final ClassHierarchy hierarchy;
 
@@ -342,8 +348,9 @@
       required this.uri,
       required this.typeInferrer})
       : forest = const Forest(),
-        classBuilder =
-            declarationBuilder is ClassBuilder ? declarationBuilder : null,
+        sourceClassBuilder = declarationBuilder is SourceClassBuilder
+            ? declarationBuilder
+            : null,
         enableNative = libraryBuilder.loader.target.backendTarget
             .enableNative(libraryBuilder.importUri),
         stringExpectedAfterNative = libraryBuilder
@@ -352,8 +359,9 @@
             libraryBuilder.importUri.scheme == 'dart' &&
                 (libraryBuilder.importUri.path == "_builtin" ||
                     libraryBuilder.importUri.path == "ui"),
-        needsImplicitSuperInitializer = declarationBuilder is ClassBuilder &&
-            coreTypes.objectClass != declarationBuilder.cls,
+        needsImplicitSuperInitializer =
+            declarationBuilder is SourceClassBuilder &&
+                coreTypes.objectClass != declarationBuilder.cls,
         super(enclosingScope) {
     formalParameterScope?.forEach((String name, Builder builder) {
       if (builder is VariableBuilder) {
@@ -1763,7 +1771,7 @@
           fasta.messageConstructorNotSync, body!.fileOffset, noLength)));
     }
     if (libraryBuilder.enableEnhancedEnumsInLibrary &&
-        classBuilder is SourceEnumBuilder &&
+        sourceClassBuilder is SourceEnumBuilder &&
         constructor.initializers.isNotEmpty &&
         constructor.initializers.last is RedirectingInitializer) {
       RedirectingInitializer redirectingInitializer =
@@ -1806,7 +1814,7 @@
         positionalArguments = positionalSuperParametersAsArguments;
         namedArguments = namedSuperParametersAsArguments;
       }
-      if (classBuilder is SourceEnumBuilder) {
+      if (sourceClassBuilder is SourceEnumBuilder) {
         assert(constructor.function.positionalParameters.length >= 2 &&
             constructor.function.positionalParameters[0].name == "index" &&
             constructor.function.positionalParameters[1].name == "name");
@@ -1826,7 +1834,8 @@
           checkArgumentsForFunction(superTarget.function, arguments,
                   builder.charOffset, const <TypeParameter>[]) !=
               null) {
-        String superclass = classBuilder!.supertypeBuilder!.fullNameForErrors;
+        String superclass =
+            sourceClassBuilder!.supertypeBuilder!.fullNameForErrors;
         int length = constructor.name.text.length;
         if (length == 0) {
           length = (constructor.parent as Class).name.length;
@@ -2563,15 +2572,15 @@
   }
 
   @override
-  Member? lookupInstanceMember(Name name,
-      {bool isSetter: false, bool isSuper: false}) {
-    return classBuilder!.lookupInstanceMember(hierarchy, name,
-        isSetter: isSetter, isSuper: isSuper);
+  Member? lookupSuperMember(Name name, {bool isSetter: false}) {
+    return (declarationBuilder as ClassBuilder).lookupInstanceMember(
+        hierarchy, name,
+        isSetter: isSetter, isSuper: true);
   }
 
   @override
   Constructor? lookupConstructor(Name name, {bool isSuper: false}) {
-    return classBuilder!.lookupConstructor(name, isSuper: isSuper);
+    return sourceClassBuilder!.lookupConstructor(name, isSuper: isSuper);
   }
 
   @override
@@ -2650,9 +2659,9 @@
     Builder? declaration = scope.lookup(name, charOffset, uri);
     if (declaration == null &&
         prefix == null &&
-        (classBuilder?.isPatch ?? false)) {
+        (sourceClassBuilder?.isPatch ?? false)) {
       // The scope of a patched method includes the origin class.
-      declaration = classBuilder!.origin
+      declaration = sourceClassBuilder!.origin
           .findStaticBuilder(name, charOffset, uri, libraryBuilder);
     }
     if (declaration != null &&
@@ -3120,8 +3129,8 @@
     constantContext = member.isConst
         ? ConstantContext.inferred
         : !member.isStatic &&
-                classBuilder != null &&
-                classBuilder!.declaresConstConstructor
+                sourceClassBuilder != null &&
+                sourceClassBuilder!.declaresConstConstructor
             ? ConstantContext.required
             : ConstantContext.none;
     if (member is SourceFieldBuilder) {
@@ -3155,8 +3164,8 @@
     constantContext = member.isConst
         ? ConstantContext.inferred
         : !member.isStatic &&
-                classBuilder != null &&
-                classBuilder!.declaresConstConstructor
+                sourceClassBuilder != null &&
+                sourceClassBuilder!.declaresConstConstructor
             ? ConstantContext.required
             : ConstantContext.none;
     if (constantContext == ConstantContext.inferred) {
@@ -6968,7 +6977,7 @@
   Initializer buildRedirectingInitializer(
       Constructor constructor, Arguments arguments,
       [int charOffset = -1]) {
-    if (classBuilder!
+    if (sourceClassBuilder!
         .checkConstructorCyclic(member.name!, constructor.name.text)) {
       int length = constructor.name.text.length;
       if (length == 0) length = "this".length;
@@ -7188,7 +7197,7 @@
           offset,
           name.text.length);
     }
-    Member? target = lookupInstanceMember(name, isSuper: true);
+    Member? target = lookupSuperMember(name);
 
     if (target == null || (target is Procedure && !target.isAccessor)) {
       if (target == null) {
@@ -7317,7 +7326,7 @@
   String constructorNameForDiagnostics(String name,
       {String? className, bool isSuper: false}) {
     if (className == null) {
-      Class cls = classBuilder!.cls;
+      Class cls = sourceClassBuilder!.cls;
       if (isSuper) {
         cls = cls.superclass!;
         while (cls.isMixinApplication) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index f792c94..ec5e04c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -4492,9 +4492,8 @@
       }
     } else {
       if (isSuper) {
-        Member? getter = _helper.lookupInstanceMember(name, isSuper: isSuper);
-        Member? setter = _helper.lookupInstanceMember(name,
-            isSuper: isSuper, isSetter: true);
+        Member? getter = _helper.lookupSuperMember(name);
+        Member? setter = _helper.lookupSuperMember(name, isSetter: true);
         return new SuperPropertyAccessGenerator(
             _helper,
             // TODO(ahe): This is not the 'super' token.
@@ -4659,10 +4658,8 @@
           _helper,
           token,
           index,
-          _helper.lookupInstanceMember(indexGetName, isSuper: true)
-              as Procedure?,
-          _helper.lookupInstanceMember(indexSetName, isSuper: true)
-              as Procedure?);
+          _helper.lookupSuperMember(indexGetName) as Procedure?,
+          _helper.lookupSuperMember(indexSetName) as Procedure?);
     } else {
       return new ThisIndexedAccessGenerator(_helper, token, index,
           thisOffset: fileOffset, isNullAware: isNullAware);
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index 42258ae..4805dac 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -55,7 +55,7 @@
 
   Expression toValue(Object? node);
 
-  Member? lookupInstanceMember(Name name, {bool isSetter, bool isSuper});
+  Member? lookupSuperMember(Name name, {bool isSetter});
 
   bool get enableExtensionTypesInLibrary;
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index c95900c..e47921b 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -88,7 +88,6 @@
 
 class SourceClassBuilder extends ClassBuilderImpl
     implements Comparable<SourceClassBuilder> {
-  @override
   final Class actualCls;
 
   final List<ConstructorReferenceBuilder>? constructorReferences;
@@ -137,6 +136,11 @@
 
   SourceClassBuilder? get patchForTesting => _patchBuilder;
 
+  SourceClassBuilder? actualOrigin;
+
+  @override
+  SourceClassBuilder get origin => actualOrigin ?? this;
+
   @override
   Class get cls => origin.actualCls;
 
@@ -419,6 +423,66 @@
     constructors.forEach(callbackFilteringFieldBuilders);
   }
 
+  /// Looks up the constructor by [name] on the class built by this class
+  /// builder.
+  ///
+  /// If [isSuper] is `true`, constructors in the superclass are searched.
+  Constructor? lookupConstructor(Name name, {bool isSuper: false}) {
+    if (name.text == "new") {
+      name = new Name("", name.library);
+    }
+
+    Class? instanceClass = cls;
+    if (isSuper) {
+      instanceClass = instanceClass.superclass;
+    }
+    if (instanceClass != null) {
+      for (Constructor constructor in instanceClass.constructors) {
+        if (constructor.name == name) {
+          return constructor;
+        }
+      }
+    }
+
+    /// Performs a similar lookup to [lookupConstructor], but using a slower
+    /// implementation.
+    Constructor? lookupConstructorWithPatches(Name name, bool isSuper) {
+      ClassBuilder? builder = this.origin;
+
+      ClassBuilder? getSuperclass(ClassBuilder builder) {
+        // This way of computing the superclass is slower than using the kernel
+        // objects directly.
+        TypeBuilder? supertype = builder.supertypeBuilder;
+        if (supertype is NamedTypeBuilder) {
+          TypeDeclarationBuilder? builder = supertype.declaration;
+          if (builder is ClassBuilder) return builder;
+          if (builder is TypeAliasBuilder) {
+            TypeDeclarationBuilder? declarationBuilder =
+                builder.unaliasDeclaration(supertype.arguments,
+                    isUsedAsClass: true,
+                    usedAsClassCharOffset: supertype.charOffset,
+                    usedAsClassFileUri: supertype.fileUri);
+            if (declarationBuilder is ClassBuilder) return declarationBuilder;
+          }
+        }
+        return null;
+      }
+
+      if (isSuper) {
+        builder = getSuperclass(builder)?.origin;
+      }
+      if (builder != null) {
+        Class cls = builder.cls;
+        for (Constructor constructor in cls.constructors) {
+          if (constructor.name == name) return constructor;
+        }
+      }
+      return null;
+    }
+
+    return lookupConstructorWithPatches(name, isSuper);
+  }
+
   @override
   int get typeVariablesCount => typeVariables?.length ?? 0;
 
@@ -907,6 +971,25 @@
     }
   }
 
+  Map<String, ConstructorRedirection>? _redirectingConstructors;
+
+  /// Registers a constructor redirection for this class and returns true if
+  /// this redirection gives rise to a cycle that has not been reported before.
+  bool checkConstructorCyclic(String source, String target) {
+    ConstructorRedirection? redirect = new ConstructorRedirection(target);
+    _redirectingConstructors ??= <String, ConstructorRedirection>{};
+    _redirectingConstructors![source] = redirect;
+    while (redirect != null) {
+      if (redirect.cycleReported) return false;
+      if (redirect.target == source) {
+        redirect.cycleReported = true;
+        return true;
+      }
+      redirect = _redirectingConstructors![redirect.target];
+    }
+    return false;
+  }
+
   TypeBuilder _checkSupertype(TypeBuilder supertype) {
     if (typeVariables == null) return supertype;
     Message? message;
diff --git a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
index c9f1615..d79e266 100644
--- a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
@@ -19,7 +19,6 @@
         InstanceAccessKind,
         InstanceGet,
         IntLiteral,
-        InterfaceType,
         ListLiteral,
         Name,
         ProcedureKind,
@@ -450,12 +449,6 @@
   TypeBuilder? get mixedInTypeBuilder => null;
 
   @override
-  InterfaceType buildType(LibraryBuilder library,
-      NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments) {
-    return rawType(nullabilityBuilder.build(library));
-  }
-
-  @override
   Class build(SourceLibraryBuilder libraryBuilder, LibraryBuilder coreLibrary) {
     cls.isEnum = true;
     intType.resolveIn(coreLibrary.scope, charOffset, fileUri, libraryBuilder);
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index e105550..ca03543 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -1110,6 +1110,7 @@
 reloading
 remapped
 remedy
+remotely
 removal
 remover
 renames
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 3c9845d..dba09e0 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -325,6 +325,7 @@
 ec
 echo
 edits
+ei
 einst
 elapse
 elegantly
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart
new file mode 100644
index 0000000..971776f
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart
@@ -0,0 +1,58 @@
+// 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.
+
+enum E<X> {
+  one(1),
+  two("2");
+
+  final X field;
+
+  const E(this.field);
+}
+
+test() {
+  foo(E.one, E.two); // Ok.
+}
+
+foo(E<int> ei, E<String> es) {
+  bar(ei, es); // Ok.
+  bar(E.one, E.two); // Ok.
+  bar(es, ei); // Error.
+  bar(E.two, E.one); // Error.
+}
+
+bar(E<int> ei, E<String> es) {
+  baz(ei, es); // Ok.
+}
+
+baz(E<Object> ei, E<Object> es) {
+  boz(ei, es); // Error.
+  boz(E.one, E.two); // Error.
+}
+
+boz(E<Never> ei, E<Never> es) {}
+
+checkIsType<T>(x) {
+  if (x is! T) {
+    throw "Expected value of type ${x.runtimeType} to also be of type ${T}.";
+  }
+}
+
+checkIsNotType<T>(x) {
+  if (x is T) {
+    throw "Expected value of type ${x.runtimeType} to not be of type ${T}.";
+  }
+}
+
+main() {
+  checkIsType<E<dynamic>>(E.one);
+  checkIsType<E<dynamic>>(E.two);
+  checkIsType<E<int>>(E.one);
+  checkIsType<E<String>>(E.two);
+
+  checkIsNotType<E<Never>>(E.one);
+  checkIsNotType<E<Never>>(E.two);
+  checkIsNotType<E<String>>(E.one);
+  checkIsNotType<E<int>>(E.two);
+}
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.expect
new file mode 100644
index 0000000..7e8bae6
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//                ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = #C8;
+  static const field self::E<core::int> one = #C4;
+  static const field self::E<core::String> two = #C7;
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic {
+  self::foo(#C4, #C7);
+}
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::bar(ei, es);
+  self::bar(#C4, #C7);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+      ^" in es as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+          ^" in ei as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+        ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+               ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+}
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::baz(ei, es);
+}
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic {
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+      ^" in ei as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+          ^" in es as{TypeError,ForNonNullableByDefault} self::E<Never>);
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+        ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+               ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<Never>);
+}
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic {}
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(!(x is{ForNonNullableByDefault} self::checkIsType::T%)) {
+    throw "Expected value of type ${x.{core::Object::runtimeType}{core::Type}} to also be of type ${self::checkIsType::T%}.";
+  }
+}
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(x is{ForNonNullableByDefault} self::checkIsNotType::T%) {
+    throw "Expected value of type ${x{self::checkIsNotType::T%}.{core::Object::runtimeType}{core::Type}} to not be of type ${self::checkIsNotType::T%}.";
+  }
+}
+static method main() → dynamic {
+  self::checkIsType<self::E<dynamic>>(#C4);
+  self::checkIsType<self::E<dynamic>>(#C7);
+  self::checkIsType<self::E<core::int>>(#C4);
+  self::checkIsType<self::E<core::String>>(#C7);
+  self::checkIsNotType<self::E<Never>>(#C4);
+  self::checkIsNotType<self::E<Never>>(#C7);
+  self::checkIsNotType<self::E<core::String>>(#C4);
+  self::checkIsNotType<self::E<core::int>>(#C7);
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E<core::int> {field:#C1, index:#C2, _name:#C3}
+  #C5 = "2"
+  #C6 = "two"
+  #C7 = self::E<core::String> {field:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E<dynamic>>[#C4, #C7]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///instantiated_generic_enum_types.dart:
+- E. (from org-dartlang-testcase:///instantiated_generic_enum_types.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.transformed.expect
new file mode 100644
index 0000000..7e8bae6
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.strong.transformed.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//                ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = #C8;
+  static const field self::E<core::int> one = #C4;
+  static const field self::E<core::String> two = #C7;
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic {
+  self::foo(#C4, #C7);
+}
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::bar(ei, es);
+  self::bar(#C4, #C7);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+      ^" in es as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+          ^" in ei as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+        ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+               ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+}
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::baz(ei, es);
+}
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic {
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+      ^" in ei as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+          ^" in es as{TypeError,ForNonNullableByDefault} self::E<Never>);
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+        ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+               ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<Never>);
+}
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic {}
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(!(x is{ForNonNullableByDefault} self::checkIsType::T%)) {
+    throw "Expected value of type ${x.{core::Object::runtimeType}{core::Type}} to also be of type ${self::checkIsType::T%}.";
+  }
+}
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(x is{ForNonNullableByDefault} self::checkIsNotType::T%) {
+    throw "Expected value of type ${x{self::checkIsNotType::T%}.{core::Object::runtimeType}{core::Type}} to not be of type ${self::checkIsNotType::T%}.";
+  }
+}
+static method main() → dynamic {
+  self::checkIsType<self::E<dynamic>>(#C4);
+  self::checkIsType<self::E<dynamic>>(#C7);
+  self::checkIsType<self::E<core::int>>(#C4);
+  self::checkIsType<self::E<core::String>>(#C7);
+  self::checkIsNotType<self::E<Never>>(#C4);
+  self::checkIsNotType<self::E<Never>>(#C7);
+  self::checkIsNotType<self::E<core::String>>(#C4);
+  self::checkIsNotType<self::E<core::int>>(#C7);
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E<core::int> {field:#C1, index:#C2, _name:#C3}
+  #C5 = "2"
+  #C6 = "two"
+  #C7 = self::E<core::String> {field:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E<dynamic>>[#C4, #C7]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///instantiated_generic_enum_types.dart:
+- E. (from org-dartlang-testcase:///instantiated_generic_enum_types.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.textual_outline.expect
new file mode 100644
index 0000000..8ce4f0c
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+enum E<X> { one(1), two("2"); final X field; const E(this.field); }
+test() {}
+foo(E<int> ei, E<String> es) {}
+bar(E<int> ei, E<String> es) {}
+baz(E<Object> ei, E<Object> es) {}
+boz(E<Never> ei, E<Never> es) {}
+checkIsType<T>(x) {}
+checkIsNotType<T>(x) {}
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.expect
new file mode 100644
index 0000000..fb83333
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//                ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = #C8;
+  static const field self::E<core::int> one = #C4;
+  static const field self::E<core::String> two = #C7;
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic {
+  self::foo(#C4, #C7);
+}
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::bar(ei, es);
+  self::bar(#C4, #C7);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+      ^" in es as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+          ^" in ei as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+        ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+               ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+}
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::baz(ei, es);
+}
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic {
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+      ^" in ei as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+          ^" in es as{TypeError,ForNonNullableByDefault} self::E<Never>);
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+        ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+               ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<Never>);
+}
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic {}
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(!(x is{ForNonNullableByDefault} self::checkIsType::T%)) {
+    throw "Expected value of type ${x.{core::Object::runtimeType}{core::Type}} to also be of type ${self::checkIsType::T%}.";
+  }
+}
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(x is{ForNonNullableByDefault} self::checkIsNotType::T%) {
+    throw "Expected value of type ${x{self::checkIsNotType::T%}.{core::Object::runtimeType}{core::Type}} to not be of type ${self::checkIsNotType::T%}.";
+  }
+}
+static method main() → dynamic {
+  self::checkIsType<self::E<dynamic>>(#C4);
+  self::checkIsType<self::E<dynamic>>(#C7);
+  self::checkIsType<self::E<core::int>>(#C4);
+  self::checkIsType<self::E<core::String>>(#C7);
+  self::checkIsNotType<self::E<Never>>(#C4);
+  self::checkIsNotType<self::E<Never>>(#C7);
+  self::checkIsNotType<self::E<core::String>>(#C4);
+  self::checkIsNotType<self::E<core::int>>(#C7);
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E<core::int*> {field:#C1, index:#C2, _name:#C3}
+  #C5 = "2"
+  #C6 = "two"
+  #C7 = self::E<core::String*> {field:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E<dynamic>*>[#C4, #C7]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///instantiated_generic_enum_types.dart:
+- E. (from org-dartlang-testcase:///instantiated_generic_enum_types.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.modular.expect
new file mode 100644
index 0000000..fb83333
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.modular.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//                ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = #C8;
+  static const field self::E<core::int> one = #C4;
+  static const field self::E<core::String> two = #C7;
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic {
+  self::foo(#C4, #C7);
+}
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::bar(ei, es);
+  self::bar(#C4, #C7);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+      ^" in es as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+          ^" in ei as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+        ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+               ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+}
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::baz(ei, es);
+}
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic {
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+      ^" in ei as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+          ^" in es as{TypeError,ForNonNullableByDefault} self::E<Never>);
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+        ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+               ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<Never>);
+}
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic {}
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(!(x is{ForNonNullableByDefault} self::checkIsType::T%)) {
+    throw "Expected value of type ${x.{core::Object::runtimeType}{core::Type}} to also be of type ${self::checkIsType::T%}.";
+  }
+}
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(x is{ForNonNullableByDefault} self::checkIsNotType::T%) {
+    throw "Expected value of type ${x{self::checkIsNotType::T%}.{core::Object::runtimeType}{core::Type}} to not be of type ${self::checkIsNotType::T%}.";
+  }
+}
+static method main() → dynamic {
+  self::checkIsType<self::E<dynamic>>(#C4);
+  self::checkIsType<self::E<dynamic>>(#C7);
+  self::checkIsType<self::E<core::int>>(#C4);
+  self::checkIsType<self::E<core::String>>(#C7);
+  self::checkIsNotType<self::E<Never>>(#C4);
+  self::checkIsNotType<self::E<Never>>(#C7);
+  self::checkIsNotType<self::E<core::String>>(#C4);
+  self::checkIsNotType<self::E<core::int>>(#C7);
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E<core::int*> {field:#C1, index:#C2, _name:#C3}
+  #C5 = "2"
+  #C6 = "two"
+  #C7 = self::E<core::String*> {field:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E<dynamic>*>[#C4, #C7]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///instantiated_generic_enum_types.dart:
+- E. (from org-dartlang-testcase:///instantiated_generic_enum_types.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.outline.expect
new file mode 100644
index 0000000..0f67ffa
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.outline.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = const <self::E<dynamic>>[self::E::one, self::E::two];
+  static const field self::E<core::int> one = const self::E::•<core::int>(0, "one", 1);
+  static const field self::E<core::String> two = const self::E::•<core::String>(1, "two", "2");
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic
+  ;
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic
+  ;
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic
+  ;
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic
+  ;
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic
+  ;
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic
+  ;
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///instantiated_generic_enum_types.dart:5:6 -> ListConstant(const <E<dynamic>*>[const E<int*>{E.field: 1, _Enum.index: 0, _Enum._name: "one"}, const E<String*>{E.field: "2", _Enum.index: 1, _Enum._name: "two"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///instantiated_generic_enum_types.dart:6:3 -> InstanceConstant(const E<int*>{E.field: 1, _Enum.index: 0, _Enum._name: "one"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///instantiated_generic_enum_types.dart:7:3 -> InstanceConstant(const E<String*>{E.field: "2", _Enum.index: 1, _Enum._name: "two"})
+Extra constant evaluation: evaluated: 9, effectively constant: 3
diff --git a/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.transformed.expect
new file mode 100644
index 0000000..fb83333
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart.weak.transformed.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(es, ei); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   bar(E.two, E.one); // Error.
+//                ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//       ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//  - 'Object' is from 'dart:core'.
+//   boz(ei, es); // Error.
+//           ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//         ^
+//
+// pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+//  - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+//   boz(E.one, E.two); // Error.
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class E<X extends core::Object? = dynamic> extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E<dynamic>> values = #C8;
+  static const field self::E<core::int> one = #C4;
+  static const field self::E<core::String> two = #C7;
+  final field self::E::X% field;
+  const constructor •(core::int index, core::String name, self::E::X% field) → self::E<self::E::X%>
+    : self::E::field = field, super core::_Enum::•(index, name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method test() → dynamic {
+  self::foo(#C4, #C7);
+}
+static method foo(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::bar(ei, es);
+  self::bar(#C4, #C7);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:7: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+      ^" in es as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:21:11: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(es, ei); // Error.
+          ^" in ei as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+  self::bar(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:9: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<int>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+        ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<core::int>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:22:16: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<String>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  bar(E.two, E.one); // Error.
+               ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<core::String>);
+}
+static method bar(self::E<core::int> ei, self::E<core::String> es) → dynamic {
+  self::baz(ei, es);
+}
+static method baz(self::E<core::Object> ei, self::E<core::Object> es) → dynamic {
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:7: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+      ^" in ei as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:30:11: Error: The argument type 'E<Object>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+ - 'Object' is from 'dart:core'.
+  boz(ei, es); // Error.
+          ^" in es as{TypeError,ForNonNullableByDefault} self::E<Never>);
+  self::boz(invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:9: Error: The argument type 'E<int>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+        ^" in #C4 as{TypeError,ForNonNullableByDefault} self::E<Never>, invalid-expression "pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart:31:16: Error: The argument type 'E<String>' can't be assigned to the parameter type 'E<Never>'.
+ - 'E' is from 'pkg/front_end/testcases/enhanced_enums/instantiated_generic_enum_types.dart'.
+  boz(E.one, E.two); // Error.
+               ^" in #C7 as{TypeError,ForNonNullableByDefault} self::E<Never>);
+}
+static method boz(self::E<Never> ei, self::E<Never> es) → dynamic {}
+static method checkIsType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(!(x is{ForNonNullableByDefault} self::checkIsType::T%)) {
+    throw "Expected value of type ${x.{core::Object::runtimeType}{core::Type}} to also be of type ${self::checkIsType::T%}.";
+  }
+}
+static method checkIsNotType<T extends core::Object? = dynamic>(dynamic x) → dynamic {
+  if(x is{ForNonNullableByDefault} self::checkIsNotType::T%) {
+    throw "Expected value of type ${x{self::checkIsNotType::T%}.{core::Object::runtimeType}{core::Type}} to not be of type ${self::checkIsNotType::T%}.";
+  }
+}
+static method main() → dynamic {
+  self::checkIsType<self::E<dynamic>>(#C4);
+  self::checkIsType<self::E<dynamic>>(#C7);
+  self::checkIsType<self::E<core::int>>(#C4);
+  self::checkIsType<self::E<core::String>>(#C7);
+  self::checkIsNotType<self::E<Never>>(#C4);
+  self::checkIsNotType<self::E<Never>>(#C7);
+  self::checkIsNotType<self::E<core::String>>(#C4);
+  self::checkIsNotType<self::E<core::int>>(#C7);
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 0
+  #C3 = "one"
+  #C4 = self::E<core::int*> {field:#C1, index:#C2, _name:#C3}
+  #C5 = "2"
+  #C6 = "two"
+  #C7 = self::E<core::String*> {field:#C5, index:#C1, _name:#C6}
+  #C8 = <self::E<dynamic>*>[#C4, #C7]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///instantiated_generic_enum_types.dart:
+- E. (from org-dartlang-testcase:///instantiated_generic_enum_types.dart:11:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:76:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.strong.expect
index d81899d..c358d70 100644
--- a/pkg/front_end/testcases/enhanced_enums/members.dart.strong.expect
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.strong.expect
@@ -33,7 +33,7 @@
     ;
   method toString() → core::String
     return "E2.${this.{core::_Enum::_name}{core::String}}";
-  static factory f<X extends core::Object? = dynamic>() → self::E2<dynamic>
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
     return throw 42;
   method method(core::int value) → core::int
     return value.{core::num::+}(10){(core::num) → core::int};
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.strong.transformed.expect
index d81899d..c358d70 100644
--- a/pkg/front_end/testcases/enhanced_enums/members.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.strong.transformed.expect
@@ -33,7 +33,7 @@
     ;
   method toString() → core::String
     return "E2.${this.{core::_Enum::_name}{core::String}}";
-  static factory f<X extends core::Object? = dynamic>() → self::E2<dynamic>
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
     return throw 42;
   method method(core::int value) → core::int
     return value.{core::num::+}(10){(core::num) → core::int};
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.expect
index 7aa96cc..16019e2 100644
--- a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.expect
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.expect
@@ -33,7 +33,7 @@
     ;
   method toString() → core::String
     return "E2.${this.{core::_Enum::_name}{core::String}}";
-  static factory f<X extends core::Object? = dynamic>() → self::E2<dynamic>
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
     return throw 42;
   method method(core::int value) → core::int
     return value.{core::num::+}(10){(core::num) → core::int};
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.modular.expect
index 7aa96cc..16019e2 100644
--- a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.modular.expect
@@ -33,7 +33,7 @@
     ;
   method toString() → core::String
     return "E2.${this.{core::_Enum::_name}{core::String}}";
-  static factory f<X extends core::Object? = dynamic>() → self::E2<dynamic>
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
     return throw 42;
   method method(core::int value) → core::int
     return value.{core::num::+}(10){(core::num) → core::int};
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.outline.expect
index f6877f8..65b7311 100644
--- a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.outline.expect
@@ -33,7 +33,7 @@
     ;
   method toString() → core::String
     return "E2.${this.{core::_Enum::_name}{core::String}}";
-  static factory f<X extends core::Object? = dynamic>() → self::E2<dynamic>
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
     ;
   method method(core::int value) → core::int
     ;
diff --git a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.transformed.expect
index 7aa96cc..16019e2 100644
--- a/pkg/front_end/testcases/enhanced_enums/members.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/enhanced_enums/members.dart.weak.transformed.expect
@@ -33,7 +33,7 @@
     ;
   method toString() → core::String
     return "E2.${this.{core::_Enum::_name}{core::String}}";
-  static factory f<X extends core::Object? = dynamic>() → self::E2<dynamic>
+  static factory f<X extends core::Object? = dynamic>() → self::E2<self::E2::f::X%>
     return throw 42;
   method method(core::int value) → core::int
     return value.{core::num::+}(10){(core::num) → core::int};
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 35116bf..6afc196 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -30,6 +30,7 @@
 dart2js/late_statics: FormatterCrash
 enhanced_enums/entries_with_type_arguments: FormatterCrash
 enhanced_enums/inference_in_constructor_parameters: FormatterCrash
+enhanced_enums/instantiated_generic_enum_types: FormatterCrash
 enhanced_enums/issue48084: FormatterCrash
 enhanced_enums/members: FormatterCrash
 enhanced_enums/qualified_names_with_no_type_arguments: FormatterCrash
diff --git a/tools/VERSION b/tools/VERSION
index 019f1ab..cb01692 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 16
+PRERELEASE 17
 PRERELEASE_PATCH 0
\ No newline at end of file