Version 2.13.0-144.0.dev

Merge commit '33cabf43133fe2cece89bca00cc84171a5fd1d2a' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 6fffc20..48079d1 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2021-03-12T09:00:31.497265",
+  "generated": "2021-03-15T10:48:35.022974",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -220,7 +220,7 @@
       "name": "dart_style",
       "rootUri": "../third_party/pkg_tested/dart_style",
       "packageUri": "lib/",
-      "languageVersion": "2.9"
+      "languageVersion": "2.12"
     },
     {
       "name": "dartdev",
@@ -695,13 +695,13 @@
       "name": "test_descriptor",
       "rootUri": "../third_party/pkg/test_descriptor",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.12"
     },
     {
       "name": "test_process",
       "rootUri": "../third_party/pkg/test_process",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.12"
     },
     {
       "name": "test_reflective_loader",
diff --git a/DEPS b/DEPS
index 09155e8..17c6ed1 100644
--- a/DEPS
+++ b/DEPS
@@ -98,7 +98,7 @@
   #     and land the review.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-  "dart_style_tag": "1.3.11",  # Please see the note above before updating.
+  "dart_style_tag": "a1d65dd9c4b83c9702ba409465879b94caeb04ea",
 
   "chromedriver_tag": "83.0.4103.39",
   "dartdoc_rev" : "174021f3d76c2a8500b54977c80f32c5bbc099f1",
@@ -155,8 +155,8 @@
   "stream_channel_tag": "d7251e61253ec389ee6e045ee1042311bced8f1d",
   "string_scanner_rev": "1b63e6e5db5933d7be0a45da6e1129fe00262734",
   "sync_http_rev": "b59c134f2e34d12acac110d4f17f83e5a7db4330",
-  "test_descriptor_tag": "1.1.1",
-  "test_process_tag": "1.0.3",
+  "test_descriptor_tag": "2.0.0",
+  "test_process_tag": "2.0.0",
   "term_glyph_rev": "6a0f9b6fb645ba75e7a00a4e20072678327a0347",
   "test_reflective_loader_rev": "54e930a11c372683792e22bddad79197728c91ce",
   "test_rev": "e673623f45d75ccec750d35271b0b4d1423e9fac",
diff --git a/benchmarks/FfiMemory/dart/FfiMemory.dart b/benchmarks/FfiMemory/dart/FfiMemory.dart
index 1b822fb..26ff8e7 100644
--- a/benchmarks/FfiMemory/dart/FfiMemory.dart
+++ b/benchmarks/FfiMemory/dart/FfiMemory.dart
@@ -390,6 +390,30 @@
   }
 }
 
+class PointerUint32Unaligned extends BenchmarkBase {
+  Pointer<Uint32> pointer = nullptr;
+  Pointer<Uint32> unalignedPointer = nullptr;
+  PointerUint32Unaligned() : super('FfiMemory.PointerUint32Unaligned');
+
+  @override
+  void setup() {
+    pointer = calloc(N + 1);
+    unalignedPointer = Pointer.fromAddress(pointer.address + 1);
+  }
+
+  @override
+  void teardown() => calloc.free(pointer);
+
+  @override
+  void run() {
+    doStoreUint32(unalignedPointer, N);
+    final int x = doLoadUint32(unalignedPointer, N);
+    if (x != N) {
+      throw Exception('$name: Unexpected result: $x');
+    }
+  }
+}
+
 class PointerInt64 extends BenchmarkBase {
   Pointer<Int64> pointer = nullptr;
   PointerInt64() : super('FfiMemory.PointerInt64');
@@ -527,6 +551,7 @@
     () => PointerUint16(),
     () => PointerInt32(),
     () => PointerUint32(),
+    () => PointerUint32Unaligned(),
     () => PointerInt64(),
     () => PointerInt64Mint(),
     () => PointerUint64(),
diff --git a/benchmarks/FfiMemory/dart2/FfiMemory.dart b/benchmarks/FfiMemory/dart2/FfiMemory.dart
index f788959..8ed6302 100644
--- a/benchmarks/FfiMemory/dart2/FfiMemory.dart
+++ b/benchmarks/FfiMemory/dart2/FfiMemory.dart
@@ -390,6 +390,30 @@
   }
 }
 
+class PointerUint32Unaligned extends BenchmarkBase {
+  Pointer<Float> pointer;
+  Pointer<Uint32> unalignedPointer;
+  PointerUint32Unaligned() : super('FfiMemory.PointerUint32Unaligned');
+
+  @override
+  void setup() {
+    pointer = calloc(N + 1);
+    unalignedPointer = Pointer.fromAddress(pointer.address + 1);
+  }
+
+  @override
+  void teardown() => calloc.free(pointer);
+
+  @override
+  void run() {
+    doStoreUint32(unalignedPointer, N);
+    final int x = doLoadUint32(unalignedPointer, N);
+    if (x != N) {
+      throw Exception('$name: Unexpected result: $x');
+    }
+  }
+}
+
 class PointerInt64 extends BenchmarkBase {
   Pointer<Int64> pointer;
   PointerInt64() : super('FfiMemory.PointerInt64');
@@ -527,6 +551,7 @@
     () => PointerUint16(),
     () => PointerInt32(),
     () => PointerUint32(),
+    () => PointerUint32Unaligned(),
     () => PointerInt64(),
     () => PointerInt64Mint(),
     () => PointerUint64(),
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/for_in_loop_type_not_iterable_nullability_error.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/for_in_loop_type_not_iterable_nullability_error.dart
index 639222f..3b89bde7 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/for_in_loop_type_not_iterable_nullability_error.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/for_in_loop_type_not_iterable_nullability_error.dart
@@ -11,9 +11,80 @@
   List<int>? bad;
 }
 
-test(C1 c) {
+forStatement(C1 c) {
   if (c.bad == null) return;
   for (var x
       in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
           . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad) {}
 }
+
+forElementInList(C1 c) {
+  if (c.bad == null) return;
+  [
+    for (var x
+        in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+            . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+      null
+  ];
+}
+
+forElementInSet(C1 c) {
+  if (c.bad == null) return;
+  <dynamic>{
+    for (var x
+        in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+            . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+      null
+  };
+}
+
+forElementInMap(C1 c) {
+  if (c.bad == null) return;
+  <dynamic, dynamic>{
+    for (var x
+        in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+            . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+      null,
+    null
+  };
+}
+
+forElementInAmbiguousSet_resolvableDuringParsing(C1 c) {
+  if (c.bad == null) return;
+  ({
+    for (var x
+        in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+            . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+      null
+  });
+}
+
+forElementInAmbiguousMap_resolvableDuringParsing(C1 c) {
+  if (c.bad == null) return;
+  ({
+    for (var x
+        in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+            . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+      null: null
+  });
+}
+
+forElementInAmbiguousSet_notResolvableDuringParsing(C1 c, List list) {
+  if (c.bad == null) return;
+  ({
+    for (var x
+        in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+            . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+      ...list
+  });
+}
+
+forElementInAmbiguousMap_notResolvableDuringParsing(C1 c, Map map) {
+  if (c.bad == null) return;
+  ({
+    for (var x
+        in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+            . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+      ...map
+  });
+}
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
index c67d3f7..d55238b 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
@@ -1573,3 +1573,135 @@
   @override
   String toString() => jsonEncoder.convert(toJson());
 }
+
+class SnippetTextEdit implements TextEdit, ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(SnippetTextEdit.canParse, SnippetTextEdit.fromJson);
+
+  SnippetTextEdit(
+      {@required this.insertTextFormat,
+      @required this.range,
+      @required this.newText}) {
+    if (insertTextFormat == null) {
+      throw 'insertTextFormat is required but was not provided';
+    }
+    if (range == null) {
+      throw 'range is required but was not provided';
+    }
+    if (newText == null) {
+      throw 'newText is required but was not provided';
+    }
+  }
+  static SnippetTextEdit fromJson(Map<String, dynamic> json) {
+    final insertTextFormat = json['insertTextFormat'] != null
+        ? InsertTextFormat.fromJson(json['insertTextFormat'])
+        : null;
+    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
+    final newText = json['newText'];
+    return SnippetTextEdit(
+        insertTextFormat: insertTextFormat, range: range, newText: newText);
+  }
+
+  final InsertTextFormat insertTextFormat;
+
+  /// The string to be inserted. For delete operations use an empty string.
+  final String newText;
+
+  /// The range of the text document to be manipulated. To insert text into a
+  /// document create a range where start === end.
+  final Range range;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['insertTextFormat'] = insertTextFormat?.toJson() ??
+        (throw 'insertTextFormat is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
+    __result['newText'] =
+        newText ?? (throw 'newText is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('insertTextFormat');
+      try {
+        if (!obj.containsKey('insertTextFormat')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['insertTextFormat'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(InsertTextFormat.canParse(obj['insertTextFormat'], reporter))) {
+          reporter.reportError('must be of type InsertTextFormat');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('range');
+      try {
+        if (!obj.containsKey('range')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['range'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(Range.canParse(obj['range'], reporter))) {
+          reporter.reportError('must be of type Range');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('newText');
+      try {
+        if (!obj.containsKey('newText')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['newText'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['newText'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SnippetTextEdit');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SnippetTextEdit && other.runtimeType == SnippetTextEdit) {
+      return insertTextFormat == other.insertTextFormat &&
+          range == other.range &&
+          newText == other.newText &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, insertTextFormat.hashCode);
+    hash = JenkinsSmiHash.combine(hash, range.hashCode);
+    hash = JenkinsSmiHash.combine(hash, newText.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index 215bf08..d3c551b 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -30666,14 +30666,17 @@
         ? OptionalVersionedTextDocumentIdentifier.fromJson(json['textDocument'])
         : null;
     final edits = json['edits']
-        ?.map((item) => TextEdit.canParse(item, nullLspJsonReporter)
-            ? Either2<TextEdit, AnnotatedTextEdit>.t1(
-                item != null ? TextEdit.fromJson(item) : null)
+        ?.map((item) => SnippetTextEdit.canParse(item, nullLspJsonReporter)
+            ? Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>.t1(
+                item != null ? SnippetTextEdit.fromJson(item) : null)
             : (AnnotatedTextEdit.canParse(item, nullLspJsonReporter)
-                ? Either2<TextEdit, AnnotatedTextEdit>.t2(
+                ? Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>.t2(
                     item != null ? AnnotatedTextEdit.fromJson(item) : null)
-                : (throw '''${item} was not one of (TextEdit, AnnotatedTextEdit)''')))
-        ?.cast<Either2<TextEdit, AnnotatedTextEdit>>()
+                : (TextEdit.canParse(item, nullLspJsonReporter)
+                    ? Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>.t3(
+                        item != null ? TextEdit.fromJson(item) : null)
+                    : (throw '''${item} was not one of (SnippetTextEdit, AnnotatedTextEdit, TextEdit)'''))))
+        ?.cast<Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>>()
         ?.toList();
     return TextDocumentEdit(textDocument: textDocument, edits: edits);
   }
@@ -30681,7 +30684,7 @@
   /// The edits to be applied.
   ///  @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the
   /// client capability `workspace.workspaceEdit.changeAnnotationSupport`
-  final List<Either2<TextEdit, AnnotatedTextEdit>> edits;
+  final List<Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>> edits;
 
   /// The text document to change.
   final OptionalVersionedTextDocumentIdentifier textDocument;
@@ -30726,10 +30729,12 @@
           return false;
         }
         if (!((obj['edits'] is List &&
-            (obj['edits'].every((item) => (TextEdit.canParse(item, reporter) ||
-                AnnotatedTextEdit.canParse(item, reporter))))))) {
+            (obj['edits'].every((item) =>
+                (SnippetTextEdit.canParse(item, reporter) ||
+                    AnnotatedTextEdit.canParse(item, reporter) ||
+                    TextEdit.canParse(item, reporter))))))) {
           reporter.reportError(
-              'must be of type List<Either2<TextEdit, AnnotatedTextEdit>>');
+              'must be of type List<Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>>');
           return false;
         }
       } finally {
@@ -30749,8 +30754,9 @@
           listEqual(
               edits,
               other.edits,
-              (Either2<TextEdit, AnnotatedTextEdit> a,
-                      Either2<TextEdit, AnnotatedTextEdit> b) =>
+              (Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit> a,
+                      Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>
+                          b) =>
                   a == b) &&
           true;
     }
@@ -31777,6 +31783,9 @@
     if (AnnotatedTextEdit.canParse(json, nullLspJsonReporter)) {
       return AnnotatedTextEdit.fromJson(json);
     }
+    if (SnippetTextEdit.canParse(json, nullLspJsonReporter)) {
+      return SnippetTextEdit.fromJson(json);
+    }
     final range = json['range'] != null ? Range.fromJson(json['range']) : null;
     final newText = json['newText'];
     return TextEdit(range: range, newText: newText);
diff --git a/pkg/analysis_server/lib/src/lsp/client_capabilities.dart b/pkg/analysis_server/lib/src/lsp/client_capabilities.dart
index 2c16de4..1047961 100644
--- a/pkg/analysis_server/lib/src/lsp/client_capabilities.dart
+++ b/pkg/analysis_server/lib/src/lsp/client_capabilities.dart
@@ -78,6 +78,7 @@
   final Set<SymbolKind> workspaceSymbolKinds;
   final Set<CompletionItemKind> completionItemKinds;
   final Set<InsertTextMode> completionInsertTextModes;
+  final bool experimentalSnippetTextEdit;
 
   LspClientCapabilities(this.raw)
       : applyEdit = raw?.workspace?.applyEdit ?? false,
@@ -125,7 +126,10 @@
         workDoneProgress = raw.window?.workDoneProgress ?? false,
         workspaceSymbolKinds = _listToSet(
             raw?.workspace?.symbol?.symbolKind?.valueSet,
-            defaults: defaultSupportedSymbolKinds);
+            defaults: defaultSupportedSymbolKinds),
+        experimentalSnippetTextEdit =
+            raw.experimental is Map<String, dynamic> &&
+                raw.experimental['snippetTextEdit'] == true;
 
   static Set<MarkupKind> _completionDocumentationFormats(
       ClientCapabilities raw) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
index 6ac4547..581c499 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
@@ -87,7 +87,7 @@
             return fileModifiedError;
           }
 
-          final edit = createWorkspaceEdit(server, change.edits);
+          final edit = createWorkspaceEdit(server, change);
           return await sendWorkspaceEditToClient(edit);
         } on InconsistentAnalysisException {
           return fileModifiedError;
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index f51367f..f7afd25 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -143,7 +143,7 @@
       title: assist.change.message,
       kind: toCodeActionKind(assist.change.id, CodeActionKind.Refactor),
       diagnostics: const [],
-      edit: createWorkspaceEdit(server, assist.change.edits),
+      edit: createWorkspaceEdit(server, assist.change),
     );
   }
 
@@ -156,7 +156,7 @@
       title: fix.change.message,
       kind: toCodeActionKind(fix.change.id, CodeActionKind.QuickFix),
       diagnostics: [diagnostic],
-      edit: createWorkspaceEdit(server, fix.change.edits),
+      edit: createWorkspaceEdit(server, fix.change),
     );
   }
 
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index 3c3ea2c..cafa2b6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -146,7 +146,8 @@
         // a command that the client will call to apply those edits later.
         Command command;
         if (otherFilesChanges.isNotEmpty) {
-          final workspaceEdit = createWorkspaceEdit(server, otherFilesChanges);
+          final workspaceEdit =
+              createPlainWorkspaceEdit(server, otherFilesChanges);
           command = Command(
               title: 'Add import',
               command: Commands.sendWorkspaceEdit,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
index eae5c8c..d1c3aca 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
@@ -187,7 +187,7 @@
         return fileModifiedError;
       }
 
-      final workspaceEdit = createWorkspaceEdit(server, change.edits);
+      final workspaceEdit = createWorkspaceEdit(server, change);
       return success(workspaceEdit);
     });
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
index 2beb369..3d32e86 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
@@ -53,7 +53,7 @@
     }
 
     final change = await refactoring.createChange();
-    final edit = createWorkspaceEdit(server, change.edits);
+    final edit = createWorkspaceEdit(server, change);
 
     return success(edit);
   }
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 9e59ec6..a409c06 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -108,10 +108,12 @@
   return output.join('');
 }
 
+/// Creates a [lsp.WorkspaceEdit] from simple [server.SourceFileEdit]s.
+///
 /// Note: This code will fetch the version of each document being modified so
 /// it's important to call this immediately after computing edits to ensure
 /// the document is not modified before the version number is read.
-lsp.WorkspaceEdit createWorkspaceEdit(
+lsp.WorkspaceEdit createPlainWorkspaceEdit(
     lsp.LspAnalysisServer server, List<server.SourceFileEdit> edits) {
   return toWorkspaceEdit(
       server.clientCapabilities,
@@ -126,6 +128,52 @@
           .toList());
 }
 
+/// Creates a [lsp.WorkspaceEdit] from a [server.SourceChange] that can include
+/// experimental [server.SnippetTextEdit]s if the client has indicated support
+/// for these in the experimental section of their client capabilities.
+///
+/// Note: This code will fetch the version of each document being modified so
+/// it's important to call this immediately after computing edits to ensure
+/// the document is not modified before the version number is read.
+lsp.WorkspaceEdit createWorkspaceEdit(
+    lsp.LspAnalysisServer server, server.SourceChange change) {
+  // In order to return snippets, we must ensure we are only modifying a single
+  // existing file with a single edit and that there is a linked edit group with
+  // only one position and no suggestions.
+  if (!server.clientCapabilities.experimentalSnippetTextEdit ||
+      change.edits.length != 1 ||
+      change.edits.first.fileStamp == -1 || // new file
+      change.edits.first.edits.length != 1 ||
+      change.linkedEditGroups.isEmpty ||
+      change.linkedEditGroups.first.positions.length != 1 ||
+      change.linkedEditGroups.first.suggestions.isNotEmpty) {
+    return createPlainWorkspaceEdit(server, change.edits);
+  }
+
+  // Additionally, the selection must fall within the edit offset.
+  final edit = change.edits.first.edits.first;
+  final selectionOffset = change.linkedEditGroups.first.positions.first.offset;
+  final selectionLength = change.linkedEditGroups.first.length;
+
+  if (selectionOffset < edit.offset ||
+      selectionOffset + selectionLength > edit.offset + edit.length) {
+    return createPlainWorkspaceEdit(server, change.edits);
+  }
+
+  return toWorkspaceEdit(
+      server.clientCapabilities,
+      change.edits
+          .map((e) => FileEditInformation(
+                server.getVersionedDocumentIdentifier(e.file),
+                server.getLineInfo(e.file),
+                e.edits,
+                selectionOffsetRelative: selectionOffset - edit.offset,
+                selectionLength: selectionLength,
+                newFile: e.fileStamp == -1,
+              ))
+          .toList());
+}
+
 lsp.CompletionItemKind declarationKindToCompletionItemKind(
   Set<lsp.CompletionItemKind> supportedCompletionKinds,
   dec.DeclarationKind kind,
@@ -1224,6 +1272,21 @@
   );
 }
 
+lsp.SnippetTextEdit toSnippetTextEdit(
+    LspClientCapabilities capabilities,
+    server.LineInfo lineInfo,
+    server.SourceEdit edit,
+    int selectionOffsetRelative,
+    int selectionLength) {
+  assert(selectionOffsetRelative != null);
+  return lsp.SnippetTextEdit(
+    insertTextFormat: lsp.InsertTextFormat.Snippet,
+    range: toRange(lineInfo, edit.offset, edit.length),
+    newText: buildSnippetStringWithTabStops(
+        edit.replacement, [selectionOffsetRelative, selectionLength ?? 0]),
+  );
+}
+
 ErrorOr<server.SourceRange> toSourceRange(
     server.LineInfo lineInfo, Range range) {
   if (range == null) {
@@ -1247,14 +1310,33 @@
   return success(server.SourceRange(startOffset, endOffset - startOffset));
 }
 
-lsp.TextDocumentEdit toTextDocumentEdit(FileEditInformation edit) {
+lsp.TextDocumentEdit toTextDocumentEdit(
+    LspClientCapabilities capabilities, FileEditInformation edit) {
   return lsp.TextDocumentEdit(
-    textDocument: edit.doc,
-    edits: edit.edits
-        .map((e) => Either2<lsp.TextEdit, lsp.AnnotatedTextEdit>.t1(
-            toTextEdit(edit.lineInfo, e)))
-        .toList(),
-  );
+      textDocument: edit.doc,
+      edits: edit.edits
+          .map((e) => toTextDocumentEditEdit(capabilities, edit.lineInfo, e,
+              selectionOffsetRelative: edit.selectionOffsetRelative,
+              selectionLength: edit.selectionLength))
+          .toList());
+}
+
+Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit, lsp.TextEdit>
+    toTextDocumentEditEdit(
+  LspClientCapabilities capabilities,
+  server.LineInfo lineInfo,
+  server.SourceEdit edit, {
+  int selectionOffsetRelative,
+  int selectionLength,
+}) {
+  if (!capabilities.experimentalSnippetTextEdit ||
+      selectionOffsetRelative == null) {
+    return Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit, lsp.TextEdit>.t3(
+        toTextEdit(lineInfo, edit));
+  }
+  return Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit, lsp.TextEdit>.t1(
+      toSnippetTextEdit(capabilities, lineInfo, edit, selectionOffsetRelative,
+          selectionLength));
 }
 
 lsp.TextEdit toTextEdit(server.LineInfo lineInfo, server.SourceEdit edit) {
@@ -1286,7 +1368,7 @@
         changes.add(createUnion);
       }
 
-      final textDocEdit = toTextDocumentEdit(edit);
+      final textDocEdit = toTextDocumentEdit(capabilities, edit);
       final textDocEditUnion = Either4<lsp.TextDocumentEdit, lsp.CreateFile,
           lsp.RenameFile, lsp.DeleteFile>.t1(textDocEdit);
       changes.add(textDocEditUnion);
diff --git a/pkg/analysis_server/lib/src/lsp/source_edits.dart b/pkg/analysis_server/lib/src/lsp/source_edits.dart
index e1cc013..d97576f 100644
--- a/pkg/analysis_server/lib/src/lsp/source_edits.dart
+++ b/pkg/analysis_server/lib/src/lsp/source_edits.dart
@@ -307,6 +307,12 @@
   final List<server.SourceEdit> edits;
   final bool newFile;
 
+  /// The selection offset, relative to the edit.
+  final int selectionOffsetRelative;
+  final int selectionLength;
+
   FileEditInformation(this.doc, this.lineInfo, this.edits,
-      {this.newFile = false});
+      {this.newFile = false,
+      this.selectionOffsetRelative,
+      this.selectionLength});
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 30182b7..5f512c5 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -38,7 +38,6 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/util/file_paths.dart' as file_paths;
@@ -338,7 +337,7 @@
   @override
   bool get inConstantContext {
     var entity = target.entity;
-    return entity is ExpressionImpl && entity.inConstantContext;
+    return entity is Expression && entity.inConstantContext;
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
index c8c935b..b2d6d98 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/source/source_range.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer_plugin/utilities/assist/assist.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/range_factory.dart';
@@ -143,8 +142,7 @@
 
   @override
   List<String> get _leadingLines {
-    var keyword =
-        (widgetExpr as ExpressionImpl).inConstantContext ? '' : ' const';
+    var keyword = widgetExpr.inConstantContext ? '' : ' const';
     return ['padding:$keyword EdgeInsets.all(8.0),'];
   }
 
diff --git a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
index 03def9f..b70a2c2 100644
--- a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
@@ -2,7 +2,9 @@
 // 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:analysis_server/lsp_protocol/protocol_custom_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -16,6 +18,15 @@
 
 @reflectiveTest
 class AssistsCodeActionsTest extends AbstractCodeActionsTest {
+  @override
+  void setUp() {
+    super.setUp();
+    writePackageConfig(
+      projectFolderPath,
+      flutter: true,
+    );
+  }
+
   Future<void> test_appliesCorrectEdits_withDocumentChangesSupport() async {
     // This code should get an assist to add a show combinator.
     const content = '''
@@ -107,4 +118,171 @@
         await getCodeActions(pubspecFileUri.toString(), range: startOfDocRange);
     expect(codeActions, isEmpty);
   }
+
+  Future<void> test_snippetTextEdits_supported() async {
+    // This tests experimental support for including Snippets in TextEdits.
+    // https://github.com/rust-analyzer/rust-analyzer/blob/b35559a2460e7f0b2b79a7029db0c5d4e0acdb44/docs/dev/lsp-extensions.md#snippet-textedit
+    //
+    // This allows setting the cursor position/selection in TextEdits included
+    // in CodeActions, for example Flutter's "Wrap with widget" assist that
+    // should select the text "widget".
+
+    const content = '''
+    import 'package:flutter/widgets.dart';
+    build() {
+      return Container(
+        child: Row(
+          children: [^
+            Text('111'),
+            Text('222'),
+            Container(),
+          ],
+        ),
+      );
+    }
+    ''';
+
+    // For testing, the snippet will be inserted literally into the text, as
+    // this requires some magic on the client. The expected text should therefore
+    // contain the snippets in the standard format.
+    const expectedContent = r'''
+    import 'package:flutter/widgets.dart';
+    build() {
+      return Container(
+        child: Row(
+          children: [
+            ${0:widget}(
+              children: [
+                Text('111'),
+                Text('222'),
+                Container(),
+              ],
+            ),
+          ],
+        ),
+      );
+    }
+    ''';
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+      workspaceCapabilities:
+          withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
+      experimentalCapabilities: {
+        'snippetTextEdit': true,
+      },
+    );
+
+    final marker = positionFromMarker(content);
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: Range(start: marker, end: marker));
+    final assist = findEditAction(codeActions,
+        CodeActionKind('refactor.flutter.wrap.generic'), 'Wrap with widget...');
+
+    // Ensure the edit came back, and using documentChanges.
+    expect(assist, isNotNull);
+    expect(assist.edit.documentChanges, isNotNull);
+    expect(assist.edit.changes, isNull);
+
+    // Ensure applying the changes will give us the expected content.
+    final contents = {
+      mainFilePath: withoutMarkers(content),
+    };
+    applyDocumentChanges(contents, assist.edit.documentChanges);
+    expect(contents[mainFilePath], equals(expectedContent));
+
+    // Also ensure there was a single edit that was correctly marked
+    // as a SnippetTextEdit.
+    final textEdits = _extractTextDocumentEdits(assist.edit.documentChanges)
+        .expand((tde) => tde.edits)
+        .map((edit) => edit.map(
+              (e) => e,
+              (e) => throw 'Expected SnippetTextEdit, got AnnotatedTextEdit',
+              (e) => throw 'Expected SnippetTextEdit, got TextEdit',
+            ))
+        .toList();
+    expect(textEdits, hasLength(1));
+    expect(textEdits.first.insertTextFormat, equals(InsertTextFormat.Snippet));
+  }
+
+  Future<void> test_snippetTextEdits_unsupported() async {
+    // This tests experimental support for including Snippets in TextEdits
+    // is not active when the client capabilities do not advertise support for it.
+    // https://github.com/rust-analyzer/rust-analyzer/blob/b35559a2460e7f0b2b79a7029db0c5d4e0acdb44/docs/dev/lsp-extensions.md#snippet-textedit
+
+    const content = '''
+    import 'package:flutter/widgets.dart';
+    build() {
+      return Container(
+        child: Row(
+          children: [^
+            Text('111'),
+            Text('222'),
+            Container(),
+          ],
+        ),
+      );
+    }
+    ''';
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+      workspaceCapabilities:
+          withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
+    );
+
+    final marker = positionFromMarker(content);
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: Range(start: marker, end: marker));
+    final assist = findEditAction(codeActions,
+        CodeActionKind('refactor.flutter.wrap.generic'), 'Wrap with widget...');
+
+    // Ensure the edit came back, and using documentChanges.
+    expect(assist, isNotNull);
+    expect(assist.edit.documentChanges, isNotNull);
+    expect(assist.edit.changes, isNull);
+
+    // Extract just TextDocumentEdits, create/rename/delete are not relevant.
+    final textDocumentEdits =
+        _extractTextDocumentEdits(assist.edit.documentChanges);
+    final textEdits = textDocumentEdits
+        .expand((tde) => tde.edits)
+        .map((edit) => edit.map((e) => e, (e) => e, (e) => e))
+        .toList();
+
+    // Ensure the edit does _not_ have a format of Snippet, nor does it include
+    // any $ characters that would indicate snippet text.
+    for (final edit in textEdits) {
+      expect(edit, isNot(TypeMatcher<SnippetTextEdit>()));
+      expect(edit.newText, isNot(contains(r'$')));
+    }
+  }
+
+  List<TextDocumentEdit> _extractTextDocumentEdits(
+          Either2<
+                  List<TextDocumentEdit>,
+                  List<
+                      Either4<TextDocumentEdit, CreateFile, RenameFile,
+                          DeleteFile>>>
+              documentChanges) =>
+      documentChanges.map(
+        // Already TextDocumentEdits
+        (edits) => edits,
+        // Extract TextDocumentEdits from union of resource changes
+        (changes) => changes
+            .map(
+              (change) => change.map(
+                (textDocEdit) => textDocEdit,
+                (create) => null,
+                (rename) => null,
+                (delete) => null,
+              ),
+            )
+            .where((e) => e != null)
+            .toList(),
+      );
 }
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 2cf21e5..dd35465 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -650,10 +650,10 @@
     });
   }
 
-  String applyTextEdit(
-      String content, Either2<TextEdit, AnnotatedTextEdit> change) {
+  String applyTextEdit(String content,
+      Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit> change) {
     // Both sites of the union can cast to TextEdit.
-    final edit = change.map((e) => e, (e) => e);
+    final edit = change.map((e) => e, (e) => e, (e) => e);
     final startPos = edit.range.start;
     final endPos = edit.range.end;
     final lineInfo = LineInfo.fromContent(content);
@@ -714,8 +714,8 @@
       );
 
     for (final change in sortedChanges) {
-      newContent = applyTextEdit(
-          newContent, Either2<TextEdit, AnnotatedTextEdit>.t1(change));
+      newContent = applyTextEdit(newContent,
+          Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>.t3(change));
     }
 
     return newContent;
@@ -1217,6 +1217,7 @@
     TextDocumentClientCapabilities textDocumentCapabilities,
     ClientCapabilitiesWorkspace workspaceCapabilities,
     ClientCapabilitiesWindow windowCapabilities,
+    Map<String, Object> experimentalCapabilities,
     Map<String, Object> initializationOptions,
     bool throwOnFailure = true,
     bool allowEmptyRootUri = false,
@@ -1225,6 +1226,7 @@
       workspace: workspaceCapabilities,
       textDocument: textDocumentCapabilities,
       window: windowCapabilities,
+      experimental: experimentalCapabilities,
     );
 
     // Handle any standard incoming requests that aren't test-specific, for example
diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
index 782aa26..ace8ef1 100644
--- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart
+++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
@@ -272,6 +272,26 @@
       ],
       baseType: 'CompletionItemResolutionInfo',
     ),
+    // Custom types for experimental SnippetTextEdits
+    // https://github.com/rust-analyzer/rust-analyzer/blob/b35559a2460e7f0b2b79a7029db0c5d4e0acdb44/docs/dev/lsp-extensions.md#snippet-textedit
+    interface(
+      'SnippetTextEdit',
+      [
+        field('insertTextFormat', type: 'InsertTextFormat'),
+      ],
+      baseType: 'TextEdit',
+    ),
+    TypeAlias(
+      null,
+      Token.identifier('TextDocumentEditEdits'),
+      ArrayType(
+        UnionType([
+          Type.identifier('SnippetTextEdit'),
+          Type.identifier('AnnotatedTextEdit'),
+          Type.identifier('TextEdit'),
+        ]),
+      ),
+    )
   ];
   return customTypes;
 }
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript.dart b/pkg/analysis_server/tool/lsp_spec/typescript.dart
index 575d66e..801b093 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript.dart
@@ -124,6 +124,9 @@
     },
     'ServerCapabilities': {
       'changeNotifications': 'bool',
+    },
+    'TextDocumentEdit': {
+      'edits': 'TextDocumentEditEdits',
     }
   };
 
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index d44c693..8b10921 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.3.0-dev
+* Added `Expression.inConstantContext` to API.
+* Updated documentation comments for some getters that don't return `null`.
+
 ## 1.2.0
 * Deprecated all setters in API of AST. Use `parseString()` instead.
 * `AnalysisSession.getErrors()` does not return `null`, check its `state`.
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 64526cc..41b1d1c 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -2144,6 +2144,29 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class Expression implements CollectionElement {
+  /// An expression _e_ is said to _occur in a constant context_,
+  /// * if _e_ is an element of a constant list literal, or a key or value of an
+  ///   entry of a constant map literal.
+  /// * if _e_ is an actual argument of a constant object expression or of a
+  ///   metadata annotation.
+  /// * if _e_ is the initializing expression of a constant variable
+  ///   declaration.
+  /// * if _e_ is a switch case expression.
+  /// * if _e_ is an immediate subexpression of an expression _e1_ which occurs
+  ///   in a constant context, unless _e1_ is a `throw` expression or a function
+  ///   literal.
+  ///
+  /// This roughly means that everything which is inside a syntactically
+  /// constant expression is in a constant context. A `throw` expression is
+  /// currently not allowed in a constant expression, but extensions affecting
+  /// that status may be considered. A similar situation arises for function
+  /// literals.
+  ///
+  /// Note that the default value of an optional formal parameter is _not_ a
+  /// constant context. This choice reserves some freedom to modify the
+  /// semantics of default values.
+  bool get inConstantContext;
+
   /// Return `true` if this expression is syntactically valid for the LHS of an
   /// [AssignmentExpression].
   bool get isAssignable;
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 85778f6..edfcd2e 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -531,8 +531,8 @@
   /// element, e.g. a synthetic property accessor), return itself.
   Element? get declaration;
 
-  /// Return the display name of this element, or `null` if this element does
-  /// not have a name.
+  /// Return the display name of this element, possibly the empty string if
+  /// this element does not have a name.
   ///
   /// In most cases the name and the display name are the same. Differences
   /// though are cases such as setters where the name of some setter `set f(x)`
@@ -1041,9 +1041,7 @@
   Element get enclosingElement;
 
   /// Return `true` if this executable element did not have an explicit return
-  /// type specified for it in the original source. Note that if there was no
-  /// explicit return type, and if the element model is fully populated, then
-  /// the [returnType] will not be `null`.
+  /// type specified for it in the original source.
   bool get hasImplicitReturnType;
 
   /// Return `true` if this executable element is abstract. Executable elements
@@ -1231,9 +1229,7 @@
   /// element.
   List<ParameterElement> get parameters;
 
-  /// Return the return type defined by this element. If the element model is
-  /// fully populated, then the [returnType] will not be `null`, even if no
-  /// return type was explicitly specified.
+  /// Return the return type defined by this element.
   DartType get returnType;
 
   /// Return the type defined by this element.
@@ -1874,9 +1870,7 @@
   /// > implicitly static.
   bool get isStatic;
 
-  /// Return the declared type of this variable, or `null` if the variable did
-  /// not have a declared type (such as if it was declared using the keyword
-  /// 'var').
+  /// Return the declared type of this variable.
   DartType get type;
 
   /// Return a representation of the value of this variable, forcing the value
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index e38573d..575cac0 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3490,27 +3490,7 @@
   @override
   DartType? staticType;
 
-  /// An expression _e_ is said to _occur in a constant context_,
-  /// * if _e_ is an element of a constant list literal, or a key or value of an
-  ///   entry of a constant map literal.
-  /// * if _e_ is an actual argument of a constant object expression or of a
-  ///   metadata annotation.
-  /// * if _e_ is the initializing expression of a constant variable
-  ///   declaration.
-  /// * if _e_ is a switch case expression.
-  /// * if _e_ is an immediate subexpression of an expression _e1_ which occurs
-  ///   in a constant context, unless _e1_ is a `throw` expression or a function
-  ///   literal.
-  ///
-  /// This roughly means that everything which is inside a syntactically
-  /// constant expression is in a constant context. A `throw` expression is
-  /// currently not allowed in a constant expression, but extensions affecting
-  /// that status may be considered. A similar situation arises for function
-  /// literals.
-  ///
-  /// Note that the default value of an optional formal parameter is _not_ a
-  /// constant context. This choice reserves some freedom to modify the
-  /// semantics of default values.
+  @override
   bool get inConstantContext {
     AstNode child = this;
     while (child is Expression ||
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 14c858c..cb24558 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -617,6 +617,10 @@
       });
     }
 
+    if (isThirdParty) {
+      options.hint = false;
+    }
+
     return options;
   }
 
diff --git a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
index 336b180..e0c34fd 100644
--- a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
+++ b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:pub_semver/pub_semver.dart';
@@ -113,8 +112,7 @@
 
   @override
   void visitAsExpression(AsExpression node) {
-    if (checkConstantUpdate2018 &&
-        (node as AsExpressionImpl).inConstantContext) {
+    if (checkConstantUpdate2018 && node.inConstantContext) {
       _errorReporter.reportErrorForNode(
           HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT, node);
     }
@@ -131,15 +129,14 @@
       } else if ((operatorType == TokenType.AMPERSAND ||
               operatorType == TokenType.BAR ||
               operatorType == TokenType.CARET) &&
-          (node as BinaryExpressionImpl).inConstantContext) {
+          node.inConstantContext) {
         if (node.leftOperand.typeOrThrow.isDartCoreBool) {
           _errorReporter.reportErrorForToken(
               HintCode.SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT,
               node.operator,
               [node.operator.lexeme]);
         }
-      } else if (operatorType == TokenType.EQ_EQ &&
-          (node as BinaryExpressionImpl).inConstantContext) {
+      } else if (operatorType == TokenType.EQ_EQ && node.inConstantContext) {
         bool primitive(Expression node) {
           DartType type = node.typeOrThrow;
           return type.isDartCoreBool ||
@@ -204,8 +201,7 @@
 
   @override
   void visitIsExpression(IsExpression node) {
-    if (checkConstantUpdate2018 &&
-        (node as IsExpressionImpl).inConstantContext) {
+    if (checkConstantUpdate2018 && node.inConstantContext) {
       _errorReporter.reportErrorForNode(
           HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT, node);
     }
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 02e11bc..e4fea47 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -21,14 +21,6 @@
     show CompileTimeErrorCode, StrongModeCode;
 import 'package:analyzer/src/task/inference_error.dart';
 
-DartType _elementType(Element? e) {
-  if (e == null) {
-    // Malformed code - just return dynamic.
-    return DynamicTypeImpl.instance;
-  }
-  return (e as dynamic).type;
-}
-
 Element? _getKnownElement(Expression expression) {
   if (expression is ParenthesizedExpression) {
     return _getKnownElement(expression.expression);
@@ -86,7 +78,7 @@
         // so no need to insert an error for this here.
         continue;
       }
-      checkArgument(arg, _elementType(element));
+      checkArgument(arg, element.type);
     }
   }
 
@@ -244,7 +236,6 @@
     node.visitChildren(this);
   }
 
-  // Check invocations
   /// Check constructor declaration to ensure correct super call placement.
   @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
@@ -270,8 +261,9 @@
   void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
     var field = node.fieldName;
     var element = field.staticElement;
-    DartType staticType = _elementType(element);
-    checkAssignment(node.expression, staticType);
+    if (element != null) {
+      checkAssignment(node.expression, _elementType(element));
+    }
     node.visitChildren(this);
   }
 
@@ -279,9 +271,10 @@
   void visitDefaultFormalParameter(DefaultFormalParameter node) {
     // Check that defaults have the proper subtype.
     var parameter = node.parameter;
-    var parameterType = _elementType(parameter.declaredElement);
     var defaultValue = node.defaultValue;
-    if (defaultValue != null) {
+    var element = parameter.declaredElement;
+    if (defaultValue != null && element != null) {
+      var parameterType = _elementType(element);
       checkAssignment(defaultValue, parameterType);
     }
 
@@ -363,7 +356,7 @@
     var arguments = node.argumentList;
     var element = node.constructorName.staticElement;
     if (element != null) {
-      var type = _elementType(element) as FunctionType;
+      var type = element.type;
       checkArgumentList(arguments, type);
     }
     node.visitChildren(this);
@@ -709,7 +702,7 @@
     FunctionType functionType;
     var parent = body.parent;
     if (parent is Declaration) {
-      functionType = _elementType(parent.declaredElement) as FunctionType;
+      functionType = _elementType(parent.declaredElement!) as FunctionType;
     } else {
       assert(parent is FunctionExpression);
       functionType = (parent as FunctionExpression).staticType as FunctionType;
@@ -974,6 +967,21 @@
           to: loopVariableElement.type, from: elementType);
     }
   }
+
+  static DartType _elementType(Element e) {
+    if (e is ConstructorElement) {
+      return e.type;
+    } else if (e is FieldElement) {
+      return e.type;
+    } else if (e is MethodElement) {
+      return e.type;
+    } else if (e is ParameterElement) {
+      return e.type;
+    } else if (e is PropertyAccessorElement) {
+      return e.type;
+    }
+    throw StateError('${e.runtimeType} is unhandled type');
+  }
 }
 
 class _TopLevelInitializerValidator extends RecursiveAstVisitor<void> {
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 5be43d5..325dd01 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 1.2.0
+version: 1.3.0-dev
 description: This package provides a library that performs static analysis of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
 
diff --git a/pkg/analyzer/test/src/dart/micro/file_resolution.dart b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
index 67ea722..55d7031 100644
--- a/pkg/analyzer/test/src/dart/micro/file_resolution.dart
+++ b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
@@ -65,7 +65,8 @@
 
   @override
   Future<ResolvedUnitResult> resolveFile(String path) async {
-    return fileResolver.resolve(path: path);
+    result = fileResolver.resolve(path: path);
+    return result;
   }
 
   @override
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 5decd67..15b8ebd 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -481,6 +481,15 @@
     ]);
   }
 
+  test_hint_in_third_party() async {
+    var aPath = convertPath('/workspace/third_party/dart/aaa/lib/a.dart');
+    newFile(aPath, content: r'''
+import 'dart:math';
+''');
+    await resolveFile(aPath);
+    assertNoErrorsInResult();
+  }
+
   test_linkLibraries_getErrors() {
     addTestFile(r'''
 var a = b;
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
index 5f103da..ec6150f 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
@@ -6,7 +6,6 @@
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../dart/resolution/context_collection_resolution.dart';
 import 'sdk_constraint_verifier_support.dart';
 
 main() {
@@ -22,18 +21,6 @@
       '${ExperimentStatus.currentVersion.major}.'
       '${ExperimentStatus.currentVersion.minor}';
 
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageAnalysisOptionsFile(
-      AnalysisOptionsFileConfig(
-        experiments: [
-          EnableString.triple_shift,
-        ],
-      ),
-    );
-  }
-
   test_const_equals() async {
     // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
     //  UNDEFINED_OPERATOR when triple_shift is enabled by default.
@@ -75,7 +62,7 @@
 
   test_nonConst_equals() async {
     // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
-    //  UNDEFINED_OPERATOR when constant update is enabled by default.
+    //  UNDEFINED_OPERATOR when triple_shift is enabled by default.
     await verifyVersion('2.5.0', '''
 var a = 42 >>> 3;
 ''', expectedErrors: [
@@ -85,7 +72,7 @@
 
   test_nonConst_lessThan() async {
     // TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
-    //  UNDEFINED_OPERATOR when constant update is enabled by default.
+    //  UNDEFINED_OPERATOR when triple_shift is enabled by default.
     await verifyVersion('2.2.0', '''
 var a = 42 >>> 3;
 ''', expectedErrors: [
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index e921146..571e8ce 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -20,7 +20,6 @@
 import 'common_elements.dart' show ElementEnvironment;
 import 'deferred_load.dart' show DeferredLoadTask, OutputUnitData;
 import 'diagnostics/code_location.dart';
-import 'diagnostics/diagnostic_listener.dart' show DiagnosticReporter;
 import 'diagnostics/messages.dart' show Message, MessageTemplate;
 import 'dump_info.dart' show DumpInfoTask;
 import 'elements/entities.dart';
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index 910485e9..a59366a 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -10,7 +10,6 @@
 import '../common.dart';
 import '../diagnostics/invariant.dart' show DEBUG_MODE;
 import '../util/util.dart';
-import 'trace.dart';
 
 export 'debug_collection.dart';
 export 'expensive_map.dart';
diff --git a/pkg/compiler/lib/src/ir/debug.dart b/pkg/compiler/lib/src/ir/debug.dart
index bb24302..3b9e11a 100644
--- a/pkg/compiler/lib/src/ir/debug.dart
+++ b/pkg/compiler/lib/src/ir/debug.dart
@@ -7,7 +7,6 @@
 library kernel.debug;
 
 import 'package:kernel/ast.dart';
-import 'package:kernel/visitor.dart';
 
 import '../util/util.dart' show Indentation, Tagging;
 
diff --git a/pkg/compiler/lib/src/js_backend/annotations.dart b/pkg/compiler/lib/src/js_backend/annotations.dart
index 8955a8d..f702ca37 100644
--- a/pkg/compiler/lib/src/js_backend/annotations.dart
+++ b/pkg/compiler/lib/src/js_backend/annotations.dart
@@ -7,8 +7,6 @@
 import 'package:kernel/ast.dart' as ir;
 
 import '../common.dart';
-import '../diagnostics/diagnostic_listener.dart';
-import '../diagnostics/messages.dart';
 import '../elements/entities.dart';
 import '../ir/annotations.dart';
 import '../ir/util.dart';
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 4d0546c..9fea86f 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -18,7 +18,6 @@
 import '../js_emitter/code_emitter_task.dart';
 import '../js_model/type_recipe.dart' show TypeExpressionRecipe;
 import '../options.dart';
-import 'field_analysis.dart' show JFieldAnalysis;
 import 'namer.dart';
 import 'runtime_types_new.dart' show RecipeEncoder;
 import 'runtime_types_resolution.dart';
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index fee1573..9596fd0 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -11,7 +11,6 @@
 import '../common/backend_api.dart' show ImpactTransformer;
 import '../common/codegen.dart' show CodegenImpact;
 import '../common/resolution.dart' show ResolutionImpact;
-import '../common_elements.dart' show ElementEnvironment;
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 44b6cd1..d63ee32 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -15,7 +15,6 @@
 import '../ir/closure.dart';
 import '../ir/static_type_provider.dart';
 import '../ir/util.dart';
-import '../js_model/closure.dart' show JRecordField;
 import '../js_model/elements.dart' show JGeneratorBody;
 import '../native/behavior.dart';
 import '../serialization/serialization.dart';
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 868ef6f..66f8efc 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -10,7 +10,6 @@
 import '../common/names.dart';
 import '../common_elements.dart' show JCommonElements, JElementEnvironment;
 import '../deferred_load.dart';
-import '../diagnostics/diagnostic_listener.dart';
 import '../elements/entities.dart';
 import '../elements/entity_utils.dart' as utils;
 import '../elements/names.dart';
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index f8b1da3..9a7fe7f 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -11,7 +11,6 @@
 
 import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
 
-import '../compiler.dart' as api show Diagnostic;
 import '../compiler_new.dart' as api;
 import '../compiler_new.dart';
 import 'colors.dart' as colors;
diff --git a/pkg/compiler/test/analyses/analysis_helper.dart b/pkg/compiler/test/analyses/analysis_helper.dart
index fb096c3..43fb4db 100644
--- a/pkg/compiler/test/analyses/analysis_helper.dart
+++ b/pkg/compiler/test/analyses/analysis_helper.dart
@@ -11,9 +11,6 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
-import 'package:compiler/src/diagnostics/messages.dart';
-import 'package:compiler/src/diagnostics/source_span.dart';
 import 'package:compiler/src/ir/constants.dart';
 import 'package:compiler/src/ir/scope.dart';
 import 'package:compiler/src/ir/static_type.dart';
diff --git a/pkg/compiler/test/closure/closure_test.dart b/pkg/compiler/test/closure/closure_test.dart
index 231025d..78c02dc 100644
--- a/pkg/compiler/test/closure/closure_test.dart
+++ b/pkg/compiler/test/closure/closure_test.dart
@@ -11,7 +11,6 @@
 import 'package:compiler/src/closure.dart';
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/js_model/element_map.dart';
 import 'package:compiler/src/js_model/js_world.dart';
diff --git a/pkg/compiler/test/codegen/expect_annotations_test.dart b/pkg/compiler/test/codegen/expect_annotations_test.dart
index a3df294..5587f3f 100644
--- a/pkg/compiler/test/codegen/expect_annotations_test.dart
+++ b/pkg/compiler/test/codegen/expect_annotations_test.dart
@@ -10,7 +10,6 @@
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/inferrer/abstract_value_domain.dart';
-import 'package:compiler/src/inferrer/types.dart';
 import 'package:compiler/src/world.dart' show JClosedWorld;
 import '../inference/type_mask_test_helper.dart';
 import '../helpers/memory_compiler.dart';
diff --git a/pkg/compiler/test/deferred/closures_test.dart b/pkg/compiler/test/deferred/closures_test.dart
index 5969125..c672c81 100644
--- a/pkg/compiler/test/deferred/closures_test.dart
+++ b/pkg/compiler/test/deferred/closures_test.dart
@@ -11,7 +11,6 @@
 import 'package:expect/expect.dart';
 
 import '../helpers/memory_compiler.dart';
-import '../helpers/output_collector.dart';
 
 void main() {
   asyncTest(() async {
diff --git a/pkg/compiler/test/deferred/constant_emission_test_helper.dart b/pkg/compiler/test/deferred/constant_emission_test_helper.dart
index ce54b1b..d8fc00a 100644
--- a/pkg/compiler/test/deferred/constant_emission_test_helper.dart
+++ b/pkg/compiler/test/deferred/constant_emission_test_helper.dart
@@ -7,7 +7,6 @@
 // Test that the additional runtime type support is output to the right
 // Files when using deferred loading.
 
-import 'package:compiler/compiler_new.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/constants/values.dart';
 import 'package:compiler/src/deferred_load.dart';
@@ -17,7 +16,6 @@
 import 'package:compiler/src/util/util.dart';
 import 'package:expect/expect.dart';
 import '../helpers/memory_compiler.dart';
-import '../helpers/output_collector.dart';
 import '../helpers/program_lookup.dart';
 
 class OutputUnitDescriptor {
diff --git a/pkg/compiler/test/deferred/emit_type_checks_test.dart b/pkg/compiler/test/deferred/emit_type_checks_test.dart
index 38150fc..d4184ad8 100644
--- a/pkg/compiler/test/deferred/emit_type_checks_test.dart
+++ b/pkg/compiler/test/deferred/emit_type_checks_test.dart
@@ -13,7 +13,6 @@
 import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:expect/expect.dart';
 import '../helpers/memory_compiler.dart';
-import '../helpers/output_collector.dart';
 
 void main() {
   runTest() async {
diff --git a/pkg/compiler/test/equivalence/id_testing_test.dart b/pkg/compiler/test/equivalence/id_testing_test.dart
index ff453fe..5789c7c 100644
--- a/pkg/compiler/test/equivalence/id_testing_test.dart
+++ b/pkg/compiler/test/equivalence/id_testing_test.dart
@@ -5,7 +5,6 @@
 // @dart = 2.7
 
 import 'dart:io';
-import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
diff --git a/pkg/compiler/test/helpers/compiler_helper.dart b/pkg/compiler/test/helpers/compiler_helper.dart
index 8faa745..514b1ca 100644
--- a/pkg/compiler/test/helpers/compiler_helper.dart
+++ b/pkg/compiler/test/helpers/compiler_helper.dart
@@ -17,7 +17,6 @@
 import 'package:expect/expect.dart';
 import 'package:_fe_analyzer_shared/src/util/link.dart' show Link;
 import 'memory_compiler.dart';
-import 'output_collector.dart';
 
 export 'package:compiler/src/diagnostics/messages.dart';
 export 'package:compiler/src/diagnostics/source_span.dart';
diff --git a/pkg/compiler/test/helpers/d8_helper.dart b/pkg/compiler/test/helpers/d8_helper.dart
index dae47ad..d02ff9e 100644
--- a/pkg/compiler/test/helpers/d8_helper.dart
+++ b/pkg/compiler/test/helpers/d8_helper.dart
@@ -11,7 +11,6 @@
 import 'dart:async';
 import 'dart:io';
 
-import 'package:compiler/compiler_new.dart';
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/dart2js.dart' as dart2js;
 import 'package:_fe_analyzer_shared/src/util/filenames.dart';
diff --git a/pkg/compiler/test/jumps/jump_test.dart b/pkg/compiler/test/jumps/jump_test.dart
index b848bd7..e483cba 100644
--- a/pkg/compiler/test/jumps/jump_test.dart
+++ b/pkg/compiler/test/jumps/jump_test.dart
@@ -8,7 +8,6 @@
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/elements/jumps.dart';
 import 'package:compiler/src/js_model/element_map.dart';
diff --git a/pkg/compiler/test/model/cfe_constant_test.dart b/pkg/compiler/test/model/cfe_constant_test.dart
index 4ae3771..d9dfbf0 100644
--- a/pkg/compiler/test/model/cfe_constant_test.dart
+++ b/pkg/compiler/test/model/cfe_constant_test.dart
@@ -5,7 +5,6 @@
 // @dart = 2.7
 
 import 'dart:io';
-import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
diff --git a/pkg/compiler/test/sourcemaps/helpers/sourcemap_helper.dart b/pkg/compiler/test/sourcemaps/helpers/sourcemap_helper.dart
index f5e0509..cc8df9a 100644
--- a/pkg/compiler/test/sourcemaps/helpers/sourcemap_helper.dart
+++ b/pkg/compiler/test/sourcemaps/helpers/sourcemap_helper.dart
@@ -22,7 +22,6 @@
 import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/source_file_provider.dart';
 import '../../helpers/memory_compiler.dart';
-import '../../helpers/output_collector.dart';
 
 class SourceFileSink implements OutputSink {
   final String filename;
diff --git a/pkg/compiler/test/sourcemaps/stacktrace_test.dart b/pkg/compiler/test/sourcemaps/stacktrace_test.dart
index 6785cc0..7468227 100644
--- a/pkg/compiler/test/sourcemaps/stacktrace_test.dart
+++ b/pkg/compiler/test/sourcemaps/stacktrace_test.dart
@@ -9,7 +9,6 @@
 
 import 'package:args/args.dart';
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/compiler_new.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/dart2js.dart' as entry;
 
diff --git a/pkg/compiler/test/sourcemaps/stepping_test.dart b/pkg/compiler/test/sourcemaps/stepping_test.dart
index 28712e6..c6a0504 100644
--- a/pkg/compiler/test/sourcemaps/stepping_test.dart
+++ b/pkg/compiler/test/sourcemaps/stepping_test.dart
@@ -10,7 +10,6 @@
 import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
 import 'package:args/args.dart';
 import 'package:async_helper/async_helper.dart';
-import 'package:compiler/compiler_new.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/dart2js.dart' as entry;
 import 'package:expect/expect.dart';
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index ec0a9bb..45d2b4d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -1009,6 +1009,8 @@
     ExecutionStatus status = statement.accept(statementEvaluator);
     if (status is ReturnStatus) {
       return status.value;
+    } else if (status is AbortStatus) {
+      return status.error;
     }
     return createInvalidExpressionConstant(statement,
         'No valid constant returned from the execution of $statement.');
@@ -3342,7 +3344,7 @@
   @override
   ExecutionStatus visitIfStatement(IfStatement node) {
     Constant condition = evaluate(node.condition);
-    if (condition is AbortConstant) return new ReturnStatus(condition);
+    if (condition is AbortConstant) return new AbortStatus(condition);
     if (condition is BoolConstant) {
       if (condition.value) {
         return node.then.accept(this);
@@ -3352,7 +3354,7 @@
         return const ProceedStatus();
       }
     } else {
-      return new ReturnStatus(exprEvaluator.createErrorConstant(
+      return new AbortStatus(exprEvaluator.createErrorConstant(
           node.condition,
           templateConstEvalInvalidType.withArguments(
               condition,
@@ -3365,7 +3367,7 @@
   @override
   ExecutionStatus visitExpressionStatement(ExpressionStatement node) {
     Constant value = evaluate(node.expression);
-    if (value is AbortConstant) return new ReturnStatus(value);
+    if (value is AbortConstant) return new AbortStatus(value);
     return const ProceedStatus();
   }
 
@@ -3376,7 +3378,7 @@
   @override
   ExecutionStatus visitVariableDeclaration(VariableDeclaration node) {
     Constant value = evaluate(node.initializer);
-    if (value is AbortConstant) return new ReturnStatus(value);
+    if (value is AbortConstant) return new AbortStatus(value);
     exprEvaluator.env.addVariableValue(node, value);
     return const ProceedStatus();
   }
@@ -3549,6 +3551,12 @@
   ReturnStatus(this.value);
 }
 
+/// Status with an exception or error that the statement has thrown.
+class AbortStatus extends ExecutionStatus {
+  final AbortConstant error;
+  AbortStatus(this.error);
+}
+
 /// An intermediate result that is used within the [ConstantEvaluator].
 class IntermediateValue implements Constant {
   dynamic value;
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart
new file mode 100644
index 0000000..fb50083
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart
@@ -0,0 +1,3 @@
+main() {
+  if (n is int or
+}
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.expect
new file mode 100644
index 0000000..6c4db58
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.expect
@@ -0,0 +1,49 @@
+Problems reported:
+
+parser/error_recovery/issue_45327.crash:2:16: Expected ';' after this.
+  if (n is int or
+               ^^
+
+parser/error_recovery/issue_45327.crash:2:6: Can't find ')' to match '('.
+  if (n is int or
+     ^
+
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(UnmatchedToken((), null)
+      handleNoType(UnmatchedToken(())
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginIfStatement(if)
+          handleIdentifier(n, expression)
+          handleNoTypeArguments(is)
+          handleNoArguments(is)
+          handleSend(n, is)
+          beginIsOperatorType(is)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(or)
+            handleType(int, null)
+          endIsOperatorType(is)
+          handleIsOperator(is, null)
+          handleParenthesizedCondition(()
+          beginThenStatement(or)
+            handleIdentifier(or, expression)
+            handleNoTypeArguments(})
+            handleNoArguments(})
+            handleSend(or, })
+            handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], or, or)
+            handleExpressionStatement(;)
+          endThenStatement(;)
+        endIfStatement(if, null)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+  handleErrorToken(UnmatchedToken(())
+  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.intertwined.expect
new file mode 100644
index 0000000..841133c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.intertwined.expect
@@ -0,0 +1,101 @@
+parseUnit(UnmatchedToken(())
+  skipErrorTokens(UnmatchedToken(())
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(UnmatchedToken((), Instance of 'DirectiveContext')
+    parseMetadataStar(UnmatchedToken(())
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(UnmatchedToken(())
+      listener: beginTopLevelMember(main)
+      isReservedKeyword(()
+      parseTopLevelMethod(UnmatchedToken((), null, UnmatchedToken((), Instance of 'NoType', null, main, false)
+        listener: beginTopLevelMethod(UnmatchedToken((), null)
+        listener: handleNoType(UnmatchedToken(())
+        ensureIdentifierPotentiallyRecovered(UnmatchedToken((), topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(main, topLevelFunctionDeclaration)
+        parseMethodTypeVar(main)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(main, main, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(main, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, if)
+          parseStatement({)
+            parseStatementX({)
+              parseIfStatement({)
+                listener: beginIfStatement(if)
+                ensureParenthesizedCondition(if)
+                  parseExpressionInParenthesisRest(()
+                    parseExpression(()
+                      parsePrecedenceExpression((, 1, true)
+                        parseUnaryExpression((, true)
+                          parsePrimary((, expression)
+                            parseSendOrFunctionLiteral((, expression)
+                              parseSend((, expression)
+                                ensureIdentifier((, expression)
+                                  listener: handleIdentifier(n, expression)
+                                listener: handleNoTypeArguments(is)
+                                parseArgumentsOpt(n)
+                                  listener: handleNoArguments(is)
+                                listener: handleSend(n, is)
+                        parseIsOperatorRest(n)
+                          listener: beginIsOperatorType(is)
+                          computeTypeAfterIsOrAs(is)
+                          listener: handleIdentifier(int, typeReference)
+                          listener: handleNoTypeArguments(or)
+                          listener: handleType(int, null)
+                          listener: endIsOperatorType(is)
+                          listener: handleIsOperator(is, null)
+                          skipChainedAsIsOperators(int)
+                        rewriter()
+                        parsePrecedenceExpression(||, 6, true)
+                          parseUnaryExpression(||, true)
+                            parsePrimary(||, expression)
+                              parseSend(||, expression)
+                                ensureIdentifier(||, expression)
+                                  reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
+                                  rewriter()
+                                parseArgumentsOpt()
+                    ensureCloseParen(int, ()
+                      rewriter()
+                  listener: handleParenthesizedCondition(()
+                listener: beginThenStatement(or)
+                parseStatement())
+                  parseStatementX())
+                    parseExpressionStatementOrDeclarationAfterModifiers(), ), null, null, null, false)
+                      looksLikeLocalFunction(or)
+                      parseExpressionStatement())
+                        parseExpression())
+                          parsePrecedenceExpression(), 1, true)
+                            parseUnaryExpression(), true)
+                              parsePrimary(), expression)
+                                parseSendOrFunctionLiteral(), expression)
+                                  parseSend(), expression)
+                                    ensureIdentifier(), expression)
+                                      listener: handleIdentifier(or, expression)
+                                    listener: handleNoTypeArguments(})
+                                    parseArgumentsOpt(or)
+                                      listener: handleNoArguments(})
+                                    listener: handleSend(or, })
+                        ensureSemicolon(or)
+                          reportRecoverableError(or, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], or, or)
+                          rewriter()
+                        listener: handleExpressionStatement(;)
+                listener: endThenStatement(;)
+                listener: endIfStatement(if, null)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(UnmatchedToken(())
+    listener: handleErrorToken(UnmatchedToken(())
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.parser.expect
new file mode 100644
index 0000000..2e09cb4
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.parser.expect
@@ -0,0 +1,11 @@
+NOTICE: Stream was rewritten by parser!
+
+main() {
+if (n is int )or
+;}
+
+
+[UnmatchedToken]main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]n[StringToken] is[KeywordToken] int[StringToken] )[SyntheticToken]or[StringToken]
+;[SyntheticToken]}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.scanner.expect
new file mode 100644
index 0000000..321f988
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.scanner.expect
@@ -0,0 +1,9 @@
+main() {
+if (n is int or
+)}
+
+
+[UnmatchedToken]main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]n[StringToken] is[KeywordToken] int[StringToken] or[StringToken]
+)[SyntheticToken]}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart
new file mode 100644
index 0000000..2afc4b5
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart
@@ -0,0 +1,5 @@
+class Foo<T> {
+  foo(Object? key) {
+    if (key is! T or
+  }
+}
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.expect
new file mode 100644
index 0000000..a9b75e9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.expect
@@ -0,0 +1,82 @@
+Problems reported:
+
+parser/error_recovery/issue_45327_prime_1.crash:3:19: Expected ';' after this.
+    if (key is! T or
+                  ^^
+
+parser/error_recovery/issue_45327_prime_1.crash:3:8: Can't find ')' to match '('.
+    if (key is! T or
+       ^
+
+beginCompilationUnit(class)
+  beginMetadataStar(class)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(class)
+    handleIdentifier(Foo, classOrMixinDeclaration)
+    beginTypeVariables(<)
+      beginMetadataStar(T)
+      endMetadataStar(0)
+      handleIdentifier(T, typeVariableDeclaration)
+      beginTypeVariable(T)
+        handleTypeVariablesDefined(T, 1)
+        handleNoType(T)
+      endTypeVariable(>, 0, null, null)
+    endTypeVariables(<, >)
+    beginClassDeclaration(class, null, Foo)
+      handleNoType(>)
+      handleClassExtends(null, 1)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(class, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(foo)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, foo)
+            handleNoType({)
+            handleIdentifier(foo, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(Object)
+              endMetadataStar(0)
+              beginFormalParameter(Object, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(Object, typeReference)
+                handleNoTypeArguments(?)
+                handleType(Object, ?)
+                handleIdentifier(key, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, key, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(1, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginIfStatement(if)
+                handleIdentifier(key, expression)
+                handleNoTypeArguments(is)
+                handleNoArguments(is)
+                handleSend(key, is)
+                beginIsOperatorType(is)
+                  handleIdentifier(T, typeReference)
+                  handleNoTypeArguments(or)
+                  handleType(T, null)
+                endIsOperatorType(is)
+                handleIsOperator(is, !)
+                handleParenthesizedCondition(()
+                beginThenStatement(or)
+                  handleIdentifier(or, expression)
+                  handleNoTypeArguments(})
+                  handleNoArguments(})
+                  handleSend(or, })
+                  handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], or, or)
+                  handleExpressionStatement(;)
+                endThenStatement(;)
+              endIfStatement(if, null)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, foo, (, null, })
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+    endClassDeclaration(class, })
+  endTopLevelDeclaration()
+  handleErrorToken(UnmatchedToken(())
+  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.intertwined.expect
new file mode 100644
index 0000000..d794537
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.intertwined.expect
@@ -0,0 +1,153 @@
+parseUnit(UnmatchedToken(())
+  skipErrorTokens(UnmatchedToken(())
+  listener: beginCompilationUnit(class)
+  syntheticPreviousToken(class)
+  parseTopLevelDeclarationImpl(UnmatchedToken((), Instance of 'DirectiveContext')
+    parseMetadataStar(UnmatchedToken(())
+      listener: beginMetadataStar(class)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(UnmatchedToken((), class, Instance of 'DirectiveContext')
+      parseClassDeclarationModifiers(UnmatchedToken((), class)
+      parseClassOrNamedMixinApplication(null, class)
+        listener: beginClassOrNamedMixinApplicationPrelude(class)
+        ensureIdentifier(class, classOrMixinDeclaration)
+          listener: handleIdentifier(Foo, classOrMixinDeclaration)
+        listener: beginTypeVariables(<)
+        listener: beginMetadataStar(T)
+        listener: endMetadataStar(0)
+        listener: handleIdentifier(T, typeVariableDeclaration)
+        listener: beginTypeVariable(T)
+        listener: handleTypeVariablesDefined(T, 1)
+        listener: handleNoType(T)
+        listener: endTypeVariable(>, 0, null, null)
+        listener: endTypeVariables(<, >)
+        listener: beginClassDeclaration(class, null, Foo)
+        parseClass(>, class, class, Foo)
+          parseClassHeaderOpt(>, class, class)
+            parseClassExtendsOpt(>)
+              listener: handleNoType(>)
+              listener: handleClassExtends(null, 1)
+            parseWithClauseOpt(>)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(>)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(class, class, null)
+          parseClassOrMixinOrExtensionBody(>, DeclarationKind.Class, Foo)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, foo)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, Foo)
+              parseMetadataStar({)
+                listener: beginMetadataStar(foo)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod({, null, null, null, null, null, null, {, Instance of 'NoType', null, foo, DeclarationKind.Class, Foo, false)
+                listener: beginMethod(null, null, null, null, null, foo)
+                listener: handleNoType({)
+                ensureIdentifierPotentiallyRecovered({, methodDeclaration, false)
+                  listener: handleIdentifier(foo, methodDeclaration)
+                parseQualifiedRestOpt(foo, methodDeclarationContinuation)
+                parseMethodTypeVar(foo)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(foo, foo, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(foo, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(Object)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(Object, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(Object, typeReference)
+                        listener: handleNoTypeArguments(?)
+                        listener: handleType(Object, ?)
+                        ensureIdentifier(?, formalParameterDeclaration)
+                          listener: handleIdentifier(key, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, key, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(1, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, if)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseIfStatement({)
+                        listener: beginIfStatement(if)
+                        ensureParenthesizedCondition(if)
+                          parseExpressionInParenthesisRest(()
+                            parseExpression(()
+                              parsePrecedenceExpression((, 1, true)
+                                parseUnaryExpression((, true)
+                                  parsePrimary((, expression)
+                                    parseSendOrFunctionLiteral((, expression)
+                                      parseSend((, expression)
+                                        ensureIdentifier((, expression)
+                                          listener: handleIdentifier(key, expression)
+                                        listener: handleNoTypeArguments(is)
+                                        parseArgumentsOpt(key)
+                                          listener: handleNoArguments(is)
+                                        listener: handleSend(key, is)
+                                parseIsOperatorRest(key)
+                                  listener: beginIsOperatorType(is)
+                                  computeTypeAfterIsOrAs(!)
+                                  listener: handleIdentifier(T, typeReference)
+                                  listener: handleNoTypeArguments(or)
+                                  listener: handleType(T, null)
+                                  listener: endIsOperatorType(is)
+                                  listener: handleIsOperator(is, !)
+                                  skipChainedAsIsOperators(T)
+                                rewriter()
+                                parsePrecedenceExpression(||, 6, true)
+                                  parseUnaryExpression(||, true)
+                                    parsePrimary(||, expression)
+                                      parseSend(||, expression)
+                                        ensureIdentifier(||, expression)
+                                          reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
+                                          rewriter()
+                                        parseArgumentsOpt()
+                            ensureCloseParen(T, ()
+                              rewriter()
+                          listener: handleParenthesizedCondition(()
+                        listener: beginThenStatement(or)
+                        parseStatement())
+                          parseStatementX())
+                            parseExpressionStatementOrDeclarationAfterModifiers(), ), null, null, null, false)
+                              looksLikeLocalFunction(or)
+                              parseExpressionStatement())
+                                parseExpression())
+                                  parsePrecedenceExpression(), 1, true)
+                                    parseUnaryExpression(), true)
+                                      parsePrimary(), expression)
+                                        parseSendOrFunctionLiteral(), expression)
+                                          parseSend(), expression)
+                                            ensureIdentifier(), expression)
+                                              listener: handleIdentifier(or, expression)
+                                            listener: handleNoTypeArguments(})
+                                            parseArgumentsOpt(or)
+                                              listener: handleNoArguments(})
+                                            listener: handleSend(or, })
+                                ensureSemicolon(or)
+                                  reportRecoverableError(or, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                                    listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], or, or)
+                                  rewriter()
+                                listener: handleExpressionStatement(;)
+                        listener: endThenStatement(;)
+                        listener: endIfStatement(if, null)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, foo, (, null, })
+              listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+          listener: endClassDeclaration(class, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(UnmatchedToken(())
+    listener: handleErrorToken(UnmatchedToken(())
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.parser.expect
new file mode 100644
index 0000000..8515a43
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.parser.expect
@@ -0,0 +1,15 @@
+NOTICE: Stream was rewritten by parser!
+
+class Foo<T> {
+foo(Object? key) {
+if (key is! T )or
+;}
+}
+
+
+[UnmatchedToken]class[KeywordToken] Foo[StringToken]<[BeginToken]T[StringToken]>[SimpleToken] {[BeginToken]
+foo[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] key[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]key[StringToken] is[KeywordToken]![SimpleToken] T[StringToken] )[SyntheticToken]or[StringToken]
+;[SyntheticToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.scanner.expect
new file mode 100644
index 0000000..b7836d3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.scanner.expect
@@ -0,0 +1,13 @@
+class Foo<T> {
+foo(Object? key) {
+if (key is! T or
+)}
+}
+
+
+[UnmatchedToken]class[KeywordToken] Foo[StringToken]<[BeginToken]T[StringToken]>[SimpleToken] {[BeginToken]
+foo[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] key[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]key[StringToken] is[KeywordToken]![SimpleToken] T[StringToken] or[StringToken]
+)[SyntheticToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline.expect b/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline.expect
index e109be7..0224cb7 100644
--- a/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline.expect
@@ -1,15 +1,19 @@
 class A<T> {
   const A();
 }
+
 class B<S, T> {
   const B();
 }
+
 class C<T extends num> {
   const C();
 }
+
 class D<S extends num, T extends S> {
   const D();
 }
+
 @A<int, num>()
 @B<int>()
 @C<String>()
diff --git a/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d5e1444
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline_modelled.expect
@@ -0,0 +1,32 @@
+class A<T> {
+  const A();
+}
+
+class B<S, T> {
+  const B();
+}
+
+class C<T extends num> {
+  const C();
+}
+
+class D<S extends num, T extends S> {
+  const D();
+}
+
+@A()
+@A<int>()
+@B()
+@B<int, String>()
+@C()
+@C<num>()
+@C<int>()
+@D()
+@D<num, num>()
+@D<num, int>()
+main() {}
+@A<int, num>()
+@B<int>()
+@C<String>()
+@D<int, num>()
+test() {}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 6fef290..b703c23 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -62,7 +62,6 @@
 general/null_safety_invalid_experiment_and_language_version: FormatterCrash
 general/type_parameters_on_void: FormatterCrash
 general/var_as_type_name: FormatterCrash
-generic_metadata/generic_metadata: FormatterCrash
 inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1: FormatterCrash
 inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1: FormatterCrash
 late_lowering/covariant_late_field: FormatterCrash
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index 11032aa..c40fde0 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -884,6 +884,13 @@
   }
 
   @override
+  R visitExtensionReference(Extension node) {
+    throw new UnimplementedError(
+        'Unimplemented ${runtimeType}.visitExtensionReference for '
+        '${node} (${node.runtimeType})');
+  }
+
+  @override
   R defaultConstantReference(Constant node) {
     throw new UnimplementedError(
         'Unimplemented ${runtimeType}.defaultConstantReference for '
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart b/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
index 1cb4d54..183f332 100644
--- a/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
@@ -7708,7 +7708,7 @@
 ''';
 
 String _migration_js;
-// migration_dart md5 is 'a1ff0191d3960968e178bcb372181074'
+// migration_dart md5 is '542403f76ced1ab36ca5079ac60b8199'
 String _migration_js_base64 = '''
 KGZ1bmN0aW9uIGRhcnRQcm9ncmFtKCl7ZnVuY3Rpb24gY29weVByb3BlcnRpZXMoYSxiKXt2YXIgcz1P
 YmplY3Qua2V5cyhhKQpmb3IodmFyIHI9MDtyPHMubGVuZ3RoO3IrKyl7dmFyIHE9c1tyXQpiW3FdPWFb
@@ -9339,20 +9339,20 @@
 c2UgcmV0dXJuIGF9LApPdDpmdW5jdGlvbihhKXtzd2l0Y2goYS5yKXtjYXNlIEMuY3c6YnJlYWsKY2Fz
 ZSBDLldEOmEucj1DLlhqCmJyZWFrCmNhc2UgQy5YajphLnI9Qy5XRApicmVhawpjYXNlIEMuZGM6dGhy
 b3cgSC5iKFAuUFYoIkZpbGUgIitILkVqKGEuYykrIiBzaG91bGQgbm90IGhhdmUgaW5kZXRlcm1pbmF0
-ZSBtaWdyYXRpb24gc3RhdHVzIikpfX0sCnhuOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPSJkaXNhYmxl
-ZCIscD1iLmdMKCkKTC50YShhLHApCmlmKGIuYz09JC5EOSgpLmlubmVyVGV4dCl7cz1iIGluc3RhbmNl
-b2YgTC5jRCYmIUgub1QoYi54KQpyPUouWUUoYSkKaWYocylyLmdQKGEpLmkoMCxxKQplbHNlIHIuZ1Ao
-YSkuUigwLHEpCkwudGEoJC5jMCgpLHApfX0sCnRhOmZ1bmN0aW9uKGEsYil7dmFyIHMscj0iY2hlY2tf
-Ym94IixxPSJ0aXRsZSIscD0ib3B0ZWQtb3V0IixvPSJtaWdyYXRpbmciCnN3aXRjaChiKXtjYXNlIEMu
-Y3c6YS5pbm5lclRleHQ9cgpzPUouWUUoYSkKcy5nUChhKS5pKDAsImFscmVhZHktbWlncmF0ZWQiKQpz
-LmdQKGEpLmkoMCwiZGlzYWJsZWQiKQphLnNldEF0dHJpYnV0ZShxLCJBbHJlYWR5IG1pZ3JhdGVkIikK
-YnJlYWsKY2FzZSBDLldEOmEuaW5uZXJUZXh0PXIKcz1KLllFKGEpCnMuZ1AoYSkuUigwLHApCnMuZ1Ao
-YSkuaSgwLG8pCmEuc2V0QXR0cmlidXRlKHEsIk1pZ3JhdGluZyB0byBudWxsIHNhZmV0eSIpCmJyZWFr
-CmNhc2UgQy5YajphLmlubmVyVGV4dD0iY2hlY2tfYm94X291dGxpbmVfYmxhbmsiCnM9Si5ZRShhKQpz
-LmdQKGEpLlIoMCxvKQpzLmdQKGEpLmkoMCxwKQphLnNldEF0dHJpYnV0ZShxLCJPcHRpbmcgb3V0IG9m
-IG51bGwgc2FmZXR5IikKYnJlYWsKZGVmYXVsdDphLmlubmVyVGV4dD0iaW5kZXRlcm1pbmF0ZV9jaGVj
-a19ib3giCnM9Si5ZRShhKQpzLmdQKGEpLlIoMCxvKQpzLmdQKGEpLmkoMCxwKQphLnNldEF0dHJpYnV0
-ZShxLCJNaXhlZCBzdGF0dXNlcyBvZiAnbWlncmF0aW5nJyBhbmQgJ29wdGluZyBvdXQnIikKYnJlYWt9
+ZSBtaWdyYXRpb24gc3RhdHVzIikpfX0sCnRhOmZ1bmN0aW9uKGEsYil7dmFyIHMscj0iY2hlY2tfYm94
+IixxPSJ0aXRsZSIscD0ib3B0ZWQtb3V0IixvPSJtaWdyYXRpbmciCnN3aXRjaChiKXtjYXNlIEMuY3c6
+YS5pbm5lclRleHQ9cgpzPUouWUUoYSkKcy5nUChhKS5pKDAsImFscmVhZHktbWlncmF0ZWQiKQpzLmdQ
+KGEpLmkoMCwiZGlzYWJsZWQiKQphLnNldEF0dHJpYnV0ZShxLCJBbHJlYWR5IG1pZ3JhdGVkIikKYnJl
+YWsKY2FzZSBDLldEOmEuaW5uZXJUZXh0PXIKcz1KLllFKGEpCnMuZ1AoYSkuUigwLHApCnMuZ1AoYSku
+aSgwLG8pCmEuc2V0QXR0cmlidXRlKHEsIk1pZ3JhdGluZyB0byBudWxsIHNhZmV0eSIpCmJyZWFrCmNh
+c2UgQy5YajphLmlubmVyVGV4dD0iY2hlY2tfYm94X291dGxpbmVfYmxhbmsiCnM9Si5ZRShhKQpzLmdQ
+KGEpLlIoMCxvKQpzLmdQKGEpLmkoMCxwKQphLnNldEF0dHJpYnV0ZShxLCJPcHRpbmcgb3V0IG9mIG51
+bGwgc2FmZXR5IikKYnJlYWsKZGVmYXVsdDphLmlubmVyVGV4dD0iaW5kZXRlcm1pbmF0ZV9jaGVja19i
+b3giCnM9Si5ZRShhKQpzLmdQKGEpLlIoMCxvKQpzLmdQKGEpLmkoMCxwKQphLnNldEF0dHJpYnV0ZShx
+LCJNaXhlZCBzdGF0dXNlcyBvZiAnbWlncmF0aW5nJyBhbmQgJ29wdGluZyBvdXQnIikKYnJlYWt9fSwK
+eG46ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9ImRpc2FibGVkIixwPWIuZ0woKQpMLnRhKGEscCkKaWYo
+Yi5jPT0kLkQ5KCkuaW5uZXJUZXh0KXtzPWIgaW5zdGFuY2VvZiBMLmNEJiYhSC5vVChiLngpCnI9Si5Z
+RShhKQppZihzKXIuZ1AoYSkuaSgwLHEpCmVsc2Ugci5nUChhKS5SKDAscSkKTC50YSgkLmMwKCkscCl9
 fSwKQlg6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9e30KcS5hPWEKYT1MLkVuKGEpCnEuYT1hCkouZHIo
 JC5EOSgpLGEpCnM9ZG9jdW1lbnQKSC5EaCh0LmcsdC5oLCJUIiwicXVlcnlTZWxlY3RvckFsbCIpCnM9
 bmV3IFcud3oocy5xdWVyeVNlbGVjdG9yQWxsKCIubmF2LXBhbmVsIC5uYXYtbGluayIpLHQuUikKcy5L
@@ -11572,11 +11572,11 @@
 dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIuZWRpdC1wYW5lbCAucGFuZWwtY29udGVudCIpfSkKcigk
 LCJUUiIsIkRXIixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiZm9vdGVyIil9
 KQpyKCQsIkVZIiwiZmkiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCJoZWFk
-ZXIiKX0pCnIoJCwiYXYiLCJEOSIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3Io
-IiN1bml0LW5hbWUiKX0pCnIoJCwidDAiLCJiTiIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5
-U2VsZWN0b3IoIiNtaWdyYXRlLXVuaXQtc3RhdHVzLWljb24tbGFiZWwiKX0pCnIoJCwiYkEiLCJjMCIs
-ZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiNtaWdyYXRlLXVuaXQtc3RhdHVz
-LWljb24iKX0pCnIoJCwiZmUiLCJLRyIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEwuWEEoKX0pCnMoJCwi
+ZXIiKX0pCnIoJCwiYkEiLCJjMCIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3Io
+IiNtaWdyYXRlLXVuaXQtc3RhdHVzLWljb24iKX0pCnIoJCwidDAiLCJiTiIsZnVuY3Rpb24oKXtyZXR1
+cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiNtaWdyYXRlLXVuaXQtc3RhdHVzLWljb24tbGFiZWwiKX0p
+CnIoJCwiYXYiLCJEOSIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiN1bml0
+LW5hbWUiKX0pCnIoJCwiZmUiLCJLRyIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEwuWEEoKX0pCnMoJCwi
 ZW8iLCJuVSIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IE0ubEkoJC5IaygpKX0pCnMoJCwieXIiLCJiRCIs
 ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEUuT0YoUC5udSgiLyIpLFAubnUoIlteL10kIiksUC5udSgiXi8i
 KSl9KQpzKCQsIk1rIiwiS2siLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBMLklWKFAubnUoIlsvXFxcXF0i
diff --git a/pkg/nnbd_migration/lib/src/front_end/web/migration.dart b/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
index 672b45c..c01ccee 100644
--- a/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
@@ -129,20 +129,20 @@
 
 final Element headerPanel = document.querySelector('header');
 
-final Element unitName = document.querySelector('#unit-name');
+final Element migrateUnitStatusIcon =
+    document.querySelector('#migrate-unit-status-icon');
 
 final Element migrateUnitStatusIconLabel =
     document.querySelector('#migrate-unit-status-icon-label');
 
-final Element migrateUnitStatusIcon =
-    document.querySelector('#migrate-unit-status-icon');
+List<NavigationTreeNode> /*?*/ navigationTree;
+
+final Element unitName = document.querySelector('#unit-name');
 
 String get rootPath => querySelector('.root').text.trim();
 
 String get sdkVersion => document.getElementById('sdk-version').text;
 
-List<NavigationTreeNode> /*?*/ navigationTree;
-
 void addArrowClickHandler(Element arrow) {
   var childList = (arrow.parentNode as Element).querySelector(':scope > ul');
   // Animating height from "auto" to "0" is not supported by CSS [1], so all we
@@ -730,25 +730,6 @@
   }
 }
 
-/// Updates the navigation [icon] and current file icon according to the current
-/// migration status of [entity].
-void updateIconsForNode(Element icon, NavigationTreeNode entity) {
-  var status = entity.migrationStatus;
-  updateIconForStatus(icon, status);
-  // Update the status at the top of the file view if [entity] represents the
-  // current file.
-  var unitPath = unitName.innerText;
-  if (entity.path == unitPath) {
-    if (entity is NavigationTreeFileNode &&
-        !entity.migrationStatusCanBeChanged) {
-      icon.classes.add('disabled');
-    } else {
-      icon.classes.remove('disabled');
-    }
-    updateIconForStatus(migrateUnitStatusIcon, status);
-  }
-}
-
 /// Updates [icon] according to [status].
 void updateIconForStatus(Element icon, UnitMigrationStatus status) {
   switch (status) {
@@ -781,6 +762,25 @@
   }
 }
 
+/// Updates the navigation [icon] and current file icon according to the current
+/// migration status of [entity].
+void updateIconsForNode(Element icon, NavigationTreeNode entity) {
+  var status = entity.migrationStatus;
+  updateIconForStatus(icon, status);
+  // Update the status at the top of the file view if [entity] represents the
+  // current file.
+  var unitPath = unitName.innerText;
+  if (entity.path == unitPath) {
+    if (entity is NavigationTreeFileNode &&
+        !entity.migrationStatusCanBeChanged) {
+      icon.classes.add('disabled');
+    } else {
+      icon.classes.remove('disabled');
+    }
+    updateIconForStatus(migrateUnitStatusIcon, status);
+  }
+}
+
 /// Update the heading and navigation links.
 ///
 /// Call this after updating page content on a navigation.
diff --git a/pkg/nnbd_migration/tool/codegen/extract_resource.dart b/pkg/nnbd_migration/tool/codegen/extract_resource.dart
new file mode 100644
index 0000000..3b60593
--- /dev/null
+++ b/pkg/nnbd_migration/tool/codegen/extract_resource.dart
@@ -0,0 +1,128 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This script provides a quick way, via the command line, to extract one of the
+// resources encoded in the file lib/src/front_end/resources/resources.g.dart.
+
+import 'dart:convert';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:analyzer/dart/analysis/utilities.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:args/args.dart';
+import 'package:path/path.dart' as path;
+
+main(List<String> args) {
+  var argResults = argParser.parse(args);
+  if (argResults['help'] as bool) {
+    fail(null, showUsage: true);
+  }
+  if (argResults.rest.isNotEmpty) {
+    fail('Unexpected extra arguments', showUsage: true);
+  }
+  bool list = argResults['list'] as bool;
+  String path = argResults['path'] as String;
+  String resource = argResults['resource'] as String;
+  if (list && resource != null) {
+    fail('Only one of --resource and --list may be provided');
+  } else if (!list && resource == null) {
+    fail('Either --resource or --list must be provided');
+  }
+  var file = locateResourcesFile(path);
+  var parseResult =
+      parseString(content: file.readAsStringSync(), path: file.path);
+  final variableNameRegExp = RegExp(r'^_(.*)_base64$');
+  for (var declaration in parseResult.unit.declarations) {
+    if (declaration is TopLevelVariableDeclaration) {
+      for (var variable in declaration.variables.variables) {
+        if (variable.initializer == null) continue;
+        var match = variableNameRegExp.matchAsPrefix(variable.name.name);
+        if (match == null) continue;
+        var shortName = match.group(1);
+        if (list) {
+          stdout.writeln(shortName);
+        } else if (resource == shortName) {
+          stdout.add(decodeVariableDeclaration(variable));
+          return;
+        }
+      }
+    }
+  }
+  if (list) {
+    return;
+  } else {
+    fail('Resource $resource not found in ${file.path}');
+  }
+}
+
+final argParser = ArgParser()
+  ..addOption('resource',
+      abbr: 'r', valueHelp: 'RESOURCE', help: 'Extract resource RESOURCE')
+  ..addFlag('list',
+      negatable: false, abbr: 'l', help: 'List which resources are present')
+  ..addOption('path',
+      abbr: 'p',
+      valueHelp: 'PATH',
+      help:
+          'Search for resources.g.dart inside PATH rather than current working '
+          'directory')
+  ..addFlag('help', negatable: false, abbr: 'h');
+
+Uint8List decodeVariableDeclaration(VariableDeclaration variable) {
+  var initializer = variable.initializer as StringLiteral;
+  var stringValue = initializer.stringValue;
+  return base64.decode(stringValue.replaceAll('\n', '').trim());
+}
+
+void fail(String message, {bool showUsage = false}) {
+  if (message != null) {
+    stderr.writeln(message);
+  }
+  if (showUsage) {
+    stderr.writeln('''
+usage: dart pkg/nnbd_migration/tool/codegen/extract_resource.dart -r <resource>
+
+Reads the file `resources.g.dart` from the appropriate directory, extracts the
+embedded resource named `<resource>`, and prints it to standard out.
+''');
+    stderr.writeln(argParser.usage);
+  }
+  exit(1);
+}
+
+/// Tries to guess the location of `resources.g.dart` using optional [pathHint]
+/// as a starting point.
+File locateResourcesFile(String pathHint) {
+  pathHint ??= '.';
+  final pathParts =
+      'pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart'
+          .split('/');
+  var currentPath = path.normalize(pathHint);
+  while (true) {
+    for (int i = 0; i <= pathParts.length; i++) {
+      var pathToTry = path.normalize(path.join(
+          currentPath, path.joinAll(pathParts.sublist(pathParts.length - i))));
+      var file = File(pathToTry);
+      var type = file.statSync().type;
+      if (type == FileSystemEntityType.notFound && i == 0) {
+        fail('No such file or directory: $pathToTry');
+      }
+      if (type == FileSystemEntityType.link) {
+        type = File(file.resolveSymbolicLinksSync()).statSync().type;
+      }
+      if (type == FileSystemEntityType.file) {
+        return file;
+      }
+    }
+    if (currentPath == '.') {
+      currentPath = Directory.current.path;
+    }
+    var nextPath = path.dirname(currentPath);
+    if (nextPath == currentPath) {
+      fail('Could not find file `resources.g.dart` starting at $pathHint');
+    }
+    currentPath = nextPath;
+  }
+}
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index d390576..ef653b0 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1069,7 +1069,6 @@
     s->Push(data->untag()->parent_function_);
     s->Push(data->untag()->closure_);
     s->Push(data->untag()->default_type_arguments_);
-    s->Push(data->untag()->default_type_arguments_info_);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -1093,7 +1092,8 @@
       WriteField(data, parent_function_);
       WriteField(data, closure_);
       WriteField(data, default_type_arguments_);
-      WriteField(data, default_type_arguments_info_);
+      s->WriteUnsigned(
+          static_cast<intptr_t>(data->untag()->default_type_arguments_kind_));
     }
   }
 
@@ -1134,8 +1134,8 @@
       data->untag()->closure_ = static_cast<InstancePtr>(d->ReadRef());
       data->untag()->default_type_arguments_ =
           static_cast<TypeArgumentsPtr>(d->ReadRef());
-      data->untag()->default_type_arguments_info_ =
-          static_cast<SmiPtr>(d->ReadRef());
+      data->untag()->default_type_arguments_kind_ =
+          static_cast<ClosureData::DefaultTypeArgumentsKind>(d->ReadUnsigned());
     }
   }
 };
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 2821fad..8aa57f7 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -2768,7 +2768,7 @@
     case Slot::Kind::kClosure_instantiator_type_arguments:
     case Slot::Kind::kClosure_hash:
     case Slot::Kind::kClosureData_default_type_arguments:
-    case Slot::Kind::kClosureData_default_type_arguments_info:
+    case Slot::Kind::kClosureData_default_type_arguments_kind:
     case Slot::Kind::kCapturedVariable:
     case Slot::Kind::kDartField:
     case Slot::Kind::kFunction_data:
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index cac72cc..e39dff8 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2742,8 +2742,9 @@
   switch (r) {
     case kTagged:
       return RangeBoundary::kRangeBoundarySmi;
+    case kUnboxedUint8:  // Overapproximate Uint8 as Int16.
+      return RangeBoundary::kRangeBoundaryInt16;
     case kUnboxedInt32:
-    case kUnboxedUint8:  // Overapproximate Uint8 as Int32.
       return RangeBoundary::kRangeBoundaryInt32;
     case kUnboxedInt64:
     case kUnboxedUint32:  // Overapproximate Uint32 as Int64.
@@ -2821,6 +2822,7 @@
       UNREACHABLE();
       break;
 
+    case Slot::Kind::kClosureData_default_type_arguments_kind:
     case Slot::Kind::kFunction_kind_tag:
     case Slot::Kind::kFunction_packed_fields:
     case Slot::Kind::kTypeParameter_flags:
@@ -2841,9 +2843,6 @@
     case Slot::Kind::kArgumentsDescriptor_size:
       *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
       break;
-
-    case Slot::Kind::kClosureData_default_type_arguments_info:
-      *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
   }
 }
 
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index ab21d74..b0037f4 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -32,6 +32,7 @@
 
   enum RangeSize {
     kRangeBoundarySmi,
+    kRangeBoundaryInt16,
     kRangeBoundaryInt32,
     kRangeBoundaryInt64,
   };
@@ -97,6 +98,8 @@
     switch (size) {
       case kRangeBoundarySmi:
         return FromConstant(compiler::target::kSmiMin);
+      case kRangeBoundaryInt16:
+        return FromConstant(kMinInt16);
       case kRangeBoundaryInt32:
         return FromConstant(kMinInt32);
       case kRangeBoundaryInt64:
@@ -110,6 +113,8 @@
     switch (size) {
       case kRangeBoundarySmi:
         return FromConstant(compiler::target::kSmiMax);
+      case kRangeBoundaryInt16:
+        return FromConstant(kMaxInt16);
       case kRangeBoundaryInt32:
         return FromConstant(kMaxInt32);
       case kRangeBoundaryInt64:
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 3a2a1cd..8096b2d 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -83,7 +83,6 @@
   V(Closure, UntaggedClosure, function, Function, FINAL)                       \
   V(Closure, UntaggedClosure, context, Context, FINAL)                         \
   V(Closure, UntaggedClosure, hash, Context, VAR)                              \
-  V(ClosureData, UntaggedClosureData, default_type_arguments_info, Smi, FINAL) \
   V(Function, UntaggedFunction, data, Dynamic, FINAL)                          \
   V(FunctionType, UntaggedFunctionType, parameter_names, Array, FINAL)         \
   V(FunctionType, UntaggedFunctionType, parameter_types, Array, FINAL)         \
@@ -125,6 +124,8 @@
 //
 // Note: As the underlying field is unboxed, these slots cannot be nullable.
 #define UNBOXED_NATIVE_SLOTS_LIST(V)                                           \
+  V(ClosureData, UntaggedClosureData, default_type_arguments_kind, Uint8,      \
+    FINAL)                                                                     \
   V(Function, UntaggedFunction, kind_tag, Uint32, FINAL)                       \
   V(Function, UntaggedFunction, packed_fields, Uint32, FINAL)                  \
   V(FunctionType, UntaggedFunctionType, packed_fields, Uint32, FINAL)          \
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index dce6e90..c8e01c4 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -900,7 +900,7 @@
   } else if (type_ != NULL) {
     type_name = type_->IsDynamicType()
                     ? "*"
-                    : String::Handle(type_->UserVisibleName()).ToCString();
+                    : String::Handle(type_->ScrubbedName()).ToCString();
   } else if (!is_nullable()) {
     type_name = "!null";
   }
diff --git a/runtime/vm/compiler/frontend/constant_reader.cc b/runtime/vm/compiler/frontend/constant_reader.cc
index 7c0d3ad..215ced2 100644
--- a/runtime/vm/compiler/frontend/constant_reader.cc
+++ b/runtime/vm/compiler/frontend/constant_reader.cc
@@ -122,6 +122,9 @@
   KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
   reader.ReadUInt();  // skip variable-sized int for adjusted constant offset
   reader.SetOffset(reader.ReaderOffset() + constant_offset);
+  // No function types returned as part of any types built should reference
+  // free parent type args, ensured by clearing the enclosing function type.
+  ActiveEnclosingFunctionScope scope(active_class_, nullptr);
   // Construct constant from raw bytes.
   Instance& instance = Instance::Handle(Z);
   const intptr_t constant_tag = reader.ReadByte();
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index db41553..7437768 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1598,9 +1598,8 @@
         StoreInstanceFieldInstr::Kind::kInitializing);
   }
 
-  // The function signature cannot have uninstantiated function type parameters,
-  // because the function cannot be local and have parent generic functions.
-  ASSERT(target.HasInstantiatedSignature(kFunctions));
+  // The function cannot be local and have parent generic functions.
+  ASSERT(!target.HasGenericParent());
 
   // Allocate a context that closes over `this`.
   // Note: this must be kept in sync with ScopeBuilder::BuildScopes.
@@ -2095,8 +2094,6 @@
   LocalVariable* parameter_names = nullptr;
   LocalVariable* parameter_types = nullptr;
   LocalVariable* type_parameters = nullptr;
-  LocalVariable* closure_data = nullptr;
-  LocalVariable* default_tav_info = nullptr;
   LocalVariable* instantiator_type_args = nullptr;
   LocalVariable* parent_function_type_args = nullptr;
 };
@@ -2216,38 +2213,40 @@
   // Load the defaults, instantiating or replacing them with the other type
   // arguments as appropriate.
   Fragment store_default;
-  store_default += LoadLocal(info.default_tav_info);
-  static_assert(
-      Function::DefaultTypeArgumentsKindField::shift() == 0,
-      "Need to generate shift for DefaultTypeArgumentsKindField bit field");
-  store_default += IntConstant(Function::DefaultTypeArgumentsKindField::mask());
-  store_default += SmiBinaryOp(Token::kBIT_AND);
+  store_default += LoadLocal(info.closure);
+  store_default += LoadNativeField(Slot::Closure_function());
+  store_default += LoadNativeField(Slot::Function_data());
+  LocalVariable* closure_data = MakeTemporary("closure_data");
+
+  store_default += LoadLocal(closure_data);
+  const auto& slot = Slot::ClosureData_default_type_arguments_kind();
+  store_default += LoadNativeField(slot);
+  store_default += Box(slot.representation());
   LocalVariable* default_tav_kind = MakeTemporary("default_tav_kind");
 
-  // One read-only stack values (default_tav_kind) that must be dropped after
-  // rejoining at done.
+  // Two locals to drop after join, closure_data and default_tav_kind.
   JoinEntryInstr* done = BuildJoinEntry();
 
   store_default += LoadLocal(default_tav_kind);
   TargetEntryInstr *is_instantiated, *is_not_instantiated;
   store_default += IntConstant(static_cast<intptr_t>(
-      Function::DefaultTypeArgumentsKind::kIsInstantiated));
+      ClosureData::DefaultTypeArgumentsKind::kIsInstantiated));
   store_default += BranchIfEqual(&is_instantiated, &is_not_instantiated);
   store_default.current = is_not_instantiated;  // Check next case.
   store_default += LoadLocal(default_tav_kind);
   TargetEntryInstr *needs_instantiation, *can_share;
   store_default += IntConstant(static_cast<intptr_t>(
-      Function::DefaultTypeArgumentsKind::kNeedsInstantiation));
+      ClosureData::DefaultTypeArgumentsKind::kNeedsInstantiation));
   store_default += BranchIfEqual(&needs_instantiation, &can_share);
   store_default.current = can_share;  // Check next case.
   store_default += LoadLocal(default_tav_kind);
   TargetEntryInstr *can_share_instantiator, *can_share_function;
   store_default += IntConstant(static_cast<intptr_t>(
-      Function::DefaultTypeArgumentsKind::kSharesInstantiatorTypeArguments));
+      ClosureData::DefaultTypeArgumentsKind::kSharesInstantiatorTypeArguments));
   store_default += BranchIfEqual(&can_share_instantiator, &can_share_function);
 
   Fragment instantiated(is_instantiated);
-  instantiated += LoadLocal(info.closure_data);
+  instantiated += LoadLocal(closure_data);
   instantiated += LoadNativeField(Slot::ClosureData_default_type_arguments());
   instantiated += StoreLocal(info.vars->function_type_args);
   instantiated += Drop();
@@ -2260,7 +2259,7 @@
   // can be used within the defaults).
   do_instantiation += LoadLocal(info.parent_function_type_args);
   // Load the default type arguments to instantiate.
-  do_instantiation += LoadLocal(info.closure_data);
+  do_instantiation += LoadLocal(closure_data);
   do_instantiation +=
       LoadNativeField(Slot::ClosureData_default_type_arguments());
   do_instantiation += InstantiateDynamicTypeArguments();
@@ -2284,6 +2283,7 @@
 
   store_default.current = done;  // Return here after branching.
   store_default += DropTemporary(&default_tav_kind);
+  store_default += DropTemporary(&closure_data);
 
   Fragment store_delayed;
   store_delayed += LoadLocal(info.closure);
@@ -2723,13 +2723,6 @@
   // full set of function type arguments, then check the local function type
   // arguments against the closure function's type parameter bounds.
   Fragment generic;
-  generic += LoadLocal(info.closure);
-  generic += LoadNativeField(Slot::Closure_function());
-  generic += LoadNativeField(Slot::Function_data());
-  info.closure_data = MakeTemporary("closure_data");
-  generic += LoadLocal(info.closure_data);
-  generic += LoadNativeField(Slot::ClosureData_default_type_arguments_info());
-  info.default_tav_info = MakeTemporary("default_tav_info");
   // Calculate the local function type arguments and store them in
   // info.vars->function_type_args.
   generic += BuildClosureCallDefaultTypeHandling(info);
@@ -2738,13 +2731,10 @@
   // Load the parent function type args.
   generic += LoadLocal(info.parent_function_type_args);
   // Load the number of parent type parameters.
-  generic += LoadLocal(info.default_tav_info);
-  static_assert(Function::NumParentTypeParametersField::shift() > 0,
-                "No need to shift for NumParentTypeParametersField bit field");
-  generic += IntConstant(Function::NumParentTypeParametersField::shift());
-  generic += SmiBinaryOp(Token::kSHR);
-  generic += IntConstant(Function::NumParentTypeParametersField::mask());
-  generic += SmiBinaryOp(Token::kBIT_AND);
+  generic += LoadLocal(info.signature);
+  generic += BuildExtractUnboxedSlotBitFieldIntoSmi<
+      UntaggedFunctionType::PackedNumParentTypeArguments>(
+      Slot::FunctionType_packed_fields());
   // Load the number of total type parameters.
   LocalVariable* num_parents = MakeTemporary();
   generic += LoadLocal(info.type_parameters);
@@ -2757,8 +2747,6 @@
                         PrependTypeArgumentsFunction(), 4, ICData::kStatic);
   generic += StoreLocal(info.vars->function_type_args);
   generic += Drop();
-  generic += DropTemporary(&info.default_tav_info);
-  generic += DropTemporary(&info.closure_data);
 
   // Now that we have the full set of function type arguments, check them
   // against the type parameter bounds. However, if the local function type
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 5078854..b7126d7 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -3054,22 +3054,26 @@
 
   // Suspend finalization of types inside this one. They will be finalized after
   // the whole function type is constructed.
-  //
-  // TODO(31213): Test further when nested generic function types
-  // are supported by fasta.
   bool finalize = finalize_;
   finalize_ = false;
+  intptr_t type_parameter_count = 0;
 
   if (!simple) {
+    type_parameter_count = helper_->ReadListLength();
     LoadAndSetupTypeParameters(
         active_class_, Object::null_function(), Object::null_class(), signature,
-        helper_->ReadListLength(), active_class_->klass->nnbd_mode());
+        type_parameter_count, active_class_->klass->nnbd_mode());
   }
 
   ActiveTypeParametersScope scope(
       active_class_, &signature,
       TypeArguments::Handle(Z, signature.type_parameters()), Z);
 
+  if (!simple) {
+    LoadAndSetupBounds(active_class_, Object::null_function(),
+                       Object::null_class(), signature, type_parameter_count);
+  }
+
   intptr_t required_count;
   intptr_t all_count;
   intptr_t positional_count;
@@ -3324,7 +3328,6 @@
                                       ? Nullability::kNonNullable
                                       : Nullability::kLegacy;
 
-  // Step a)
   // - Create array of [TypeParameter] objects (without bound).
   // - Create array of [String] objects.
   type_parameters = TypeArguments::New(type_parameter_count);
@@ -3354,20 +3357,35 @@
       } else {
         name = H.DartIdentifier(lib, helper.name_index_).ptr();
       }
+      // Bounds are filled later in LoadAndSetupBounds as bound types may
+      // reference type parameters which are not created yet.
       parameter = TypeParameter::New(
           parameterized_class, offset, offset + i, name, null_bound,
           helper.IsGenericCovariantImpl(), nullability);
       type_parameters.SetTypeAt(i, parameter);
     }
   }
+}
 
-  const FunctionType* enclosing = NULL;
-  if (!parameterized_signature.IsNull()) {
-    enclosing = &parameterized_signature;
+void TypeTranslator::LoadAndSetupBounds(
+    ActiveClass* active_class,
+    const Function& function,
+    const Class& parameterized_class,
+    const FunctionType& parameterized_signature,
+    intptr_t type_parameter_count) {
+  ASSERT(parameterized_class.IsNull() != parameterized_signature.IsNull());
+  ASSERT(type_parameter_count >= 0);
+  if (type_parameter_count == 0) {
+    return;
   }
-  ActiveTypeParametersScope scope(active_class, enclosing, type_parameters, Z);
 
-  // Step b) Fill in the bounds and default arguments of all [TypeParameter]s.
+  const TypeArguments& type_parameters =
+      TypeArguments::Handle(Z, !parameterized_class.IsNull()
+                                   ? parameterized_class.type_parameters()
+                                   : parameterized_signature.type_parameters());
+  TypeParameter& parameter = TypeParameter::Handle(Z);
+
+  // Fill in the bounds and default arguments of all [TypeParameter]s.
   for (intptr_t i = 0; i < type_parameter_count; i++) {
     TypeParameterHelper helper(helper_);
     helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
@@ -3389,6 +3407,9 @@
 
   // Fix bounds and default arguments in all derived type parameters (with
   // different nullabilities).
+  const intptr_t offset = !parameterized_signature.IsNull()
+                              ? parameterized_signature.NumParentTypeArguments()
+                              : 0;
   if (active_class->derived_type_parameters != nullptr) {
     auto& derived = TypeParameter::Handle(Z);
     auto& type = AbstractType::Handle(Z);
@@ -3535,15 +3556,22 @@
 
   const FunctionType& signature = FunctionType::Handle(Z, function.signature());
   ASSERT(!signature.IsNull());
+  intptr_t type_parameter_count = 0;
   if (!is_factory) {
+    type_parameter_count = helper_->ReadListLength();
     LoadAndSetupTypeParameters(active_class_, function, Class::Handle(Z),
-                               signature, helper_->ReadListLength(),
+                               signature, type_parameter_count,
                                function.nnbd_mode());
-    function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
   }
 
   ActiveTypeParametersScope scope(active_class_, function, &signature, Z);
 
+  if (!is_factory) {
+    LoadAndSetupBounds(active_class_, function, Class::Handle(Z), signature,
+                       type_parameter_count);
+    function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
+  }
+
   function_node_helper->ReadUntilExcluding(
       FunctionNodeHelper::kPositionalParameters);
 
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index d5d39fe..03e6378 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -1478,6 +1478,12 @@
                                   intptr_t type_parameter_count,
                                   const NNBDMode nnbd_mode);
 
+  void LoadAndSetupBounds(ActiveClass* active_class,
+                          const Function& function,
+                          const Class& parameterized_class,
+                          const FunctionType& parameterized_signature,
+                          intptr_t type_parameter_count);
+
   const Type& ReceiverType(const Class& klass);
 
   void SetupFunctionParameters(const Class& klass,
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 3c934f6..7f0425a 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -1276,7 +1276,7 @@
 class ClosureData : public AllStatic {
  public:
   static word default_type_arguments_offset();
-  static word default_type_arguments_info_offset();
+  static word default_type_arguments_kind_offset();
   static word InstanceSize();
   static word NextFieldOffset();
 };
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index efd12ee..70016d86 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -113,7 +113,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 20;
+    ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -647,7 +647,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -1186,7 +1186,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 20;
+    ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -1717,7 +1717,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -2257,7 +2257,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -2796,7 +2796,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -3336,7 +3336,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 20;
+    ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -3864,7 +3864,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -4397,7 +4397,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 20;
+    ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -4922,7 +4922,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -5456,7 +5456,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -5989,7 +5989,7 @@
 static constexpr dart::compiler::target::word
     ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 40;
+    ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -6530,7 +6530,7 @@
 static constexpr dart::compiler::target::word
     AOT_ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 20;
+    AOT_ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 24;
@@ -7125,7 +7125,7 @@
 static constexpr dart::compiler::target::word
     AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -7726,7 +7726,7 @@
 static constexpr dart::compiler::target::word
     AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -8325,7 +8325,7 @@
 static constexpr dart::compiler::target::word
     AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -8923,7 +8923,7 @@
 static constexpr dart::compiler::target::word
     AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -9521,7 +9521,7 @@
 static constexpr dart::compiler::target::word
     AOT_ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 20;
+    AOT_ClosureData_default_type_arguments_kind_offset = 20;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 24;
@@ -10109,7 +10109,7 @@
 static constexpr dart::compiler::target::word
     AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -10703,7 +10703,7 @@
 static constexpr dart::compiler::target::word
     AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -11295,7 +11295,7 @@
 static constexpr dart::compiler::target::word
     AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -11886,7 +11886,7 @@
 static constexpr dart::compiler::target::word
     AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 40;
+    AOT_ClosureData_default_type_arguments_kind_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index e708265..d2dac49 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -89,7 +89,7 @@
   FIELD(Closure, hash_offset)                                                  \
   FIELD(Closure, instantiator_type_arguments_offset)                           \
   FIELD(ClosureData, default_type_arguments_offset)                            \
-  FIELD(ClosureData, default_type_arguments_info_offset)                       \
+  FIELD(ClosureData, default_type_arguments_kind_offset)                       \
   FIELD(Code, object_pool_offset)                                              \
   FIELD(Code, saved_instructions_offset)                                       \
   FIELD(Code, owner_offset)                                                    \
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 7a1788d..58072ba 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1424,6 +1424,9 @@
                                Object::null_function_type(),
                                type_parameter_count, klass->nnbd_mode());
 
+  T.LoadAndSetupBounds(&active_class_, Object::null_function(), *klass,
+                       Object::null_function_type(), type_parameter_count);
+
   // Set super type.  Some classes (e.g., Object) do not have one.
   Tag type_tag = helper_.ReadTag();  // read super class type (part 1).
   if (type_tag == kSomething) {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 4d07a98..e1e0d82 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -7057,18 +7057,16 @@
 }
 
 FunctionPtr Function::parent_function() const {
-  if (IsClosureFunction()) {
-    const Object& obj = Object::Handle(untag()->data());
-    ASSERT(!obj.IsNull());
-    return ClosureData::Cast(obj).parent_function();
-  }
-  return Function::null();
+  if (!IsClosureFunction()) return Function::null();
+  const Object& obj = Object::Handle(untag()->data());
+  ASSERT(!obj.IsNull());
+  return ClosureData::Cast(obj).parent_function();
 }
 
 void Function::set_parent_function(const Function& value) const {
+  ASSERT(IsClosureFunction());
   const Object& obj = Object::Handle(untag()->data());
   ASSERT(!obj.IsNull());
-  ASSERT(IsClosureFunction());
   ClosureData::Cast(obj).set_parent_function(value);
 }
 
@@ -7150,8 +7148,7 @@
       ClosureData::Handle(ClosureData::RawCast(untag()->data()));
   ASSERT(!closure_data.IsNull());
   if (kind_out != nullptr) {
-    *kind_out = DefaultTypeArgumentsKindField::decode(
-        closure_data.default_type_arguments_info());
+    *kind_out = closure_data.default_type_arguments_kind();
   }
   return closure_data.default_type_arguments();
 }
@@ -7163,13 +7160,9 @@
   const auto& closure_data =
       ClosureData::Handle(ClosureData::RawCast(untag()->data()));
   ASSERT(!closure_data.IsNull());
-  intptr_t updated_info = closure_data.default_type_arguments_info();
   auto kind = DefaultTypeArgumentsKindFor(value);
   ASSERT(kind != DefaultTypeArgumentsKind::kInvalid);
-  updated_info = DefaultTypeArgumentsKindField::update(kind, updated_info);
-  updated_info = NumParentTypeParametersField::update(NumParentTypeArguments(),
-                                                      updated_info);
-  closure_data.set_default_type_arguments_info(updated_info);
+  closure_data.set_default_type_arguments_kind(kind);
   // We could just store null for the ksharesFunction/kSharesInstantiator cases,
   // assuming all clients retrieve the DefaultTypeArgumentsKind to distinguish.
   closure_data.set_default_type_arguments(value);
@@ -7204,22 +7197,6 @@
   return function.ptr();
 }
 
-bool Function::HasGenericParent() const {
-  if (IsImplicitClosureFunction()) {
-    // The parent function of an implicit closure function is not the enclosing
-    // function we are asking about here.
-    return false;
-  }
-  Function& parent = Function::Handle(parent_function());
-  while (!parent.IsNull()) {
-    if (parent.IsGeneric()) {
-      return true;
-    }
-    parent = parent.parent_function();
-  }
-  return false;
-}
-
 FunctionPtr Function::implicit_closure_function() const {
   if (IsClosureFunction() || IsFactory() || IsDispatcherOrImplicitAccessor() ||
       IsFieldInitializer() || IsFfiTrampoline()) {
@@ -7721,17 +7698,9 @@
 }
 
 intptr_t Function::NumParentTypeArguments() const {
-  if (IsImplicitClosureFunction()) {
-    return 0;
-  }
-  Function& parent = Function::Handle(parent_function());
-  intptr_t num_parent_type_args = 0;
-  while (!parent.IsNull()) {
-    num_parent_type_args += parent.NumTypeParameters();
-    if (parent.IsImplicitClosureFunction()) break;
-    parent = parent.parent_function();
-  }
-  return num_parent_type_args;
+  // Don't allocate handle in cases where we know it is 0.
+  if (!IsClosureFunction()) return 0;
+  return FunctionType::Handle(signature()).NumParentTypeArguments();
 }
 
 TypeParameterPtr Function::LookupTypeParameter(const String& type_name,
@@ -8420,32 +8389,30 @@
     Heap::Space space,
     TrailPtr trail) const {
   ASSERT(IsFinalized() || IsBeingFinalized());
-  // A FunctionType cannot be part of a cycle (self-referencing typedefs are not
-  // allowed), therefore, the passed in trail does not need to be propagated to
-  // calls instantiating types of the signature.
   Zone* zone = Thread::Current()->zone();
-  // See the comment on kCurrentAndEnclosingFree to understand why we don't
-  // adjust 'num_free_fun_type_params' downward in this case.
   const intptr_t num_parent_type_args = NumParentTypeArguments();
   bool delete_type_parameters = false;
   if (num_free_fun_type_params == kCurrentAndEnclosingFree) {
+    // See the comment on kCurrentAndEnclosingFree to understand why we don't
+    // adjust 'num_free_fun_type_params' downward in this case.
     num_free_fun_type_params = kAllFree;
     delete_type_parameters = true;
   } else {
     ASSERT(!IsInstantiated(kAny, num_free_fun_type_params));
-    if (IsGeneric() || HasGenericParent()) {
-      // We only consider the function type parameters declared by the parents
-      // of this signature function as free.
-      if (num_parent_type_args < num_free_fun_type_params) {
-        num_free_fun_type_params = num_parent_type_args;
-      }
+    // We only consider the function type parameters declared by the parents
+    // of this signature function as free.
+    if (num_parent_type_args < num_free_fun_type_params) {
+      num_free_fun_type_params = num_parent_type_args;
     }
   }
 
-  // TODO(regis): Is this correct to use num_parent_type_args here?
-  // Or should it be 0 after instantiation?
+  // The number of parent type parameters that remain uninstantiated.
+  const intptr_t remaining_parent_type_params =
+      num_free_fun_type_params < num_parent_type_args
+          ? num_parent_type_args - num_free_fun_type_params
+          : 0;
   FunctionType& sig = FunctionType::Handle(
-      FunctionType::New(num_parent_type_args, nullability(), space));
+      FunctionType::New(remaining_parent_type_params, nullability(), space));
   AbstractType& type = AbstractType::Handle(zone);
 
   // Copy the type parameters and instantiate their bounds (if necessary).
@@ -8463,7 +8430,7 @@
         if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
           type = type.InstantiateFrom(instantiator_type_arguments,
                                       function_type_arguments,
-                                      num_free_fun_type_params, space);
+                                      num_free_fun_type_params, space, trail);
           // A returned null type indicates a failed instantiation in dead code
           // that must be propagated up to the caller, the optimizing compiler.
           if (type.IsNull()) {
@@ -8498,7 +8465,7 @@
   if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
     type = type.InstantiateFrom(instantiator_type_arguments,
                                 function_type_arguments,
-                                num_free_fun_type_params, space);
+                                num_free_fun_type_params, space, trail);
     // A returned null type indicates a failed instantiation in dead code that
     // must be propagated up to the caller, the optimizing compiler.
     if (type.IsNull()) {
@@ -8517,7 +8484,7 @@
     if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
       type = type.InstantiateFrom(instantiator_type_arguments,
                                   function_type_arguments,
-                                  num_free_fun_type_params, space);
+                                  num_free_fun_type_params, space, trail);
       // A returned null type indicates a failed instantiation in dead code that
       // must be propagated up to the caller, the optimizing compiler.
       if (type.IsNull()) {
@@ -9090,7 +9057,7 @@
   if (!HasInstantiatedSignature(kCurrentClass)) {
     instantiator_type_arguments = receiver.GetTypeArguments();
   }
-  ASSERT(HasInstantiatedSignature(kFunctions));  // No generic parent function.
+  ASSERT(!HasGenericParent());  // No generic parent function.
   return Closure::New(instantiator_type_arguments,
                       Object::null_type_arguments(), *this, context);
 }
@@ -9188,13 +9155,18 @@
   if (num_free_fun_type_params == kCurrentAndEnclosingFree) {
     num_free_fun_type_params = kAllFree;
   } else if (genericity != kCurrentClass) {
-    if (IsGeneric() || HasGenericParent()) {
-      // We only consider the function type parameters declared by the parents
-      // of this signature function as free.
-      const int num_parent_type_args = NumParentTypeArguments();
-      if (num_parent_type_args < num_free_fun_type_params) {
-        num_free_fun_type_params = num_parent_type_args;
-      }
+    const intptr_t num_parent_type_args = NumParentTypeArguments();
+    if (num_parent_type_args > 0 && num_free_fun_type_params > 0) {
+      // The number of parent type arguments is cached in the FunctionType, so
+      // we can't consider any FunctionType with free parent type arguments as
+      // fully instantiated. Instead, the FunctionType must be instantiated to
+      // reduce the number of parent type arguments, even if they're unused in
+      // its component types.
+      return false;
+    }
+    // Don't consider local function type parameters as free.
+    if (num_free_fun_type_params > num_parent_type_args) {
+      num_free_fun_type_params = num_parent_type_args;
     }
   }
   AbstractType& type = AbstractType::Handle(result_type());
@@ -9924,20 +9896,14 @@
   untag()->set_default_type_arguments(value.ptr());
 }
 
-intptr_t ClosureData::default_type_arguments_info() const {
-  const SmiPtr value = untag()->default_type_arguments_info();
-  if (value == Smi::null()) {
-    static_assert(Function::DefaultTypeArgumentsKindField::decode(0) ==
-                      Function::DefaultTypeArgumentsKind::kInvalid,
-                  "Returning valid value for null Smi");
-    return 0;
-  }
-  return Smi::Value(untag()->default_type_arguments_info());
+ClosureData::DefaultTypeArgumentsKind ClosureData::default_type_arguments_kind()
+    const {
+  return LoadNonPointer(&untag()->default_type_arguments_kind_);
 }
 
-void ClosureData::set_default_type_arguments_info(intptr_t value) const {
-  ASSERT(Smi::IsValid(value));
-  untag()->set_default_type_arguments_info(Smi::New(value));
+void ClosureData::set_default_type_arguments_kind(
+    DefaultTypeArgumentsKind value) const {
+  StoreNonPointer(&untag()->default_type_arguments_kind_, value);
 }
 
 ClosureDataPtr ClosureData::New() {
@@ -19467,7 +19433,7 @@
     case Nullability::kNonNullable:
       return "";
     case Nullability::kLegacy:
-      return (FLAG_show_internal_names || name_visibility == kInternalName)
+      return (FLAG_show_internal_names || name_visibility != kUserVisibleName)
                  ? "*"
                  : "";
     default:
@@ -19489,6 +19455,13 @@
   return Symbols::New(thread, printer.buffer());
 }
 
+StringPtr AbstractType::ScrubbedName() const {
+  Thread* thread = Thread::Current();
+  ZoneTextBuffer printer(thread->zone());
+  PrintName(kScrubbedName, &printer);
+  return Symbols::New(thread, printer.buffer());
+}
+
 void AbstractType::PrintName(NameVisibility name_visibility,
                              BaseTextBuffer* printer) const {
   if (IsTypeRef()) {
@@ -19498,11 +19471,9 @@
     ref_type.PrintName(name_visibility, printer);
     return;
   }
-  ASSERT(name_visibility != kScrubbedName);
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Class& cls = Class::Handle(zone);
-  String& name_str = String::Handle(zone);
   if (IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(*this);
     printer->AddString(String::Handle(type_param.name()).ToCString());
@@ -19528,14 +19499,7 @@
   cls = type_class();
   // Do not print the full vector, but only the declared type parameters.
   num_type_params = cls.NumTypeParameters();
-  if (name_visibility == kInternalName) {
-    name_str = cls.Name();
-    printer->AddString(name_str.ToCString());
-  } else {
-    ASSERT(name_visibility == kUserVisibleName);
-    // Map internal types to their corresponding public interfaces.
-    printer->AddString(cls.UserVisibleNameCString());
-  }
+  printer->AddString(cls.NameCString(name_visibility));
   if (num_type_params > num_args) {
     first_type_param_index = 0;
     if (!IsFinalized() || IsBeingFinalized()) {
@@ -21153,10 +21117,12 @@
         return false;
       }
       // Compare bounds.
+      if (TestAndAddBuddyToTrail(&trail, other_type_param)) {
+        return true;
+      }
       AbstractType& type = AbstractType::Handle(bound());
       AbstractType& other_type = AbstractType::Handle(other_type_param.bound());
-      if (!TestAndAddBuddyToTrail(&trail, other_type_param) &&
-          !type.IsEquivalent(other_type, kind, trail)) {
+      if (!type.IsEquivalent(other_type, kind, trail)) {
         return false;
       }
       if (kind == TypeEquality::kCanonical) {
@@ -21200,11 +21166,13 @@
       }
     }
     // Compare bounds.
+    if (TestAndAddBuddyToTrail(&trail, other_type_param)) {
+      return true;
+    }
     AbstractType& upper_bound = AbstractType::Handle(bound());
     AbstractType& other_type_param_upper_bound =
         AbstractType::Handle(other_type_param.bound());
-    if (!TestAndAddBuddyToTrail(&trail, other_type_param) &&
-        !upper_bound.IsEquivalent(other_type_param_upper_bound, kind, trail)) {
+    if (!upper_bound.IsEquivalent(other_type_param_upper_bound, kind, trail)) {
       return false;
     }
   }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 535c62e..740afd0 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2599,7 +2599,7 @@
   // Generic dispatchers only set the number without actual type parameters.
   bool IsGeneric() const { return NumTypeParameters() > 0; }
   // Return true if any parent function of this function is generic.
-  bool HasGenericParent() const;
+  bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
 
   // Not thread-safe; must be called in the main thread.
   // Sets function's code and code's function.
@@ -2677,41 +2677,8 @@
   // Enclosing function of this local function.
   FunctionPtr parent_function() const;
 
-  enum class DefaultTypeArgumentsKind : uint8_t {
-    // Only here to make sure it's explicitly set appropriately.
-    kInvalid = 0,
-    // Must instantiate the default type arguments before use.
-    kNeedsInstantiation,
-    // The default type arguments are already instantiated.
-    kIsInstantiated,
-    // Use the instantiator type arguments that would be used to instantiate
-    // the default type arguments, as instantiating produces the same result.
-    kSharesInstantiatorTypeArguments,
-    // Use the function type arguments that would be used to instantiate
-    // the default type arguments, as instantiating produces the same result.
-    kSharesFunctionTypeArguments,
-  };
-  static constexpr intptr_t kDefaultTypeArgumentsKindFieldSize = 3;
-  static_assert(static_cast<uint8_t>(
-                    DefaultTypeArgumentsKind::kSharesFunctionTypeArguments) <
-                    (1 << kDefaultTypeArgumentsKindFieldSize),
-                "Wrong bit size chosen for default TAV kind field");
-
-  // Fields encoded in an integer stored alongside a default TAV. The size of
-  // the integer should be <= the size of a target Smi.
-  using DefaultTypeArgumentsKindField =
-      BitField<intptr_t,
-               DefaultTypeArgumentsKind,
-               0,
-               kDefaultTypeArgumentsKindFieldSize>;
-  // TODO(regis): Rename to NumParentTypeArgumentsField.
-  // Just use the rest of the space for the number of parent type parameters.
-  using NumParentTypeParametersField =
-      BitField<intptr_t,
-               intptr_t,
-               DefaultTypeArgumentsKindField::kNextBit,
-               compiler::target::kSmiBits -
-                   DefaultTypeArgumentsKindField::kNextBit>;
+  using DefaultTypeArgumentsKind =
+      UntaggedClosureData::DefaultTypeArgumentsKind;
 
   // Returns a canonicalized vector of the type parameters instantiated
   // to bounds. If non-generic, the empty type arguments vector is returned.
@@ -3763,10 +3730,13 @@
   static intptr_t default_type_arguments_offset() {
     return OFFSET_OF(UntaggedClosureData, default_type_arguments_);
   }
-  static intptr_t default_type_arguments_info_offset() {
-    return OFFSET_OF(UntaggedClosureData, default_type_arguments_info_);
+  static intptr_t default_type_arguments_kind_offset() {
+    return OFFSET_OF(UntaggedClosureData, default_type_arguments_kind_);
   }
 
+  using DefaultTypeArgumentsKind =
+      UntaggedClosureData::DefaultTypeArgumentsKind;
+
  private:
   ContextScopePtr context_scope() const { return untag()->context_scope_; }
   void set_context_scope(const ContextScope& value) const;
@@ -3785,8 +3755,8 @@
   }
   void set_default_type_arguments(const TypeArguments& value) const;
 
-  intptr_t default_type_arguments_info() const;
-  void set_default_type_arguments_info(intptr_t value) const;
+  DefaultTypeArgumentsKind default_type_arguments_kind() const;
+  void set_default_type_arguments_kind(DefaultTypeArgumentsKind value) const;
 
   static ClosureDataPtr New();
 
@@ -7712,6 +7682,10 @@
   // Names of internal classes are mapped to their public interfaces.
   virtual StringPtr UserVisibleName() const;
 
+  // The name of this type, including the names of its type arguments, if any.
+  // Privacy suffixes are dropped.
+  virtual StringPtr ScrubbedName() const;
+
   // Return the internal or public name of this type, including the names of its
   // type arguments, if any.
   void PrintName(NameVisibility visibility, BaseTextBuffer* printer) const;
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 5bf6bc9..adc346f 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1216,9 +1216,29 @@
                 closure)  // Closure object for static implicit closures.
   // Instantiate-to-bounds TAV for use when no TAV is provided.
   POINTER_FIELD(TypeArgumentsPtr, default_type_arguments)
-  // Additional information about the instantiate-to-bounds TAV.
-  POINTER_FIELD(SmiPtr, default_type_arguments_info)
-  VISIT_TO(ObjectPtr, default_type_arguments_info)
+  VISIT_TO(ObjectPtr, default_type_arguments)
+
+  enum class DefaultTypeArgumentsKind : uint8_t {
+    // Only here to make sure it's explicitly set appropriately.
+    kInvalid = 0,
+    // Must instantiate the default type arguments before use.
+    kNeedsInstantiation,
+    // The default type arguments are already instantiated.
+    kIsInstantiated,
+    // Use the instantiator type arguments that would be used to instantiate
+    // the default type arguments, as instantiating produces the same result.
+    kSharesInstantiatorTypeArguments,
+    // Use the function type arguments that would be used to instantiate
+    // the default type arguments, as instantiating produces the same result.
+    kSharesFunctionTypeArguments,
+  };
+
+  // kernel_to_il.cc assumes we can load the untagged value and box it in a Smi.
+  static_assert(sizeof(DefaultTypeArgumentsKind) * kBitsPerByte <=
+                    compiler::target::kSmiBits,
+                "Default type arguments kind must fit in a Smi");
+
+  DefaultTypeArgumentsKind default_type_arguments_kind_;
 
   friend class Function;
 };
@@ -2348,6 +2368,8 @@
   static constexpr intptr_t kMaxOptionalParametersBits =
       UntaggedFunction::kMaxOptionalParametersBits;
 
+  // The bit fields are public for use in kernel_to_il.cc.
+ public:
   typedef BitField<uint32_t, uint8_t, 0, kMaxParentTypeArgumentsBits>
       PackedNumParentTypeArguments;
   typedef BitField<uint32_t,
@@ -2378,6 +2400,7 @@
                 "In-place mask for number of optional parameters cannot fit in "
                 "a Smi on the target architecture");
 
+ private:
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   friend class Function;
diff --git a/sdk_args.gni b/sdk_args.gni
index 2776011..736f414 100644
--- a/sdk_args.gni
+++ b/sdk_args.gni
@@ -18,7 +18,13 @@
   #
   # to out/ReleaseX64/args.gn. The path above can be extracted from the `.git`
   # file under the git worktree folder.
-  default_git_folder = "$_dart_root/.git"
+  # The script run here should take care of everything automatically though.
+  default_git_folder = exec_script("$_dart_root/tools/get_dot_git_folder.py",
+                                   [
+                                     rebase_path("$_dart_root/.git"),
+                                     "$_dart_root/.git",
+                                   ],
+                                   "trim string")
 
   # Whether to enable the SDK hash check that will prevent loading a kernel
   # into a VM which was built with a different SDK.
diff --git a/tests/ffi/unaligned_test.dart b/tests/ffi/unaligned_test.dart
new file mode 100644
index 0000000..3220003
--- /dev/null
+++ b/tests/ffi/unaligned_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This tests exercises misaligned reads/writes on memory.
+//
+// The only architecture on which this is known to fail is arm32 on Android.
+
+import 'dart:ffi';
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+import 'package:ffi/ffi.dart';
+
+void main() {
+  print("hello");
+  testUnalignedInt16(); //# 01: ok
+  testUnalignedInt32(); //# 02: ok
+  testUnalignedInt64(); //# 03: ok
+  if (!Platform.isAndroid || sizeOf<Pointer>() == 8) {
+    // TODO(http://dartbug.com/45009): Support unaligned reads/writes on
+    // Android arm32.
+    testUnalignedFloat(); //# 04: ok
+    testUnalignedDouble(); //# 05: ok
+  }
+  _freeAll();
+}
+
+void testUnalignedInt16() {
+  final pointer = _allocateUnaligned<Int16>();
+  pointer.value = 20;
+  Expect.equals(20, pointer.value);
+}
+
+void testUnalignedInt32() {
+  final pointer = _allocateUnaligned<Int32>();
+  pointer.value = 20;
+  Expect.equals(20, pointer.value);
+}
+
+void testUnalignedInt64() {
+  final pointer = _allocateUnaligned<Int64>();
+  pointer.value = 20;
+  Expect.equals(20, pointer.value);
+}
+
+void testUnalignedFloat() {
+  final pointer = _allocateUnaligned<Float>();
+  pointer.value = 20.0;
+  Expect.approxEquals(20.0, pointer.value);
+}
+
+void testUnalignedDouble() {
+  final pointer = _allocateUnaligned<Double>();
+  pointer.value = 20.0;
+  Expect.equals(20.0, pointer.value);
+}
+
+final Set<Pointer> _pool = {};
+
+void _freeAll() {
+  for (final pointer in _pool) {
+    calloc.free(pointer);
+  }
+}
+
+/// Up to `size<T>() == 8`.
+Pointer<T> _allocateUnaligned<T extends NativeType>() {
+  final pointer = calloc<Int8>(16);
+  _pool.add(pointer);
+  final misaligned = pointer.elementAt(1).cast<T>();
+  Expect.equals(1, misaligned.address % 2);
+  return misaligned;
+}
diff --git a/tests/ffi_2/unaligned_test.dart b/tests/ffi_2/unaligned_test.dart
new file mode 100644
index 0000000..3220003
--- /dev/null
+++ b/tests/ffi_2/unaligned_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This tests exercises misaligned reads/writes on memory.
+//
+// The only architecture on which this is known to fail is arm32 on Android.
+
+import 'dart:ffi';
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+import 'package:ffi/ffi.dart';
+
+void main() {
+  print("hello");
+  testUnalignedInt16(); //# 01: ok
+  testUnalignedInt32(); //# 02: ok
+  testUnalignedInt64(); //# 03: ok
+  if (!Platform.isAndroid || sizeOf<Pointer>() == 8) {
+    // TODO(http://dartbug.com/45009): Support unaligned reads/writes on
+    // Android arm32.
+    testUnalignedFloat(); //# 04: ok
+    testUnalignedDouble(); //# 05: ok
+  }
+  _freeAll();
+}
+
+void testUnalignedInt16() {
+  final pointer = _allocateUnaligned<Int16>();
+  pointer.value = 20;
+  Expect.equals(20, pointer.value);
+}
+
+void testUnalignedInt32() {
+  final pointer = _allocateUnaligned<Int32>();
+  pointer.value = 20;
+  Expect.equals(20, pointer.value);
+}
+
+void testUnalignedInt64() {
+  final pointer = _allocateUnaligned<Int64>();
+  pointer.value = 20;
+  Expect.equals(20, pointer.value);
+}
+
+void testUnalignedFloat() {
+  final pointer = _allocateUnaligned<Float>();
+  pointer.value = 20.0;
+  Expect.approxEquals(20.0, pointer.value);
+}
+
+void testUnalignedDouble() {
+  final pointer = _allocateUnaligned<Double>();
+  pointer.value = 20.0;
+  Expect.equals(20.0, pointer.value);
+}
+
+final Set<Pointer> _pool = {};
+
+void _freeAll() {
+  for (final pointer in _pool) {
+    calloc.free(pointer);
+  }
+}
+
+/// Up to `size<T>() == 8`.
+Pointer<T> _allocateUnaligned<T extends NativeType>() {
+  final pointer = calloc<Int8>(16);
+  _pool.add(pointer);
+  final misaligned = pointer.elementAt(1).cast<T>();
+  Expect.equals(1, misaligned.address % 2);
+  return misaligned;
+}
diff --git a/tests/language/regress/regress45313_test.dart b/tests/language/regress/regress45313_test.dart
new file mode 100644
index 0000000..0c6a5a1
--- /dev/null
+++ b/tests/language/regress/regress45313_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=generic-metadata
+
+import "package:expect/expect.dart";
+
+typedef TEST_TYPEDEF<TT extends T Function<T>(T)> = void
+    Function<TTT extends TT>();
+void testme<TT extends T Function<T>(T)>() {}
+
+main() {
+  Expect.isTrue(testme is TEST_TYPEDEF);
+  TEST_TYPEDEF ttttt = testme;
+  Expect.isTrue(ttttt is TEST_TYPEDEF);
+}
diff --git a/tools/VERSION b/tools/VERSION
index b04191b..7948628 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 143
+PRERELEASE 144
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/get_dot_git_folder.py b/tools/get_dot_git_folder.py
new file mode 100755
index 0000000..443addbf
--- /dev/null
+++ b/tools/get_dot_git_folder.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+# Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+#
+# This python script is a wrapper around `git rev-parse --resolve-git-dir`.
+# This is used for the build system to work with git worktrees.
+
+import sys
+import subprocess
+import os
+import utils
+
+
+def main():
+    try:
+        if len(sys.argv) != 3:
+            raise Exception('Expects exactly 2 arguments.')
+        args = ['git', 'rev-parse', '--resolve-git-dir', sys.argv[1]]
+
+        windows = utils.GuessOS() == 'win32'
+        if windows:
+            process = subprocess.Popen(args,
+                                       stdout=subprocess.PIPE,
+                                       stderr=subprocess.PIPE,
+                                       stdin=subprocess.PIPE,
+                                       shell=True)
+        else:
+            process = subprocess.Popen(args,
+                                       stdout=subprocess.PIPE,
+                                       stderr=subprocess.PIPE,
+                                       stdin=subprocess.PIPE,
+                                       shell=False)
+
+        outs, _ = process.communicate()
+
+        if process.returncode != 0:
+            raise Exception('Got non-0 exit code from git.')
+
+        print(outs.strip())
+    except:
+        # Fall back to fall-back path.
+        print(sys.argv[2])
+
+
+if __name__ == '__main__':
+    sys.exit(main())