Version 2.15.0-188.0.dev

Merge commit 'd5fada929d7bc496d281615532053445255b137d' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
index 1d103e5..245bef3 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
@@ -65,11 +65,11 @@
   Token,
   Type,
   TypeArguments,
+  TypeBuilder,
   TypeBuilderList,
   TypeList,
   TypeVariable,
   TypeVariables,
-  UnresolvedType,
   VarFinalOrConstToken,
   WithClause,
 }
@@ -377,7 +377,7 @@
   @override
   void handleNoType(Token lastConsumed) {
     debugEvent("NoType");
-    push(NullValue.UnresolvedType);
+    push(NullValue.TypeBuilder);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
index 740fde3..74797c3 100644
--- a/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
@@ -7,6 +7,7 @@
 import '../problems.dart';
 import '../source/source_library_builder.dart';
 import 'library_builder.dart';
+import 'named_type_builder.dart';
 import 'nullability_builder.dart';
 import 'type_builder.dart';
 
@@ -21,7 +22,7 @@
 
   @override
   TypeBuilder clone(
-      List<TypeBuilder> newTypes,
+      List<NamedTypeBuilder> newTypes,
       SourceLibraryBuilder contextLibrary,
       TypeParameterScopeBuilder contextDeclaration) {
     return this;
diff --git a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
index 42c1ce6..3e47192 100644
--- a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
@@ -42,6 +42,7 @@
 import 'library_builder.dart';
 import 'metadata_builder.dart';
 import 'modifier_builder.dart';
+import 'named_type_builder.dart';
 import 'type_builder.dart';
 import 'variable_builder.dart';
 
@@ -150,7 +151,7 @@
   }
 
   FormalParameterBuilder clone(
-      List<TypeBuilder> newTypes,
+      List<NamedTypeBuilder> newTypes,
       SourceLibraryBuilder contextLibrary,
       TypeParameterScopeBuilder contextDeclaration) {
     // TODO(dmitryas):  It's not clear how [metadata] is used currently, and
diff --git a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
index 58226d1..d995931 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
@@ -20,6 +20,7 @@
 
 import 'formal_parameter_builder.dart';
 import 'library_builder.dart';
+import 'named_type_builder.dart';
 import 'nullability_builder.dart';
 import 'type_builder.dart';
 import 'type_variable_builder.dart';
@@ -137,7 +138,7 @@
 
   @override
   FunctionTypeBuilder clone(
-      List<TypeBuilder> newTypes,
+      List<NamedTypeBuilder> newTypes,
       SourceLibraryBuilder contextLibrary,
       TypeParameterScopeBuilder contextDeclaration) {
     List<TypeVariableBuilder>? clonedTypeVariables;
@@ -153,15 +154,13 @@
         return formal.clone(newTypes, contextLibrary, contextDeclaration);
       }, growable: false);
     }
-    FunctionTypeBuilder newType = new FunctionTypeBuilder(
+    return new FunctionTypeBuilder(
         returnType?.clone(newTypes, contextLibrary, contextDeclaration),
         clonedTypeVariables,
         clonedFormals,
         nullabilityBuilder,
         fileUri,
         charOffset);
-    newTypes.add(newType);
-    return newType;
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart b/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart
index ade332c..f6d7e56 100644
--- a/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart
@@ -10,6 +10,7 @@
 import '../source/source_library_builder.dart';
 
 import 'library_builder.dart';
+import 'named_type_builder.dart';
 import 'nullability_builder.dart';
 import 'type_builder.dart';
 import 'type_variable_builder.dart';
@@ -82,7 +83,7 @@
 
   @override
   MixinApplicationBuilder clone(
-      List<TypeBuilder> newTypes,
+      List<NamedTypeBuilder> newTypes,
       SourceLibraryBuilder contextLibrary,
       TypeParameterScopeBuilder contextDeclaration) {
     int charOffset = -1; // TODO(dmitryas): Provide these.
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index e6547b9..0bfffd5 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -507,7 +507,7 @@
 
   @override
   NamedTypeBuilder clone(
-      List<TypeBuilder> newTypes,
+      List<NamedTypeBuilder> newTypes,
       SourceLibraryBuilder contextLibrary,
       TypeParameterScopeBuilder contextDeclaration) {
     List<TypeBuilder>? clonedArguments;
diff --git a/pkg/front_end/lib/src/fasta/builder/type_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
index 8fc9d35..73607dd 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
@@ -9,6 +9,7 @@
 import '../scope.dart';
 import '../source/source_library_builder.dart';
 import 'library_builder.dart';
+import 'named_type_builder.dart';
 import 'nullability_builder.dart';
 import 'type_declaration_builder.dart';
 import 'type_variable_builder.dart';
@@ -62,7 +63,7 @@
   /// are added to [newTypes], so that they can be added to a proper scope and
   /// resolved later.
   TypeBuilder clone(
-      List<TypeBuilder> newTypes,
+      List<NamedTypeBuilder> newTypes,
       SourceLibraryBuilder contextLibrary,
       TypeParameterScopeBuilder contextDeclaration);
 
diff --git a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
index 1dd6221..2430ab7a 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
@@ -23,6 +23,7 @@
 import 'library_builder.dart';
 import 'member_builder.dart';
 import 'metadata_builder.dart';
+import 'named_type_builder.dart';
 import 'nullability_builder.dart';
 import 'type_builder.dart';
 import 'type_declaration_builder.dart';
@@ -185,7 +186,7 @@
   }
 
   TypeVariableBuilder clone(
-      List<TypeBuilder> newTypes,
+      List<NamedTypeBuilder> newTypes,
       SourceLibraryBuilder contextLibrary,
       TypeParameterScopeBuilder contextDeclaration) {
     // TODO(dmitryas): Figure out if using [charOffset] here is a good idea.
diff --git a/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart b/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
deleted file mode 100644
index 39c5f37..0000000
--- a/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.unresolved_type;
-
-import '../scope.dart';
-
-import 'library_builder.dart';
-import 'type_builder.dart';
-
-/// A wrapper around a type that is yet to be resolved.
-class UnresolvedType {
-  final TypeBuilder builder;
-  final int charOffset;
-  final Uri fileUri;
-
-  UnresolvedType(this.builder, this.charOffset, this.fileUri);
-
-  void resolveIn(Scope scope, LibraryBuilder library) {
-    builder.resolveIn(scope, charOffset, fileUri, library);
-  }
-
-  /// Performs checks on the type after it's resolved.
-  void checkType(LibraryBuilder library) {
-    return builder.check(library, charOffset, fileUri);
-  }
-
-  @override
-  String toString() => "UnresolvedType(@$charOffset, $builder)";
-}
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 ec84e16..82d3011 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -71,7 +71,6 @@
 import '../builder/type_builder.dart';
 import '../builder/type_declaration_builder.dart';
 import '../builder/type_variable_builder.dart';
-import '../builder/unresolved_type.dart';
 import '../builder/variable_builder.dart';
 import '../builder/void_type_declaration_builder.dart';
 
@@ -868,7 +867,7 @@
       // not calling [buildDartType] leads to a missing compile-time
       // error. Also, notice that the type of the problematic field isn't
       // `invalid-type`.
-      UnresolvedType? type = pop() as UnresolvedType?;
+      TypeBuilder? type = pop() as TypeBuilder?;
       if (type != null) {
         buildDartType(type, allowPotentiallyConstantType: false);
       }
@@ -1851,7 +1850,7 @@
     ]));
     debugEvent("Send");
     Object? arguments = pop();
-    List<UnresolvedType>? typeArguments = pop() as List<UnresolvedType>?;
+    List<TypeBuilder>? typeArguments = pop() as List<TypeBuilder>?;
     Object receiver = pop()!;
     // Delay adding [typeArguments] to [forest] for type aliases: They
     // must be unaliased to the type arguments of the denoted type.
@@ -1901,11 +1900,8 @@
   }
 
   @override
-  Expression_Generator_Initializer finishSend(
-      Object receiver,
-      List<UnresolvedType>? typeArguments,
-      ArgumentsImpl arguments,
-      int charOffset,
+  Expression_Generator_Initializer finishSend(Object receiver,
+      List<TypeBuilder>? typeArguments, ArgumentsImpl arguments, int charOffset,
       {bool isTypeArgumentsInForest = false}) {
     if (receiver is Generator) {
       return receiver.doInvocation(charOffset, typeArguments, arguments,
@@ -3030,8 +3026,7 @@
     if (!libraryBuilder.isNonNullableByDefault) {
       reportNonNullableModifierError(lateToken);
     }
-    UnresolvedType? unresolvedType =
-        pop(NullValue.UnresolvedType) as UnresolvedType?;
+    TypeBuilder? unresolvedType = pop(NullValue.TypeBuilder) as TypeBuilder?;
     DartType? type = unresolvedType != null
         ? buildDartType(unresolvedType, allowPotentiallyConstantType: false)
         : null;
@@ -3464,7 +3459,7 @@
       }
     }
 
-    List<UnresolvedType>? typeArguments = pop() as List<UnresolvedType>?;
+    List<TypeBuilder>? typeArguments = pop() as List<TypeBuilder>?;
 
     DartType typeArgument;
     if (typeArguments != null) {
@@ -3496,7 +3491,7 @@
     push(node);
   }
 
-  void buildLiteralSet(List<UnresolvedType>? typeArguments, Token? constKeyword,
+  void buildLiteralSet(List<TypeBuilder>? typeArguments, Token? constKeyword,
       Token leftBrace, List<dynamic>? setOrMapEntries) {
     DartType typeArgument;
     if (typeArguments != null) {
@@ -3565,7 +3560,7 @@
         setOrMapEntries[i] = toValue(elem);
       }
     }
-    List<UnresolvedType>? typeArguments = pop() as List<UnresolvedType>?;
+    List<TypeBuilder>? typeArguments = pop() as List<TypeBuilder>?;
 
     // Replicate existing behavior that has been removed from the parser.
     // This will be removed once unified collections is implemented.
@@ -3632,7 +3627,7 @@
     push(forest.createNullLiteral(offsetForToken(token)));
   }
 
-  void buildLiteralMap(List<UnresolvedType>? typeArguments, Token? constKeyword,
+  void buildLiteralMap(List<TypeBuilder>? typeArguments, Token? constKeyword,
       Token leftBrace, List<MapLiteralEntry> entries) {
     DartType keyType;
     DartType valueType;
@@ -3740,7 +3735,7 @@
       reportErrorIfNullableType(questionMark);
     }
     bool isMarkedAsNullable = questionMark != null;
-    List<UnresolvedType>? arguments = pop() as List<UnresolvedType>?;
+    List<TypeBuilder>? arguments = pop() as List<TypeBuilder>?;
     Object? name = pop();
     if (name is QualifiedName) {
       QualifiedName qualified = name;
@@ -3755,19 +3750,16 @@
         Message message = fasta.templateNotAType.withArguments(displayName);
         libraryBuilder.addProblem(
             message, offset, lengthOfSpan(beginToken, suffix), uri);
-        push(new UnresolvedType(
-            new NamedTypeBuilder.fromTypeDeclarationBuilder(
-                new InvalidTypeDeclarationBuilder(
-                    name,
-                    message.withLocation(
-                        uri, offset, lengthOfSpan(beginToken, suffix))),
-                libraryBuilder.nullableBuilderIfTrue(isMarkedAsNullable),
-                fileUri: uri,
-                charOffset: offset,
-                instanceTypeVariableAccess:
-                    InstanceTypeVariableAccessState.Unexpected),
-            offset,
-            uri));
+        push(new NamedTypeBuilder.fromTypeDeclarationBuilder(
+            new InvalidTypeDeclarationBuilder(
+                name,
+                message.withLocation(
+                    uri, offset, lengthOfSpan(beginToken, suffix))),
+            libraryBuilder.nullableBuilderIfTrue(isMarkedAsNullable),
+            fileUri: uri,
+            charOffset: offset,
+            instanceTypeVariableAccess:
+                InstanceTypeVariableAccessState.Unexpected));
         return;
       }
     }
@@ -3808,7 +3800,7 @@
       unhandled(
           "${name.runtimeType}", "handleType", beginToken.charOffset, uri);
     }
-    push(new UnresolvedType(result, beginToken.charOffset, uri));
+    push(result);
   }
 
   @override
@@ -3842,7 +3834,7 @@
       reportErrorIfNullableType(questionMark);
     }
     FormalParameters formals = pop() as FormalParameters;
-    UnresolvedType? returnType = pop() as UnresolvedType?;
+    TypeBuilder? returnType = pop() as TypeBuilder?;
     List<TypeVariableBuilder>? typeVariables =
         pop() as List<TypeVariableBuilder>?;
     if (typeVariables != null) {
@@ -3858,7 +3850,7 @@
         }
       }
     }
-    UnresolvedType type = formals.toFunctionType(
+    TypeBuilder type = formals.toFunctionType(
         returnType,
         libraryBuilder.nullableBuilderIfTrue(questionMark != null),
         typeVariables);
@@ -3871,17 +3863,14 @@
     debugEvent("VoidKeyword");
     int offset = offsetForToken(token);
     // "void" is always nullable.
-    push(new UnresolvedType(
-        new NamedTypeBuilder.fromTypeDeclarationBuilder(
-            new VoidTypeDeclarationBuilder(
-                const VoidType(), libraryBuilder, offset),
-            const NullabilityBuilder.nullable(),
-            fileUri: uri,
-            charOffset: offset,
-            instanceTypeVariableAccess:
-                InstanceTypeVariableAccessState.Unexpected),
-        offset,
-        uri));
+    push(new NamedTypeBuilder.fromTypeDeclarationBuilder(
+        new VoidTypeDeclarationBuilder(
+            const VoidType(), libraryBuilder, offset),
+        const NullabilityBuilder.nullable(),
+        fileUri: uri,
+        charOffset: offset,
+        instanceTypeVariableAccess:
+            InstanceTypeVariableAccessState.Unexpected));
   }
 
   @override
@@ -3908,7 +3897,7 @@
   @override
   void handleAsOperator(Token operator) {
     debugEvent("AsOperator");
-    DartType type = buildDartType(pop() as UnresolvedType,
+    DartType type = buildDartType(pop() as TypeBuilder,
         allowPotentiallyConstantType: libraryBuilder.isNonNullableByDefault);
     libraryBuilder.checkBoundsInType(
         type, typeEnvironment, uri, operator.charOffset);
@@ -3932,7 +3921,7 @@
   @override
   void handleIsOperator(Token isOperator, Token? not) {
     debugEvent("IsOperator");
-    DartType type = buildDartType(pop() as UnresolvedType,
+    DartType type = buildDartType(pop() as TypeBuilder,
         allowPotentiallyConstantType: libraryBuilder.isNonNullableByDefault);
     Expression operand = popForValue();
     Expression isExpression = forest.createIsExpression(
@@ -4025,7 +4014,7 @@
       }
     }
     Object? nameNode = pop();
-    UnresolvedType? type = pop() as UnresolvedType?;
+    TypeBuilder? type = pop() as TypeBuilder?;
     if (functionNestingLevel == 0 && type != null) {
       // TODO(ahe): The type we compute here may be different from what is
       // computed in the outline phase. We should make sure that the outline
@@ -4059,7 +4048,7 @@
         return;
       }
     } else {
-      parameter = new FormalParameterBuilder(null, modifiers, type?.builder,
+      parameter = new FormalParameterBuilder(null, modifiers, type,
           name?.name ?? '', libraryBuilder, offsetForToken(nameToken),
           fileUri: uri)
         ..hasDeclaredInitializer = (initializerStart != null);
@@ -4134,13 +4123,13 @@
       exitLocalScope();
     }
     FormalParameters formals = pop() as FormalParameters;
-    UnresolvedType? returnType = pop() as UnresolvedType?;
+    TypeBuilder? returnType = pop() as TypeBuilder?;
     List<TypeVariableBuilder>? typeVariables =
         pop() as List<TypeVariableBuilder>?;
     if (!libraryBuilder.isNonNullableByDefault) {
       reportErrorIfNullableType(question);
     }
-    UnresolvedType type = formals.toFunctionType(returnType,
+    TypeBuilder type = formals.toFunctionType(returnType,
         libraryBuilder.nullableBuilderIfTrue(question != null), typeVariables);
     exitLocalScope();
     push(type);
@@ -4237,8 +4226,8 @@
     }
     FormalParameters? catchParameters =
         popIfNotNull(catchKeyword) as FormalParameters?;
-    UnresolvedType? unresolvedExceptionType =
-        popIfNotNull(onKeyword) as UnresolvedType?;
+    TypeBuilder? unresolvedExceptionType =
+        popIfNotNull(onKeyword) as TypeBuilder?;
     DartType exceptionType;
     if (unresolvedExceptionType != null) {
       exceptionType = buildDartType(unresolvedExceptionType,
@@ -4498,7 +4487,7 @@
     }
 
     Identifier? identifier;
-    List<UnresolvedType>? typeArguments = pop() as List<UnresolvedType>?;
+    List<TypeBuilder>? typeArguments = pop() as List<TypeBuilder>?;
     Object? type = pop();
     if (type is QualifiedName) {
       identifier = type;
@@ -4888,7 +4877,7 @@
     Identifier? nameLastIdentifier = pop(NullValue.Identifier) as Identifier?;
     Token nameLastToken = nameLastIdentifier?.token ?? nameToken;
     String name = pop() as String;
-    List<UnresolvedType>? typeArguments = pop() as List<UnresolvedType>?;
+    List<TypeBuilder>? typeArguments = pop() as List<TypeBuilder>?;
     if (inMetadata && typeArguments != null) {
       if (!libraryBuilder.enableGenericMetadataInLibrary) {
         handleRecoverableError(fasta.messageMetadataTypeArguments,
@@ -4935,7 +4924,7 @@
   @override
   Expression createInstantiationAndInvocation(
       Expression Function() receiverFunction,
-      List<UnresolvedType>? typeArguments,
+      List<TypeBuilder>? typeArguments,
       String className,
       String constructorName,
       Arguments arguments,
@@ -4985,7 +4974,7 @@
       Token nameLastToken,
       Arguments? arguments,
       String name,
-      List<UnresolvedType>? typeArguments,
+      List<TypeBuilder>? typeArguments,
       int charOffset,
       Constness constness,
       {bool isTypeArgumentsInForest = false,
@@ -5026,8 +5015,8 @@
           usedAsClassFileUri: uri);
       List<TypeBuilder> typeArgumentBuilders = [];
       if (typeArguments != null) {
-        for (UnresolvedType unresolvedType in typeArguments) {
-          typeArgumentBuilders.add(unresolvedType.builder);
+        for (TypeBuilder typeBuilder in typeArguments) {
+          typeArgumentBuilders.add(typeBuilder);
         }
       } else {
         if (aliasBuilder.typeVariablesCount > 0) {
@@ -5397,8 +5386,8 @@
   @override
   void endTypeArguments(int count, Token beginToken, Token endToken) {
     debugEvent("TypeArguments");
-    push(const FixedNullableList<UnresolvedType>()
-            .popNonNullable(stack, count, dummyUnresolvedType) ??
+    push(const FixedNullableList<TypeBuilder>()
+            .popNonNullable(stack, count, dummyTypeBuilder) ??
         NullValue.TypeArguments);
   }
 
@@ -5562,7 +5551,7 @@
     exitLocalScope();
     FormalParameters formals = pop() as FormalParameters;
     Object? declaration = pop();
-    UnresolvedType? returnType = pop() as UnresolvedType?;
+    TypeBuilder? returnType = pop() as TypeBuilder?;
     bool hasImplicitReturnType = returnType == null;
     exitFunction();
     List<TypeVariableBuilder>? typeParameters =
@@ -6475,13 +6464,13 @@
   void endTypeVariable(
       Token token, int index, Token? extendsOrSuper, Token? variance) {
     debugEvent("TypeVariable");
-    UnresolvedType? bound = pop() as UnresolvedType?;
+    TypeBuilder? bound = pop() as TypeBuilder?;
     // Peek to leave type parameters on top of stack.
     List<TypeVariableBuilder> typeVariables =
         peek() as List<TypeVariableBuilder>;
 
     TypeVariableBuilder variable = typeVariables[index];
-    variable.bound = bound?.builder;
+    variable.bound = bound;
     if (variance != null) {
       if (!libraryBuilder.enableVarianceInLibrary) {
         reportVarianceModifierNotEnabled(variance);
@@ -6845,8 +6834,8 @@
       ValueKinds.TypeArguments,
       unionOfKinds([ValueKinds.Generator, ValueKinds.Expression])
     ]));
-    List<UnresolvedType>? typeArguments =
-        pop() as List<UnresolvedType>?; // typeArguments
+    List<TypeBuilder>? typeArguments =
+        pop() as List<TypeBuilder>?; // typeArguments
     if (libraryBuilder.enableConstructorTearOffsInLibrary) {
       Object? operand = pop();
       if (operand is Generator) {
@@ -6877,18 +6866,16 @@
   }
 
   @override
-  UnresolvedType validateTypeVariableUse(UnresolvedType unresolved,
+  TypeBuilder validateTypeVariableUse(TypeBuilder typeBuilder,
       {required bool allowPotentiallyConstantType}) {
     // ignore: unnecessary_null_comparison
     assert(allowPotentiallyConstantType != null);
-    _validateTypeVariableUseInternal(
-        unresolved.builder, unresolved.fileUri, unresolved.charOffset,
+    _validateTypeVariableUseInternal(typeBuilder,
         allowPotentiallyConstantType: allowPotentiallyConstantType);
-    return unresolved;
+    return typeBuilder;
   }
 
-  void _validateTypeVariableUseInternal(
-      TypeBuilder? builder, Uri fileUri, int charOffset,
+  void _validateTypeVariableUseInternal(TypeBuilder? builder,
       {required bool allowPotentiallyConstantType}) {
     // ignore: unnecessary_null_comparison
     assert(allowPotentiallyConstantType != null);
@@ -6906,7 +6893,9 @@
                       !allowPotentiallyConstantType)) {
                 LocatedMessage message =
                     fasta.messageTypeVariableInConstantContext.withLocation(
-                        fileUri, charOffset, typeParameter.name!.length);
+                        builder.fileUri!,
+                        builder.charOffset!,
+                        typeParameter.name!.length);
                 builder.bind(new InvalidTypeDeclarationBuilder(
                     typeParameter.name!, message));
                 addProblem(
@@ -6921,9 +6910,7 @@
               // which seems like an odd prioritization.
               // TODO: Handle this case.
               LocatedMessage message = fasta.messageTypeVariableInStaticContext
-                  .withLocation(
-                      builder.fileUri ?? fileUri,
-                      builder.charOffset ?? charOffset,
+                  .withLocation(builder.fileUri!, builder.charOffset!,
                       typeParameter.name!.length);
               builder.bind(new InvalidTypeDeclarationBuilder(
                   typeParameter.name!, message));
@@ -6941,21 +6928,17 @@
       }
       if (builder.arguments != null) {
         for (TypeBuilder typeBuilder in builder.arguments!) {
-          _validateTypeVariableUseInternal(
-              typeBuilder,
-              typeBuilder.fileUri ?? fileUri,
-              typeBuilder.charOffset ?? charOffset,
+          _validateTypeVariableUseInternal(typeBuilder,
               allowPotentiallyConstantType: allowPotentiallyConstantType);
         }
       }
     } else if (builder is FunctionTypeBuilder) {
-      _validateTypeVariableUseInternal(builder.returnType, fileUri, charOffset,
+      _validateTypeVariableUseInternal(builder.returnType,
           allowPotentiallyConstantType: allowPotentiallyConstantType);
       if (builder.formals != null) {
         for (FormalParameterBuilder formalParameterBuilder
             in builder.formals!) {
-          _validateTypeVariableUseInternal(
-              formalParameterBuilder.type, fileUri, charOffset,
+          _validateTypeVariableUseInternal(formalParameterBuilder.type,
               allowPotentiallyConstantType: allowPotentiallyConstantType);
         }
       }
@@ -7117,25 +7100,23 @@
   }
 
   @override
-  DartType buildDartType(UnresolvedType unresolvedType,
+  DartType buildDartType(TypeBuilder typeBuilder,
       {required bool allowPotentiallyConstantType}) {
-    return validateTypeVariableUse(unresolvedType,
+    return validateTypeVariableUse(typeBuilder,
             allowPotentiallyConstantType: allowPotentiallyConstantType)
-        .builder
         .build(libraryBuilder);
   }
 
   @override
-  DartType buildTypeLiteralDartType(UnresolvedType unresolvedType,
+  DartType buildTypeLiteralDartType(TypeBuilder typeBuilder,
       {required bool allowPotentiallyConstantType}) {
-    return validateTypeVariableUse(unresolvedType,
+    return validateTypeVariableUse(typeBuilder,
             allowPotentiallyConstantType: allowPotentiallyConstantType)
-        .builder
         .buildTypeLiteralType(libraryBuilder);
   }
 
   @override
-  List<DartType> buildDartTypeArguments(List<UnresolvedType>? unresolvedTypes,
+  List<DartType> buildDartTypeArguments(List<TypeBuilder>? unresolvedTypes,
       {required bool allowPotentiallyConstantType}) {
     if (unresolvedTypes == null) return <DartType>[];
     return new List<DartType>.generate(
@@ -7363,14 +7344,13 @@
 
   FunctionNode buildFunctionNode(
       SourceLibraryBuilder library,
-      UnresolvedType? returnType,
+      TypeBuilder? returnType,
       List<TypeVariableBuilder>? typeParameters,
       AsyncMarker asyncModifier,
       Statement body,
       int fileEndOffset) {
     FunctionType type = toFunctionType(
             returnType, const NullabilityBuilder.omitted(), typeParameters)
-        .builder
         .build(library) as FunctionType;
     List<VariableDeclaration> positionalParameters = <VariableDeclaration>[];
     List<VariableDeclaration> namedParameters = <VariableDeclaration>[];
@@ -7397,14 +7377,11 @@
       ..fileEndOffset = fileEndOffset;
   }
 
-  UnresolvedType toFunctionType(
-      UnresolvedType? returnType, NullabilityBuilder nullabilityBuilder,
+  TypeBuilder toFunctionType(
+      TypeBuilder? returnType, NullabilityBuilder nullabilityBuilder,
       [List<TypeVariableBuilder>? typeParameters]) {
-    return new UnresolvedType(
-        new FunctionTypeBuilder(returnType?.builder, typeParameters, parameters,
-            nullabilityBuilder, uri, charOffset),
-        charOffset,
-        uri);
+    return new FunctionTypeBuilder(returnType, typeParameters, parameters,
+        nullabilityBuilder, uri, charOffset);
   }
 
   Scope computeFormalParameterScope(
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 d3f4eec..a9c9d65 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -27,7 +27,6 @@
 import '../builder/type_builder.dart';
 import '../builder/type_declaration_builder.dart';
 import '../builder/type_variable_builder.dart';
-import '../builder/unresolved_type.dart';
 
 import '../constant_context.dart' show ConstantContext;
 
@@ -217,7 +216,7 @@
   /// If the invocation has explicit type arguments
   /// [buildTypeWithResolvedArguments] called instead.
   Expression_Generator_Initializer doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, ArgumentsImpl arguments,
+      int offset, List<TypeBuilder>? typeArguments, ArgumentsImpl arguments,
       {bool isTypeArgumentsInForest = false});
 
   Expression_Generator buildSelectorAccess(
@@ -258,7 +257,7 @@
   }
 
   Expression_Generator applyTypeArguments(
-      int fileOffset, List<UnresolvedType>? typeArguments) {
+      int fileOffset, List<TypeBuilder>? typeArguments) {
     return new Instantiation(
         buildSimpleRead(),
         _helper.buildDartTypeArguments(typeArguments,
@@ -272,7 +271,7 @@
   /// The type arguments have not been resolved and should be resolved to
   /// create a [TypeBuilder] for a valid type.
   TypeBuilder buildTypeWithResolvedArguments(
-      NullabilityBuilder nullabilityBuilder, List<UnresolvedType>? arguments,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments,
       {required bool allowPotentiallyConstantType}) {
     // TODO(johnniwinther): Could we use a FixedTypeBuilder(InvalidType()) here?
     NamedTypeBuilder result = new NamedTypeBuilder(
@@ -295,7 +294,7 @@
   }
 
   Expression invokeConstructor(
-      List<UnresolvedType>? typeArguments,
+      List<TypeBuilder>? typeArguments,
       String name,
       Arguments arguments,
       Token nameToken,
@@ -413,7 +412,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return _helper.forest.createExpressionInvocation(
         adjustForImplicitCall(_plainNameForRead, offset),
@@ -475,7 +474,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return _helper.buildMethodInvocation(receiver, name, arguments, offset);
   }
@@ -705,7 +704,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return _helper.buildMethodInvocation(
         _forest.createThisExpression(fileOffset), name, arguments, offset);
@@ -813,7 +812,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return unsupported("doInvocation", offset, _uri);
   }
@@ -920,7 +919,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     if (_helper.constantContext != ConstantContext.none) {
       // TODO(brianwilkerson) Fix the length
@@ -1083,7 +1082,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return _helper.forest.createExpressionInvocation(
         arguments.fileOffset, buildSimpleRead(), arguments);
@@ -1206,7 +1205,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return _helper.forest
         .createExpressionInvocation(offset, buildSimpleRead(), arguments);
@@ -1311,7 +1310,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return _helper.forest
         .createExpressionInvocation(offset, buildSimpleRead(), arguments);
@@ -1502,7 +1501,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     if (_helper.constantContext != ConstantContext.none &&
         !_helper.isIdentical(readTarget) &&
@@ -1775,7 +1774,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, ArgumentsImpl arguments,
+      int offset, List<TypeBuilder>? typeArguments, ArgumentsImpl arguments,
       {bool isTypeArgumentsInForest = false}) {
     if (invokeTarget != null) {
       return _helper.buildExtensionMethodInvocation(
@@ -2185,7 +2184,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     VariableDeclarationImpl? receiverVariable;
     Expression receiverExpression = receiver;
@@ -2506,7 +2505,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return _helper.forest
         .createExpressionInvocation(offset, buildSimpleRead(), arguments);
@@ -2678,7 +2677,7 @@
 
   @override
   Expression_Generator_Initializer doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, ArgumentsImpl arguments,
+      int offset, List<TypeBuilder>? typeArguments, ArgumentsImpl arguments,
       {bool isTypeArgumentsInForest = false}) {
     Generator generator = _createInstanceAccess(token, callName);
     return generator.doInvocation(offset, typeArguments, arguments,
@@ -2792,7 +2791,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     if (_forest.argumentsPositional(arguments).length > 0 ||
         _forest.argumentsNamed(arguments).length > 0) {
@@ -2902,7 +2901,7 @@
 
   @override
   TypeBuilder buildTypeWithResolvedArguments(
-      NullabilityBuilder nullabilityBuilder, List<UnresolvedType>? arguments,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments,
       {required bool allowPotentiallyConstantType}) {
     String name = "${prefixGenerator._plainNameForRead}."
         "${suffixGenerator._plainNameForRead}";
@@ -2919,7 +2918,7 @@
       int charOffset = offsetForToken(prefixGenerator.token);
       message = templateDeferredTypeAnnotation
           .withArguments(
-              _helper.buildDartType(new UnresolvedType(type, charOffset, _uri),
+              _helper.buildDartType(type,
                   allowPotentiallyConstantType: allowPotentiallyConstantType),
               prefixGenerator._plainNameForRead,
               _helper.libraryBuilder.isNonNullableByDefault)
@@ -2938,7 +2937,7 @@
 
   @override
   Expression_Generator_Initializer doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, ArgumentsImpl arguments,
+      int offset, List<TypeBuilder>? typeArguments, ArgumentsImpl arguments,
       {bool isTypeArgumentsInForest = false}) {
     Object suffix = suffixGenerator.doInvocation(
         offset, typeArguments, arguments,
@@ -2954,7 +2953,7 @@
 
   @override
   Expression invokeConstructor(
-      List<UnresolvedType>? typeArguments,
+      List<TypeBuilder>? typeArguments,
       String name,
       Arguments arguments,
       Token nameToken,
@@ -3008,7 +3007,7 @@
 ///
 class TypeUseGenerator extends AbstractReadOnlyAccessGenerator {
   final TypeDeclarationBuilder declaration;
-  List<UnresolvedType>? typeArguments;
+  List<TypeBuilder>? typeArguments;
 
   @override
   final String targetName;
@@ -3031,7 +3030,7 @@
 
   @override
   TypeBuilder buildTypeWithResolvedArguments(
-      NullabilityBuilder nullabilityBuilder, List<UnresolvedType>? arguments,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments,
       {required bool allowPotentiallyConstantType}) {
     if (declaration.isExtension && !_helper.enableExtensionTypesInLibrary) {
       // Extension declarations cannot be used as types.
@@ -3058,10 +3057,8 @@
     if (arguments != null) {
       argumentBuilders =
           new List<TypeBuilder>.generate(arguments.length, (int i) {
-        return _helper
-            .validateTypeVariableUse(arguments![i],
-                allowPotentiallyConstantType: allowPotentiallyConstantType)
-            .builder;
+        return _helper.validateTypeVariableUse(arguments![i],
+            allowPotentiallyConstantType: allowPotentiallyConstantType);
       }, growable: false);
     }
     return new NamedTypeBuilder(
@@ -3072,7 +3069,7 @@
 
   @override
   Expression invokeConstructor(
-      List<UnresolvedType>? typeArguments,
+      List<TypeBuilder>? typeArguments,
       String name,
       Arguments arguments,
       Token nameToken,
@@ -3111,13 +3108,9 @@
         _expression = _forest.createTypeLiteral(
             offsetForToken(token),
             _helper.buildTypeLiteralDartType(
-                new UnresolvedType(
-                    buildTypeWithResolvedArguments(
-                        _helper.libraryBuilder.nonNullableBuilder,
-                        typeArguments,
-                        allowPotentiallyConstantType: true),
-                    fileOffset,
-                    _uri),
+                buildTypeWithResolvedArguments(
+                    _helper.libraryBuilder.nonNullableBuilder, typeArguments,
+                    allowPotentiallyConstantType: true),
                 allowPotentiallyConstantType:
                     _helper.enableConstructorTearOffsInLibrary));
       }
@@ -3147,10 +3140,8 @@
           _helper.enableConstructorTearOffsInLibrary &&
           declarationBuilder is ClassBuilder;
       List<TypeBuilder>? aliasedTypeArguments = typeArguments
-          ?.map((unknownType) => _helper
-              .validateTypeVariableUse(unknownType,
-                  allowPotentiallyConstantType: isConstructorTearOff)
-              .builder)
+          ?.map((unknownType) => _helper.validateTypeVariableUse(unknownType,
+              allowPotentiallyConstantType: isConstructorTearOff))
           .toList();
       if (aliasedTypeArguments != null &&
           aliasedTypeArguments.length != aliasBuilder.typeVariablesCount) {
@@ -3367,7 +3358,7 @@
 
   @override
   Expression_Generator_Builder doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     if (declaration.isExtension) {
       ExtensionBuilder extensionBuilder = declaration as ExtensionBuilder;
@@ -3404,7 +3395,7 @@
 
   @override
   Expression_Generator applyTypeArguments(
-      int fileOffset, List<UnresolvedType>? typeArguments) {
+      int fileOffset, List<TypeBuilder>? typeArguments) {
     return new TypeUseGenerator(_helper, token, declaration, targetName)
       ..typeArguments = typeArguments;
   }
@@ -3551,7 +3542,7 @@
 
   @override
   Expression_Generator_Initializer doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return _helper.forest.createExpressionInvocation(
         adjustForImplicitCall(targetName, offset), _createRead(), arguments);
@@ -3606,7 +3597,7 @@
 
   @override
   Expression_Generator_Initializer doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return buildError(arguments,
         charOffset: offset, kind: UnresolvedKind.Method);
@@ -3682,7 +3673,7 @@
 
   @override
   Expression invokeConstructor(
-      List<UnresolvedType>? typeArguments,
+      List<TypeBuilder>? typeArguments,
       String name,
       Arguments arguments,
       Token nameToken,
@@ -3734,7 +3725,7 @@
 
   @override
   Expression doInvocation(
-      int charOffset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int charOffset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return buildError(arguments,
         charOffset: charOffset, kind: UnresolvedKind.Method);
@@ -3811,7 +3802,7 @@
 
   @override
   Never doInvocation(
-      int charOffset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int charOffset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return unhandled("${runtimeType}", "doInvocation", charOffset, _uri);
   }
@@ -4057,7 +4048,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return _helper.wrapInLocatedProblem(
         _helper.evaluateArgumentsBefore(
@@ -4160,7 +4151,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return _helper.buildUnresolvedError(_forest.createNullLiteral(offset),
         _plainNameForRead, arguments, fileOffset,
@@ -4169,7 +4160,7 @@
 
   @override
   TypeBuilder buildTypeWithResolvedArguments(
-      NullabilityBuilder nullabilityBuilder, List<UnresolvedType>? arguments,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments,
       {required bool allowPotentiallyConstantType}) {
     Template<Message Function(String, String)> template = isUnresolved
         ? templateUnresolvedPrefixInTypeAnnotation
@@ -4282,7 +4273,7 @@
 
   @override
   Expression doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     return buildProblem();
   }
@@ -4295,7 +4286,7 @@
 
   @override
   TypeBuilder buildTypeWithResolvedArguments(
-      NullabilityBuilder nullabilityBuilder, List<UnresolvedType>? arguments,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder>? arguments,
       {required bool allowPotentiallyConstantType}) {
     // TODO(johnniwinther): Could we use a FixedTypeBuilder(InvalidType()) here?
     NamedTypeBuilder result = new NamedTypeBuilder(
@@ -4318,7 +4309,7 @@
 
   @override
   Expression invokeConstructor(
-      List<UnresolvedType>? typeArguments,
+      List<TypeBuilder>? typeArguments,
       String name,
       Arguments arguments,
       Token nameToken,
@@ -4503,7 +4494,7 @@
 
   @override
   Expression_Generator_Initializer doInvocation(
-      int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+      int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
       {bool isTypeArgumentsInForest = false}) {
     if (isInitializer) {
       return buildConstructorInitializer(offset, new Name(""), arguments);
@@ -4704,7 +4695,7 @@
 
   @override
   Generator doInvocation(
-          int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
+          int offset, List<TypeBuilder>? typeArguments, Arguments arguments,
           {bool isTypeArgumentsInForest = false}) =>
       this;
 
@@ -4820,7 +4811,7 @@
   Expression_Generator withReceiver(Object? receiver, int operatorOffset,
       {bool isNullAware: false});
 
-  List<UnresolvedType>? get typeArguments => null;
+  List<TypeBuilder>? get typeArguments => null;
 
   bool get isTypeArgumentsInForest => true;
 
@@ -4857,7 +4848,7 @@
   final Name name;
 
   @override
-  final List<UnresolvedType>? typeArguments;
+  final List<TypeBuilder>? typeArguments;
 
   @override
   final bool isTypeArgumentsInForest;
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 d0aaf1f..0bd29ce 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
@@ -13,8 +13,8 @@
 import '../builder/formal_parameter_builder.dart';
 import '../builder/named_type_builder.dart';
 import '../builder/prefix_builder.dart';
+import '../builder/type_builder.dart';
 import '../builder/type_declaration_builder.dart';
-import '../builder/unresolved_type.dart';
 
 import '../constant_context.dart' show ConstantContext;
 import '../fasta_codes.dart' show LocatedMessage;
@@ -70,7 +70,7 @@
       {bool isQualified: false, PrefixBuilder? prefix});
 
   Expression_Generator_Initializer finishSend(Object receiver,
-      List<UnresolvedType>? typeArguments, ArgumentsImpl arguments, int offset,
+      List<TypeBuilder>? typeArguments, ArgumentsImpl arguments, int offset,
       {bool isTypeArgumentsInForest = false});
 
   Initializer buildInvalidInitializer(Expression expression,
@@ -126,14 +126,14 @@
       Token nameLastToken,
       Arguments? arguments,
       String name,
-      List<UnresolvedType>? typeArguments,
+      List<TypeBuilder>? typeArguments,
       int charOffset,
       Constness constness,
       {bool isTypeArgumentsInForest = false,
       TypeDeclarationBuilder? typeAliasBuilder,
       required UnresolvedKind unresolvedKind});
 
-  UnresolvedType validateTypeVariableUse(UnresolvedType unresolved,
+  TypeBuilder validateTypeVariableUse(TypeBuilder typeBuilder,
       {required bool allowPotentiallyConstantType});
 
   void addProblemErrorIfConst(Message message, int charOffset, int length);
@@ -156,13 +156,13 @@
   Expression evaluateArgumentsBefore(
       Arguments arguments, Expression expression);
 
-  DartType buildDartType(UnresolvedType unresolvedType,
+  DartType buildDartType(TypeBuilder typeBuilder,
       {required bool allowPotentiallyConstantType});
 
-  DartType buildTypeLiteralDartType(UnresolvedType unresolvedType,
+  DartType buildTypeLiteralDartType(TypeBuilder typeBuilder,
       {required bool allowPotentiallyConstantType});
 
-  List<DartType> buildDartTypeArguments(List<UnresolvedType>? unresolvedTypes,
+  List<DartType> buildDartTypeArguments(List<TypeBuilder>? typeArguments,
       {required bool allowPotentiallyConstantType});
 
   void reportDuplicatedDeclaration(
@@ -205,7 +205,7 @@
   /// creating the instantiation and invocation.
   Expression createInstantiationAndInvocation(
       Expression Function() receiverFunction,
-      List<UnresolvedType>? typeArguments,
+      List<TypeBuilder>? typeArguments,
       String className,
       String constructorName,
       Arguments arguments,
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index ad50b91..3a85b46 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart
@@ -20,7 +20,6 @@
 import '../builder/metadata_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_variable_builder.dart';
-import '../builder/unresolved_type.dart';
 import '../combinator.dart';
 import '../configuration.dart';
 import '../identifiers.dart';
@@ -213,5 +212,3 @@
 final Label dummyLabel = new Label('', -1);
 final FieldInfo dummyFieldInfo = new FieldInfo('', -1, null, dummyToken, -1);
 final Configuration dummyConfiguration = new Configuration(-1, '', '', '');
-final UnresolvedType dummyUnresolvedType =
-    new UnresolvedType(dummyTypeBuilder, -1, dummyUri);
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 77966df..902f60b 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -41,7 +41,6 @@
 import '../builder/nullability_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_variable_builder.dart';
-import '../builder/unresolved_type.dart';
 
 import '../combinator.dart' show CombinatorBuilder;
 
@@ -856,7 +855,7 @@
     // Resolve unresolved types from the class header (i.e., superclass, mixins,
     // and implemented types) before adding members from the class body which
     // should not shadow these unresolved types.
-    libraryBuilder.currentTypeParameterScopeBuilder.resolveTypes(
+    libraryBuilder.currentTypeParameterScopeBuilder.resolveNamedTypes(
         libraryBuilder.currentTypeParameterScopeBuilder.typeVariables,
         libraryBuilder);
   }
@@ -1016,7 +1015,7 @@
       libraryBuilder
           .endNestedDeclaration(
               TypeParameterScopeKind.classDeclaration, "<syntax-error>")
-          .resolveTypes(typeVariables, libraryBuilder);
+          .resolveNamedTypes(typeVariables, libraryBuilder);
     } else {
       final int startCharOffset =
           metadata == null ? beginToken.charOffset : metadata.first.charOffset;
@@ -1105,7 +1104,7 @@
       libraryBuilder
           .endNestedDeclaration(
               TypeParameterScopeKind.mixinDeclaration, "<syntax-error>")
-          .resolveTypes(typeVariables, libraryBuilder);
+          .resolveNamedTypes(typeVariables, libraryBuilder);
     } else {
       int startOffset =
           metadata == null ? mixinToken.charOffset : metadata.first.charOffset;
@@ -1345,7 +1344,7 @@
     checkEmpty(beginToken.charOffset);
     libraryBuilder
         .endNestedDeclaration(TypeParameterScopeKind.topLevelMethod, "#method")
-        .resolveTypes(typeVariables, libraryBuilder);
+        .resolveNamedTypes(typeVariables, libraryBuilder);
     if (name is! ParserRecovery) {
       final int startCharOffset =
           metadata == null ? beginToken.charOffset : metadata.first.charOffset;
@@ -1676,7 +1675,7 @@
     if (name is ParserRecovery) {
       nativeMethodName = null;
       inConstructor = false;
-      declarationBuilder.resolveTypes(typeVariables, libraryBuilder);
+      declarationBuilder.resolveNamedTypes(typeVariables, libraryBuilder);
     } else {
       String? constructorName;
       switch (methodKind) {
@@ -1725,14 +1724,13 @@
         List<FormalParameterBuilder> synthesizedFormals = [];
         TypeBuilder thisType = extension.extensionThisType;
         if (substitution != null) {
-          List<TypeBuilder> unboundTypes = [];
+          List<NamedTypeBuilder> unboundTypes = [];
           List<TypeVariableBuilder> unboundTypeVariables = [];
           thisType = substitute(thisType, substitution,
               unboundTypes: unboundTypes,
               unboundTypeVariables: unboundTypeVariables)!;
-          for (TypeBuilder unboundType in unboundTypes) {
-            extension.addType(new UnresolvedType(
-                unboundType, thisType.charOffset!, thisType.fileUri!));
+          for (NamedTypeBuilder unboundType in unboundTypes) {
+            extension.registerUnresolvedNamedType(unboundType);
           }
           libraryBuilder.unboundTypeVariables.addAll(unboundTypeVariables);
         }
@@ -1745,7 +1743,7 @@
         formals = synthesizedFormals;
       }
 
-      declarationBuilder.resolveTypes(typeVariables, libraryBuilder);
+      declarationBuilder.resolveNamedTypes(typeVariables, libraryBuilder);
       if (constructorName != null) {
         if (isConst &&
             bodyKind != MethodBody.Abstract &&
@@ -1842,7 +1840,7 @@
       libraryBuilder
           .endNestedDeclaration(
               TypeParameterScopeKind.namedMixinApplication, "<syntax-error>")
-          .resolveTypes(typeVariables, libraryBuilder);
+          .resolveNamedTypes(typeVariables, libraryBuilder);
     } else {
       if (libraryBuilder.isNonNullableByDefault) {
         String classNameForErrors = "${name}";
@@ -2265,7 +2263,7 @@
         libraryBuilder
             .endNestedDeclaration(
                 TypeParameterScopeKind.typedef, "<syntax-error>")
-            .resolveTypes(typeVariables, libraryBuilder);
+            .resolveNamedTypes(typeVariables, libraryBuilder);
         popDeclarationContext(DeclarationContext.Typedef);
         return;
       }
@@ -2285,7 +2283,7 @@
         libraryBuilder
             .endNestedDeclaration(
                 TypeParameterScopeKind.functionType, "<syntax-error>")
-            .resolveTypes(typeVariables, libraryBuilder);
+            .resolveNamedTypes(typeVariables, libraryBuilder);
         popDeclarationContext(DeclarationContext.Typedef);
         return;
       }
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 39420c4..19782a3 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -64,7 +64,6 @@
 import '../builder/type_builder.dart';
 import '../builder/type_declaration_builder.dart';
 import '../builder/type_variable_builder.dart';
-import '../builder/unresolved_type.dart';
 import '../builder/void_type_declaration_builder.dart';
 
 import '../combinator.dart' show CombinatorBuilder;
@@ -134,7 +133,7 @@
   @override
   final SourceLoader loader;
 
-  final TypeParameterScopeBuilder libraryDeclaration;
+  final TypeParameterScopeBuilder _libraryTypeParameterScopeBuilder;
 
   final List<ConstructorReferenceBuilder> constructorReferences =
       <ConstructorReferenceBuilder>[];
@@ -284,18 +283,18 @@
       this.fileUri,
       this._packageUri,
       this.packageLanguageVersion,
-      this.libraryDeclaration,
+      this._libraryTypeParameterScopeBuilder,
       this.importScope,
       this.actualOrigin,
       this.library,
       this._nameOrigin,
       this.referencesFrom)
       : _languageVersion = packageLanguageVersion,
-        currentTypeParameterScopeBuilder = libraryDeclaration,
+        currentTypeParameterScopeBuilder = _libraryTypeParameterScopeBuilder,
         referencesFromIndexed =
             referencesFrom == null ? null : new IndexedLibrary(referencesFrom),
-        super(
-            fileUri, libraryDeclaration.toScope(importScope), new Scope.top()) {
+        super(fileUri, _libraryTypeParameterScopeBuilder.toScope(importScope),
+            new Scope.top()) {
     assert(
         _packageUri == null ||
             importUri.scheme != 'package' ||
@@ -308,6 +307,9 @@
         "'${importUri}'.");
   }
 
+  TypeParameterScopeBuilder get libraryTypeParameterScopeBuilderForTesting =>
+      _libraryTypeParameterScopeBuilder;
+
   bool? _enableConstFunctionsInLibrary;
   bool? _enableVarianceInLibrary;
   bool? _enableNonfunctionTypeAliasesInLibrary;
@@ -451,14 +453,14 @@
   @override
   bool get isPart => partOfName != null || partOfUri != null;
 
-  List<UnresolvedType> get types => libraryDeclaration.types;
+  List<NamedTypeBuilder> get unresolvedNamedTypes =>
+      _libraryTypeParameterScopeBuilder.unresolvedNamedTypes;
 
   @override
   bool get isSynthetic => accessProblem != null;
 
-  T addType<T extends TypeBuilder>(T type, int charOffset) {
-    currentTypeParameterScopeBuilder
-        .addType(new UnresolvedType(type, charOffset, fileUri));
+  NamedTypeBuilder registerUnresolvedNamedType(NamedTypeBuilder type) {
+    currentTypeParameterScopeBuilder.registerUnresolvedNamedType(type);
     return type;
   }
 
@@ -812,7 +814,7 @@
     if (setterReference != null) {
       loader.buildersCreatedWithReferences[setterReference] = declaration;
     }
-    if (currentTypeParameterScopeBuilder == libraryDeclaration) {
+    if (currentTypeParameterScopeBuilder == _libraryTypeParameterScopeBuilder) {
       if (declaration is MemberBuilder) {
         declaration.parent = this;
       } else if (declaration is TypeDeclarationBuilder) {
@@ -824,7 +826,8 @@
             "${declaration.runtimeType}", "addBuilder", charOffset, fileUri);
       }
     } else {
-      assert(currentTypeParameterScopeBuilder.parent == libraryDeclaration);
+      assert(currentTypeParameterScopeBuilder.parent ==
+          _libraryTypeParameterScopeBuilder);
     }
     bool isConstructor = declaration is FunctionBuilder &&
         (declaration.isConstructor || declaration.isFactory);
@@ -1237,7 +1240,7 @@
           addBuilder(name, declaration, declaration.charOffset);
         }
       }
-      types.addAll(part.types);
+      unresolvedNamedTypes.addAll(part.unresolvedNamedTypes);
       constructorReferences.addAll(part.constructorReferences);
       part.partOfLibrary = this;
       part.scope.becomePartOf(scope);
@@ -1396,15 +1399,16 @@
     }
   }
 
-  /// Resolves all unresolved types in [types]. The list of types is cleared
-  /// when done.
+  /// Resolves all unresolved types in [unresolvedNamedTypes]. The list of types
+  /// is cleared when done.
   int resolveTypes() {
-    int typeCount = types.length;
-    for (UnresolvedType t in types) {
-      t.resolveIn(scope, this);
-      t.checkType(this);
+    int typeCount = unresolvedNamedTypes.length;
+    for (NamedTypeBuilder namedType in unresolvedNamedTypes) {
+      namedType.resolveIn(
+          scope, namedType.charOffset!, namedType.fileUri!, this);
+      namedType.check(this, namedType.charOffset!, namedType.fileUri!);
     }
-    types.clear();
+    unresolvedNamedTypes.clear();
     return typeCount;
   }
 
@@ -1486,18 +1490,14 @@
   TypeBuilder addNamedType(Object name, NullabilityBuilder nullabilityBuilder,
       List<TypeBuilder>? arguments, int charOffset,
       {required InstanceTypeVariableAccessState instanceTypeVariableAccess}) {
-    return addType(
-        new NamedTypeBuilder(
-            name, nullabilityBuilder, arguments, fileUri, charOffset,
-            instanceTypeVariableAccess: instanceTypeVariableAccess),
-        charOffset);
+    return registerUnresolvedNamedType(new NamedTypeBuilder(
+        name, nullabilityBuilder, arguments, fileUri, charOffset,
+        instanceTypeVariableAccess: instanceTypeVariableAccess));
   }
 
   TypeBuilder addMixinApplication(
       TypeBuilder? supertype, List<TypeBuilder> mixins, int charOffset) {
-    return addType(
-        new MixinApplicationBuilder(supertype, mixins, fileUri, charOffset),
-        charOffset);
+    return new MixinApplicationBuilder(supertype, mixins, fileUri, charOffset);
   }
 
   TypeBuilder addVoidType(int charOffset) {
@@ -1665,8 +1665,8 @@
     // Nested declaration began in `OutlineBuilder.beginClassDeclaration`.
     TypeParameterScopeBuilder declaration =
         endNestedDeclaration(kind, className)
-          ..resolveTypes(typeVariables, this);
-    assert(declaration.parent == libraryDeclaration);
+          ..resolveNamedTypes(typeVariables, this);
+    assert(declaration.parent == _libraryTypeParameterScopeBuilder);
     Map<String, Builder> members = declaration.members!;
     Map<String, MemberBuilder> constructors = declaration.constructors!;
     Map<String, MemberBuilder> setters = declaration.setters!;
@@ -1895,8 +1895,8 @@
     // Nested declaration began in `OutlineBuilder.beginExtensionDeclaration`.
     TypeParameterScopeBuilder declaration = endNestedDeclaration(
         TypeParameterScopeKind.extensionDeclaration, extensionName)
-      ..resolveTypes(typeVariables, this);
-    assert(declaration.parent == libraryDeclaration);
+      ..resolveNamedTypes(typeVariables, this);
+    assert(declaration.parent == _libraryTypeParameterScopeBuilder);
     Map<String, Builder> members = declaration.members!;
     Map<String, MemberBuilder> constructors = declaration.constructors!;
     Map<String, MemberBuilder> setters = declaration.setters!;
@@ -2111,7 +2111,7 @@
             applicationTypeVariables = copyTypeVariables(
                 typeVariables!, currentTypeParameterScopeBuilder);
 
-            List<TypeBuilder> newTypes = <TypeBuilder>[];
+            List<NamedTypeBuilder> newTypes = <NamedTypeBuilder>[];
             if (supertype is NamedTypeBuilder && supertype.arguments != null) {
               for (int i = 0; i < supertype.arguments!.length; ++i) {
                 supertype.arguments![i] = supertype.arguments![i]
@@ -2124,16 +2124,16 @@
                     .clone(newTypes, this, currentTypeParameterScopeBuilder);
               }
             }
-            for (TypeBuilder newType in newTypes) {
-              currentTypeParameterScopeBuilder.addType(new UnresolvedType(
-                  newType, newType.charOffset!, newType.fileUri!));
+            for (NamedTypeBuilder newType in newTypes) {
+              currentTypeParameterScopeBuilder
+                  .registerUnresolvedNamedType(newType);
             }
 
             TypeParameterScopeBuilder mixinDeclaration = this
                 .endNestedDeclaration(
                     TypeParameterScopeKind.unnamedMixinApplication,
                     "mixin application");
-            mixinDeclaration.resolveTypes(applicationTypeVariables, this);
+            mixinDeclaration.resolveNamedTypes(applicationTypeVariables, this);
 
             applicationTypeArguments = <TypeBuilder>[];
             for (TypeVariableBuilder typeVariable in typeVariables) {
@@ -2219,7 +2219,7 @@
       int charEndOffset) {
     // Nested declaration began in `OutlineBuilder.beginNamedMixinApplication`.
     endNestedDeclaration(TypeParameterScopeKind.namedMixinApplication, name)
-        .resolveTypes(typeVariables, this);
+        .resolveNamedTypes(typeVariables, this);
     TypeBuilder supertype = applyMixins(mixinApplication, startCharOffset,
         charOffset, charEndOffset, name, false,
         metadata: metadata,
@@ -2637,7 +2637,7 @@
     }
     currentTypeParameterScopeBuilder = savedDeclaration;
 
-    factoryDeclaration.resolveTypes(procedureBuilder.typeVariables, this);
+    factoryDeclaration.resolveNamedTypes(procedureBuilder.typeVariables, this);
     addBuilder(procedureName, procedureBuilder, charOffset,
         getterReference: constructorReference);
     if (nativeMethodName != null) {
@@ -2688,7 +2688,7 @@
     checkTypeVariables(typeVariables, typedefBuilder);
     // Nested declaration began in `OutlineBuilder.beginFunctionTypeAlias`.
     endNestedDeclaration(TypeParameterScopeKind.typedef, "#typedef")
-        .resolveTypes(typeVariables, this);
+        .resolveNamedTypes(typeVariables, this);
     addBuilder(name, typedefBuilder, charOffset,
         getterReference: referenceFrom?.reference);
   }
@@ -2716,8 +2716,8 @@
     // Nested declaration began in `OutlineBuilder.beginFunctionType` or
     // `OutlineBuilder.beginFunctionTypedFormalParameter`.
     endNestedDeclaration(TypeParameterScopeKind.functionType, "#function_type")
-        .resolveTypes(typeVariables, this);
-    return addType(builder, charOffset);
+        .resolveNamedTypes(typeVariables, this);
+    return builder;
   }
 
   FormalParameterBuilder addFormalParameter(
@@ -3054,7 +3054,7 @@
   List<TypeVariableBuilder> copyTypeVariables(
       List<TypeVariableBuilder> original, TypeParameterScopeBuilder declaration,
       {bool isExtensionTypeParameter: false}) {
-    List<TypeBuilder> newTypes = <TypeBuilder>[];
+    List<NamedTypeBuilder> newTypes = <NamedTypeBuilder>[];
     List<TypeVariableBuilder> copy = <TypeVariableBuilder>[];
     for (TypeVariableBuilder variable in original) {
       TypeVariableBuilder newVariable = new TypeVariableBuilder(
@@ -3066,9 +3066,8 @@
       copy.add(newVariable);
       unboundTypeVariables.add(newVariable);
     }
-    for (TypeBuilder newType in newTypes) {
-      declaration.addType(
-          new UnresolvedType(newType, newType.charOffset!, newType.fileUri!));
+    for (NamedTypeBuilder newType in newTypes) {
+      declaration.registerUnresolvedNamedType(newType);
     }
     return copy;
   }
@@ -3183,7 +3182,8 @@
   @override
   int computeVariances() {
     int count = 0;
-    for (Builder? declaration in libraryDeclaration.members!.values) {
+    for (Builder? declaration
+        in _libraryTypeParameterScopeBuilder.members!.values) {
       while (declaration != null) {
         if (declaration is TypeAliasBuilder &&
             declaration.typeVariablesCount > 0) {
@@ -3306,7 +3306,7 @@
         }
 
         if (!haveErroneousBounds) {
-          List<TypeBuilder> unboundTypes = [];
+          List<NamedTypeBuilder> unboundTypes = [];
           List<TypeVariableBuilder> unboundTypeVariables = [];
           List<TypeBuilder> calculatedBounds = calculateBounds(
               variables,
@@ -3315,9 +3315,9 @@
               objectClass,
               unboundTypes: unboundTypes,
               unboundTypeVariables: unboundTypeVariables);
-          for (TypeBuilder unboundType in unboundTypes) {
-            currentTypeParameterScopeBuilder.addType(new UnresolvedType(
-                unboundType, unboundType.charOffset!, unboundType.fileUri!));
+          for (NamedTypeBuilder unboundType in unboundTypes) {
+            currentTypeParameterScopeBuilder
+                .registerUnresolvedNamedType(unboundType);
           }
           this.unboundTypeVariables.addAll(unboundTypeVariables);
           for (int i = 0; i < variables.length; ++i) {
@@ -3344,7 +3344,8 @@
       }
     }
 
-    for (Builder declaration in libraryDeclaration.members!.values) {
+    for (Builder declaration
+        in _libraryTypeParameterScopeBuilder.members!.values) {
       if (declaration is ClassBuilder) {
         {
           List<NonSimplicityIssue> issues =
@@ -3493,7 +3494,8 @@
             "(${declaration.runtimeType}).");
       }
     }
-    for (Builder declaration in libraryDeclaration.setters!.values) {
+    for (Builder declaration
+        in _libraryTypeParameterScopeBuilder.setters!.values) {
       assert(
           declaration is ProcedureBuilder,
           "Expected setter to be a ProcedureBuilder, "
@@ -4584,7 +4586,7 @@
 
   final Set<SourceExtensionBuilder>? extensions;
 
-  final List<UnresolvedType> types = <UnresolvedType>[];
+  final List<NamedTypeBuilder> unresolvedNamedTypes = <NamedTypeBuilder>[];
 
   // TODO(johnniwinther): Stop using [_name] for determining the declaration
   // kind.
@@ -4743,15 +4745,17 @@
 
   /// Adds the yet unresolved [type] to this scope builder.
   ///
-  /// Unresolved type will be resolved through [resolveTypes] when the scope
-  /// is fully built. This allows for resolving self-referencing types, like
-  /// type parameter used in their own bound, for instance `<T extends A<T>>`.
-  void addType(UnresolvedType type) {
-    types.add(type);
+  /// Unresolved type will be resolved through [resolveNamedTypes] when the
+  /// scope is fully built. This allows for resolving self-referencing types,
+  /// like type parameter used in their own bound, for instance
+  /// `<T extends A<T>>`.
+  void registerUnresolvedNamedType(NamedTypeBuilder type) {
+    unresolvedNamedTypes.add(type);
   }
 
-  /// Resolves type variables in [types] and propagate other types to [parent].
-  void resolveTypes(
+  /// Resolves type variables in [unresolvedNamedTypes] and propagate other
+  /// types to [parent].
+  void resolveNamedTypes(
       List<TypeVariableBuilder>? typeVariables, SourceLibraryBuilder library) {
     Map<String, TypeVariableBuilder>? map;
     if (typeVariables != null) {
@@ -4761,8 +4765,8 @@
       }
     }
     Scope? scope;
-    for (UnresolvedType type in types) {
-      Object? nameOrQualified = type.builder.name;
+    for (NamedTypeBuilder namedTypeBuilder in unresolvedNamedTypes) {
+      Object? nameOrQualified = namedTypeBuilder.name;
       String? name = nameOrQualified is QualifiedName
           ? nameOrQualified.qualifier as String
           : nameOrQualified as String?;
@@ -4778,25 +4782,30 @@
       if (declaration == null) {
         // Since name didn't resolve in this scope, propagate it to the
         // parent declaration.
-        parent!.addType(type);
+        parent!.registerUnresolvedNamedType(namedTypeBuilder);
       } else if (nameOrQualified is QualifiedName) {
-        NamedTypeBuilder builder = type.builder as NamedTypeBuilder;
         // Attempt to use a member or type variable as a prefix.
         Message message = templateNotAPrefixInTypeAnnotation.withArguments(
-            flattenName(
-                nameOrQualified.qualifier, type.charOffset, type.fileUri),
+            flattenName(nameOrQualified.qualifier, namedTypeBuilder.charOffset!,
+                namedTypeBuilder.fileUri!),
             nameOrQualified.name);
-        library.addProblem(message, type.charOffset,
-            nameOrQualified.endCharOffset - type.charOffset, type.fileUri);
-        builder.bind(builder.buildInvalidTypeDeclarationBuilder(
-            message.withLocation(type.fileUri, type.charOffset,
-                nameOrQualified.endCharOffset - type.charOffset)));
+        library.addProblem(
+            message,
+            namedTypeBuilder.charOffset!,
+            nameOrQualified.endCharOffset - namedTypeBuilder.charOffset!,
+            namedTypeBuilder.fileUri!);
+        namedTypeBuilder.bind(namedTypeBuilder
+            .buildInvalidTypeDeclarationBuilder(message.withLocation(
+                namedTypeBuilder.fileUri!,
+                namedTypeBuilder.charOffset!,
+                nameOrQualified.endCharOffset - namedTypeBuilder.charOffset!)));
       } else {
         scope ??= toScope(null).withTypeVariables(typeVariables);
-        type.resolveIn(scope, library);
+        namedTypeBuilder.resolveIn(scope, namedTypeBuilder.charOffset!,
+            namedTypeBuilder.fileUri!, library);
       }
     }
-    types.clear();
+    unresolvedNamedTypes.clear();
   }
 
   Scope toScope(Scope? parent) {
diff --git a/pkg/front_end/lib/src/fasta/source/value_kinds.dart b/pkg/front_end/lib/src/fasta/source/value_kinds.dart
index 2c88740..9a81d93 100644
--- a/pkg/front_end/lib/src/fasta/source/value_kinds.dart
+++ b/pkg/front_end/lib/src/fasta/source/value_kinds.dart
@@ -18,7 +18,6 @@
 import '../builder/metadata_builder.dart' as type;
 import '../builder/type_builder.dart' as type;
 import '../builder/type_variable_builder.dart' as type;
-import '../builder/unresolved_type.dart' as type;
 
 import '../identifiers.dart' as type;
 
@@ -108,15 +107,15 @@
   static const ValueKind TokenOrNull =
       const SingleValueKind<type.Token>(NullValue.Token);
   static const ValueKind TypeOrNull =
-      const SingleValueKind<type.UnresolvedType>(NullValue.UnresolvedType);
+      const SingleValueKind<type.TypeBuilder>(NullValue.TypeBuilder);
   static const ValueKind TypeArguments =
-      const SingleValueKind<List<type.UnresolvedType>>();
+      const SingleValueKind<List<type.TypeBuilder>>();
   static const ValueKind TypeArgumentsOrNull =
-      const SingleValueKind<List<type.UnresolvedType>>(NullValue.TypeArguments);
+      const SingleValueKind<List<type.TypeBuilder>>(NullValue.TypeArguments);
   static const ValueKind TypeBuilder =
       const SingleValueKind<type.TypeBuilder>();
   static const ValueKind TypeBuilderOrNull =
-      const SingleValueKind<type.TypeBuilder>(NullValue.UnresolvedType);
+      const SingleValueKind<type.TypeBuilder>(NullValue.TypeBuilder);
   static const ValueKind TypeBuilderListOrNull =
       const SingleValueKind<List<type.TypeBuilder>>(NullValue.TypeBuilderList);
   static const ValueKind TypeVariableListOrNull =
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index f9729d3..02297a9 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -137,7 +137,7 @@
   SourceLibraryBuilder builder =
       lookupLibraryBuilder(compilerResult, library, required: required)
           as SourceLibraryBuilder;
-  return builder.libraryDeclaration;
+  return builder.libraryTypeParameterScopeBuilderForTesting;
 }
 
 ClassBuilder? lookupClassBuilder(
diff --git a/pkg/front_end/test/explicit_creation_git_test.dart b/pkg/front_end/test/explicit_creation_git_test.dart
index 287b605..5028925 100644
--- a/pkg/front_end/test/explicit_creation_git_test.dart
+++ b/pkg/front_end/test/explicit_creation_git_test.dart
@@ -16,8 +16,8 @@
 import 'package:front_end/src/fasta/builder/declaration_builder.dart';
 import 'package:front_end/src/fasta/builder/field_builder.dart';
 import 'package:front_end/src/fasta/builder/modifier_builder.dart';
+import 'package:front_end/src/fasta/builder/type_builder.dart';
 import 'package:front_end/src/fasta/builder/type_declaration_builder.dart';
-import 'package:front_end/src/fasta/builder/unresolved_type.dart';
 import 'package:front_end/src/fasta/compiler_context.dart';
 import 'package:front_end/src/fasta/constant_context.dart';
 import 'package:front_end/src/fasta/dill/dill_target.dart';
@@ -235,7 +235,7 @@
       Token nameLastToken,
       Arguments arguments,
       String name,
-      List<UnresolvedType> typeArguments,
+      List<TypeBuilder> typeArguments,
       int charOffset,
       Constness constness,
       {bool isTypeArgumentsInForest = false,
diff --git a/pkg/front_end/test/unit_test_suites_impl.dart b/pkg/front_end/test/unit_test_suites_impl.dart
index 3376bd2..997a51f 100644
--- a/pkg/front_end/test/unit_test_suites_impl.dart
+++ b/pkg/front_end/test/unit_test_suites_impl.dart
@@ -608,14 +608,26 @@
           });
           await exitPort.first;
           errorPort.close();
-          bool gotError = !await errorPort.isEmpty;
+          List<dynamic> allErrors = await errorPort.toList();
+          bool gotError = allErrors.isNotEmpty;
           if (gotError) {
+            print("Suite $naming encountered ${allErrors.length} error(s).");
+            print("Errors:");
+            for (int i = 0; i < allErrors.length; i++) {
+              print("-----------");
+              print("Error #$i:");
+              print(allErrors[i]);
+            }
+            print("-----------");
             timedOutOrCrash = true;
           }
           timer.cancel();
+          int seconds = stopwatch.elapsedMilliseconds ~/ 1000;
           if (!timedOutOrCrash) {
-            int seconds = stopwatch.elapsedMilliseconds ~/ 1000;
             print("Suite $naming finished (took ${seconds} seconds)");
+          } else {
+            print("Suite $naming finished badly (see above) "
+                "(took ${seconds} seconds)");
           }
           return timedOutOrCrash;
         } finally {
@@ -626,7 +638,7 @@
     }
   }
   // Wait for isolates to terminate and clean up.
-  Iterable<bool> timeouts = await Future.wait(futures);
+  Iterable<bool> timeoutsOrCrashes = await Future.wait(futures);
   resultsPort.close();
   logsPort.close();
   // Write results.json and logs.json.
@@ -638,9 +650,9 @@
       " ${logsJsonUri.toFilePath()}");
   print("Entire run took ${totalRuntime.elapsed}.");
   // Return with exit code 1 if at least one suite timed out.
-  bool timeout = timeouts.any((timeout) => timeout);
-  if (timeout) {
-    exitCode = 1;
+  bool timedOutOrCrashed = timeoutsOrCrashes.any((timeout) => timeout);
+  if (timedOutOrCrashed) {
+    throw "Crashed or timed out. Check stdout for more details.";
   } else {
     // The testing framework (package:testing) sets the exitCode to `1` if any
     // test failed, so we reset it here to indicate that the test runner was
diff --git a/pkg/vm/lib/transformations/ffi_native.dart b/pkg/vm/lib/transformations/ffi_native.dart
index 0752ed2..3427f28 100644
--- a/pkg/vm/lib/transformations/ffi_native.dart
+++ b/pkg/vm/lib/transformations/ffi_native.dart
@@ -103,9 +103,9 @@
         node.function.computeThisFunctionType(Nullability.nonNullable);
     // Double Function(Double)
     final nativeType = annotationConst.typeArguments[0] as FunctionType;
-    // InterfaceType(NativeFunction<Double Function(Double)>*)
-    final DartType nativeInterfaceType =
-        InterfaceType(nativeFunctionClass, Nullability.legacy, [nativeType]);
+    // InterfaceType(NativeFunction<Double Function(Double)>)
+    final DartType nativeInterfaceType = InterfaceType(
+        nativeFunctionClass, Nullability.nonNullable, [nativeType]);
 
     // Derive number of arguments from the native function signature.
     final args_n = nativeType.positionalParameters.length;
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index a90f1ec..2dc593a 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -398,7 +398,7 @@
                   env.isSubtypeOf(ffiParams[i], pointerType,
                       SubtypeCheckMode.ignoringNullabilities)) {
                 // final NativeFieldWrapperClass1 #t1 = MyNFWC1();.
-                final tmpPtr = VariableDeclaration('',
+                final tmpPtr = VariableDeclaration(null,
                     initializer: origArgs[i],
                     type: nativeFieldWrapperClassType,
                     isFinal: true);
@@ -419,7 +419,7 @@
               }
               // Note: We also evaluate, and assign temporaries for, non-wrapped
               // arguments as we need to preserve the original evaluation order.
-              final tmpArg = VariableDeclaration('',
+              final tmpArg = VariableDeclaration(null,
                   initializer: origArgs[i], isFinal: true);
               tmpsArgs.add(tmpArg);
               callArgs.add(VariableGet(tmpArg));
@@ -434,7 +434,7 @@
             //   reachabilityFence(#t1);
             // } => #t0
             final tmpResult =
-                VariableDeclaration('', type: target.function.returnType);
+                VariableDeclaration(null, type: target.function.returnType);
             return BlockExpression(
               Block([
                 tmpResult,
diff --git a/pkg/vm/test/transformations/ffinative_test.dart b/pkg/vm/test/transformations/ffinative_test.dart
new file mode 100644
index 0000000..76eba47
--- /dev/null
+++ b/pkg/vm/test/transformations/ffinative_test.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/kernel.dart';
+import 'package:kernel/reference_from_index.dart';
+import 'package:kernel/target/targets.dart';
+import 'package:kernel/verifier.dart';
+
+import 'package:test/test.dart';
+
+import 'package:vm/transformations/ffi_native.dart' show transformLibraries;
+
+import '../common_test_utils.dart';
+
+final String pkgVmDir = Platform.script.resolve('../..').toFilePath();
+
+class TestDiagnosticReporter extends DiagnosticReporter<Object, Object> {
+  @override
+  void report(Object message, int charOffset, int length, Uri? fileUri,
+      {List<Object>? context}) {/* nop */}
+}
+
+runTestCase(Uri source) async {
+  final target = TestingVmTarget(TargetFlags());
+
+  Component component = await compileTestCaseToKernelProgram(source,
+      target: target, experimentalFlags: ['generic-metadata']);
+
+  final ReferenceFromIndex? referenceFromIndex = null;
+  final DiagnosticReporter diagnosticReporter = TestDiagnosticReporter();
+
+  transformLibraries(
+      component, component.libraries, diagnosticReporter, referenceFromIndex);
+
+  verifyComponent(component);
+
+  final actual = kernelLibraryToString(component.mainMethod!.enclosingLibrary);
+
+  compareResultWithExpectationsFile(source, actual);
+}
+
+main() {
+  group('ffi-transformations', () {
+    final testCasesDir = Directory(pkgVmDir + '/testcases/transformations/ffi');
+
+    for (var entry in testCasesDir
+        .listSync(recursive: true, followLinks: false)
+        .reversed) {
+      if (entry.path.endsWith(".dart")) {
+        test(entry.path, () => runTestCase(entry.uri));
+      }
+    }
+  });
+}
diff --git a/pkg/vm/testcases/transformations/ffi/ffinative.dart b/pkg/vm/testcases/transformations/ffi/ffinative.dart
new file mode 100644
index 0000000..5cb2397
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/ffinative.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests for @FfiNative related transformations.
+
+// @dart=2.14
+
+import 'dart:ffi';
+import 'dart:nativewrappers';
+
+@FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr')
+external int returnIntPtr(int x);
+
+@FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr', isLeaf: true)
+external int returnIntPtrLeaf(int x);
+
+class Classy {
+  @FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr')
+  external static int returnIntPtrStatic(int x);
+}
+
+void main() {
+  returnIntPtr(13);
+  returnIntPtrLeaf(37);
+  Classy.returnIntPtrStatic(0xDE);
+}
diff --git a/pkg/vm/testcases/transformations/ffi/ffinative.dart.expect b/pkg/vm/testcases/transformations/ffi/ffinative.dart.expect
new file mode 100644
index 0000000..09cb43b
--- /dev/null
+++ b/pkg/vm/testcases/transformations/ffi/ffinative.dart.expect
@@ -0,0 +1,55 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "dart:_internal" as _in;
+
+import "dart:ffi";
+import "dart:nativewrappers";
+
+class Classy extends core::Object {
+  static final field (core::int) → core::int _@FfiNative_returnIntPtrStatic = ffi::_asFunctionInternal<(core::int) → core::int, (ffi::IntPtr*) →* ffi::IntPtr*>(ffi::_fromAddress<ffi::NativeFunction<(ffi::IntPtr*) →* ffi::IntPtr*>>(ffi::_ffi_resolver(#C1, #C2, #C3){(core::Object, core::Object, core::int) → core::int}), false)/*isLegacy*/;
+  synthetic constructor •() → self::Classy
+    : super core::Object::•()
+    ;
+  @#C5
+  static method returnIntPtrStatic(core::int x) → core::int
+    return self::Classy::_@FfiNative_returnIntPtrStatic(x){(core::int) → core::int};
+}
+static final field (core::int) → core::int _@FfiNative_returnIntPtr = ffi::_asFunctionInternal<(core::int) → core::int, (ffi::IntPtr*) →* ffi::IntPtr*>(ffi::_fromAddress<ffi::NativeFunction<(ffi::IntPtr*) →* ffi::IntPtr*>>(ffi::_ffi_resolver(#C1, #C2, #C3){(core::Object, core::Object, core::int) → core::int}), false)/*isLegacy*/;
+static final field (core::int) → core::int _@FfiNative_returnIntPtrLeaf = ffi::_asFunctionInternal<(core::int) → core::int, (ffi::IntPtr*) →* ffi::IntPtr*>(ffi::_fromAddress<ffi::NativeFunction<(ffi::IntPtr*) →* ffi::IntPtr*>>(ffi::_ffi_resolver(#C1, #C2, #C3){(core::Object, core::Object, core::int) → core::int}), true)/*isLegacy*/;
+@#C5
+static method returnIntPtr(core::int x) → core::int
+  return self::_@FfiNative_returnIntPtr(x){(core::int) → core::int};
+@#C7
+static method returnIntPtrLeaf(core::int x) → core::int
+  return self::_@FfiNative_returnIntPtrLeaf(x){(core::int) → core::int};
+static method main() → void {
+  block {
+    core::int #t1;
+    final dynamic #t2 = 13;
+    #t1 = self::returnIntPtr(#t2);
+    _in::reachabilityFence(#t2);
+  } =>#t1;
+  block {
+    core::int #t3;
+    final dynamic #t4 = 37;
+    #t3 = self::returnIntPtrLeaf(#t4);
+    _in::reachabilityFence(#t4);
+  } =>#t3;
+  block {
+    core::int #t5;
+    final dynamic #t6 = 222;
+    #t5 = self::Classy::returnIntPtrStatic(#t6);
+    _in::reachabilityFence(#t6);
+  } =>#t5;
+}
+constants  {
+  #C1 = "#lib"
+  #C2 = "ReturnIntPtr"
+  #C3 = 1
+  #C4 = false
+  #C5 = ffi::FfiNative<(ffi::IntPtr*) →* ffi::IntPtr*> {nativeName:#C2, isLeaf:#C4}
+  #C6 = true
+  #C7 = ffi::FfiNative<(ffi::IntPtr*) →* ffi::IntPtr*> {nativeName:#C2, isLeaf:#C6}
+}
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 02c28b2..abc0291 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -28,7 +28,7 @@
 #ifdef __cplusplus
 #define DART_EXTERN_C extern "C"
 #else
-#define DART_EXTERN_C
+#define DART_EXTERN_C extern
 #endif
 
 #if defined(__CYGWIN__)
diff --git a/runtime/include/dart_api_dl.h b/runtime/include/dart_api_dl.h
index 0854d71..1521df2 100644
--- a/runtime/include/dart_api_dl.h
+++ b/runtime/include/dart_api_dl.h
@@ -22,13 +22,7 @@
  * `Dart_InitializeApiDL` with `NativeApi.initializeApiDLData`.
  */
 
-#ifdef __cplusplus
-#define DART_EXTERN extern "C"
-#else
-#define DART_EXTERN extern
-#endif
-
-DART_EXTERN intptr_t Dart_InitializeApiDL(void* data);
+DART_EXPORT intptr_t Dart_InitializeApiDL(void* data);
 
 // ============================================================================
 // IMPORTANT! Never update these signatures without properly updating
@@ -114,14 +108,43 @@
 // End of verbatim copy.
 // ============================================================================
 
+// Copy of definition of DART_EXPORT without 'used' attribute.
+//
+// The 'used' attribute cannot be used with DART_API_ALL_DL_SYMBOLS because
+// they are not function declarations, but variable declarations with a
+// function pointer type.
+//
+// The function pointer variables are initialized with the addresses of the
+// functions in the VM. If we were to use function declarations instead, we
+// would need to forward the call to the VM adding indirection.
+#if defined(__CYGWIN__)
+#error Tool chain and platform not supported.
+#elif defined(_WIN32)
+#if defined(DART_SHARED_LIB)
+#define DART_EXPORT_DL DART_EXTERN_C __declspec(dllexport)
+#else
+#define DART_EXPORT_DL DART_EXTERN_C
+#endif
+#else
+#if __GNUC__ >= 4
+#if defined(DART_SHARED_LIB)
+#define DART_EXPORT_DL DART_EXTERN_C __attribute__((visibility("default")))
+#else
+#define DART_EXPORT_DL DART_EXTERN_C
+#endif
+#else
+#error Tool chain not supported.
+#endif
+#endif
+
 #define DART_API_DL_DECLARATIONS(name, R, A)                                   \
   typedef R(*name##_Type) A;                                                   \
-  DART_EXTERN name##_Type name##_DL;
+  DART_EXPORT_DL name##_Type name##_DL;
 
 DART_API_ALL_DL_SYMBOLS(DART_API_DL_DECLARATIONS)
 
-#undef DART_API_DL_DEFINITIONS
+#undef DART_API_DL_DECLARATIONS
 
-#undef DART_EXTERN
+#undef DART_EXPORT_DL
 
 #endif /* RUNTIME_INCLUDE_DART_API_DL_H_ */ /* NOLINT */
diff --git a/tests/ffi/vmspecific_ffi_native_test.dart b/tests/ffi/vmspecific_ffi_native_test.dart
index 8838ebc..9caa53d 100644
--- a/tests/ffi/vmspecific_ffi_native_test.dart
+++ b/tests/ffi/vmspecific_ffi_native_test.dart
@@ -23,9 +23,6 @@
     nativeLib.lookupFunction<Void Function(Handle), void Function(Object)>(
         'SetFfiNativeResolverForTest');
 
-final triggerGC = nativeLib
-    .lookupFunction<Void Function(IntPtr), void Function(int)>('TriggerGC');
-
 @FfiNative<Handle Function(Handle, IntPtr, IntPtr)>(
     'Dart_SetNativeInstanceField')
 external Object setNativeInstanceField(Object obj, int index, int ptr);
@@ -71,38 +68,6 @@
 @FfiNative<IntPtr Function(IntPtr, Pointer<Void>)>('PassAsValueAndPointer')
 external int passAsValueAndPointer(int value, NativeFieldWrapperClass1 obj);
 
-// Allocate new native resource we can use to keep track of whether the
-// finalizer has run.
-@FfiNative<Pointer<Void> Function(IntPtr)>('AllocateResource')
-external Pointer<Void> allocateResource(int value);
-
-@FfiNative<Void Function(Pointer<Void>)>('DeleteResource')
-external void deleteResource(Pointer<Void> resource);
-
-// Set up the object's finalizer to reset the resource.
-@FfiNative<Void Function(Handle, Pointer<Void>)>('SetResourceFinalizer')
-external void setResourceFinalizer(
-    NativeFieldWrapperClass1 obj, Pointer<Void> resource);
-
-// Return the native resource's value.
-@FfiNative<IntPtr Function(Pointer<Void>)>('GetResourceValue')
-external int getResourceValue(Pointer<Void> resource);
-
-// Class which ties itself to a resource, resetting the value of the resource
-// when the instance gets collected.
-class ResourceResetter extends NativeFieldWrapperClass1 {
-  ResourceResetter(Pointer<Void> resource) {
-    setNativeInstanceField(this, 0, 0);
-    setResourceFinalizer(this, resource);
-  }
-}
-
-// Helper to embed triggerGC(..) as an expression.
-int triggerGCWrap() {
-  triggerGC(0);
-  return 0;
-}
-
 // Helpers for testing argumnent evaluation order is preserved.
 int state = 0;
 int setState(int value) {
@@ -141,22 +106,6 @@
     Expect.equals(123456, passAsPointer(cwnf));
   }
 
-  // Test that the transform to wrap NativeFieldWrapperClass1 objects in
-  // _getNativeField(..) doesn't violate the original argument's liveness.
-  final resource = allocateResource(314159);
-  Expect.equals(
-      314159,
-      passAsPointerAndValue(
-          // 1: Locally alloc. instance.
-          // If this gets wrapped in another call the instance does not live
-          // past the return of the wrapper call.
-          ResourceResetter(resource),
-          // 2: Force GC, to collect the above if it isn't being kept alive.
-          // 3: Check that the underlying (dummy) resource hasn't been
-          // "collected" (i.e. reset to 0).
-          triggerGCWrap() + getResourceValue(resource)));
-  deleteResource(resource);
-
   // Test that the order of argument evaluation is being preserved through the
   // transform wrapping NativeFieldWrapperClass1 objects.
   state = 0;
diff --git a/tools/VERSION b/tools/VERSION
index 051c4b1..47a58ca 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 187
+PRERELEASE 188
 PRERELEASE_PATCH 0
\ No newline at end of file