Version 2.18.0-67.0.dev

Merge commit '08c60454c1f3de61c474ee1663d9cd6dcd751c5d' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 689dd80..74c2841 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -860,7 +860,8 @@
     // Optionally add Flutter child widget details.
     // todo (pq): revisit this special casing; likely it can be generalized away
     var element = parameter.enclosingElement;
-    if (element is ConstructorElement) {
+    // If appendColon is false, default values should never be appended.
+    if (element is ConstructorElement && appendColon) {
       if (Flutter.instance.isWidget(element.enclosingElement)) {
         // Don't bother with nullability. It won't affect default list values.
         var defaultValue =
diff --git a/pkg/analysis_server/test/lsp/completion_dart_test.dart b/pkg/analysis_server/test/lsp/completion_dart_test.dart
index 66574a8..3a55f69 100644
--- a/pkg/analysis_server/test/lsp/completion_dart_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_dart_test.dart
@@ -1117,6 +1117,53 @@
     expect(res.items.map((item) => item.label).contains('aaa'), isTrue);
   }
 
+  Future<void> test_namedArg_flutterChildren() async {
+    final content = '''
+import 'package:flutter/widgets.dart';
+
+final a = Flex(c^);
+''';
+
+    final expectedContent = '''
+import 'package:flutter/widgets.dart';
+
+final a = Flex(children: [^],);
+''';
+
+    await verifyCompletions(
+      mainFileUri,
+      content,
+      expectCompletions: ['children: []'],
+      applyEditsFor: 'children: []',
+      expectedContent: expectedContent,
+    );
+  }
+
+  Future<void> test_namedArg_flutterChildren_existingValue() async {
+    // Flutter's widget classes have special handling that adds `[]` after the
+    // children named arg, but this should not occur if there's already a value
+    // for this named arg.
+    final content = '''
+import 'package:flutter/widgets.dart';
+
+final a = Flex(c^: []);
+''';
+
+    final expectedContent = '''
+import 'package:flutter/widgets.dart';
+
+final a = Flex(children: []);
+''';
+
+    await verifyCompletions(
+      mainFileUri,
+      content,
+      expectCompletions: ['children'],
+      applyEditsFor: 'children',
+      expectedContent: expectedContent,
+    );
+  }
+
   Future<void> test_namedArg_insertReplaceRanges() async {
     /// Helper to check multiple completions in the same template file.
     Future<void> check(
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index ed5279a..57dca5f 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -216,6 +216,28 @@
     ]);
   }
 
+  Future<void>
+      test_flutter_InstanceCreationExpression_children_existingValue() async {
+    // Ensure we don't include list markers if there's already a value.
+    writeTestPackageConfig(flutter: true);
+
+    addTestSource('''
+import 'package:flutter/material.dart';
+
+build() => new Row(
+    ch^: []
+  );
+''');
+
+    var response = await computeSuggestions2();
+    _checkNamedArguments(response).containsMatch(
+      (suggestion) => suggestion
+        ..completion.isEqualTo('children')
+        ..defaultArgumentListString.isNull
+        ..hasSelection(offset: 8),
+    );
+  }
+
   Future<void> test_flutter_InstanceCreationExpression_children_Map() async {
     // Ensure we don't generate Map params for a future API
     writeTestPackageConfig(flutter: true);
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index a0f91f2..c203686 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -48,7 +48,7 @@
 
 /// A concrete implementation of a [ClassElement].
 abstract class AbstractClassElementImpl extends _ExistingElementImpl
-    with TypeParameterizedElementMixin, HasCompletionData
+    with TypeParameterizedElementMixin, HasCompletionData, MacroTargetElement
     implements ClassElement {
   /// The superclass of the class, or `null` for [Object].
   InterfaceType? _supertype;
@@ -78,9 +78,6 @@
   List<InterfaceType>? Function(AbstractClassElementImpl)?
       mixinInferenceCallback;
 
-  /// Errors registered while applying macros to this element.
-  List<MacroApplicationError> macroApplicationErrors = [];
-
   /// Initialize a newly created class element to have the given [name] at the
   /// given [offset] in the file that contains the declaration of this element.
   AbstractClassElementImpl(String name, int offset) : super(name, offset);
@@ -4155,6 +4152,11 @@
       visitor.visitLocalVariableElement(this);
 }
 
+mixin MacroTargetElement {
+  /// Errors registered while applying macros to this element.
+  List<MacroApplicationError> macroApplicationErrors = [];
+}
+
 /// A concrete implementation of a [MethodElement].
 class MethodElementImpl extends ExecutableElementImpl implements MethodElement {
   /// Is `true` if this method is `operator==`, and there is no explicit
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
index 2e85266..e6bd686 100644
--- a/pkg/analyzer/lib/src/dart/scanner/scanner.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -221,5 +221,7 @@
               enableExtensionMethods:
                   featureSet.isEnabled(Feature.extension_methods),
               enableTripleShift: featureSet.isEnabled(Feature.triple_shift),
-              enableNonNullable: featureSet.isEnabled(Feature.non_nullable));
+              enableNonNullable: featureSet.isEnabled(Feature.non_nullable),
+              forAugmentationLibrary: featureSet.isEnabled(Feature.macros),
+            );
 }
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 3f1f4a4..8864dac 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -182,8 +182,14 @@
       return;
     }
 
-    var applier = LibraryMacroApplier(this);
-    var augmentationLibrary = await applier.executeMacroTypesPhase();
+    final macroExecutor = linker.macroExecutor;
+    if (macroExecutor == null) {
+      return;
+    }
+
+    var applier = LibraryMacroApplier(macroExecutor, this);
+    await applier.buildApplications();
+    var augmentationLibrary = await applier.executeTypesPhase();
     if (augmentationLibrary == null) {
       return;
     }
diff --git a/pkg/analyzer/lib/src/summary2/macro.dart b/pkg/analyzer/lib/src/summary2/macro.dart
index bf4756d..c9931b4 100644
--- a/pkg/analyzer/lib/src/summary2/macro.dart
+++ b/pkg/analyzer/lib/src/summary2/macro.dart
@@ -58,13 +58,14 @@
     required String className,
     required String constructorName,
     required macro.Arguments arguments,
-    required macro.Declaration declaration,
     required macro.IdentifierResolver identifierResolver,
+    required macro.DeclarationKind declarationKind,
+    required macro.Declaration declaration,
   }) async {
     var instanceIdentifier = await macroExecutor.instantiateMacro(
         libraryUri, className, constructorName, arguments);
-    return MacroClassInstance._(
-        this, identifierResolver, declaration, instanceIdentifier);
+    return MacroClassInstance._(this, identifierResolver, instanceIdentifier,
+        declarationKind, declaration);
   }
 }
 
@@ -81,14 +82,16 @@
 class MacroClassInstance {
   final BundleMacroExecutor _bundleExecutor;
   final macro.IdentifierResolver _identifierResolver;
-  final macro.Declaration _declaration;
   final macro.MacroInstanceIdentifier _instanceIdentifier;
+  final macro.DeclarationKind _declarationKind;
+  final macro.Declaration _declaration;
 
   MacroClassInstance._(
     this._bundleExecutor,
     this._identifierResolver,
-    this._declaration,
     this._instanceIdentifier,
+    this._declarationKind,
+    this._declaration,
   );
 
   Future<macro.MacroExecutionResult> executeTypesPhase() async {
@@ -96,6 +99,10 @@
     return await executor.executeTypesPhase(
         _instanceIdentifier, _declaration, _identifierResolver);
   }
+
+  bool shouldExecute(macro.Phase phase) {
+    return _instanceIdentifier.shouldExecute(_declarationKind, phase);
+  }
 }
 
 abstract class MacroFileEntry {
diff --git a/pkg/analyzer/lib/src/summary2/macro_application.dart b/pkg/analyzer/lib/src/summary2/macro_application.dart
index d9719b2..15da245 100644
--- a/pkg/analyzer/lib/src/summary2/macro_application.dart
+++ b/pkg/analyzer/lib/src/summary2/macro_application.dart
@@ -6,6 +6,7 @@
 import 'package:_fe_analyzer_shared/src/macros/executor.dart' as macro;
 import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart'
     as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart';
 import 'package:_fe_analyzer_shared/src/macros/executor/protocol.dart' as macro;
 import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart'
     as macro;
@@ -13,95 +14,71 @@
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/summary2/library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
 import 'package:analyzer/src/summary2/macro.dart';
 import 'package:analyzer/src/summary2/macro_application_error.dart';
 
 class LibraryMacroApplier {
+  final MultiMacroExecutor macroExecutor;
   final LibraryBuilder libraryBuilder;
 
+  final Map<MacroTargetElement, List<MacroApplication>> _applications =
+      Map.identity();
+
   final Map<ClassDeclaration, macro.ClassDeclaration> _classDeclarations = {};
 
-  LibraryMacroApplier(this.libraryBuilder);
+  LibraryMacroApplier(this.macroExecutor, this.libraryBuilder);
 
-  /// TODO(scheglov) check `shouldExecute`.
-  /// TODO(scheglov) check `supportsDeclarationKind`.
-  Future<String?> executeMacroTypesPhase() async {
-    var macroResults = <macro.MacroExecutionResult>[];
-    for (var unitElement in libraryBuilder.element.units) {
-      for (var classElement in unitElement.classes) {
+  Linker get _linker => libraryBuilder.linker;
+
+  /// Fill [_applications]s with macro applications.
+  Future<void> buildApplications() async {
+    for (final unitElement in libraryBuilder.element.units) {
+      for (final classElement in unitElement.classes) {
         classElement as ClassElementImpl;
-        var classNode = libraryBuilder.linker.elementNodes[classElement];
+        final classNode = _linker.elementNodes[classElement];
         // TODO(scheglov) support other declarations
         if (classNode is ClassDeclaration) {
-          var annotationList = classNode.metadata;
-          for (var i = 0; i < annotationList.length; i++) {
-            final annotation = annotationList[i];
-            var annotationNameNode = annotation.name;
-            var argumentsNode = annotation.arguments;
-            if (annotationNameNode is SimpleIdentifier &&
-                argumentsNode != null) {
-              // TODO(scheglov) Create a Scope.
-              for (var import in libraryBuilder.element.imports) {
-                var importedLibrary = import.importedLibrary;
-                if (importedLibrary is LibraryElementImpl) {
-                  var importedUri = importedLibrary.source.uri;
-                  if (!libraryBuilder.linker.builders
-                      .containsKey(importedUri)) {
-                    var lookupResult = importedLibrary.scope.lookup(
-                      annotationNameNode.name,
-                    );
-                    var getter = lookupResult.getter;
-                    if (getter is ClassElementImpl && getter.isMacro) {
-                      var macroExecutor = importedLibrary.bundleMacroExecutor;
-                      if (macroExecutor != null) {
-                        try {
-                          final arguments = _buildArguments(
-                            annotationIndex: i,
-                            node: argumentsNode,
-                          );
-                          final macroResult = await _runSingleMacro(
-                            macroExecutor,
-                            getClassDeclaration(classNode),
-                            getter,
-                            arguments,
-                          );
-                          if (macroResult.isNotEmpty) {
-                            macroResults.add(macroResult);
-                          }
-                        } on MacroApplicationError catch (e) {
-                          classElement.macroApplicationErrors.add(e);
-                        } on macro.RemoteException catch (e) {
-                          classElement.macroApplicationErrors.add(
-                            UnknownMacroApplicationError(
-                              annotationIndex: i,
-                              message: e.error,
-                              stackTrace: e.stackTrace ?? '<null>',
-                            ),
-                          );
-                        } catch (e, stackTrace) {
-                          classElement.macroApplicationErrors.add(
-                            UnknownMacroApplicationError(
-                              annotationIndex: i,
-                              message: e.toString(),
-                              stackTrace: stackTrace.toString(),
-                            ),
-                          );
-                        }
-                      }
-                    }
+          await _buildApplications(
+            classElement,
+            classNode.metadata,
+            () => getClassDeclaration(classNode),
+          );
+        }
+      }
+    }
+  }
+
+  Future<String?> executeTypesPhase() async {
+    final results = <macro.MacroExecutionResult>[];
+    for (final unitElement in libraryBuilder.element.units) {
+      for (final classElement in unitElement.classes) {
+        classElement as ClassElementImpl;
+        final applications = _applications[classElement];
+        if (applications != null) {
+          for (final application in applications) {
+            if (application.shouldExecute(macro.Phase.types)) {
+              await _runWithCatchingExceptions(
+                () async {
+                  final result = await application.instance.executeTypesPhase();
+                  if (result.isNotEmpty) {
+                    results.add(result);
                   }
-                }
-              }
+                },
+                annotationIndex: application.annotationIndex,
+                onError: (error) {
+                  classElement.macroApplicationErrors.add(error);
+                },
+              );
             }
           }
         }
       }
     }
 
-    var macroExecutor = libraryBuilder.linker.macroExecutor;
-    if (macroExecutor != null && macroResults.isNotEmpty) {
-      var code = macroExecutor.buildAugmentationLibrary(
-        macroResults,
+    if (results.isNotEmpty) {
+      final code = macroExecutor.buildAugmentationLibrary(
+        results,
         _resolveIdentifier,
         _inferOmittedType,
       );
@@ -110,10 +87,103 @@
     return null;
   }
 
+  /// TODO(scheglov) Do we need this caching?
+  /// Or do we need it only during macro applications creation?
   macro.ClassDeclaration getClassDeclaration(ClassDeclaration node) {
     return _classDeclarations[node] ??= _buildClassDeclaration(node);
   }
 
+  /// If there are any macro applications in [annotations], record for the
+  /// [targetElement] in [_applications], for future execution.
+  Future<void> _buildApplications(
+    MacroTargetElement targetElement,
+    List<Annotation> annotations,
+    macro.Declaration Function() getDeclaration,
+  ) async {
+    final applications = <MacroApplication>[];
+    for (var i = 0; i < annotations.length; i++) {
+      final annotation = annotations[i];
+      final macroElement = _importedMacroElement(annotation.name);
+      final argumentsNode = annotation.arguments;
+      if (macroElement is ClassElementImpl && argumentsNode != null) {
+        final importedLibrary = macroElement.library;
+        final macroExecutor = importedLibrary.bundleMacroExecutor;
+        if (macroExecutor != null) {
+          await _runWithCatchingExceptions(
+            () async {
+              final arguments = _buildArguments(
+                annotationIndex: i,
+                node: argumentsNode,
+              );
+              final declaration = getDeclaration();
+              final macroInstance = await macroExecutor.instantiate(
+                libraryUri: macroElement.librarySource.uri,
+                className: macroElement.name,
+                constructorName: '', // TODO
+                arguments: arguments,
+                identifierResolver: _FakeIdentifierResolver(),
+                declarationKind: macro.DeclarationKind.clazz,
+                declaration: declaration,
+              );
+              applications.add(
+                MacroApplication(
+                  annotationIndex: i,
+                  instance: macroInstance,
+                ),
+              );
+            },
+            annotationIndex: i,
+            onError: (error) {
+              targetElement.macroApplicationErrors.add(error);
+            },
+          );
+        }
+      }
+    }
+    if (applications.isNotEmpty) {
+      _applications[targetElement] = applications;
+    }
+  }
+
+  /// Return the macro element referenced by the [node].
+  ElementImpl? _importedMacroElement(Identifier node) {
+    final String? prefix;
+    final String name;
+    if (node is PrefixedIdentifier) {
+      prefix = node.prefix.name;
+      name = node.identifier.name;
+    } else if (node is SimpleIdentifier) {
+      prefix = null;
+      name = node.name;
+    } else {
+      throw StateError('${node.runtimeType} $node');
+    }
+
+    for (final import in libraryBuilder.element.imports) {
+      if (import.prefix?.name != prefix) {
+        continue;
+      }
+
+      final importedLibrary = import.importedLibrary;
+      if (importedLibrary == null) {
+        continue;
+      }
+
+      // Skip if a library that is being linked.
+      final importedUri = importedLibrary.source.uri;
+      if (_linker.builders.containsKey(importedUri)) {
+        continue;
+      }
+
+      final lookupResult = importedLibrary.scope.lookup(name);
+      final element = lookupResult.getter;
+      if (element is ClassElementImpl && element.isMacro) {
+        return element;
+      }
+    }
+    return null;
+  }
+
   macro.TypeAnnotation _inferOmittedType(
     macro.OmittedTypeAnnotation omittedType,
   ) {
@@ -124,23 +194,6 @@
     throw UnimplementedError();
   }
 
-  Future<macro.MacroExecutionResult> _runSingleMacro(
-    BundleMacroExecutor macroExecutor,
-    macro.Declaration declaration,
-    ClassElementImpl classElement,
-    macro.Arguments arguments,
-  ) async {
-    var macroInstance = await macroExecutor.instantiate(
-      libraryUri: classElement.librarySource.uri,
-      className: classElement.name,
-      constructorName: '', // TODO
-      arguments: arguments,
-      declaration: declaration,
-      identifierResolver: _FakeIdentifierResolver(),
-    );
-    return await macroInstance.executeTypesPhase();
-  }
-
   static macro.Arguments _buildArguments({
     required int annotationIndex,
     required ArgumentList node,
@@ -278,6 +331,47 @@
       return const [];
     }
   }
+
+  /// Run the [body], report exceptions as [MacroApplicationError]s to [onError].
+  static Future<void> _runWithCatchingExceptions<T>(
+    Future<T> Function() body, {
+    required int annotationIndex,
+    required void Function(MacroApplicationError) onError,
+  }) async {
+    try {
+      await body();
+    } on MacroApplicationError catch (e) {
+      onError(e);
+    } on macro.RemoteException catch (e) {
+      onError(
+        UnknownMacroApplicationError(
+          annotationIndex: annotationIndex,
+          message: e.error,
+          stackTrace: e.stackTrace ?? '<null>',
+        ),
+      );
+    } catch (e, stackTrace) {
+      onError(
+        UnknownMacroApplicationError(
+          annotationIndex: annotationIndex,
+          message: e.toString(),
+          stackTrace: stackTrace.toString(),
+        ),
+      );
+    }
+  }
+}
+
+class MacroApplication {
+  final int annotationIndex;
+  final MacroClassInstance instance;
+
+  MacroApplication({
+    required this.annotationIndex,
+    required this.instance,
+  });
+
+  bool shouldExecute(macro.Phase phase) => instance.shouldExecute(phase);
 }
 
 /// Helper class for evaluating arguments for a single constructor based
diff --git a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
index 48deb10..6f7b7b7 100644
--- a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
@@ -233,7 +233,6 @@
     _assertSource("abstract macro class C {}", declaration);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/48541')
   void test_visitClassDeclaration_augment() {
     var findNode = _parseStringToFindNode(r'''
 augment class A {}
@@ -461,7 +460,6 @@
             isMacro: true));
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/48541')
   void test_visitClassTypeAlias_augment() {
     var findNode = _parseStringToFindNode(r'''
 augment class A = S with M;
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart
index fe971f4..c4ea903 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart
@@ -356,4 +356,34 @@
     // regardless of whether the experiment is enabled.
     assertType(findNode.simple('i; // (2)'), 'int?');
   }
+
+  test_write_capture_deferred_redirecting_constructor() async {
+    await assertNoErrorsInCode('''
+class C {
+  C(int? i) : this.other(i!, () { i = null; }, i);
+  C.other(Object? x, void Function() g, Object? y);
+}
+''');
+    // With the feature enabled, analysis of the closure is deferred until after
+    // all the other arguments to `this.other`, so the `i` passed to `y` is not
+    // yet write captured and retains its promoted value.  With the experiment
+    // disabled, it is write captured immediately.
+    assertType(findNode.simple('i);'), _isEnabled ? 'int' : 'int?');
+  }
+
+  test_write_capture_deferred_super_constructor() async {
+    await assertNoErrorsInCode('''
+class B {
+  B(Object? x, void Function() g, Object? y);
+}
+class C extends B {
+  C(int? i) : super(i!, () { i = null; }, i);
+}
+''');
+    // With the feature enabled, analysis of the closure is deferred until after
+    // all the other arguments to `this.other`, so the `i` passed to `y` is not
+    // yet write captured and retains its promoted value.  With the experiment
+    // disabled, it is write captured immediately.
+    assertType(findNode.simple('i);'), _isEnabled ? 'int' : 'int?');
+  }
 }
diff --git a/pkg/analyzer/test/src/fasta/ast_builder_test.dart b/pkg/analyzer/test/src/fasta/ast_builder_test.dart
index 8c4659e..b1cbcbd 100644
--- a/pkg/analyzer/test/src/fasta/ast_builder_test.dart
+++ b/pkg/analyzer/test/src/fasta/ast_builder_test.dart
@@ -15,7 +15,6 @@
 
 @reflectiveTest
 class AstBuilderTest extends ParserDiagnosticsTest {
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/48541')
   void test_class_augment() {
     var parseResult = parseStringWithErrors(r'''
 augment class A {}
diff --git a/pkg/analyzer/test/src/summary/macro_test.dart b/pkg/analyzer/test/src/summary/macro_test.dart
index e2dd9f2..e073d88 100644
--- a/pkg/analyzer/test/src/summary/macro_test.dart
+++ b/pkg/analyzer/test/src/summary/macro_test.dart
@@ -63,6 +63,131 @@
     );
   }
 
+  test_application_newInstance_withoutPrefix() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import 'dart:async';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+macro class MyMacro implements ClassTypesMacro {
+  FutureOr<void> buildTypesForClass(clazz, builder) {
+    builder.declareType(
+      'MyClass',
+      DeclarationCode.fromString('class MyClass {}'),
+    );
+  }
+}
+''');
+
+    var library = await buildLibrary(r'''
+import 'a.dart';
+
+@MyMacro()
+class A {}
+''', preBuildSequence: [
+      {'package:test/a.dart'}
+    ]);
+
+    checkElementText(
+        library,
+        r'''
+library
+  imports
+    package:test/a.dart
+  definingUnit
+    classes
+      class A @35
+        metadata
+          Annotation
+            atSign: @ @18
+            name: SimpleIdentifier
+              token: MyMacro @19
+              staticElement: package:test/a.dart::@class::MyMacro
+              staticType: null
+            arguments: ArgumentList
+              leftParenthesis: ( @26
+              rightParenthesis: ) @27
+            element: package:test/a.dart::@class::MyMacro::@constructor::•
+        constructors
+          synthetic @-1
+  parts
+    package:test/_macro_types.dart
+      classes
+        class MyClass @6
+          constructors
+            synthetic @-1
+  exportScope
+    A: package:test/test.dart;A
+    MyClass: package:test/test.dart;package:test/_macro_types.dart;MyClass
+''',
+        withExportScope: true);
+  }
+
+  test_application_newInstance_withPrefix() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+macro class MyMacro implements ClassTypesMacro {
+  buildTypesForClass(clazz, builder) {
+    builder.declareType(
+      'MyClass',
+      DeclarationCode.fromString('class MyClass {}'),
+    );
+  }
+}
+''');
+
+    var library = await buildLibrary(r'''
+import 'a.dart' as prefix;
+
+@prefix.MyMacro()
+class A {}
+''', preBuildSequence: [
+      {'package:test/a.dart'}
+    ]);
+
+    checkElementText(
+        library,
+        r'''
+library
+  imports
+    package:test/a.dart as prefix @19
+  definingUnit
+    classes
+      class A @52
+        metadata
+          Annotation
+            atSign: @ @28
+            name: PrefixedIdentifier
+              prefix: SimpleIdentifier
+                token: prefix @29
+                staticElement: self::@prefix::prefix
+                staticType: null
+              period: . @35
+              identifier: SimpleIdentifier
+                token: MyMacro @36
+                staticElement: package:test/a.dart::@class::MyMacro
+                staticType: null
+              staticElement: package:test/a.dart::@class::MyMacro
+              staticType: null
+            arguments: ArgumentList
+              leftParenthesis: ( @43
+              rightParenthesis: ) @44
+            element: package:test/a.dart::@class::MyMacro::@constructor::•
+        constructors
+          synthetic @-1
+  parts
+    package:test/_macro_types.dart
+      classes
+        class MyClass @6
+          constructors
+            synthetic @-1
+  exportScope
+    A: package:test/test.dart;A
+    MyClass: package:test/test.dart;package:test/_macro_types.dart;MyClass
+''',
+        withExportScope: true);
+  }
+
   test_arguments_error() async {
     await _assertTypesPhaseArgumentsText(
       fields: {
@@ -259,65 +384,6 @@
     );
   }
 
-  test_build_types() async {
-    newFile('$testPackageLibPath/a.dart', r'''
-import 'dart:async';
-import 'package:_fe_analyzer_shared/src/macros/api.dart';
-
-macro class MyMacro implements ClassTypesMacro {
-  FutureOr<void> buildTypesForClass(clazz, builder) {
-    builder.declareType(
-      'MyClass',
-      DeclarationCode.fromString('class MyClass {}'),
-    );
-  }
-}
-''');
-
-    var library = await buildLibrary(r'''
-import 'a.dart';
-
-@MyMacro()
-class A {}
-''', preBuildSequence: [
-      {'package:test/a.dart'}
-    ]);
-
-    checkElementText(
-        library,
-        r'''
-library
-  imports
-    package:test/a.dart
-  definingUnit
-    classes
-      class A @35
-        metadata
-          Annotation
-            atSign: @ @18
-            name: SimpleIdentifier
-              token: MyMacro @19
-              staticElement: package:test/a.dart::@class::MyMacro
-              staticType: null
-            arguments: ArgumentList
-              leftParenthesis: ( @26
-              rightParenthesis: ) @27
-            element: package:test/a.dart::@class::MyMacro::@constructor::•
-        constructors
-          synthetic @-1
-  parts
-    package:test/_macro_types.dart
-      classes
-        class MyClass @6
-          constructors
-            synthetic @-1
-  exportScope
-    A: package:test/test.dart;A
-    MyClass: package:test/test.dart;package:test/_macro_types.dart;MyClass
-''',
-        withExportScope: true);
-  }
-
   test_introspect_types_ClassDeclaration_interfaces() async {
     await _assertTypesPhaseIntrospectionText(r'''
 class A implements B, C<int, String> {}
diff --git a/pkg/compiler/lib/src/common/elements.dart b/pkg/compiler/lib/src/common/elements.dart
index c190bfc..27c63f4 100644
--- a/pkg/compiler/lib/src/common/elements.dart
+++ b/pkg/compiler/lib/src/common/elements.dart
@@ -17,7 +17,7 @@
 import 'names.dart' show Identifiers, Uris;
 
 /// The common elements and types in Dart.
-abstract class CommonElements {
+abstract class CommonElements implements CommonElementsForDartTypes {
   final DartTypes dartTypes;
   final ElementEnvironment _env;
   ClassEntity _objectClass;
@@ -332,6 +332,7 @@
   DynamicType get dynamicType => _env.dynamicType;
 
   /// The `Object` type defined in 'dart:core'.
+  @override // CommonElementsForDartTypes
   InterfaceType get objectType => _getRawType(objectClass);
 
   /// The `bool` type defined in 'dart:core'.
@@ -341,9 +342,11 @@
   InterfaceType get numType => _getRawType(numClass);
 
   /// The `int` type defined in 'dart:core'.
+  @override // CommonElementsForDartTypes
   InterfaceType get intType => _getRawType(intClass);
 
   /// The `double` type defined in 'dart:core'.
+  @override // CommonElementsForDartTypes
   InterfaceType get doubleType => _getRawType(doubleClass);
 
   /// The `String` type defined in 'dart:core'.
@@ -353,9 +356,11 @@
   InterfaceType get symbolType => _getRawType(symbolClass);
 
   /// The `Function` type defined in 'dart:core'.
+  @override // CommonElementsForDartTypes
   InterfaceType get functionType => _getRawType(functionClass);
 
   /// The `Null` type defined in 'dart:core'.
+  @override // CommonElementsForDartTypes
   InterfaceType get nullType => _getRawType(nullClass);
 
   /// The `Type` type defined in 'dart:core'.
@@ -418,6 +423,7 @@
   /// [elementType] as its type argument.
   ///
   /// If no type argument is provided, the canonical raw type is returned.
+  @override // CommonElementsForDartTypes
   InterfaceType futureType([DartType elementType]) {
     if (elementType == null) {
       return _getRawType(futureClass);
@@ -701,6 +707,7 @@
   ClassEntity get jsJavaScriptFunctionClass => _jsJavaScriptFunctionClass ??=
       _findInterceptorsClass('JavaScriptFunction');
 
+  @override // CommonElementsForDartTypes
   InterfaceType get jsJavaScriptFunctionType =>
       _getRawType(jsJavaScriptFunctionClass);
 
@@ -1567,7 +1574,7 @@
   InterfaceType getThisType(ClassEntity cls);
 
   /// Returns the instantiation of [cls] to bounds.
-  InterfaceType getClassInstantiationToBounds(ClassEntity cls);
+  InterfaceType /*!*/ getClassInstantiationToBounds(ClassEntity cls);
 
   /// Returns `true` if [cls] is generic.
   bool isGenericClass(ClassEntity cls);
@@ -1595,7 +1602,7 @@
   FunctionType getLocalFunctionType(Local local);
 
   /// Returns the type of [field].
-  DartType getFieldType(FieldEntity field);
+  DartType /*!*/ getFieldType(FieldEntity field);
 
   /// Returns `true` if [cls] is a Dart enum class.
   bool isEnumClass(ClassEntity cls);
diff --git a/pkg/compiler/lib/src/elements/entities.dart b/pkg/compiler/lib/src/elements/entities.dart
index 737b529..5a4ac84 100644
--- a/pkg/compiler/lib/src/elements/entities.dart
+++ b/pkg/compiler/lib/src/elements/entities.dart
@@ -245,6 +245,10 @@
 // TODO(johnniwinther): Remove factory constructors from the set of
 // constructors.
 abstract class ConstructorEntity extends FunctionEntity {
+  // Constructors always have an enclosing class.
+  @override
+  ClassEntity get enclosingClass;
+
   /// Whether this is a generative constructor, possibly redirecting.
   bool get isGenerativeConstructor;
 
diff --git a/pkg/compiler/lib/src/elements/indexed.dart b/pkg/compiler/lib/src/elements/indexed.dart
index efc5b92..fef7e77 100644
--- a/pkg/compiler/lib/src/elements/indexed.dart
+++ b/pkg/compiler/lib/src/elements/indexed.dart
@@ -241,6 +241,46 @@
     return register(entity, data, env);
   }
 
+  void _preRegister<E0 extends E, V0 extends V>(E0 entity, V0 env) {
+    assert(
+        !_closed, "Trying to register $entity @ ${_list.length} when closed.");
+    assert(entity != null);
+    assert(entity._index == null);
+    assert(
+        _list.length == _env.length,
+        'Env list length ${_env.length} inconsistent '
+        'with entity list length ${_list.length}.');
+    entity._index = _list.length;
+    _list.add(entity);
+    _size++;
+    assert(env != null);
+    _env.add(env);
+  }
+
+  /// Registers a new [entity] with an associated environment [env] by the given
+  /// [index]. [postRegisterData] should be called with the same [entity] after
+  /// this is called and before any other entity is registered.
+  void preRegisterByIndex<E0 extends E, V0 extends V>(
+      int index, E0 entity, V0 env) {
+    assert(index >= _list.length);
+    _list.length = _data.length = _env.length = index;
+    _preRegister(entity, env);
+  }
+
+  /// Registers an [entity] with an associated [data] object. This should only
+  /// be used if the entity was pre-registered with [preRegisterByIndex].
+  void postRegisterData<E0 extends E, D0 extends D>(E0 entity, D0 data) {
+    assert(
+        !_closed, "Trying to register $entity @ ${_list.length} when closed.");
+    assert(entity != null);
+    assert(
+        (_list.length - 1) == _data.length,
+        'Data list length ${_data.length} inconsistent '
+        'with entity list length ${_list.length}.');
+    assert(data != null);
+    _data.add(data);
+  }
+
   /// Calls [f] for each non-null entity with its corresponding data object and
   /// environment.
   void forEach<E0 extends E, D0 extends D, V0 extends V>(
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 27ab75c..6f217cd 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -2,12 +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.
 
-// @dart = 2.10
-
-import '../common/elements.dart';
 import '../common/names.dart';
 import '../options.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 import '../util/util.dart' show equalElements, equalSets, identicalElements;
 import 'entities.dart';
 
@@ -39,8 +36,8 @@
 }
 
 extension on DataSinkWriter {
-  void _writeDartTypes(List<DartType /*!*/ > types,
-      List<FunctionTypeVariable /*!*/ > functionTypeVariables) {
+  void _writeDartTypes(
+      List<DartType> types, List<FunctionTypeVariable> functionTypeVariables) {
     writeInt(types.length);
     for (DartType type in types) {
       type.writeToDataSink(this, functionTypeVariables);
@@ -53,12 +50,12 @@
 
   static DartType readFromDataSource(DataSourceReader source,
       List<FunctionTypeVariable> functionTypeVariables) {
-    DartType type = readFromDataSourceOrNull(source, functionTypeVariables);
+    DartType? type = readFromDataSourceOrNull(source, functionTypeVariables);
     if (type == null) throw StateError('Unexpected null DartType');
     return type;
   }
 
-  static DartType readFromDataSourceOrNull(DataSourceReader source,
+  static DartType? readFromDataSourceOrNull(DataSourceReader source,
       List<FunctionTypeVariable> functionTypeVariables) {
     DartTypeKind kind = source.readEnum(DartTypeKind.values);
     switch (kind) {
@@ -91,11 +88,10 @@
       case DartTypeKind.futureOr:
         return FutureOrType._readFromDataSource(source, functionTypeVariables);
     }
-    throw UnsupportedError('Unexpected DartTypeKind $kind');
   }
 
-  void writeToDataSink(DataSinkWriter sink,
-      List<FunctionTypeVariable /*!*/ > functionTypeVariables);
+  void writeToDataSink(
+      DataSinkWriter sink, List<FunctionTypeVariable> functionTypeVariables);
 
   /// Returns the base type if this is a [LegacyType] or [NullableType] and
   /// returns this type otherwise.
@@ -124,12 +120,12 @@
   /// Calls the visit method on [visitor] corresponding to this type.
   R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument);
 
-  bool _equals(DartType other, _Assumptions assumptions);
+  bool _equals(DartType other, _Assumptions? assumptions);
 
   @override
   String toString() => toStructuredText(null, null);
 
-  String toStructuredText(DartTypes dartTypes, CompilerOptions options) =>
+  String toStructuredText(DartTypes? dartTypes, CompilerOptions? options) =>
       _DartTypeToStringVisitor(dartTypes, options).run(this);
 }
 
@@ -163,7 +159,7 @@
   }
 
   void _removeAssumption(FunctionTypeVariable a, FunctionTypeVariable b) {
-    Set<FunctionTypeVariable> set = _assumptionMap[a];
+    Set<FunctionTypeVariable>? set = _assumptionMap[a];
     if (set != null) {
       set.remove(b);
       if (set.isEmpty) {
@@ -209,7 +205,7 @@
 }
 
 class LegacyType extends DartType {
-  final DartType /*!*/ baseType;
+  final DartType baseType;
 
   const LegacyType._(this.baseType);
 
@@ -253,18 +249,18 @@
   }
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) {
+  bool _equals(DartType other, _Assumptions? assumptions) {
     if (identical(this, other)) return true;
     if (other is! LegacyType) return false;
     return _equalsInternal(other, assumptions);
   }
 
-  bool _equalsInternal(LegacyType other, _Assumptions assumptions) =>
+  bool _equalsInternal(LegacyType other, _Assumptions? assumptions) =>
       baseType._equals(other.baseType, assumptions);
 }
 
 class NullableType extends DartType {
-  final DartType /*!*/ baseType;
+  final DartType baseType;
 
   const NullableType._(this.baseType);
 
@@ -308,23 +304,25 @@
   }
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) {
+  bool _equals(DartType other, _Assumptions? assumptions) {
     if (identical(this, other)) return true;
     if (other is! NullableType) return false;
     return _equalsInternal(other, assumptions);
   }
 
-  bool _equalsInternal(NullableType other, _Assumptions assumptions) =>
+  bool _equalsInternal(NullableType other, _Assumptions? assumptions) =>
       baseType._equals(other.baseType, assumptions);
 }
 
 class InterfaceType extends DartType {
-  final ClassEntity /*!*/ element;
-  final List<DartType /*!*/ > typeArguments;
+  final ClassEntity element;
+  final List<DartType> typeArguments;
 
   InterfaceType._allocate(this.element, this.typeArguments);
 
   factory InterfaceType._(ClassEntity element, List<DartType> typeArguments) {
+    // TODO(48820): Remove:
+    // ignore: unnecessary_null_comparison
     assert(typeArguments.every((e) => e != null));
     if (typeArguments.isEmpty) typeArguments = const [];
     return InterfaceType._allocate(element, typeArguments);
@@ -371,8 +369,7 @@
   int get hashCode {
     int hash = element.hashCode;
     for (DartType argument in typeArguments) {
-      int argumentHash = argument != null ? argument.hashCode : 0;
-      hash = 17 * hash + 3 * argumentHash;
+      hash = 17 * hash + 3 * argument.hashCode;
     }
     return hash;
   }
@@ -385,13 +382,13 @@
   }
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) {
+  bool _equals(DartType other, _Assumptions? assumptions) {
     if (identical(this, other)) return true;
     if (other is! InterfaceType) return false;
     return _equalsInternal(other, assumptions);
   }
 
-  bool _equalsInternal(InterfaceType other, _Assumptions assumptions) {
+  bool _equalsInternal(InterfaceType other, _Assumptions? assumptions) {
     return identical(element, other.element) &&
         _equalTypes(typeArguments, other.typeArguments, assumptions);
   }
@@ -436,7 +433,7 @@
       other is TypeVariableType && identical(other.element, element);
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) => this == other;
+  bool _equals(DartType other, _Assumptions? assumptions) => this == other;
 }
 
 /// A type variable declared on a function type.
@@ -454,7 +451,8 @@
   final int index;
 
   /// The bound of this function type variable.
-  DartType _bound;
+  // TODO(48820): `bound` getter/setter can be a late final field.
+  DartType? _bound;
 
   FunctionTypeVariable._(this.index);
 
@@ -478,9 +476,9 @@
     }
   }
 
-  DartType /*!*/ get bound {
+  DartType get bound {
     assert(_bound != null, "Bound has not been set.");
-    return _bound;
+    return _bound!;
   }
 
   void set bound(DartType value) {
@@ -492,7 +490,7 @@
   int get hashCode => index * 113; // ignore bound which can have cycles.
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) {
+  bool _equals(DartType other, _Assumptions? assumptions) {
     if (identical(this, other)) return true;
     if (other is! FunctionTypeVariable) return false;
     if (assumptions != null) return assumptions.isAssumed(this, other);
@@ -529,7 +527,7 @@
   bool operator ==(other) => identical(this, other) || other is NeverType;
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) => this == other;
+  bool _equals(DartType other, _Assumptions? assumptions) => this == other;
 }
 
 class VoidType extends DartType {
@@ -556,7 +554,7 @@
   bool operator ==(other) => identical(this, other) || other is VoidType;
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) => this == other;
+  bool _equals(DartType other, _Assumptions? assumptions) => this == other;
 }
 
 class DynamicType extends DartType {
@@ -583,7 +581,7 @@
   bool operator ==(other) => identical(this, other) || other is DynamicType;
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) => this == other;
+  bool _equals(DartType other, _Assumptions? assumptions) => this == other;
 }
 
 class ErasedType extends DartType {
@@ -610,7 +608,7 @@
   bool operator ==(other) => identical(this, other) || other is ErasedType;
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) => this == other;
+  bool _equals(DartType other, _Assumptions? assumptions) => this == other;
 }
 
 /// Represents a type which is simultaneously top and bottom.
@@ -648,13 +646,13 @@
   bool operator ==(other) => identical(this, other) || other is AnyType;
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) => this == other;
+  bool _equals(DartType other, _Assumptions? assumptions) => this == other;
 }
 
 class FunctionType extends DartType {
   final DartType returnType;
-  final List<DartType /*!*/ > parameterTypes;
-  final List<DartType /*!*/ > optionalParameterTypes;
+  final List<DartType> parameterTypes;
+  final List<DartType> optionalParameterTypes;
 
   /// The names of all named parameters ordered lexicographically.
   final List<String> namedParameters;
@@ -664,9 +662,9 @@
 
   /// The types of the named parameters in the order corresponding to the
   /// [namedParameters].
-  final List<DartType /*!*/ > namedParameterTypes;
+  final List<DartType> namedParameterTypes;
 
-  final List<FunctionTypeVariable /*!*/ > typeVariables;
+  final List<FunctionTypeVariable> typeVariables;
 
   FunctionType._allocate(
       this.returnType,
@@ -676,6 +674,8 @@
       this.requiredNamedParameters,
       this.namedParameterTypes,
       this.typeVariables) {
+    // TODO(48820): Remove:
+    // ignore: unnecessary_null_comparison
     assert(returnType != null, 'Invalid return type in $this.');
     assert(!parameterTypes.contains(null), 'Invalid parameter types in $this.');
     assert(!optionalParameterTypes.contains(null),
@@ -691,12 +691,12 @@
 
   factory FunctionType._(
       DartType returnType,
-      List<DartType /*!*/ > parameterTypes,
-      List<DartType /*!*/ > optionalParameterTypes,
-      List<String /*!*/ > namedParameters,
-      Set<String /*!*/ > requiredNamedParameters,
-      List<DartType /*!*/ > namedParameterTypes,
-      List<FunctionTypeVariable /*!*/ > typeVariables) {
+      List<DartType> parameterTypes,
+      List<DartType> optionalParameterTypes,
+      List<String> namedParameters,
+      Set<String> requiredNamedParameters,
+      List<DartType> namedParameterTypes,
+      List<FunctionTypeVariable> typeVariables) {
     // Canonicalize empty collections to constants to save storage.
     if (parameterTypes.isEmpty) parameterTypes = const [];
     if (optionalParameterTypes.isEmpty) optionalParameterTypes = const [];
@@ -823,13 +823,13 @@
   }
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) {
+  bool _equals(DartType other, _Assumptions? assumptions) {
     if (identical(this, other)) return true;
     if (other is! FunctionType) return false;
     return _equalsInternal(other, assumptions);
   }
 
-  bool _equalsInternal(FunctionType other, _Assumptions assumptions) {
+  bool _equalsInternal(FunctionType other, _Assumptions? assumptions) {
     if (typeVariables.length != other.typeVariables.length) return false;
     assumptions ??= _Assumptions();
     assumptions.assumePairs(typeVariables, other.typeVariables);
@@ -856,7 +856,7 @@
 }
 
 class FutureOrType extends DartType {
-  final DartType /*!*/ typeArgument;
+  final DartType typeArgument;
 
   const FutureOrType._(this.typeArgument);
 
@@ -897,18 +897,19 @@
   }
 
   @override
-  bool _equals(DartType other, _Assumptions assumptions) {
+  bool _equals(DartType other, _Assumptions? assumptions) {
     if (identical(this, other)) return true;
     if (other is! FutureOrType) return false;
     return _equalsInternal(other, assumptions);
   }
 
-  bool _equalsInternal(FutureOrType other, _Assumptions assumptions) {
+  bool _equalsInternal(FutureOrType other, _Assumptions? assumptions) {
     return typeArgument._equals(other.typeArgument, assumptions);
   }
 }
 
-bool _equalTypes(List<DartType> a, List<DartType> b, _Assumptions assumptions) {
+bool _equalTypes(
+    List<DartType> a, List<DartType> b, _Assumptions? assumptions) {
   if (a.length != b.length) return false;
   for (int index = 0; index < a.length; index++) {
     if (!a[index]._equals(b[index], assumptions)) {
@@ -921,36 +922,34 @@
 abstract class DartTypeVisitor<R, A> {
   const DartTypeVisitor();
 
-  R /*!*/ visit(covariant DartType type, A argument) =>
-      type.accept(this, argument);
+  R visit(covariant DartType type, A argument) => type.accept(this, argument);
 
-  R /*!*/ visitLegacyType(covariant LegacyType type, A argument);
+  R visitLegacyType(covariant LegacyType type, A argument);
 
-  R /*!*/ visitNullableType(covariant NullableType type, A argument);
+  R visitNullableType(covariant NullableType type, A argument);
 
-  R /*!*/ visitNeverType(covariant NeverType type, A argument);
+  R visitNeverType(covariant NeverType type, A argument);
 
-  R /*!*/ visitVoidType(covariant VoidType type, A argument);
+  R visitVoidType(covariant VoidType type, A argument);
 
-  R /*!*/ visitTypeVariableType(covariant TypeVariableType type, A argument);
+  R visitTypeVariableType(covariant TypeVariableType type, A argument);
 
-  R /*!*/ visitFunctionTypeVariable(
-      covariant FunctionTypeVariable type, A argument);
+  R visitFunctionTypeVariable(covariant FunctionTypeVariable type, A argument);
 
-  R /*!*/ visitFunctionType(covariant FunctionType type, A argument);
+  R visitFunctionType(covariant FunctionType type, A argument);
 
-  R /*!*/ visitInterfaceType(covariant InterfaceType type, A argument);
+  R visitInterfaceType(covariant InterfaceType type, A argument);
 
-  R /*!*/ visitDynamicType(covariant DynamicType type, A argument);
+  R visitDynamicType(covariant DynamicType type, A argument);
 
-  R /*!*/ visitErasedType(covariant ErasedType type, A argument);
+  R visitErasedType(covariant ErasedType type, A argument);
 
-  R /*!*/ visitAnyType(covariant AnyType type, A argument);
+  R visitAnyType(covariant AnyType type, A argument);
 
-  R /*!*/ visitFutureOrType(covariant FutureOrType type, A argument);
+  R visitFutureOrType(covariant FutureOrType type, A argument);
 }
 
-class _LegacyErasureVisitor extends DartTypeVisitor<DartType /*!*/, Null> {
+class _LegacyErasureVisitor extends DartTypeVisitor<DartType, Null> {
   final DartTypes _dartTypes;
 
   _LegacyErasureVisitor(this._dartTypes);
@@ -1024,6 +1023,7 @@
         identical(namedParameterTypes, type.namedParameterTypes) &&
         erasableTypeVariables.isEmpty) return type;
 
+    // TODO(48820): Can we avoid the cast?
     return _dartTypes.subst(
         erasedTypeVariables,
         erasableTypeVariables,
@@ -1034,7 +1034,7 @@
             type.namedParameters,
             type.requiredNamedParameters,
             namedParameterTypes,
-            typeVariables));
+            typeVariables)) as FunctionType;
   }
 
   @override
@@ -1062,13 +1062,13 @@
 }
 
 abstract class DartTypeSubstitutionVisitor<A>
-    extends DartTypeVisitor<DartType /*!*/, A> {
+    extends DartTypeVisitor<DartType, A> {
   DartTypes get dartTypes;
 
   // The input type is a DAG and we must preserve the sharing.
   final Map<DartType, DartType> _map = Map.identity();
 
-  DartType _mapped(DartType oldType, DartType /*!*/ newType) {
+  DartType _mapped(DartType oldType, DartType newType) {
     assert(_map[oldType] == null);
     return _map[oldType] = newType;
   }
@@ -1093,7 +1093,7 @@
 
   @override
   DartType visitLegacyType(covariant LegacyType type, A argument) {
-    DartType probe = _map[type];
+    DartType? probe = _map[type];
     if (probe != null) return probe;
 
     DartType newBaseType = visit(type.baseType, argument);
@@ -1106,7 +1106,7 @@
 
   @override
   DartType visitNullableType(covariant NullableType type, A argument) {
-    DartType probe = _map[type];
+    DartType? probe = _map[type];
     if (probe != null) return probe;
 
     DartType newBaseType = visit(type.baseType, argument);
@@ -1130,7 +1130,7 @@
       covariant FunctionTypeVariable type, A argument) {
     // Function type variables are added to the map only for type variables that
     // need to be replaced with updated bounds.
-    DartType probe = _map[type];
+    DartType? probe = _map[type];
     if (probe != null) return probe;
     return substituteFunctionTypeVariable(type, argument, true);
   }
@@ -1140,7 +1140,7 @@
 
   @override
   DartType visitFunctionType(covariant FunctionType type, A argument) {
-    DartType probe = _map[type];
+    DartType? probe = _map[type];
     if (probe != null) return probe;
 
     List<FunctionTypeVariable> newTypeVariables =
@@ -1190,9 +1190,8 @@
     // indirectly changed by the substitution of F. When D is replaced by `D2
     // extends Map<B,G>`, C must be replaced by `C2 extends D2`.
 
-    List<FunctionTypeVariable /*?*/ > undecided =
-        List.of(variables, growable: false);
-    List<FunctionTypeVariable> newVariables;
+    List<FunctionTypeVariable?> undecided = List.of(variables, growable: false);
+    List<FunctionTypeVariable>? newVariables;
 
     _DependencyCheck<A> dependencyCheck = _DependencyCheck<A>(this, argument);
 
@@ -1200,7 +1199,7 @@
     while (changed) {
       changed = false;
       for (int i = 0; i < undecided.length; i++) {
-        FunctionTypeVariable variable = undecided[i];
+        FunctionTypeVariable? variable = undecided[i];
         if (variable == null) continue;
         if (dependencyCheck.run(variable.bound)) {
           changed = true;
@@ -1233,7 +1232,7 @@
       return type;
     }
 
-    DartType probe = _map[type];
+    DartType? probe = _map[type];
     if (probe != null) return probe;
 
     List<DartType> newTypeArguments = _substTypes(typeArguments, argument);
@@ -1256,7 +1255,7 @@
 
   @override
   DartType visitFutureOrType(covariant FutureOrType type, A argument) {
-    DartType probe = _map[type];
+    DartType? probe = _map[type];
     if (probe != null) return probe;
 
     DartType newTypeArgument = visit(type.typeArgument, argument);
@@ -1268,7 +1267,7 @@
   }
 
   List<DartType> _substTypes(List<DartType> types, A argument) {
-    List<DartType> result;
+    List<DartType>? result;
     for (int i = 0; i < types.length; i++) {
       DartType oldType = types[i];
       DartType newType = visit(oldType, argument);
@@ -1297,7 +1296,7 @@
   bool handleFreeFunctionTypeVariable(FunctionTypeVariable type) {
     // Function type variables are added to the map for type variables that need
     // to be replaced with updated bounds.
-    DartType probe = _substitutionVisitor._map[type];
+    DartType? probe = _substitutionVisitor._map[type];
     if (probe != null) return probe != type;
     return !identical(
         type,
@@ -1310,7 +1309,7 @@
 /// visit returns `true`.  The default handlers return `false` which will search
 /// the whole structure unless overridden.
 abstract class DartTypeStructuralPredicateVisitor
-    extends DartTypeVisitor<bool, List<FunctionTypeVariable> /*?*/ > {
+    extends DartTypeVisitor<bool, List<FunctionTypeVariable>?> {
   const DartTypeStructuralPredicateVisitor();
 
   bool run(DartType type) => visit(type, null);
@@ -1330,30 +1329,30 @@
   bool handleFutureOrType(FutureOrType type) => false;
 
   @override
-  bool visitLegacyType(LegacyType type, List<FunctionTypeVariable> bindings) =>
+  bool visitLegacyType(LegacyType type, List<FunctionTypeVariable>? bindings) =>
       handleLegacyType(type) || visit(type.baseType, bindings);
 
   @override
   bool visitNullableType(
-          NullableType type, List<FunctionTypeVariable> bindings) =>
+          NullableType type, List<FunctionTypeVariable>? bindings) =>
       handleNullableType(type) || visit(type.baseType, bindings);
 
   @override
-  bool visitNeverType(NeverType type, List<FunctionTypeVariable> bindings) =>
+  bool visitNeverType(NeverType type, List<FunctionTypeVariable>? bindings) =>
       handleNeverType(type);
 
   @override
-  bool visitVoidType(VoidType type, List<FunctionTypeVariable> bindings) =>
+  bool visitVoidType(VoidType type, List<FunctionTypeVariable>? bindings) =>
       handleVoidType(type);
 
   @override
   bool visitTypeVariableType(
-          TypeVariableType type, List<FunctionTypeVariable> bindings) =>
+          TypeVariableType type, List<FunctionTypeVariable>? bindings) =>
       handleTypeVariableType(type);
 
   @override
   bool visitFunctionTypeVariable(
-      FunctionTypeVariable type, List<FunctionTypeVariable> bindings) {
+      FunctionTypeVariable type, List<FunctionTypeVariable>? bindings) {
     return bindings != null && bindings.indexOf(type) >= 0
         ? handleBoundFunctionTypeVariable(type)
         : handleFreeFunctionTypeVariable(type);
@@ -1361,7 +1360,7 @@
 
   @override
   bool visitFunctionType(
-      FunctionType type, List<FunctionTypeVariable> bindings) {
+      FunctionType type, List<FunctionTypeVariable>? bindings) {
     if (handleFunctionType(type)) return true;
     List<FunctionTypeVariable> typeVariables = type.typeVariables;
     if (typeVariables.isNotEmpty) {
@@ -1383,32 +1382,32 @@
 
   @override
   bool visitInterfaceType(
-      InterfaceType type, List<FunctionTypeVariable> bindings) {
+      InterfaceType type, List<FunctionTypeVariable>? bindings) {
     if (handleInterfaceType(type)) return true;
     return _visitAll(type.typeArguments, bindings);
   }
 
   @override
   bool visitDynamicType(
-          DynamicType type, List<FunctionTypeVariable> bindings) =>
+          DynamicType type, List<FunctionTypeVariable>? bindings) =>
       handleDynamicType(type);
 
   @override
-  bool visitErasedType(ErasedType type, List<FunctionTypeVariable> bindings) =>
+  bool visitErasedType(ErasedType type, List<FunctionTypeVariable>? bindings) =>
       handleErasedType(type);
 
   @override
-  bool visitAnyType(AnyType type, List<FunctionTypeVariable> bindings) =>
+  bool visitAnyType(AnyType type, List<FunctionTypeVariable>? bindings) =>
       handleAnyType(type);
 
   @override
   bool visitFutureOrType(
-      FutureOrType type, List<FunctionTypeVariable> bindings) {
+      FutureOrType type, List<FunctionTypeVariable>? bindings) {
     if (handleFutureOrType(type)) return true;
     return visit(type.typeArgument, bindings);
   }
 
-  bool _visitAll(List<DartType> types, List<FunctionTypeVariable> bindings) {
+  bool _visitAll(List<DartType> types, List<FunctionTypeVariable>? bindings) {
     for (DartType type in types) {
       if (visit(type, bindings)) return true;
     }
@@ -1461,33 +1460,36 @@
 }
 
 class _DeferredName {
-  String name;
+  String? name;
   _DeferredName();
   @override
-  String toString() => name;
+  String toString() => name!;
 }
 
 class _DartTypeToStringVisitor extends DartTypeVisitor<void, void> {
-  final DartTypes _dartTypes; // May be null.
-  final CompilerOptions _options; // May be null.
+  final DartTypes? _dartTypes; // May be null.
+  final CompilerOptions? _options; // May be null.
   final List _fragments = []; // Strings and _DeferredNames
   bool _lastIsIdentifier = false;
-  List<FunctionTypeVariable> _boundVariables;
-  Map<FunctionTypeVariable, _DeferredName> _variableToName;
-  Set<FunctionType> _genericFunctions;
+  List<FunctionTypeVariable>? _boundVariables;
+  Map<FunctionTypeVariable, _DeferredName>? _variableToName;
+  Set<FunctionType>? _genericFunctions;
 
   _DartTypeToStringVisitor(this._dartTypes, this._options);
 
   String run(DartType type) {
     _visit(type);
-    if (_variableToName != null &&
-        _variableToName.values.any((deferred) => deferred.name == null)) {
+    final variableToName = _variableToName;
+    if (variableToName != null &&
+        variableToName.values.any((deferred) => deferred.name == null)) {
       // Assign names to _DeferredNames that were not assigned while visiting a
       // generic function type.
-      Set<String> usedNames =
-          _variableToName.values.map((deferred) => deferred.name).toSet();
+      Set<String> usedNames = {
+        for (final deferred in variableToName.values)
+          if (deferred.name != null) deferred.name!
+      };
       int startGroup = (_genericFunctions?.length ?? 0) + 1;
-      for (var entry in _variableToName.entries) {
+      for (var entry in variableToName.entries) {
         if (entry.value.name != null) continue;
         for (int group = startGroup;; group++) {
           String name = _functionTypeVariableName(entry.key, group);
@@ -1539,7 +1541,7 @@
     // internal notion. The language specification does not define a '*' token
     // in the type language, and no such token should be surfaced to users.
     // For debugging, pass `--debug-print-legacy-stars` to emit the '*'.
-    if (_options == null || _options.printLegacyStars) {
+    if (_options == null || _options!.printLegacyStars) {
       _token('*');
     }
   }
@@ -1577,14 +1579,14 @@
 
   @override
   void visitTypeVariableType(covariant TypeVariableType type, _) {
-    _identifier(type.element.typeDeclaration.name);
+    _identifier(type.element.typeDeclaration!.name!);
     _token('.');
-    _identifier(type.element.name);
+    _identifier(type.element.name!);
   }
 
   _DeferredName _nameFor(FunctionTypeVariable type) {
     _variableToName ??= Map.identity();
-    return _variableToName[type] ??= _DeferredName();
+    return _variableToName![type] ??= _DeferredName();
   }
 
   @override
@@ -1594,7 +1596,7 @@
     // A3, etc).
     _token('#');
     _deferredNameIdentifier(_nameFor(type));
-    if (_boundVariables == null || !_boundVariables.contains(type)) {
+    if (_boundVariables == null || !_boundVariables!.contains(type)) {
       _token('/*free*/');
     }
   }
@@ -1603,13 +1605,12 @@
   void visitFunctionType(covariant FunctionType type, _) {
     if (type.typeVariables.isNotEmpty) {
       // Enter function type variable scope.
-      _boundVariables ??= [];
-      _boundVariables.addAll(type.typeVariables);
+      (_boundVariables ??= []).addAll(type.typeVariables);
       // Assign names for the function type variables. We could have already
       // assigned names for this node if we are printing a DAG.
-      _genericFunctions ??= Set.identity();
-      if (_genericFunctions.add(type)) {
-        int group = _genericFunctions.length;
+      final genericFunctions = _genericFunctions ??= Set.identity();
+      if (genericFunctions.add(type)) {
+        int group = genericFunctions.length;
         for (FunctionTypeVariable variable in type.typeVariables) {
           _DeferredName deferredName = _nameFor(variable);
           // If there is a structural error where one FunctionTypeVariable is
@@ -1628,7 +1629,7 @@
         needsComma = _comma(needsComma);
         _visit(typeVariable);
         DartType bound = typeVariable.bound;
-        if (_dartTypes == null || !_dartTypes.isTopType(bound)) {
+        if (_dartTypes == null || !_dartTypes!.isTopType(bound)) {
           _token(' extends ');
           _visit(bound);
         }
@@ -1695,17 +1696,29 @@
   }
 }
 
+/// The subset of CommonElements methods needed for DartTypes.
+// TODO(48820): Replace with CommonElements once that is migrated.
+abstract class CommonElementsForDartTypes {
+  InterfaceType get nullType;
+  InterfaceType get intType;
+  InterfaceType get doubleType;
+  InterfaceType get functionType;
+  InterfaceType get objectType;
+  InterfaceType get jsJavaScriptFunctionType;
+  InterfaceType futureType(DartType elementType);
+}
+
 /// Basic interface for the Dart type system.
 abstract class DartTypes {
   /// The types defined in 'dart:core'.
-  CommonElements get commonElements;
+  CommonElementsForDartTypes get commonElements;
 
   bool get useLegacySubtyping;
 
   DartType bottomType() =>
       useLegacySubtyping ? commonElements.nullType : neverType();
 
-  DartType legacyType(DartType /*!*/ baseType) {
+  DartType legacyType(DartType baseType) {
     DartType result;
     if (isStrongTopType(baseType) ||
         baseType.isNull ||
@@ -1718,7 +1731,7 @@
     return result;
   }
 
-  DartType nullableType(DartType /*!*/ baseType) {
+  DartType nullableType(DartType baseType) {
     bool _isNullable(DartType t) =>
         // Note that we can assume null safety is enabled here.
         t.isNull ||
@@ -1752,7 +1765,7 @@
   }
 
   InterfaceType interfaceType(
-          ClassEntity element, List<DartType /*!*/ > typeArguments) =>
+          ClassEntity element, List<DartType> typeArguments) =>
       InterfaceType._(element, typeArguments);
 
   // TODO(fishythefish): Normalize `T extends Never` to `Never`.
@@ -1775,12 +1788,12 @@
 
   FunctionType functionType(
       DartType returnType,
-      List<DartType /*!*/ > parameterTypes,
-      List<DartType /*!*/ > optionalParameterTypes,
+      List<DartType> parameterTypes,
+      List<DartType> optionalParameterTypes,
       List<String> namedParameters,
       Set<String> requiredNamedParameters,
-      List<DartType /*!*/ > namedParameterTypes,
-      List<FunctionTypeVariable /*!*/ > typeVariables) {
+      List<DartType> namedParameterTypes,
+      List<FunctionTypeVariable> typeVariables) {
     FunctionType type = FunctionType._(
         returnType,
         parameterTypes,
@@ -1797,7 +1810,7 @@
         : subst(
             List<DartType>.filled(normalizableVariables.length, neverType()),
             normalizableVariables,
-            type);
+            type) as FunctionType;
   }
 
   DartType futureOrType(DartType typeArgument) {
@@ -1914,7 +1927,7 @@
     /// Based on
     /// https://github.com/dart-lang/language/blob/master/resources/type-system/subtyping.md.
     /// See also [_isSubtype] in `dart:_rti`.
-    bool _isSubtype(DartType s, DartType t, _Assumptions env) {
+    bool _isSubtype(DartType s, DartType t, _Assumptions? env) {
       // Reflexivity:
       if (s == t) return true;
       if (env != null &&
@@ -1938,7 +1951,7 @@
         if (_isSubtype(getTypeVariableBound(s.element), t, env)) return true;
       }
       if (s is FunctionTypeVariable) {
-        if (_isSubtype(s._bound, t, env)) return true;
+        if (_isSubtype(s.bound, t, env)) return true;
       }
 
       // Left Null:
@@ -2137,7 +2150,7 @@
       // Interface Compositionality + Super-Interface:
       if (s is InterfaceType) {
         if (t is InterfaceType) {
-          InterfaceType instance =
+          InterfaceType? instance =
               s.element == t.element ? s : asInstanceOf(s, t.element);
           if (instance == null) return false;
           List<DartType> sArgs = instance.typeArguments;
@@ -2178,7 +2191,7 @@
   /// subtype of [cls].
   ///
   /// For example: `asInstanceOf(List<String>, Iterable) = Iterable<String>`.
-  InterfaceType asInstanceOf(InterfaceType type, ClassEntity cls);
+  InterfaceType? asInstanceOf(InterfaceType type, ClassEntity cls);
 
   /// Return [base] where the type variable of `context.element` are replaced
   /// by the type arguments of [context].
@@ -2195,7 +2208,7 @@
 
   /// Returns the supertype of [cls], i.e. the type in the `extends` clause of
   /// [cls].
-  InterfaceType getSupertype(ClassEntity cls);
+  InterfaceType? getSupertype(ClassEntity cls);
 
   /// Returns all supertypes of [cls].
   // TODO(johnniwinther): This should include `Function` if [cls] declares
@@ -2207,7 +2220,7 @@
 
   /// Returns the type of the `call` method on [type], or `null` if the class
   /// of [type] does not have a `call` method.
-  FunctionType getCallType(InterfaceType type);
+  FunctionType? getCallType(InterfaceType type);
 
   /// Checks the type arguments of [type] against the type variable bounds
   /// declared on `type.element`. Calls [checkTypeVariableBound] on each type
@@ -2221,11 +2234,12 @@
 
   /// Returns the [ClassEntity] which declares the type variables occurring in
   // [type], or `null` if [type] does not contain class type variables.
-  static ClassEntity getClassContext(DartType type) {
-    ClassEntity contextClass;
+  static ClassEntity? getClassContext(DartType type) {
+    ClassEntity? contextClass;
     type.forEachTypeVariable((TypeVariableType typeVariable) {
-      if (typeVariable.element.typeDeclaration is! ClassEntity) return;
-      contextClass = typeVariable.element.typeDeclaration;
+      final typeDeclaration = typeVariable.element.typeDeclaration;
+      if (typeDeclaration is! ClassEntity) return;
+      contextClass = typeDeclaration;
     });
     // GENERIC_METHODS: When generic method support is complete enough to
     // include a runtime value for method type variables this must be updated.
@@ -2268,7 +2282,7 @@
 
   /// Returns `true` if [type] occuring in a program with no sound null safety
   /// cannot accept `null` under sound rules.
-  bool isNonNullableIfSound(DartType /*!*/ type) {
+  bool isNonNullableIfSound(DartType type) {
     if (type is DynamicType ||
         type is VoidType ||
         type is AnyType ||
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index e2d23d2..39ee49c 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -1361,21 +1361,18 @@
       AbstractValueDomain abstractValueDomain) {
     return source.inMemberContext(context, () {
       source.begin(tag);
-      Map<ir.TreeNode, AbstractValue> sendMap = source.readTreeNodeMapInContext(
-          () => abstractValueDomain.readAbstractValueFromDataSource(source),
-          emptyAsNull: true);
+      Map<ir.TreeNode, AbstractValue> sendMap =
+          source.readTreeNodeMapInContextOrNull(() =>
+              abstractValueDomain.readAbstractValueFromDataSource(source));
       Map<ir.ForInStatement, AbstractValue> iteratorMap =
-          source.readTreeNodeMapInContext(
-              () => abstractValueDomain.readAbstractValueFromDataSource(source),
-              emptyAsNull: true);
+          source.readTreeNodeMapInContextOrNull(() =>
+              abstractValueDomain.readAbstractValueFromDataSource(source));
       Map<ir.ForInStatement, AbstractValue> currentMap =
-          source.readTreeNodeMapInContext(
-              () => abstractValueDomain.readAbstractValueFromDataSource(source),
-              emptyAsNull: true);
+          source.readTreeNodeMapInContextOrNull(() =>
+              abstractValueDomain.readAbstractValueFromDataSource(source));
       Map<ir.ForInStatement, AbstractValue> moveNextMap =
-          source.readTreeNodeMapInContext(
-              () => abstractValueDomain.readAbstractValueFromDataSource(source),
-              emptyAsNull: true);
+          source.readTreeNodeMapInContextOrNull(() =>
+              abstractValueDomain.readAbstractValueFromDataSource(source));
       source.end(tag);
       return KernelGlobalTypeInferenceElementData.internal(
           sendMap, iteratorMap, currentMap, moveNextMap);
diff --git a/pkg/compiler/lib/src/ir/element_map.dart b/pkg/compiler/lib/src/ir/element_map.dart
index 6d8c86a..51f1e6f 100644
--- a/pkg/compiler/lib/src/ir/element_map.dart
+++ b/pkg/compiler/lib/src/ir/element_map.dart
@@ -57,14 +57,14 @@
   CommonElements /*!*/ get commonElements;
   DiagnosticReporter get reporter;
   ir.CoreTypes get coreTypes;
-  InterfaceType getThisType(IndexedClass cls);
-  InterfaceType getSuperType(IndexedClass cls);
-  OrderedTypeSet getOrderedTypeSet(IndexedClass cls);
-  Iterable<InterfaceType> getInterfaces(IndexedClass cls);
+  InterfaceType /*!*/ getThisType(covariant ClassEntity cls);
+  InterfaceType getSuperType(covariant ClassEntity cls);
+  OrderedTypeSet getOrderedTypeSet(covariant ClassEntity cls);
+  Iterable<InterfaceType> getInterfaces(covariant ClassEntity cls);
   InterfaceType asInstanceOf(InterfaceType type, ClassEntity cls);
   DartType substByContext(DartType type, InterfaceType context);
   FunctionType getCallType(InterfaceType type);
-  int getHierarchyDepth(IndexedClass cls);
+  int getHierarchyDepth(covariant ClassEntity cls);
   DartType getTypeVariableBound(IndexedTypeVariable typeVariable);
-  List<Variance> getTypeVariableVariances(IndexedClass cls);
+  List<Variance> getTypeVariableVariances(covariant ClassEntity cls);
 }
diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart
index 462b6c3..38886b0 100644
--- a/pkg/compiler/lib/src/ir/impact_data.dart
+++ b/pkg/compiler/lib/src/ir/impact_data.dart
@@ -2122,7 +2122,7 @@
     source.begin(tag);
     RuntimeTypeUseKind kind = source.readEnum(RuntimeTypeUseKind.values);
     ir.DartType receiverType = source.readDartTypeNode();
-    ir.DartType argumentType = source.readDartTypeNode(allowNull: true);
+    ir.DartType argumentType = source.readDartTypeNodeOrNull();
     source.end(tag);
     return _RuntimeTypeUse(kind, receiverType, argumentType);
   }
@@ -2131,7 +2131,7 @@
     sink.begin(tag);
     sink.writeEnum(kind);
     sink.writeDartTypeNode(receiverType);
-    sink.writeDartTypeNode(argumentType, allowNull: true);
+    sink.writeDartTypeNodeOrNull(argumentType);
     sink.end(tag);
   }
 }
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index 35f8fee..4d1e7f4 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -826,9 +826,10 @@
 
   @override
   EvaluationComplexity visitFunctionNode(ir.FunctionNode node) {
-    VariableUse parameterUsage = node.parent is ir.Member
-        ? VariableUse.memberParameter(node.parent)
-        : VariableUse.localParameter(node.parent);
+    final parent = node.parent;
+    VariableUse parameterUsage = parent is ir.Member
+        ? VariableUse.memberParameter(parent)
+        : VariableUse.localParameter(parent);
     visitNodesInContext(node.typeParameters, parameterUsage);
     for (ir.VariableDeclaration declaration in node.positionalParameters) {
       _handleVariableDeclaration(declaration, parameterUsage);
@@ -838,9 +839,9 @@
     }
     visitInContext(
         node.returnType,
-        node.parent is ir.Member
-            ? VariableUse.memberReturnType(node.parent)
-            : VariableUse.localReturnType(node.parent));
+        parent is ir.Member
+            ? VariableUse.memberReturnType(parent)
+            : VariableUse.localReturnType(parent));
     if (node.body != null) {
       visitNode(node.body);
     }
diff --git a/pkg/compiler/lib/src/ir/static_type_cache.dart b/pkg/compiler/lib/src/ir/static_type_cache.dart
index 32d2384..92e0023 100644
--- a/pkg/compiler/lib/src/ir/static_type_cache.dart
+++ b/pkg/compiler/lib/src/ir/static_type_cache.dart
@@ -2,17 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.10
-
 import 'package:kernel/ast.dart' as ir;
 
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
 
 class StaticTypeCache {
   static const String tag = 'static-type-cache';
 
   final Map<ir.Expression, ir.DartType> _expressionTypes;
-  final Map<ir.ForInStatement, ir.DartType> _forInIteratorTypes;
+  final Map<ir.ForInStatement, ir.DartType>? _forInIteratorTypes;
 
   const StaticTypeCache(
       [this._expressionTypes = const {}, this._forInIteratorTypes]);
@@ -23,8 +21,8 @@
       source.begin(tag);
       Map<ir.Expression, ir.DartType> expressionTypes =
           source.readTreeNodeMapInContext(source.readDartTypeNode);
-      Map<ir.ForInStatement, ir.DartType> forInIteratorTypes = source
-          .readTreeNodeMapInContext(source.readDartTypeNode, emptyAsNull: true);
+      Map<ir.ForInStatement, ir.DartType>? forInIteratorTypes =
+          source.readTreeNodeMapInContextOrNull(source.readDartTypeNode);
       source.end(tag);
       return StaticTypeCache(expressionTypes, forInIteratorTypes);
     });
@@ -41,9 +39,9 @@
     });
   }
 
-  ir.DartType operator [](ir.Expression node) => _expressionTypes[node];
+  ir.DartType? operator [](ir.Expression node) => _expressionTypes[node];
 
-  ir.DartType getForInIteratorType(ir.ForInStatement node) {
-    return _forInIteratorTypes != null ? _forInIteratorTypes[node] : null;
+  ir.DartType? getForInIteratorType(ir.ForInStatement node) {
+    return _forInIteratorTypes?[node];
   }
 }
diff --git a/pkg/compiler/lib/src/ir/types.dart b/pkg/compiler/lib/src/ir/types.dart
index 4242166..a14ddbb 100644
--- a/pkg/compiler/lib/src/ir/types.dart
+++ b/pkg/compiler/lib/src/ir/types.dart
@@ -33,7 +33,7 @@
 
   @override
   Iterable<InterfaceType> getSupertypes(ClassEntity cls) {
-    return elementMap.getOrderedTypeSet(cls).supertypes;
+    return elementMap.getOrderedTypeSet(cls).supertypes ?? const [];
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index d0cd046..e4f6701 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -57,7 +57,9 @@
 
   DartTypes get _dartTypes => _closedWorld.dartTypes;
 
-  void onIsCheckForCodegen(DartType type, TransformedWorldImpact transformed) {
+  void onIsCheckForCodegen(
+      DartType /*!*/ type, TransformedWorldImpact transformed) {
+    assert((type as dynamic) != null);
     if (_dartTypes.isTopType(type)) return;
 
     _impacts.typeCheck.registerImpact(transformed, _elementEnvironment);
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
index 5e14de3..96d0951 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
@@ -482,10 +482,11 @@
   void _propagateTests() {
     void processTypeVariableType(TypeVariableType type) {
       TypeVariableEntity variable = type.element;
-      if (variable.typeDeclaration is ClassEntity) {
-        _getClassNode(variable.typeDeclaration).markTest();
+      final typeDeclaration = variable.typeDeclaration;
+      if (typeDeclaration is ClassEntity) {
+        _getClassNode(typeDeclaration).markTest();
       } else {
-        _getMethodNode(variable.typeDeclaration).markTest();
+        _getMethodNode(typeDeclaration).markTest();
       }
     }
 
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index ee8f10c..6cbb34b 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -358,8 +358,10 @@
     source.begin(classDataTag);
     entityLookup.forEachClass((int index, JClass cls) {
       JClassEnv env = JClassEnv.readFromDataSource(source);
+      classes.preRegisterByIndex(index, cls, env);
       JClassData data = JClassData.readFromDataSource(source);
-      classMap[env.cls] = classes.registerByIndex(index, cls, data, env);
+      classes.postRegisterData(cls, data);
+      classMap[env.cls] = cls;
       if (cls is! JRecord && cls is! JClosureClass) {
         // Synthesized classes are not part of the library environment.
         libraries.getEnv(cls.library).registerClass(cls.name, env);
@@ -1130,7 +1132,7 @@
     assert(checkFamily(cls));
     JClassData data = classes.getData(cls);
     _ensureSupertypes(cls, data);
-    return data.interfaces;
+    return data.interfaces /*!*/;
   }
 
   MemberDefinition getMemberDefinitionInternal(covariant IndexedMember member) {
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index c59e85e..a3a0c0c 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -673,7 +673,8 @@
     return data.getFunctionType(this);
   }
 
-  List<TypeVariableType> _getFunctionTypeVariables(IndexedFunction function) {
+  List<TypeVariableType> /*!*/ _getFunctionTypeVariables(
+      IndexedFunction function) {
     assert(checkFamily(function));
     KFunctionData data = members.getData(function);
     return data.getFunctionTypeVariables(this);
@@ -786,7 +787,7 @@
   }
 
   @override
-  OrderedTypeSet getOrderedTypeSet(IndexedClass cls) {
+  OrderedTypeSet /*!*/ getOrderedTypeSet(IndexedClass cls) {
     assert(checkFamily(cls));
     KClassData data = classes.getData(cls);
     _ensureSupertypes(cls, data);
@@ -808,10 +809,11 @@
   }
 
   @override
-  Iterable<InterfaceType> getInterfaces(IndexedClass cls) {
+  Iterable<InterfaceType> /*!*/ getInterfaces(IndexedClass cls) {
     assert(checkFamily(cls));
     KClassData data = classes.getData(cls);
     _ensureSupertypes(cls, data);
+    assert(data.interfaces != null);
     return data.interfaces;
   }
 
@@ -1164,7 +1166,7 @@
   List<ConstantValue> getMetadata(
       ir.StaticTypeContext staticTypeContext, List<ir.Expression> annotations) {
     if (annotations.isEmpty) return const <ConstantValue>[];
-    List<ConstantValue> metadata = <ConstantValue>[];
+    List<ConstantValue /*!*/ > metadata = <ConstantValue>[];
     annotations.forEach((ir.Expression node) {
       // We skip the implicit cast checks for metadata to avoid circular
       // dependencies in the js-interop class registration.
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 5829b7d..4611754 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -539,8 +539,8 @@
 
   InterfaceType get thisType;
   InterfaceType get jsInteropType;
-  InterfaceType get rawType;
-  InterfaceType get instantiationToBounds;
+  InterfaceType /*?*/ get rawType;
+  InterfaceType /*?*/ get instantiationToBounds;
   InterfaceType get supertype;
   InterfaceType get mixedInType;
   List<InterfaceType> get interfaces;
@@ -668,7 +668,7 @@
   List<TypeVariableType> _typeVariables;
 
   @override
-  List<TypeVariableType> getFunctionTypeVariables(
+  List<TypeVariableType> /*!*/ getFunctionTypeVariables(
       covariant KernelToElementMap elementMap) {
     if (_typeVariables == null) {
       if (functionNode.typeParameters.isEmpty) {
diff --git a/pkg/compiler/lib/src/kernel/kelements.dart b/pkg/compiler/lib/src/kernel/kelements.dart
index 8f185cc..1731db7 100644
--- a/pkg/compiler/lib/src/kernel/kelements.dart
+++ b/pkg/compiler/lib/src/kernel/kelements.dart
@@ -282,7 +282,7 @@
   final MemberEntity memberContext;
   final Entity executableContext;
   final ir.LocalFunction node;
-  FunctionType functionType;
+  /*late final*/ FunctionType functionType;
 
   KLocalFunction(
       this.name, this.memberContext, this.executableContext, this.node);
@@ -299,8 +299,8 @@
   final String name;
   @override
   final int index;
-  DartType bound;
-  DartType defaultType;
+  /*late final*/ DartType bound;
+  /*late final*/ DartType defaultType;
 
   KLocalTypeVariable(this.typeDeclaration, this.name, this.index);
 
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index ab584e3..64c7386 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -90,11 +90,12 @@
   /// Whether or not the CFE should evaluate constants.
   FeatureOption cfeConstants = FeatureOption('cfe-constants');
 
+  /// Whether or not to intern composite values during deserialization
+  /// (e.g. DartType).
+  FeatureOption internValues = FeatureOption('intern-composite-values');
+
   /// [FeatureOption]s which are shipped and cannot be toggled.
-  late final List<FeatureOption> shipped = [
-    newHolders,
-    legacyJavaScript,
-  ];
+  late final List<FeatureOption> shipped = [newHolders, legacyJavaScript];
 
   /// [FeatureOption]s which default to enabled.
   late final List<FeatureOption> shipping = [
@@ -107,6 +108,7 @@
     newDumpInfo,
     simpleAsyncToFuture,
     cfeConstants,
+    internValues,
   ];
 
   /// Forces canary feature on. This must run after [Option].parse.
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index 08d77ed..51e28e1 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -6,43 +6,6 @@
 
 part of 'serialization.dart';
 
-/// Enum values used for identifying different kinds of serialized data.
-///
-/// This is used to for debugging data inconsistencies between serialization
-/// and deserialization.
-enum DataKind {
-  bool,
-  uint30,
-  string,
-  enumValue,
-  uri,
-  libraryNode,
-  classNode,
-  typedefNode,
-  memberNode,
-  treeNode,
-  typeParameterNode,
-  dartType,
-  dartTypeNode,
-  sourceSpan,
-  constant,
-  import,
-  double,
-  int,
-}
-
-/// Enum used for identifying the enclosing entity of a member in serialization.
-enum MemberContextKind { library, cls }
-
-/// Enum used for identifying [Local] subclasses in serialization.
-enum LocalKind {
-  jLocal,
-  thisLocal,
-  boxLocal,
-  anonymousClosureLocal,
-  typeVariableLocal,
-}
-
 /// Enum used for identifying [ir.TreeNode] subclasses in serialization.
 enum _TreeNodeKind {
   cls,
@@ -68,64 +31,6 @@
   functionNode,
 }
 
-/// Class used for encoding tags in [ObjectDataSink] and [ObjectDataSource].
-class Tag {
-  final String value;
-
-  Tag(this.value);
-
-  @override
-  int get hashCode => value.hashCode * 13;
-
-  @override
-  bool operator ==(other) {
-    if (identical(this, other)) return true;
-    if (other is! Tag) return false;
-    return value == other.value;
-  }
-
-  @override
-  String toString() => 'Tag($value)';
-}
-
-/// Enum used for identifying [DartType] subclasses in serialization.
-enum DartTypeKind {
-  none,
-  legacyType,
-  nullableType,
-  neverType,
-  voidType,
-  typeVariable,
-  functionTypeVariable,
-  functionType,
-  interfaceType,
-  dynamicType,
-  erasedType,
-  anyType,
-  futureOr,
-}
-
-/// Enum used for identifying [ir.DartType] subclasses in serialization.
-enum DartTypeNodeKind {
-  none,
-  voidType,
-  typeParameterType,
-  functionType,
-  functionTypeVariable,
-  interfaceType,
-  typedef,
-  dynamicType,
-  invalidType,
-  thisInterfaceType,
-  exactInterfaceType,
-  doesNotComplete,
-  neverType,
-  futureOrType,
-  nullType,
-}
-
-const String functionTypeNodeTag = 'function-type-node';
-
 class DartTypeNodeWriter
     extends ir.DartTypeVisitor1<void, List<ir.TypeParameter>> {
   final DataSinkWriter _sink;
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 26a8468..2cf3679 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -4,6 +4,7 @@
 
 // @dart = 2.10
 
+import 'dart:collection';
 import 'dart:convert';
 import 'dart:typed_data';
 import 'package:kernel/ast.dart' as ir;
@@ -26,6 +27,8 @@
 
 import 'serialization_interfaces.dart' as migrated
     show DataSourceReader, DataSinkWriter;
+import 'tags.dart';
+export 'tags.dart';
 
 part 'sink.dart';
 part 'source.dart';
@@ -41,6 +44,19 @@
   String internString(String string);
 }
 
+class ValueInterner {
+  final Map<DartType, DartType> _dartTypeMap = HashMap();
+  final Map<ir.DartType, ir.DartType> _dartTypeNodeMap = HashMap();
+
+  DartType internDartType(DartType dartType) {
+    return _dartTypeMap[dartType] ??= dartType;
+  }
+
+  ir.DartType internDartTypeNode(ir.DartType dartType) {
+    return _dartTypeNodeMap[dartType] ??= dartType;
+  }
+}
+
 /// Data class representing cache information for a given [T] which can be
 /// passed from a [DataSourceReader] to other [DataSourceReader]s and [DataSinkWriter]s.
 class DataSourceTypeIndices<E, T> {
diff --git a/pkg/compiler/lib/src/serialization/serialization_interfaces.dart b/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
index 4f241ec..161aa37 100644
--- a/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
+++ b/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
@@ -2,8 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:kernel/ast.dart' as ir show DartType, Member, TreeNode;
+
 import '../elements/entities.dart';
 
+export 'tags.dart';
+
 /// NNBD-migrated interface for methods of DataSinkWriter.
 ///
 /// This is a pure interface or facade for DataSinkWriter.
@@ -55,6 +59,12 @@
   void writeLibrary(covariant LibraryEntity value); // IndexedLibrary
   void writeLibraryOrNull(covariant LibraryEntity? value); // IndexedLibrary
 
+  void writeDartTypeNode(ir.DartType value);
+  void writeDartTypeNodeOrNull(ir.DartType? value);
+
+  void inMemberContext(ir.Member context, void f());
+  void writeTreeNodeMapInContext<V>(Map<ir.TreeNode, V>? map, void f(V value),
+      {bool allowNull = false});
 }
 
 /// Migrated interface for methods of DataSourceReader.
@@ -78,4 +88,11 @@
 
   LibraryEntity readLibrary(); // IndexedLibrary;
   LibraryEntity? readLibraryOrNull(); // IndexedLibrary;
+
+  ir.DartType readDartTypeNode();
+  ir.DartType? readDartTypeNodeOrNull();
+
+  T inMemberContext<T>(ir.Member context, T f());
+  Map<K, V> readTreeNodeMapInContext<K extends ir.TreeNode, V>(V f());
+  Map<K, V>? readTreeNodeMapInContextOrNull<K extends ir.TreeNode, V>(V f());
 }
diff --git a/pkg/compiler/lib/src/serialization/sink.dart b/pkg/compiler/lib/src/serialization/sink.dart
index b70e081..a3e37af 100644
--- a/pkg/compiler/lib/src/serialization/sink.dart
+++ b/pkg/compiler/lib/src/serialization/sink.dart
@@ -544,7 +544,9 @@
   ///
   /// This is a convenience method to be used together with
   /// [DataSourceReader.readTreeNodeMapInContext].
-  void writeTreeNodeMapInContext<V>(Map<ir.TreeNode, V> map, void f(V value),
+  @override
+  void writeTreeNodeMapInContext<V>(
+      Map<ir.TreeNode, V> /*?*/ map, void f(V value),
       {bool allowNull = false}) {
     if (map == null) {
       assert(allowNull);
@@ -640,11 +642,18 @@
     }
   }
 
-  /// Writes the kernel type node [value] to this data sink. If [allowNull] is
-  /// `true`, [value] is allowed to be `null`.
-  void writeDartTypeNode(ir.DartType value, {bool allowNull = false}) {
+  /// Writes the kernel type node [value] to this data sink.
+  @override
+  void writeDartTypeNode(ir.DartType /*!*/ value) {
     _writeDataKind(DataKind.dartTypeNode);
-    _writeDartTypeNode(value, [], allowNull: allowNull);
+    _writeDartTypeNode(value, [], allowNull: false);
+  }
+
+  /// Writes the kernel type node [value] to this data sink, `null` permitted.
+  @override
+  void writeDartTypeNodeOrNull(ir.DartType /*?*/ value) {
+    _writeDataKind(DataKind.dartTypeNode);
+    _writeDartTypeNode(value, [], allowNull: true);
   }
 
   void _writeDartTypeNode(
@@ -1231,6 +1240,7 @@
   /// Invoke [f] in the context of [member]. This sets up support for
   /// serialization of `ir.TreeNode`s using the `writeTreeNode*InContext`
   /// methods.
+  @override
   void inMemberContext(ir.Member context, void f()) {
     ir.Member oldMemberContext = _currentMemberContext;
     _MemberData oldMemberData = _currentMemberData;
diff --git a/pkg/compiler/lib/src/serialization/source.dart b/pkg/compiler/lib/src/serialization/source.dart
index a81a4c9..df62ec5 100644
--- a/pkg/compiler/lib/src/serialization/source.dart
+++ b/pkg/compiler/lib/src/serialization/source.dart
@@ -43,6 +43,7 @@
       List<ir.DartType>.empty();
 
   final bool useDataKinds;
+  final ValueInterner /*?*/ interner;
   DataSourceIndices importedIndices;
   EntityReader _entityReader = const EntityReader();
   ComponentLookup _componentLookup;
@@ -71,7 +72,7 @@
   }
 
   DataSourceReader(this._sourceReader,
-      {this.useDataKinds = false, this.importedIndices}) {
+      {this.useDataKinds = false, this.importedIndices, this.interner}) {
     _stringIndex = _createSource<String>();
     _uriIndex = _createSource<Uri>();
     _memberNodeIndex = _createSource<_MemberData>();
@@ -176,6 +177,7 @@
   /// Invoke [f] in the context of [member]. This sets up support for
   /// deserialization of `ir.TreeNode`s using the `readTreeNode*InContext`
   /// methods.
+  @override
   T inMemberContext<T>(ir.Member context, T f()) {
     ir.Member oldMemberContext = _currentMemberContext;
     _MemberData oldMemberData = _currentMemberData;
@@ -591,15 +593,26 @@
 
   /// Reads a map from kernel tree nodes to [V] values in the known [context]
   /// from this data source, calling [f] to read each value from the data
-  /// source. If [emptyAsNull] is `true`, `null` is returned instead of an empty
-  /// map.
+  /// source.
   ///
   /// This is a convenience method to be used together with
   /// [DataSinkWriter.writeTreeNodeMapInContext].
-  Map<K, V> readTreeNodeMapInContext<K extends ir.TreeNode, V>(V f(),
-      {bool emptyAsNull = false}) {
+  @override
+  Map<K, V> readTreeNodeMapInContext<K extends ir.TreeNode, V>(V f()) {
+    return readTreeNodeMapInContextOrNull<K, V>(f) ?? {};
+  }
+
+  /// Reads a map from kernel tree nodes to [V] values in the known [context]
+  /// from this data source, calling [f] to read each value from the data
+  /// source. `null` is returned for an empty map.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSinkWriter.writeTreeNodeMapInContext].
+  @override
+  Map<K, V> /*?*/ readTreeNodeMapInContextOrNull<K extends ir.TreeNode, V>(
+      V f()) {
     int count = readInt();
-    if (count == 0 && emptyAsNull) return null;
+    if (count == 0) return null;
     Map<K, V> map = {};
     for (int i = 0; i < count; i++) {
       ir.TreeNode node = readTreeNodeInContextInternal(currentMemberData);
@@ -647,7 +660,8 @@
   /// Reads a type from this data source.
   DartType /*!*/ readDartType() {
     _checkDataKind(DataKind.dartType);
-    return DartType.readFromDataSource(this, []);
+    final type = DartType.readFromDataSource(this, []);
+    return interner?.internDartType(type) ?? type;
   }
 
   /// Reads a nullable type from this data source.
@@ -678,13 +692,23 @@
 
   /// Reads a kernel type node from this data source. If [allowNull], the
   /// returned type is allowed to be `null`.
-  ir.DartType readDartTypeNode({bool allowNull = false}) {
+  @override
+  ir.DartType /*!*/ readDartTypeNode() {
     _checkDataKind(DataKind.dartTypeNode);
-    ir.DartType type = _readDartTypeNode([]);
-    assert(type != null || allowNull);
+    ir.DartType type = readDartTypeNodeOrNull();
+    if (type == null) throw UnsupportedError('Unexpected `null` DartTypeNode');
     return type;
   }
 
+  /// Reads a kernel type node from this data source. The returned type is
+  /// allowed to be `null`.
+  @override
+  ir.DartType /*?*/ readDartTypeNodeOrNull() {
+    _checkDataKind(DataKind.dartTypeNode);
+    final type = _readDartTypeNode([]);
+    return interner?.internDartTypeNode(type) ?? type;
+  }
+
   ir.DartType _readDartTypeNode(List<ir.TypeParameter> functionTypeVariables) {
     DartTypeNodeKind kind = readEnum(DartTypeNodeKind.values);
     switch (kind) {
diff --git a/pkg/compiler/lib/src/serialization/tags.dart b/pkg/compiler/lib/src/serialization/tags.dart
new file mode 100644
index 0000000..9af5c36
--- /dev/null
+++ b/pkg/compiler/lib/src/serialization/tags.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Enum values used for identifying different kinds of serialized data.
+///
+/// This is used to for debugging data inconsistencies between serialization
+/// and deserialization.
+enum DataKind {
+  bool,
+  uint30,
+  string,
+  enumValue,
+  uri,
+  libraryNode,
+  classNode,
+  typedefNode,
+  memberNode,
+  treeNode,
+  typeParameterNode,
+  dartType,
+  dartTypeNode,
+  sourceSpan,
+  constant,
+  import,
+  double,
+  int,
+}
+
+/// Enum used for identifying the enclosing entity of a member in serialization.
+enum MemberContextKind { library, cls }
+
+/// Enum used for identifying [Local] subclasses in serialization.
+enum LocalKind {
+  jLocal,
+  thisLocal,
+  boxLocal,
+  anonymousClosureLocal,
+  typeVariableLocal,
+}
+
+/// Class used for encoding tags in [ObjectDataSink] and [ObjectDataSource].
+class Tag {
+  final String value;
+
+  Tag(this.value);
+
+  @override
+  int get hashCode => value.hashCode * 13;
+
+  @override
+  bool operator ==(other) {
+    if (identical(this, other)) return true;
+    if (other is! Tag) return false;
+    return value == other.value;
+  }
+
+  @override
+  String toString() => 'Tag($value)';
+}
+
+/// Enum used for identifying [DartType] subclasses in serialization.
+enum DartTypeKind {
+  none,
+  legacyType,
+  nullableType,
+  neverType,
+  voidType,
+  typeVariable,
+  functionTypeVariable,
+  functionType,
+  interfaceType,
+  dynamicType,
+  erasedType,
+  anyType,
+  futureOr,
+}
+
+/// Enum used for identifying [ir.DartType] subclasses in serialization.
+enum DartTypeNodeKind {
+  none,
+  voidType,
+  typeParameterType,
+  functionType,
+  functionTypeVariable,
+  interfaceType,
+  typedef,
+  dynamicType,
+  invalidType,
+  thisInterfaceType,
+  exactInterfaceType,
+  doesNotComplete,
+  neverType,
+  futureOrType,
+  nullType,
+}
+
+const String functionTypeNodeTag = 'function-type-node';
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index a534865..6f9d2c4 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -100,10 +100,13 @@
   final api.CompilerInput _provider;
   final api.CompilerOutput _outputProvider;
   final _stringInterner = _StringInterner();
+  final ValueInterner /*?*/ _valueInterner;
 
   SerializationTask(this._options, this._reporter, this._provider,
       this._outputProvider, Measurer measurer)
-      : super(measurer);
+      : _valueInterner =
+            _options.features.internValues.isEnabled ? ValueInterner() : null,
+        super(measurer);
 
   @override
   String get name => 'Serialization';
@@ -204,7 +207,7 @@
       data.toDataSink(binarySink);
       binarySink.close();
       var source = DataSourceReader(BinaryDataSource(bytes.builder.toBytes()),
-          useDataKinds: true);
+          useDataKinds: true, interner: _valueInterner);
       source.registerComponentLookup(ComponentLookup(component));
       ModuleData.fromDataSource(source);
     }
@@ -217,8 +220,10 @@
       for (Uri uri in _options.modularAnalysisInputs) {
         api.Input<List<int>> dataInput =
             await _provider.readFromUri(uri, inputKind: api.InputKind.binary);
-        DataSourceReader source =
-            DataSourceReader(BinaryDataSource(dataInput.data));
+        DataSourceReader source = DataSourceReader(
+          BinaryDataSource(dataInput.data),
+          interner: _valueInterner,
+        );
         source.registerComponentLookup(ComponentLookup(component));
         results.readMoreFromDataSource(source);
       }
@@ -247,7 +252,8 @@
           _options.readClosedWorldUri,
           inputKind: api.InputKind.binary);
       DataSourceReader source = DataSourceReader(
-          BinaryDataSource(dataInput.data, stringInterner: _stringInterner));
+          BinaryDataSource(dataInput.data, stringInterner: _stringInterner),
+          interner: _valueInterner);
       var closedWorld = deserializeClosedWorldFromSource(_options, _reporter,
           environment, abstractValueStrategy, component, source);
       return ClosedWorldAndIndices(closedWorld, source.exportIndices());
@@ -282,6 +288,7 @@
           .readFromUri(_options.readDataUri, inputKind: api.InputKind.binary);
       DataSourceReader source = DataSourceReader(
           BinaryDataSource(dataInput.data, stringInterner: _stringInterner),
+          interner: _valueInterner,
           importedIndices: closedWorldAndIndices.indices);
       return deserializeGlobalTypeInferenceResultsFromSource(
           _options,
@@ -362,6 +369,7 @@
       Map<MemberEntity, CodegenResult> results) {
     DataSourceReader source = DataSourceReader(
         BinaryDataSource(dataInput.data, stringInterner: _stringInterner),
+        interner: _valueInterner,
         importedIndices: importedIndices);
     backendStrategy.prepareCodegenReader(source);
     Map<MemberEntity, CodegenResult> codegenResults =
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 02d707c..d897f20 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -622,7 +622,7 @@
   }
 
   DartType _getDartTypeIfValid(ir.DartType type) {
-    if (type is ir.InvalidType) return null;
+    if (type is ir.InvalidType) return dartTypes.dynamicType();
     return _elementMap.getDartType(type);
   }
 
@@ -5186,7 +5186,8 @@
     // we could assert that the trailing arguments are all null.
     // TODO(jacobr): rewrite named arguments to an object literal matching
     // the factory constructor case.
-    List<HInstruction> inputs = arguments.where((arg) => arg != null).toList();
+    List<HInstruction /*!*/ > inputs =
+        arguments.where((arg) => arg != null).toList();
 
     var nativeBehavior = NativeBehavior()..sideEffects.setAllSideEffects();
 
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 3a96d59..36f104e 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -4321,7 +4321,7 @@
   AbstractValue supersetType = checkedAbstractValue.abstractValue;
   AbstractBool expressionIsNull = expression.isNull(abstractValueDomain);
 
-  bool _nullIs(DartType type) =>
+  bool _nullIs(DartType /*!*/ type) =>
       dartTypes.isStrongTopType(type) ||
       type is LegacyType &&
           (type.baseType.isObject || type.baseType is NeverType) ||
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index c545b07..5919cd6 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -530,19 +530,19 @@
   /// the usage changes for each member.
   void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
     if (staticUse.kind == StaticUseKind.CLOSURE) {
-      Local localFunction = staticUse.element;
+      Local /*!*/ localFunction = staticUse.element;
       FunctionType type =
           _elementEnvironment.getLocalFunctionType(localFunction);
       if (type.typeVariables.isNotEmpty) {
         _genericLocalFunctions.add(localFunction);
       }
-      _localFunctions.add(staticUse.element);
+      _localFunctions.add(localFunction);
       return;
     } else if (staticUse.kind == StaticUseKind.CLOSURE_CALL) {
-      if (staticUse.typeArguments?.isNotEmpty ?? false) {
+      final typeArguments = staticUse.typeArguments;
+      if (typeArguments != null && typeArguments.isNotEmpty) {
         registerDynamicInvocation(
-            Selector.call(Names.call, staticUse.callStructure),
-            staticUse.typeArguments);
+            Selector.call(Names.call, staticUse.callStructure), typeArguments);
       }
       return;
     }
diff --git a/pkg/dart2native/lib/macho.dart b/pkg/dart2native/lib/macho.dart
index 7aaccb8..e0d8f93 100644
--- a/pkg/dart2native/lib/macho.dart
+++ b/pkg/dart2native/lib/macho.dart
@@ -1176,7 +1176,7 @@
      * this requires the r_address field to be something other than a section
      * offset to identify the item to be relocated.  In this case r_address is
      * set to the offset from the vmaddr of the first LC_SEGMENT command.
-     * For MH_SPLIT_SEGS images r_address is set to the the offset from the
+     * For MH_SPLIT_SEGS images r_address is set to the offset from the
      * vmaddr of the first read-write LC_SEGMENT command.
      *
      * The relocation entries are grouped by module and the module table
@@ -1412,7 +1412,7 @@
  * isub_image field is an index into the sub-images (sub-frameworks and
  * sub-umbrellas list) that made up the two-level image that the undefined
  * symbol was found in when it was built by the static link editor.  If
- * isub-image is 0 the the symbol is expected to be defined in library and not
+ * isub-image is 0 the symbol is expected to be defined in library and not
  * in the sub-images.  If isub-image is non-zero it is an index into the array
  * of sub-images for the umbrella with the first index in the sub-images being
  * 1. The array of sub-images is the ordered list of sub-images of the umbrella
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index a367a17..77c6eaa 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -463,6 +463,11 @@
     return type;
   }
 
+  bool get isInferenceUpdate1Enabled =>
+      libraryFeatures.inferenceUpdate1.isSupported &&
+      languageVersion.version >=
+          libraryFeatures.inferenceUpdate1.enabledVersion;
+
   bool? _isNonNullableByDefault;
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 65866a4..415fe83 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -250,6 +250,9 @@
 
   CoreTypes get coreTypes => engine.coreTypes;
 
+  bool get isInferenceUpdate1Enabled =>
+      libraryBuilder.isInferenceUpdate1Enabled;
+
   bool get isNonNullableByDefault => libraryBuilder.isNonNullableByDefault;
 
   NnbdMode get nnbdMode => libraryBuilder.loader.nnbdMode;
@@ -2395,10 +2398,41 @@
       hoistingEndIndex = 0;
     }
 
+    ExpressionInferenceResult inferArgument(
+        DartType formalType, Expression argumentExpression,
+        {required bool isNamed}) {
+      DartType inferredFormalType = substitution != null
+          ? substitution.substituteType(formalType)
+          : formalType;
+      if (!isNamed) {
+        if (isSpecialCasedBinaryOperator) {
+          inferredFormalType =
+              typeSchemaEnvironment.getContextTypeOfSpecialCasedBinaryOperator(
+                  typeContext, receiverType!, inferredFormalType,
+                  isNonNullableByDefault: isNonNullableByDefault);
+        } else if (isSpecialCasedTernaryOperator) {
+          inferredFormalType =
+              typeSchemaEnvironment.getContextTypeOfSpecialCasedTernaryOperator(
+                  typeContext, receiverType!, inferredFormalType,
+                  isNonNullableByDefault: isNonNullableByDefault);
+        }
+      }
+      return inferExpression(
+          argumentExpression,
+          isNonNullableByDefault
+              ? inferredFormalType
+              : legacyErasure(inferredFormalType),
+          inferenceNeeded ||
+              isSpecialCasedBinaryOperator ||
+              isSpecialCasedTernaryOperator ||
+              typeChecksNeeded);
+    }
+
     List<EqualityInfo<VariableDeclaration, DartType>?>? identicalInfo =
         isIdentical && arguments.positional.length == 2 ? [] : null;
     int positionalIndex = 0;
     int namedIndex = 0;
+    List<_DeferredParamInfo>? deferredFunctionLiterals;
     for (int evaluationOrderIndex = 0;
         evaluationOrderIndex < argumentsEvaluationOrder.length;
         evaluationOrderIndex++) {
@@ -2421,60 +2455,77 @@
         formalType = getNamedParameterType(calleeType, namedArgument.name);
         argumentExpression = namedArgument.value;
       }
-      DartType inferredFormalType = substitution != null
-          ? substitution.substituteType(formalType)
-          : formalType;
-      if (isExpression) {
-        if (isImplicitExtensionMember && index == 0) {
-          assert(
-              receiverType != null,
-              "No receiver type provided for implicit extension member "
-              "invocation.");
-          continue;
-        }
-        if (isSpecialCasedBinaryOperator) {
-          inferredFormalType =
-              typeSchemaEnvironment.getContextTypeOfSpecialCasedBinaryOperator(
-                  typeContext, receiverType!, inferredFormalType,
-                  isNonNullableByDefault: isNonNullableByDefault);
-        } else if (isSpecialCasedTernaryOperator) {
-          inferredFormalType =
-              typeSchemaEnvironment.getContextTypeOfSpecialCasedTernaryOperator(
-                  typeContext, receiverType!, inferredFormalType,
-                  isNonNullableByDefault: isNonNullableByDefault);
-        }
+      if (isExpression && isImplicitExtensionMember && index == 0) {
+        assert(
+            receiverType != null,
+            "No receiver type provided for implicit extension member "
+            "invocation.");
+        continue;
       }
-      ExpressionInferenceResult result = inferExpression(
-          argumentExpression,
-          isNonNullableByDefault
-              ? inferredFormalType
-              : legacyErasure(inferredFormalType),
-          inferenceNeeded ||
-              isSpecialCasedBinaryOperator ||
-              isSpecialCasedTernaryOperator ||
-              typeChecksNeeded);
-      DartType inferredType = identical(result.inferredType, noInferredType) ||
-              isNonNullableByDefault
-          ? result.inferredType
-          : legacyErasure(result.inferredType);
-      if (localHoistedExpressions != null &&
-          evaluationOrderIndex >= hoistingEndIndex) {
-        hoistedExpressions = null;
-      }
-      Expression expression =
-          _hoist(result.expression, inferredType, hoistedExpressions);
-      identicalInfo
-          ?.add(flowAnalysis.equalityOperand_end(expression, inferredType));
-      if (isExpression) {
-        arguments.positional[index] = expression..parent = arguments;
+      if (isInferenceUpdate1Enabled &&
+          argumentExpression is FunctionExpression) {
+        (deferredFunctionLiterals ??= []).add(new _DeferredParamInfo(
+            formalType: formalType,
+            argumentExpression: argumentExpression,
+            isNamed: !isExpression,
+            evaluationOrderIndex: evaluationOrderIndex,
+            index: index));
+        // We don't have `identical` info yet, so fill it in with `null` for
+        // now.  Later, when we visit the function literal, we'll replace it.
+        identicalInfo?.add(null);
+        if (useFormalAndActualTypes) {
+          formalTypes!.add(formalType);
+          // We don't have an inferred type yet, so fill it in with UnknownType
+          // for now.  Later, when we infer a type, we'll replace it.
+          actualTypes!.add(const UnknownType());
+        }
       } else {
-        NamedExpression namedArgument = arguments.named[index];
-        namedArgument.value = expression..parent = namedArgument;
+        ExpressionInferenceResult result = inferArgument(
+            formalType, argumentExpression,
+            isNamed: !isExpression);
+        DartType inferredType = _computeInferredType(result);
+        if (localHoistedExpressions != null &&
+            evaluationOrderIndex >= hoistingEndIndex) {
+          hoistedExpressions = null;
+        }
+        Expression expression =
+            _hoist(result.expression, inferredType, hoistedExpressions);
+        identicalInfo
+            ?.add(flowAnalysis.equalityOperand_end(expression, inferredType));
+        if (isExpression) {
+          arguments.positional[index] = expression..parent = arguments;
+        } else {
+          NamedExpression namedArgument = arguments.named[index];
+          namedArgument.value = expression..parent = namedArgument;
+        }
+        gatherer?.tryConstrainLower(formalType, inferredType);
+        if (useFormalAndActualTypes) {
+          formalTypes!.add(formalType);
+          actualTypes!.add(inferredType);
+        }
       }
-      gatherer?.tryConstrainLower(formalType, inferredType);
-      if (useFormalAndActualTypes) {
-        formalTypes!.add(formalType);
-        actualTypes!.add(inferredType);
+    }
+    if (deferredFunctionLiterals != null) {
+      for (_DeferredParamInfo deferredArgument in deferredFunctionLiterals) {
+        ExpressionInferenceResult result = inferArgument(
+            deferredArgument.formalType, deferredArgument.argumentExpression,
+            isNamed: deferredArgument.isNamed);
+        DartType inferredType = _computeInferredType(result);
+        Expression expression = result.expression;
+        identicalInfo?[deferredArgument.evaluationOrderIndex] =
+            flowAnalysis.equalityOperand_end(expression, inferredType);
+        if (deferredArgument.isNamed) {
+          NamedExpression namedArgument =
+              arguments.named[deferredArgument.index];
+          namedArgument.value = expression..parent = namedArgument;
+        } else {
+          arguments.positional[deferredArgument.index] = expression
+            ..parent = arguments;
+        }
+        gatherer?.tryConstrainLower(deferredArgument.formalType, inferredType);
+        if (useFormalAndActualTypes) {
+          actualTypes![deferredArgument.evaluationOrderIndex] = inferredType;
+        }
       }
     }
     if (identicalInfo != null) {
@@ -4718,6 +4769,11 @@
   Expression createEqualsNull(int fileOffset, Expression left) {
     return new EqualsNull(left)..fileOffset = fileOffset;
   }
+
+  DartType _computeInferredType(ExpressionInferenceResult result) =>
+      identical(result.inferredType, noInferredType) || isNonNullableByDefault
+          ? result.inferredType
+          : legacyErasure(result.inferredType);
 }
 
 class TypeInferrerImplBenchmarked implements TypeInferrer {
@@ -5877,3 +5933,33 @@
   ImplicitInstantiation(
       this.typeArguments, this.functionType, this.instantiatedType);
 }
+
+/// Information about an invocation argument that needs to be resolved later due
+/// to the fact that it's a function literal and the `inference-update-1`
+/// feature is enabled.
+class _DeferredParamInfo {
+  /// The (unsubstituted) type of the formal parameter corresponding to this
+  /// argument.
+  final DartType formalType;
+
+  /// The function literal expression.
+  final FunctionExpression argumentExpression;
+
+  /// Indicates whether this is a named argument.
+  final bool isNamed;
+
+  /// The index into the full argument list (considering both named and unnamed
+  /// arguments) of the function literal expression.
+  final int evaluationOrderIndex;
+
+  /// The index into either [Arguments.named] or [Arguments.positional] of the
+  /// function literal expression (depending upon the value of [isNamed]).
+  final int index;
+
+  _DeferredParamInfo(
+      {required this.formalType,
+      required this.argumentExpression,
+      required this.isNamed,
+      required this.evaluationOrderIndex,
+      required this.index});
+}
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 3d62028..65269dd 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -68,20 +68,25 @@
     show
         AwaitExpression,
         BasicLiteral,
+        Class,
         Component,
         Constant,
         ConstantExpression,
         Expression,
         FileUriExpression,
         FileUriNode,
+        InstanceInvocation,
+        InstanceSet,
         InvalidExpression,
         Library,
         LibraryPart,
         Member,
         Node,
         NonNullableByDefaultCompiledMode,
+        Reference,
         TreeNode,
         UnevaluatedConstant,
+        VariableDeclaration,
         Version,
         Visitor,
         VisitorVoidMixin;
@@ -91,6 +96,15 @@
 import 'package:kernel/kernel.dart'
     show RecursiveResultVisitor, loadComponentFromBytes;
 import 'package:kernel/reference_from_index.dart' show ReferenceFromIndex;
+
+import 'package:kernel/src/equivalence.dart'
+    show
+        EquivalenceResult,
+        EquivalenceStrategy,
+        EquivalenceVisitor,
+        ReferenceName,
+        checkEquivalence;
+
 import 'package:kernel/target/changed_structure_notifier.dart'
     show ChangedStructureNotifier;
 import 'package:kernel/target/targets.dart'
@@ -103,6 +117,7 @@
         TestTargetFlags,
         TestTargetMixin,
         TestTargetWrapper;
+
 import 'package:kernel/type_environment.dart'
     show StaticTypeContext, TypeEnvironment;
 import 'package:testing/testing.dart'
@@ -1371,11 +1386,39 @@
             "${newUserLibraries.map((e) => e.toString()).join("\n")}\n\n"
             "${originalCompileString}");
       }
+
+      if (!compareComponents(component, newComponent)) {
+        return new Result<ComponentResult>(originalCompilationResult,
+            semiFuzzFailure, "Fuzzed component changed in an unexpected way.");
+      }
     }
 
     return null;
   }
 
+  bool compareComponents(Component a, Component b) {
+    if (a.libraries.length != b.libraries.length) {
+      print("Not the same number of libraries.");
+      return false;
+    }
+    a.libraries.sort((l1, l2) {
+      return "${l1.importUri}".compareTo("${l2.importUri}");
+    });
+    b.libraries.sort((l1, l2) {
+      return "${l1.importUri}".compareTo("${l2.importUri}");
+    });
+    for (int i = 0; i < a.libraries.length; i++) {
+      EquivalenceResult result = checkEquivalence(
+          a.libraries[i], b.libraries[i],
+          strategy: const Strategy());
+      if (!result.isEquivalent) {
+        print(result.toString());
+        return false;
+      }
+    }
+    return true;
+  }
+
   bool canSerialize(Component component) {
     ByteSink byteSink = new ByteSink();
     try {
@@ -1670,6 +1713,83 @@
   }
 }
 
+class Strategy extends EquivalenceStrategy {
+  const Strategy();
+
+  @override
+  bool checkLibrary_procedures(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkSets(node.procedures.toSet(), other.procedures.toSet(),
+        visitor.matchNamedNodes, visitor.checkNodes, 'procedures');
+  }
+
+  @override
+  bool checkClass_procedures(
+      EquivalenceVisitor visitor, Class node, Class other) {
+    return visitor.checkSets(node.procedures.toSet(), other.procedures.toSet(),
+        visitor.matchNamedNodes, visitor.checkNodes, 'procedures');
+  }
+
+  @override
+  bool checkLibrary_additionalExports(
+      EquivalenceVisitor visitor, Library node, Library other) {
+    return visitor.checkSets(
+        node.additionalExports.toSet(),
+        other.additionalExports.toSet(),
+        visitor.matchReferences,
+        visitor.checkReferences,
+        'additionalExports');
+  }
+
+  @override
+  bool checkVariableDeclaration_binaryOffsetNoTag(EquivalenceVisitor visitor,
+      VariableDeclaration node, VariableDeclaration other) {
+    return true;
+  }
+
+  /// Allow assuming references like
+  /// "_Class&Superclass&Mixin::@methods::method4" and
+  /// "Mixin::@methods::method4" are equal (an interfaceTargetReference change
+  /// that often occur on recompile in regards to mixins).
+  ///
+  /// Copied from incremental_dart2js_load_from_dill_test.dart
+  bool _isMixinOrCloneReference(EquivalenceVisitor visitor, Reference? a,
+      Reference? b, String propertyName) {
+    if (a != null && b != null) {
+      ReferenceName thisName = ReferenceName.fromReference(a)!;
+      ReferenceName otherName = ReferenceName.fromReference(b)!;
+      if (thisName.isMember &&
+          otherName.isMember &&
+          thisName.memberName == otherName.memberName) {
+        String? thisClassName = thisName.declarationName;
+        String? otherClassName = otherName.declarationName;
+        if (thisClassName != null &&
+            otherClassName != null &&
+            thisClassName.contains('&${otherClassName}')) {
+          visitor.assumeReferences(a, b);
+        }
+      }
+    }
+    return visitor.checkReferences(a, b, propertyName);
+  }
+
+  @override
+  bool checkInstanceInvocation_interfaceTargetReference(
+      EquivalenceVisitor visitor,
+      InstanceInvocation node,
+      InstanceInvocation other) {
+    return _isMixinOrCloneReference(visitor, node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+
+  @override
+  bool checkInstanceSet_interfaceTargetReference(
+      EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+    return _isMixinOrCloneReference(visitor, node.interfaceTargetReference,
+        other.interfaceTargetReference, 'interfaceTargetReference');
+  }
+}
+
 class FuzzAstVisitorSorterChunk {
   final FuzzOriginalType originalType;
   final String data;
diff --git a/pkg/front_end/test/incremental_suite.dart b/pkg/front_end/test/incremental_suite.dart
index d4399ff..e96910b 100644
--- a/pkg/front_end/test/incremental_suite.dart
+++ b/pkg/front_end/test/incremental_suite.dart
@@ -99,6 +99,8 @@
 
 import "incremental_utils.dart" as util;
 
+import 'testing_utils.dart' show checkEnvironment;
+
 import 'utils/io_utils.dart' show computeRepoDir;
 
 void main([List<String> arguments = const []]) =>
@@ -240,12 +242,22 @@
 final Expectation NNBDModeMismatch = staticExpectationSet["NNBDModeMismatch"];
 
 Future<Context> createContext(Chain suite, Map<String, String> environment) {
+  const Set<String> knownEnvironmentKeys = {
+    "updateExpectations",
+    "addDebugBreaks",
+    "skipTests",
+  };
+  checkEnvironment(environment, knownEnvironmentKeys);
+
   // Disable colors to ensure that expectation files are the same across
   // platforms and independent of stdin/stderr.
   colors.enableColors = false;
+  Set<String> skipTests = environment["skipTests"]?.split(",").toSet() ?? {};
   return new Future.value(new Context(
-      environment["updateExpectations"] == "true",
-      environment["addDebugBreaks"] == "true"));
+    environment["updateExpectations"] == "true",
+    environment["addDebugBreaks"] == "true",
+    skipTests,
+  ));
 }
 
 class Context extends ChainContext {
@@ -261,7 +273,23 @@
   /// iteration (or 'world run') when doing a "new world test".
   final bool breakBetween;
 
-  Context(this.updateExpectations, this.breakBetween);
+  final Set<String> skipTests;
+
+  Context(this.updateExpectations, this.breakBetween, this.skipTests);
+
+  @override
+  Stream<TestDescription> list(Chain suite) {
+    if (skipTests.isEmpty) return super.list(suite);
+    return filterSkipped(super.list(suite));
+  }
+
+  Stream<TestDescription> filterSkipped(Stream<TestDescription> all) async* {
+    await for (TestDescription testDescription in all) {
+      if (!skipTests.contains(testDescription.shortName)) {
+        yield testDescription;
+      }
+    }
+  }
 
   @override
   Future<void> cleanUp(TestDescription description, Result result) async {
@@ -878,6 +906,13 @@
         }
       }
 
+      util.postProcessComponent(component!);
+      String actualSerialized = componentToStringSdkFiltered(component!);
+      print("*****\n\ncomponent:\n"
+          "${actualSerialized}\n\n\n");
+      result = checkExpectFile(data, worldNum, "", context, actualSerialized);
+      if (result != null) return result;
+
       if (world["compareToPrevious"] == true && newestWholeComponent != null) {
         EquivalenceResult result = checkEquivalence(
             newestWholeComponent!, component!,
@@ -890,9 +925,6 @@
 
       newestWholeComponentData = util.postProcess(component!);
       newestWholeComponent = component;
-      String actualSerialized = componentToStringSdkFiltered(component!);
-      print("*****\n\ncomponent:\n"
-          "${actualSerialized}\n\n\n");
 
       if (world["uriToSourcesDoesntInclude"] != null) {
         for (String filename in world["uriToSourcesDoesntInclude"]) {
@@ -927,8 +959,6 @@
         }
       }
 
-      result = checkExpectFile(data, worldNum, "", context, actualSerialized);
-      if (result != null) return result;
       if (world["skipClassHierarchyTest"] != true) {
         result = checkClassHierarchy(compilerResult, data, worldNum, context);
         if (result != null) return result;
diff --git a/pkg/front_end/test/incremental_utils.dart b/pkg/front_end/test/incremental_utils.dart
index 49c7663..7ad424c 100644
--- a/pkg/front_end/test/incremental_utils.dart
+++ b/pkg/front_end/test/incremental_utils.dart
@@ -21,6 +21,11 @@
         Reference;
 
 List<int> postProcess(Component c) {
+  postProcessComponent(c);
+  return serializeComponent(c);
+}
+
+void postProcessComponent(Component c) {
   c.libraries.sort((l1, l2) {
     return "${l1.fileUri}".compareTo("${l2.fileUri}");
   });
@@ -34,8 +39,6 @@
     });
     library.problemsAsJson?.sort();
   }
-
-  return serializeComponent(c);
 }
 
 void throwOnEmptyMixinBodies(Component component) {
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 5590566..103c5d1 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -248,6 +248,7 @@
 configured
 connectivity
 consideration
+considering
 constness
 constraining
 consult
@@ -1441,6 +1442,7 @@
 unshadowed
 unsortable
 unsound
+unsubstituted
 untouched
 unwrapper
 unwraps
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 38d1b02..869c4d1 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -222,6 +222,7 @@
 draw
 dry
 dsemi
+dskip
 dumping
 dumps
 dupe
@@ -340,6 +341,7 @@
 implementor
 implementors
 imprecision
+improvement
 inclosure
 inconsistencies
 increasing
diff --git a/pkg/front_end/test/vm_service_for_leak_detection.dart b/pkg/front_end/test/vm_service_for_leak_detection.dart
index 44b38c4..0ff1658 100644
--- a/pkg/front_end/test/vm_service_for_leak_detection.dart
+++ b/pkg/front_end/test/vm_service_for_leak_detection.dart
@@ -55,6 +55,9 @@
       "--enable-asserts",
       Platform.script.resolve("incremental_suite.dart").toString(),
       "-DaddDebugBreaks=true",
+      // import_package_by_file_uri by design imports the same file in two
+      // different ways, thus getting two copies of the same library.
+      "-DskipTests=import_package_by_file_uri"
     ]);
   } else {
     await heapHelper.start([
diff --git a/pkg/front_end/testcases/incremental.status b/pkg/front_end/testcases/incremental.status
index aaa2393..1afe42e 100644
--- a/pkg/front_end/testcases/incremental.status
+++ b/pkg/front_end/testcases/incremental.status
@@ -8,4 +8,11 @@
 #strongmode_mixins_2: Crash
 
 changing_modules_16: Crash
-late_lowering: EquivalenceError
\ No newline at end of file
+late_lowering: EquivalenceError
+constant_fileoffset_and_typedef: EquivalenceError
+no_change_but_changed_type: EquivalenceError
+no_such_method_forwarder: EquivalenceError
+no_change_but_changed_type_02: EquivalenceError
+changing_nullability_on_recompile: EquivalenceError
+initializer_not_copied: EquivalenceError
+changed_error: EquivalenceError
diff --git a/pkg/front_end/testcases/incremental/changed_error.yaml b/pkg/front_end/testcases/incremental/changed_error.yaml
new file mode 100644
index 0000000..19c4d71
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changed_error.yaml
@@ -0,0 +1,36 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Recompiling with no change shouldn't change anything.
+# http://dartbug.com/48897
+
+type: newworld
+worlds:
+  - entry: main.dart
+    errors: true
+    sources:
+      main.dart: |
+        // @dart=2.12
+
+        import "lib.dart";
+
+        main() {
+          Bar<int> x = new Bar<int>();
+          print(x);
+        }
+      lib.dart: |
+        // @dart=2.12
+        class Foo<X> {}
+        typedef Bar<X> = Foo<X>;
+
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    compareToPrevious: true
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/changed_error.yaml.world.1.expect b/pkg/front_end/testcases/incremental/changed_error.yaml.world.1.expect
new file mode 100644
index 0000000..3694fc5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changed_error.yaml.world.1.expect
@@ -0,0 +1,33 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib.dart:3:16: Error: Can't create typedef from non-function type.
+// typedef Bar<X> = Foo<X>;
+//                ^
+//
+
+  typedef Bar<unrelated X extends dart.core::Object? = dynamic> = invalid-type;
+  class Foo<X extends dart.core::Object? = dynamic> extends dart.core::Object {
+    synthetic constructor •() → lib::Foo<lib::Foo::X%>
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:6:20: Error: Can't create typedef from non-function type.
+//   Bar<int> x = new Bar<int>();
+//                    ^^^
+//
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    invalid-type x = invalid-expression "org-dartlang-test:///main.dart:6:20: Error: Can't create typedef from non-function type.\n  Bar<int> x = new Bar<int>();\n                   ^^^";
+    dart.core::print(x);
+  }
+}
diff --git a/pkg/front_end/testcases/incremental/changed_error.yaml.world.2.expect b/pkg/front_end/testcases/incremental/changed_error.yaml.world.2.expect
new file mode 100644
index 0000000..1c4c0ee
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changed_error.yaml.world.2.expect
@@ -0,0 +1,33 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib.dart:3:16: Error: Can't create typedef from non-function type.
+// typedef Bar<X> = Foo<X>;
+//                ^
+//
+
+  typedef Bar<unrelated X extends dart.core::Object? = dynamic> = invalid-type;
+  class Foo<X extends dart.core::Object? = dynamic> extends dart.core::Object {
+    synthetic constructor •() → lib::Foo<lib::Foo::X%>
+      : super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:6:20: Error: Couldn't find constructor 'Bar'.
+//   Bar<int> x = new Bar<int>();
+//                    ^^^
+//
+
+  import "org-dartlang-test:///lib.dart";
+
+  static method main() → dynamic {
+    invalid-type x = invalid-expression "org-dartlang-test:///main.dart:6:20: Error: Couldn't find constructor 'Bar'.\n  Bar<int> x = new Bar<int>();\n                   ^^^";
+    dart.core::print(x);
+  }
+}
diff --git a/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml
new file mode 100644
index 0000000..2cb29e2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml
@@ -0,0 +1,35 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Recompiling with no change shouldn't change anything.
+# http://dartbug.com/48894
+
+type: newworld
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        // @dart=2.5
+
+        import 'lib.dart';
+
+        class LegacyClass extends Class implements Interface {}
+      lib.dart: |
+        abstract class Interface {
+          int method5c([int a = 0, int? b]);
+          int method7b({int a: 0, int? b});
+        }
+        class Class {
+          int method5c([int a = 0, int? b]) => 0;
+          int method7b({int a = 0, int? b}) => 0;
+        }
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    worldType: updated
+    compareToPrevious: true
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.1.expect b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.1.expect
new file mode 100644
index 0000000..7832042
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.1.expect
@@ -0,0 +1,46 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  abstract class Interface extends dart.core::Object {
+    synthetic constructor •() → lib::Interface
+      : super dart.core::Object::•()
+      ;
+    abstract method method5c([dart.core::int a = #C1, dart.core::int? b = #C2]) → dart.core::int;
+    abstract method method7b({dart.core::int a = #C1, dart.core::int? b = #C2}) → dart.core::int;
+  }
+  class Class extends dart.core::Object {
+    synthetic constructor •() → lib::Class
+      : super dart.core::Object::•()
+      ;
+    method method5c([dart.core::int a = #C1, dart.core::int? b = #C2]) → dart.core::int
+      return 0;
+    method method7b({dart.core::int a = #C1, dart.core::int? b = #C2}) → dart.core::int
+      return 0;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class LegacyClass extends lib::Class implements lib::Interface {
+    synthetic constructor •() → main::LegacyClass*
+      : super lib::Class::•()
+      ;
+    abstract member-signature method method5c([dart.core::int* a = #C1, dart.core::int* b = #C2]) → dart.core::int*; -> lib::Class::method5c
+    abstract member-signature method method7b({dart.core::int* a = #C1, dart.core::int* b = #C2}) → dart.core::int*; -> lib::Class::method7b
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
+constants  {
+  #C1 = 0
+  #C2 = null
+}
diff --git a/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.2.expect b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.2.expect
new file mode 100644
index 0000000..7832042
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.2.expect
@@ -0,0 +1,46 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  abstract class Interface extends dart.core::Object {
+    synthetic constructor •() → lib::Interface
+      : super dart.core::Object::•()
+      ;
+    abstract method method5c([dart.core::int a = #C1, dart.core::int? b = #C2]) → dart.core::int;
+    abstract method method7b({dart.core::int a = #C1, dart.core::int? b = #C2}) → dart.core::int;
+  }
+  class Class extends dart.core::Object {
+    synthetic constructor •() → lib::Class
+      : super dart.core::Object::•()
+      ;
+    method method5c([dart.core::int a = #C1, dart.core::int? b = #C2]) → dart.core::int
+      return 0;
+    method method7b({dart.core::int a = #C1, dart.core::int? b = #C2}) → dart.core::int
+      return 0;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class LegacyClass extends lib::Class implements lib::Interface {
+    synthetic constructor •() → main::LegacyClass*
+      : super lib::Class::•()
+      ;
+    abstract member-signature method method5c([dart.core::int* a = #C1, dart.core::int* b = #C2]) → dart.core::int*; -> lib::Class::method5c
+    abstract member-signature method method7b({dart.core::int* a = #C1, dart.core::int* b = #C2}) → dart.core::int*; -> lib::Class::method7b
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
+constants  {
+  #C1 = 0
+  #C2 = null
+}
diff --git a/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml
new file mode 100644
index 0000000..3e91d8d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml
@@ -0,0 +1,33 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Offset should be correct and not change when nothing changes. A type literal
+# constants FunctionType really shouldn't point to a TypedefType (and if it does
+# it shouldn't change when recompiling with no change).
+# http://dartbug.com/48890
+
+type: newworld
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "lib1.dart";
+        import "lib2.dart";
+      lib1.dart: |
+        // Stuff here to change the offset.
+        const genericFunctionTypeLiteral1 = td1;
+        typedef td1 = T Function<T>(T);
+      lib2.dart: |
+        const genericFunctionTypeLiteral2 = td2;
+        typedef td2 = T Function<T>(T);
+        typedef td3 = T1 Function<T1, T2>(T2);
+    expectedLibraryCount: 3
+
+  - entry: main.dart
+    worldType: updated
+    compareToPrevious: true
+    expectInitializeFromDill: false
+    invalidate:
+      - lib2.dart
+    expectedLibraryCount: 3
diff --git a/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.1.expect b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.1.expect
new file mode 100644
index 0000000..4c9cfb2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.1.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib1.dart" as lib1 {
+
+  typedef td1 = <T extends dart.core::Object? = dynamic>(T%) → T%;
+  static const field dart.core::Type genericFunctionTypeLiteral1 = #C1;
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  typedef td2 = <T extends dart.core::Object? = dynamic>(T%) → T%;
+  typedef td3 = <T1 extends dart.core::Object? = dynamic, T2 extends dart.core::Object? = dynamic>(T2%) → T1%;
+  static const field dart.core::Type genericFunctionTypeLiteral2 = #C1;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib1.dart";
+  import "org-dartlang-test:///lib2.dart";
+
+}
+constants  {
+  #C1 = TypeLiteralConstant(<T extends dart.core::Object? = dynamic>(T*) →* T*)
+}
diff --git a/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.2.expect b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.2.expect
new file mode 100644
index 0000000..4c9cfb2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.2.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib1.dart" as lib1 {
+
+  typedef td1 = <T extends dart.core::Object? = dynamic>(T%) → T%;
+  static const field dart.core::Type genericFunctionTypeLiteral1 = #C1;
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+  typedef td2 = <T extends dart.core::Object? = dynamic>(T%) → T%;
+  typedef td3 = <T1 extends dart.core::Object? = dynamic, T2 extends dart.core::Object? = dynamic>(T2%) → T1%;
+  static const field dart.core::Type genericFunctionTypeLiteral2 = #C1;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib1.dart";
+  import "org-dartlang-test:///lib2.dart";
+
+}
+constants  {
+  #C1 = TypeLiteralConstant(<T extends dart.core::Object? = dynamic>(T*) →* T*)
+}
diff --git a/pkg/front_end/testcases/incremental/initializer_not_copied.yaml b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml
new file mode 100644
index 0000000..f6b8c6b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml
@@ -0,0 +1,46 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Recompiling with no change shouldn't change the initializer.
+# In fact, this woukd (currently) print `[null]` when compiled once,
+# but `[a1]` if recompiling main.dart first.
+# http://dartbug.com/48895
+
+type: newworld
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        // @dart=2.9
+        import 'lib.dart';
+        class C extends C3 implements C4 {
+          void noSuchMethod(Invocation invocation) {
+            print(invocation.positionalArguments);
+          }
+        }
+        main() {
+          C c = new C();
+          c.m();
+        }
+      lib.dart: |
+        abstract class C1 {
+          m();
+        }
+        abstract class C2 {
+          m([String a = "a1"]);
+        }
+        abstract class C3 implements C1, C2 {}
+        abstract class C4 {
+          m([covariant String a = "a2"]);
+        }
+
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    worldType: updated
+    compareToPrevious: true
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.1.expect b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.1.expect
new file mode 100644
index 0000000..dc9903b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.1.expect
@@ -0,0 +1,63 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  abstract class C1 extends dart.core::Object {
+    synthetic constructor •() → lib::C1
+      : super dart.core::Object::•()
+      ;
+    abstract method m() → dynamic;
+  }
+  abstract class C2 extends dart.core::Object {
+    synthetic constructor •() → lib::C2
+      : super dart.core::Object::•()
+      ;
+    abstract method m([dart.core::String a = #C1]) → dynamic;
+  }
+  abstract class C3 extends dart.core::Object implements lib::C1, lib::C2 {
+    synthetic constructor •() → lib::C3
+      : super dart.core::Object::•()
+      ;
+    abstract member-signature method m([dart.core::String a = #C1]) → dynamic; -> lib::C2::m
+  }
+  abstract class C4 extends dart.core::Object {
+    synthetic constructor •() → lib::C4
+      : super dart.core::Object::•()
+      ;
+    abstract method m([covariant-by-declaration dart.core::String a = #C2]) → dynamic;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class C extends lib::C3 implements lib::C4 {
+    synthetic constructor •() → main::C*
+      : super lib::C3::•()
+      ;
+    method noSuchMethod(dart.core::Invocation* invocation) → void {
+      dart.core::print(invocation.{dart.core::Invocation::positionalArguments}{dart.core::List<dynamic>*});
+    }
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    no-such-method-forwarder method m([covariant-by-declaration dart.core::String* a]) → dynamic
+      return this.{main::C::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C3, 0, #C4, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(a)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C5))){(dart.core::Invocation*) →* void} as{TypeError,ForDynamic} dynamic;
+  }
+  static method main() → dynamic {
+    main::C* c = new main::C::•();
+    c.{main::C::m}(){([dart.core::String*]) →* dynamic};
+  }
+}
+constants  {
+  #C1 = "a1"
+  #C2 = "a2"
+  #C3 = #m
+  #C4 = <dart.core::Type*>[]
+  #C5 = <dart.core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.2.expect b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.2.expect
new file mode 100644
index 0000000..60cba58
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.2.expect
@@ -0,0 +1,63 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  abstract class C1 extends dart.core::Object {
+    synthetic constructor •() → lib::C1
+      : super dart.core::Object::•()
+      ;
+    abstract method m() → dynamic;
+  }
+  abstract class C2 extends dart.core::Object {
+    synthetic constructor •() → lib::C2
+      : super dart.core::Object::•()
+      ;
+    abstract method m([dart.core::String a = #C1]) → dynamic;
+  }
+  abstract class C3 extends dart.core::Object implements lib::C1, lib::C2 {
+    synthetic constructor •() → lib::C3
+      : super dart.core::Object::•()
+      ;
+    abstract member-signature method m([dart.core::String a = #C1]) → dynamic; -> lib::C2::m
+  }
+  abstract class C4 extends dart.core::Object {
+    synthetic constructor •() → lib::C4
+      : super dart.core::Object::•()
+      ;
+    abstract method m([covariant-by-declaration dart.core::String a = #C2]) → dynamic;
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class C extends lib::C3 implements lib::C4 {
+    synthetic constructor •() → main::C*
+      : super lib::C3::•()
+      ;
+    method noSuchMethod(dart.core::Invocation* invocation) → void {
+      dart.core::print(invocation.{dart.core::Invocation::positionalArguments}{dart.core::List<dynamic>*});
+    }
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    no-such-method-forwarder method m([covariant-by-declaration dart.core::String* a = #C1]) → dynamic
+      return this.{main::C::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C3, 0, #C4, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(a)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C5))){(dart.core::Invocation*) →* void} as{TypeError,ForDynamic} dynamic;
+  }
+  static method main() → dynamic {
+    main::C* c = new main::C::•();
+    c.{main::C::m}(){([dart.core::String*]) →* dynamic};
+  }
+}
+constants  {
+  #C1 = "a1"
+  #C2 = "a2"
+  #C3 = #m
+  #C4 = <dart.core::Type*>[]
+  #C5 = <dart.core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/incremental/late_lowering.yaml.world.2.expect b/pkg/front_end/testcases/incremental/late_lowering.yaml.world.2.expect
new file mode 100644
index 0000000..3537fb6
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/late_lowering.yaml.world.2.expect
@@ -0,0 +1,24 @@
+main = main::main;
+library from "org-dartlang-test:///main.dart" as main {
+
+  part part.dart;
+  class _Class extends dart.core::Object { // from org-dartlang-test:///part.dart
+    field dart.core::int? _#_Class#_privateField = null;
+    field dart.core::bool _#_Class#_privateField#isSet = false;
+    synthetic constructor •() → main::_Class
+      : super dart.core::Object::•()
+      ;
+    get _privateField() → dart.core::int {
+      if(!this.{main::_Class::_#_Class#_privateField#isSet}{dart.core::bool}) {
+        this.{main::_Class::_#_Class#_privateField} = 1;
+        this.{main::_Class::_#_Class#_privateField#isSet} = true;
+      }
+      return let final dart.core::int? #t1 = this.{main::_Class::_#_Class#_privateField}{dart.core::int?} in #t1{dart.core::int};
+    }
+    set _privateField(dart.core::int library org-dartlang-test:///main.dart::_privateField#param) → void {
+      this.{main::_Class::_#_Class#_privateField#isSet} = true;
+      this.{main::_Class::_#_Class#_privateField} = library org-dartlang-test:///main.dart::_privateField#param;
+    }
+  }
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml
new file mode 100644
index 0000000..d31202c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml
@@ -0,0 +1,30 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Recompiling with no change shouldn't change anything.
+# http://dartbug.com/48891
+
+type: newworld
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import 'lib.dart';
+        class Class2 with TestMixin<String> {}
+      lib.dart: |
+        mixin TestMixin<T> {
+          Future<T> test(Future<T> fetch) async {
+            final response = await fetch;
+            return response as T;
+          }
+        }
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    worldType: updated
+    compareToPrevious: true
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.1.expect
new file mode 100644
index 0000000..99d00d7
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.1.expect
@@ -0,0 +1,81 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  abstract class TestMixin<T extends dart.core::Object? = dynamic> extends dart.core::Object /*isMixinDeclaration*/  {
+    method test(covariant-by-class dart.async::Future<lib::TestMixin::T%> fetch) → dart.async::Future<lib::TestMixin::T%> /* futureValueType= lib::TestMixin::T% */ /* originally async */ {
+      final dart.async::_Future<lib::TestMixin::T%> :async_future = new dart.async::_Future::•<lib::TestMixin::T%>();
+      dart.core::bool* :is_sync = false;
+      FutureOr<lib::TestMixin::T%>? :return_value;
+      (dynamic) → dynamic :async_op_then;
+      (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+      dart.core::int :await_jump_var = 0;
+      dynamic :await_ctx_var;
+      dynamic :saved_try_context_var0;
+      function :async_op(dynamic :result_or_exception, dynamic :stack_trace) → dynamic yielding 
+        try {
+          #L1:
+          {
+            [yield] let dynamic #t1 = dart.async::_awaitHelper(fetch, :async_op_then, :async_op_error) in null;
+            final lib::TestMixin::T% response = dart._internal::unsafeCast<lib::TestMixin::T%>(:result_or_exception);
+            :return_value = response;
+            break #L1;
+          }
+          dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+          return;
+        }
+        on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
+          dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+        }
+      :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+      :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+      :async_op(null, null){() → dynamic};
+      :is_sync = true;
+      return :async_future;
+    }
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  abstract class _Class2&Object&TestMixin extends dart.core::Object implements lib::TestMixin<dart.core::String> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+    const synthetic constructor •() → main::_Class2&Object&TestMixin
+      : super dart.core::Object::•()
+      ;
+    method /* from org-dartlang-test:///lib.dart */ test(covariant-by-class dart.async::Future<dart.core::String> fetch) → dart.async::Future<dart.core::String> /* futureValueType= dart.core::String */ /* originally async */ {
+      final dart.async::_Future<dart.core::String> :async_future = new dart.async::_Future::•<dart.core::String>();
+      dart.core::bool* :is_sync = false;
+      dart.core::String? :return_value;
+      (dynamic) → dynamic :async_op_then;
+      (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+      dart.core::int :await_jump_var = 0;
+      dynamic :await_ctx_var;
+      dynamic :saved_try_context_var0;
+      function :async_op(dynamic :result_or_exception, dynamic :stack_trace) → dynamic yielding 
+        try {
+          #L2:
+          {
+            [yield] let dynamic #t2 = dart.async::_awaitHelper(fetch, :async_op_then, :async_op_error) in null;
+            final dart.core::String response = dart._internal::unsafeCast<dart.core::String>(:result_or_exception);
+            :return_value = response;
+            break #L2;
+          }
+          dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+          return;
+        }
+        on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
+          dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+        }
+      :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+      :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+      :async_op(null, null){() → dynamic};
+      :is_sync = true;
+      return :async_future;
+    }
+  }
+  class Class2 extends main::_Class2&Object&TestMixin {
+    synthetic constructor •() → main::Class2
+      : super main::_Class2&Object&TestMixin::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.2.expect
new file mode 100644
index 0000000..ba9e36d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.2.expect
@@ -0,0 +1,81 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  abstract class TestMixin<T extends dart.core::Object? = dynamic> extends dart.core::Object /*isMixinDeclaration*/  {
+    method test(covariant-by-class dart.async::Future<lib::TestMixin::T%> fetch) → dart.async::Future<lib::TestMixin::T%> /* futureValueType= lib::TestMixin::T% */ /* originally async */ {
+      final dart.async::_Future<lib::TestMixin::T%> :async_future = new dart.async::_Future::•<lib::TestMixin::T%>();
+      dart.core::bool* :is_sync = false;
+      FutureOr<lib::TestMixin::T%>? :return_value;
+      (dynamic) → dynamic :async_op_then;
+      (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+      dart.core::int :await_jump_var = 0;
+      dynamic :await_ctx_var;
+      dynamic :saved_try_context_var0;
+      function :async_op(dynamic :result_or_exception, dynamic :stack_trace) → dynamic yielding 
+        try {
+          #L1:
+          {
+            [yield] let dynamic #t1 = dart.async::_awaitHelper(fetch, :async_op_then, :async_op_error) in null;
+            final lib::TestMixin::T% response = dart._internal::unsafeCast<lib::TestMixin::T%>(:result_or_exception);
+            :return_value = response;
+            break #L1;
+          }
+          dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+          return;
+        }
+        on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
+          dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+        }
+      :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+      :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+      :async_op(null, null){() → dynamic};
+      :is_sync = true;
+      return :async_future;
+    }
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  abstract class _Class2&Object&TestMixin extends dart.core::Object implements lib::TestMixin<dart.core::String> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+    const synthetic constructor •() → main::_Class2&Object&TestMixin
+      : super dart.core::Object::•()
+      ;
+    method /* from org-dartlang-test:///lib.dart */ test(covariant-by-class dart.async::Future<dart.core::String> fetch) → dart.async::Future<dart.core::String> /* futureValueType= dart.core::String */ /* originally async */ {
+      final dart.async::_Future<dart.core::String> :async_future = new dart.async::_Future::•<dart.core::String>();
+      dart.core::bool* :is_sync = false;
+      FutureOr<dart.core::String>? :return_value;
+      (dynamic) → dynamic :async_op_then;
+      (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+      dart.core::int :await_jump_var = 0;
+      dynamic :await_ctx_var;
+      dynamic :saved_try_context_var0;
+      function :async_op(dynamic :result_or_exception, dynamic :stack_trace) → dynamic yielding 
+        try {
+          #L2:
+          {
+            [yield] let dynamic #t2 = dart.async::_awaitHelper(fetch, :async_op_then, :async_op_error) in null;
+            final dart.core::String response = dart._internal::unsafeCast<dart.core::String>(:result_or_exception);
+            :return_value = response;
+            break #L2;
+          }
+          dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+          return;
+        }
+        on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
+          dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+        }
+      :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+      :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+      :async_op(null, null){() → dynamic};
+      :is_sync = true;
+      return :async_future;
+    }
+  }
+  class Class2 extends main::_Class2&Object&TestMixin {
+    synthetic constructor •() → main::Class2
+      : super main::_Class2&Object&TestMixin::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml
new file mode 100644
index 0000000..549dbd7
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml
@@ -0,0 +1,30 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Recompiling with no change shouldn't change anything.
+# http://dartbug.com/48893
+
+type: newworld
+forceLateLoweringForTesting: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import 'lib.dart';
+        class B implements A {
+          int x = 3;
+        }
+      lib.dart: |
+        abstract class A {
+          late int x;
+        }
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    worldType: updated
+    compareToPrevious: true
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.1.expect
new file mode 100644
index 0000000..586c7b0
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.1.expect
@@ -0,0 +1,45 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  abstract class A extends dart.core::Object {
+    field dart.core::int? _#A#x = null;
+    field dart.core::bool _#A#x#isSet = false;
+    synthetic constructor •() → lib::A
+      : super dart.core::Object::•()
+      ;
+    get x() → dart.core::int
+      return this.{lib::A::_#A#x#isSet}{dart.core::bool} ?{dart.core::int} let final dart.core::int? #t1 = this.{lib::A::_#A#x}{dart.core::int?} in #t1{dart.core::int} : throw new dart._internal::LateError::fieldNI("x");
+    set x(dart.core::int x#param) → void {
+      this.{lib::A::_#A#x#isSet} = true;
+      this.{lib::A::_#A#x} = x#param;
+    }
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class B extends dart.core::Object implements lib::A {
+    field dart.core::int x = 3;
+    synthetic constructor •() → main::B
+      : super dart.core::Object::•()
+      ;
+    no-such-method-forwarder get /* from org-dartlang-test:///lib.dart */ _#A#x#isSet() → dynamic
+      return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} dynamic;
+    no-such-method-forwarder get /* from org-dartlang-test:///lib.dart */ _#A#x() → dart.core::int?
+      return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C5, 1, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} dart.core::int?;
+    no-such-method-forwarder set /* from org-dartlang-test:///lib.dart */ _#A#x#isSet(dynamic value) → void
+      return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(value)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic};
+    no-such-method-forwarder set /* from org-dartlang-test:///lib.dart */ _#A#x(dart.core::int? value) → void
+      return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C7, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(value)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic};
+  }
+}
+constants  {
+  #C1 = #org-dartlang-test:///main.dart::_#A#x#isSet
+  #C2 = <dart.core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = <dart.core::Symbol*, dynamic>{)
+  #C5 = #org-dartlang-test:///main.dart::_#A#x
+  #C6 = #org-dartlang-test:///main.dart::_#A#x#isSet=
+  #C7 = #org-dartlang-test:///main.dart::_#A#x=
+}
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.2.expect
new file mode 100644
index 0000000..2ac1aeb
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.2.expect
@@ -0,0 +1,45 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  abstract class A extends dart.core::Object {
+    field dart.core::int? _#A#x = null;
+    field dart.core::bool _#A#x#isSet = false;
+    synthetic constructor •() → lib::A
+      : super dart.core::Object::•()
+      ;
+    get x() → dart.core::int
+      return this.{lib::A::_#A#x#isSet}{dart.core::bool} ?{dart.core::int} let final dart.core::int? #t1 = this.{lib::A::_#A#x}{dart.core::int?} in #t1{dart.core::int} : throw new dart._internal::LateError::fieldNI("x");
+    set x(dart.core::int x#param) → void {
+      this.{lib::A::_#A#x#isSet} = true;
+      this.{lib::A::_#A#x} = x#param;
+    }
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib.dart";
+
+  class B extends dart.core::Object implements lib::A {
+    field dart.core::int x = 3;
+    synthetic constructor •() → main::B
+      : super dart.core::Object::•()
+      ;
+    no-such-method-forwarder get /* from org-dartlang-test:///lib.dart */ _#A#x#isSet() → dart.core::bool
+      return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} dart.core::bool;
+    no-such-method-forwarder get /* from org-dartlang-test:///lib.dart */ _#A#x() → dart.core::int?
+      return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C5, 1, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} dart.core::int?;
+    no-such-method-forwarder set /* from org-dartlang-test:///lib.dart */ _#A#x#isSet(dart.core::bool value) → void
+      return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(value)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic};
+    no-such-method-forwarder set /* from org-dartlang-test:///lib.dart */ _#A#x(dart.core::int? value) → void
+      return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C7, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(value)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic};
+  }
+}
+constants  {
+  #C1 = #org-dartlang-test:///main.dart::_#A#x#isSet
+  #C2 = <dart.core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = <dart.core::Symbol*, dynamic>{)
+  #C5 = #org-dartlang-test:///main.dart::_#A#x
+  #C6 = #org-dartlang-test:///main.dart::_#A#x#isSet=
+  #C7 = #org-dartlang-test:///main.dart::_#A#x=
+}
diff --git a/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml
new file mode 100644
index 0000000..eb1b359
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml
@@ -0,0 +1,35 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Recompiling shouldn't change the InstanceInvocation.interfaceTargetReference.
+# http://dartbug.com/48892
+
+type: newworld
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "lib1.dart";
+        main() {
+          Y y = new Y();
+          y.foo();
+        }
+      lib1.dart: |
+        class X {
+          void foo() => print("foo");
+        }
+        class Y implements X {
+          void noSuchMethod(Invocation _) {
+            print("Hello from noSuchMethod");
+          }
+        }
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    worldType: updated
+    compareToPrevious: true
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.1.expect
new file mode 100644
index 0000000..f9a6cfb
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.1.expect
@@ -0,0 +1,36 @@
+main = main::main;
+library from "org-dartlang-test:///lib1.dart" as lib1 {
+
+  class X extends dart.core::Object {
+    synthetic constructor •() → lib1::X
+      : super dart.core::Object::•()
+      ;
+    method foo() → void
+      return dart.core::print("foo");
+  }
+  class Y extends dart.core::Object implements lib1::X {
+    synthetic constructor •() → lib1::Y
+      : super dart.core::Object::•()
+      ;
+    method noSuchMethod(dart.core::Invocation _) → void {
+      dart.core::print("Hello from noSuchMethod");
+    }
+    no-such-method-forwarder method foo() → void
+      return this.{lib1::Y::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → void};
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib1.dart";
+
+  static method main() → dynamic {
+    lib1::Y y = new lib1::Y::•();
+    y.{lib1::X::foo}(){() → void};
+  }
+}
+constants  {
+  #C1 = #foo
+  #C2 = <dart.core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = <dart.core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.2.expect
new file mode 100644
index 0000000..b99b734
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.2.expect
@@ -0,0 +1,36 @@
+main = main::main;
+library from "org-dartlang-test:///lib1.dart" as lib1 {
+
+  class X extends dart.core::Object {
+    synthetic constructor •() → lib1::X
+      : super dart.core::Object::•()
+      ;
+    method foo() → void
+      return dart.core::print("foo");
+  }
+  class Y extends dart.core::Object implements lib1::X {
+    synthetic constructor •() → lib1::Y
+      : super dart.core::Object::•()
+      ;
+    method noSuchMethod(dart.core::Invocation _) → void {
+      dart.core::print("Hello from noSuchMethod");
+    }
+    no-such-method-forwarder method foo() → void
+      return this.{lib1::Y::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → void};
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///lib1.dart";
+
+  static method main() → dynamic {
+    lib1::Y y = new lib1::Y::•();
+    y.{lib1::Y::foo}(){() → void};
+  }
+}
+constants  {
+  #C1 = #foo
+  #C2 = <dart.core::Type*>[]
+  #C3 = <dynamic>[]
+  #C4 = <dart.core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/inference_update_1/folder.options b/pkg/front_end/testcases/inference_update_1/folder.options
new file mode 100644
index 0000000..722e700
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/folder.options
@@ -0,0 +1 @@
+--enable-experiment=inference-update-1
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart
new file mode 100644
index 0000000..454d46f
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests that when the feature is enabled, if an invocation argument is a
+// closure, write captures made by that closure do not take effect until after
+// the invocation.  This is a minor improvement to flow analysis that falls
+// naturally out of the fact that closures are analyzed last (so that their
+// types can depend on the types of other arguments).
+
+withUnnamedArguments(int? i, void Function(void Function(), Object?) f) {
+  if (i != null) {
+    f(() {
+      i = null;
+    }, i);
+    i;
+  }
+}
+
+withNamedArguments(
+    int? i, void Function({required void Function() g, Object? x}) f) {
+  if (i != null) {
+    f(
+        g: () {
+          i = null;
+        },
+        x: i);
+    i;
+  }
+}
+
+withIdentical_lhs(int? i) {
+  if (i != null) {
+    i;
+    identical(() {
+      i = null;
+    }, i);
+    i;
+  }
+}
+
+withIdentical_rhs(int? i) {
+  if (i != null) {
+    identical(i, () {
+      i = null;
+    });
+    i;
+  }
+}
+
+class B {
+  B(Object? x, void Function() g, Object? y);
+  B.redirectingConstructorInvocation(int? i)
+      : this(i!, () {
+          i = null;
+        }, i);
+}
+
+class C extends B {
+  C.superConstructorInvocation(int? i)
+      : super(i!, () {
+          i = null;
+        }, i);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline.expect
new file mode 100644
index 0000000..b846752
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+withUnnamedArguments(int? i, void Function(void Function(), Object?) f) {}
+withNamedArguments(
+    int? i, void Function({required void Function() g, Object? x}) f) {}
+withIdentical_lhs(int? i) {}
+withIdentical_rhs(int? i) {}
+
+class B {
+  B(Object? x, void Function() g, Object? y);
+  B.redirectingConstructorInvocation(int? i)
+      : this(i!, () {
+          i = null;
+        }, i);
+}
+
+class C extends B {
+  C.superConstructorInvocation(int? i)
+      : super(i!, () {
+          i = null;
+        }, i);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f4cf2ee
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class B {
+  B(Object? x, void Function() g, Object? y);
+  B.redirectingConstructorInvocation(int? i)
+      : this(i!, () {
+          i = null;
+        }, i);
+}
+
+class C extends B {
+  C.superConstructorInvocation(int? i)
+      : super(i!, () {
+          i = null;
+        }, i);
+}
+
+main() {}
+withIdentical_lhs(int? i) {}
+withIdentical_rhs(int? i) {}
+withNamedArguments(
+    int? i, void Function({required void Function() g, Object? x}) f) {}
+withUnnamedArguments(int? i, void Function(void Function(), Object?) f) {}
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.expect
new file mode 100644
index 0000000..7e1a0ea
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+  constructor •(core::Object? x, () → void g, core::Object? y) → self::B
+    : super core::Object::•()
+    ;
+  constructor redirectingConstructorInvocation(core::int? i) → self::B
+    : this self::B::•(i!, () → void {
+      i = null;
+    }, i{core::int})
+    ;
+}
+class C extends self::B {
+  constructor superConstructorInvocation(core::int? i) → self::C
+    : super self::B::•(i!, () → void {
+      i = null;
+    }, i{core::int})
+    ;
+}
+static method withUnnamedArguments(core::int? i, (() → void, core::Object?) → void f) → dynamic {
+  if(!(i == null)) {
+    f(() → void {
+      i = null;
+    }, i{core::int}){(() → void, core::Object?) → void};
+    i;
+  }
+}
+static method withNamedArguments(core::int? i, ({required g: () → void, x: core::Object?}) → void f) → dynamic {
+  if(!(i == null)) {
+    f(g: () → void {
+      i = null;
+    }, x: i{core::int}){({required g: () → void, x: core::Object?}) → void};
+    i;
+  }
+}
+static method withIdentical_lhs(core::int? i) → dynamic {
+  if(!(i == null)) {
+    i{core::int};
+    core::identical(() → Null {
+      i = null;
+    }, i{core::int});
+    i;
+  }
+}
+static method withIdentical_rhs(core::int? i) → dynamic {
+  if(!(i == null)) {
+    core::identical(i{core::int}, () → Null {
+      i = null;
+    });
+    i;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.modular.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.modular.expect
new file mode 100644
index 0000000..7e1a0ea
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.modular.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+  constructor •(core::Object? x, () → void g, core::Object? y) → self::B
+    : super core::Object::•()
+    ;
+  constructor redirectingConstructorInvocation(core::int? i) → self::B
+    : this self::B::•(i!, () → void {
+      i = null;
+    }, i{core::int})
+    ;
+}
+class C extends self::B {
+  constructor superConstructorInvocation(core::int? i) → self::C
+    : super self::B::•(i!, () → void {
+      i = null;
+    }, i{core::int})
+    ;
+}
+static method withUnnamedArguments(core::int? i, (() → void, core::Object?) → void f) → dynamic {
+  if(!(i == null)) {
+    f(() → void {
+      i = null;
+    }, i{core::int}){(() → void, core::Object?) → void};
+    i;
+  }
+}
+static method withNamedArguments(core::int? i, ({required g: () → void, x: core::Object?}) → void f) → dynamic {
+  if(!(i == null)) {
+    f(g: () → void {
+      i = null;
+    }, x: i{core::int}){({required g: () → void, x: core::Object?}) → void};
+    i;
+  }
+}
+static method withIdentical_lhs(core::int? i) → dynamic {
+  if(!(i == null)) {
+    i{core::int};
+    core::identical(() → Null {
+      i = null;
+    }, i{core::int});
+    i;
+  }
+}
+static method withIdentical_rhs(core::int? i) → dynamic {
+  if(!(i == null)) {
+    core::identical(i{core::int}, () → Null {
+      i = null;
+    });
+    i;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.outline.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.outline.expect
new file mode 100644
index 0000000..f98b778
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.outline.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+  constructor •(core::Object? x, () → void g, core::Object? y) → self::B
+    ;
+  constructor redirectingConstructorInvocation(core::int? i) → self::B
+    ;
+}
+class C extends self::B {
+  constructor superConstructorInvocation(core::int? i) → self::C
+    ;
+}
+static method withUnnamedArguments(core::int? i, (() → void, core::Object?) → void f) → dynamic
+  ;
+static method withNamedArguments(core::int? i, ({required g: () → void, x: core::Object?}) → void f) → dynamic
+  ;
+static method withIdentical_lhs(core::int? i) → dynamic
+  ;
+static method withIdentical_rhs(core::int? i) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.transformed.expect
new file mode 100644
index 0000000..7e1a0ea
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.transformed.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+  constructor •(core::Object? x, () → void g, core::Object? y) → self::B
+    : super core::Object::•()
+    ;
+  constructor redirectingConstructorInvocation(core::int? i) → self::B
+    : this self::B::•(i!, () → void {
+      i = null;
+    }, i{core::int})
+    ;
+}
+class C extends self::B {
+  constructor superConstructorInvocation(core::int? i) → self::C
+    : super self::B::•(i!, () → void {
+      i = null;
+    }, i{core::int})
+    ;
+}
+static method withUnnamedArguments(core::int? i, (() → void, core::Object?) → void f) → dynamic {
+  if(!(i == null)) {
+    f(() → void {
+      i = null;
+    }, i{core::int}){(() → void, core::Object?) → void};
+    i;
+  }
+}
+static method withNamedArguments(core::int? i, ({required g: () → void, x: core::Object?}) → void f) → dynamic {
+  if(!(i == null)) {
+    f(g: () → void {
+      i = null;
+    }, x: i{core::int}){({required g: () → void, x: core::Object?}) → void};
+    i;
+  }
+}
+static method withIdentical_lhs(core::int? i) → dynamic {
+  if(!(i == null)) {
+    i{core::int};
+    core::identical(() → Null {
+      i = null;
+    }, i{core::int});
+    i;
+  }
+}
+static method withIdentical_rhs(core::int? i) → dynamic {
+  if(!(i == null)) {
+    core::identical(i{core::int}, () → Null {
+      i = null;
+    });
+    i;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart b/pkg/front_end/testcases/regress/issue_36669.dart
index 48a19bb..64295d2 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart
+++ b/pkg/front_end/testcases/regress/issue_36669.dart
@@ -2,10 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 // @dart=2.9
-class NoUnnamedConstuctor {
-  NoUnnamedConstuctor._();
+class NoUnnamedConstructor {
+  NoUnnamedConstructor._();
 }
 
 class MixMeIn {}
 
-class Foo extends NoUnnamedConstuctor with MixMeIn {}
+class Foo extends NoUnnamedConstructor with MixMeIn {}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline.expect b/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline.expect
index 90f2098..04ff88d 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline.expect
@@ -1,8 +1,8 @@
 // @dart = 2.9
-class NoUnnamedConstuctor {
-  NoUnnamedConstuctor._();
+class NoUnnamedConstructor {
+  NoUnnamedConstructor._();
 }
 
 class MixMeIn {}
 
-class Foo extends NoUnnamedConstuctor with MixMeIn {}
+class Foo extends NoUnnamedConstructor with MixMeIn {}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline_modelled.expect
index ef3c45e..6fa6b0d 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline_modelled.expect
@@ -1,8 +1,8 @@
 // @dart = 2.9
-class Foo extends NoUnnamedConstuctor with MixMeIn {}
+class Foo extends NoUnnamedConstructor with MixMeIn {}
 
 class MixMeIn {}
 
-class NoUnnamedConstuctor {
-  NoUnnamedConstuctor._();
+class NoUnnamedConstructor {
+  NoUnnamedConstructor._();
 }
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.weak.expect b/pkg/front_end/testcases/regress/issue_36669.dart.weak.expect
index 0c77dc9..2eec808 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.weak.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.weak.expect
@@ -2,15 +2,15 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstuctor with MixMeIn', has no unnamed constructor that takes no arguments.
-// class Foo extends NoUnnamedConstuctor with MixMeIn {}
+// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstructor with MixMeIn', has no unnamed constructor that takes no arguments.
+// class Foo extends NoUnnamedConstructor with MixMeIn {}
 //       ^
 //
 import self as self;
 import "dart:core" as core;
 
-class NoUnnamedConstuctor extends core::Object {
-  constructor _() → self::NoUnnamedConstuctor*
+class NoUnnamedConstructor extends core::Object {
+  constructor _() → self::NoUnnamedConstructor*
     : super core::Object::•()
     ;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -39,12 +39,12 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn /*isAnonymousMixin*/  {
-  synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn*
-    : super self::NoUnnamedConstuctor::_()
+abstract class _Foo&NoUnnamedConstructor&MixMeIn = self::NoUnnamedConstructor with self::MixMeIn /*isAnonymousMixin*/  {
+  synthetic constructor _() → self::_Foo&NoUnnamedConstructor&MixMeIn*
+    : super self::NoUnnamedConstructor::_()
     ;
 }
-class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+class Foo extends self::_Foo&NoUnnamedConstructor&MixMeIn {
   synthetic constructor •() → self::Foo*
     : invalid-initializer
     ;
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.weak.modular.expect b/pkg/front_end/testcases/regress/issue_36669.dart.weak.modular.expect
index 0c77dc9..2eec808 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.weak.modular.expect
@@ -2,15 +2,15 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstuctor with MixMeIn', has no unnamed constructor that takes no arguments.
-// class Foo extends NoUnnamedConstuctor with MixMeIn {}
+// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstructor with MixMeIn', has no unnamed constructor that takes no arguments.
+// class Foo extends NoUnnamedConstructor with MixMeIn {}
 //       ^
 //
 import self as self;
 import "dart:core" as core;
 
-class NoUnnamedConstuctor extends core::Object {
-  constructor _() → self::NoUnnamedConstuctor*
+class NoUnnamedConstructor extends core::Object {
+  constructor _() → self::NoUnnamedConstructor*
     : super core::Object::•()
     ;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -39,12 +39,12 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn /*isAnonymousMixin*/  {
-  synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn*
-    : super self::NoUnnamedConstuctor::_()
+abstract class _Foo&NoUnnamedConstructor&MixMeIn = self::NoUnnamedConstructor with self::MixMeIn /*isAnonymousMixin*/  {
+  synthetic constructor _() → self::_Foo&NoUnnamedConstructor&MixMeIn*
+    : super self::NoUnnamedConstructor::_()
     ;
 }
-class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+class Foo extends self::_Foo&NoUnnamedConstructor&MixMeIn {
   synthetic constructor •() → self::Foo*
     : invalid-initializer
     ;
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.weak.outline.expect b/pkg/front_end/testcases/regress/issue_36669.dart.weak.outline.expect
index 1f49167..2799c79 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.weak.outline.expect
@@ -2,8 +2,8 @@
 import self as self;
 import "dart:core" as core;
 
-class NoUnnamedConstuctor extends core::Object {
-  constructor _() → self::NoUnnamedConstuctor*
+class NoUnnamedConstructor extends core::Object {
+  constructor _() → self::NoUnnamedConstructor*
     ;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
@@ -30,12 +30,12 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn /*isAnonymousMixin*/  {
-  synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn*
-    : super self::NoUnnamedConstuctor::_()
+abstract class _Foo&NoUnnamedConstructor&MixMeIn = self::NoUnnamedConstructor with self::MixMeIn /*isAnonymousMixin*/  {
+  synthetic constructor _() → self::_Foo&NoUnnamedConstructor&MixMeIn*
+    : super self::NoUnnamedConstructor::_()
     ;
 }
-class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+class Foo extends self::_Foo&NoUnnamedConstructor&MixMeIn {
   synthetic constructor •() → self::Foo*
     ;
 }
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_36669.dart.weak.transformed.expect
index 2edcce4..b37611c 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.weak.transformed.expect
@@ -2,15 +2,15 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstuctor with MixMeIn', has no unnamed constructor that takes no arguments.
-// class Foo extends NoUnnamedConstuctor with MixMeIn {}
+// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstructor with MixMeIn', has no unnamed constructor that takes no arguments.
+// class Foo extends NoUnnamedConstructor with MixMeIn {}
 //       ^
 //
 import self as self;
 import "dart:core" as core;
 
-class NoUnnamedConstuctor extends core::Object {
-  constructor _() → self::NoUnnamedConstuctor*
+class NoUnnamedConstructor extends core::Object {
+  constructor _() → self::NoUnnamedConstructor*
     : super core::Object::•()
     ;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -39,12 +39,12 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-abstract class _Foo&NoUnnamedConstuctor&MixMeIn extends self::NoUnnamedConstuctor implements self::MixMeIn /*isAnonymousMixin,isEliminatedMixin*/  {
-  synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn*
-    : super self::NoUnnamedConstuctor::_()
+abstract class _Foo&NoUnnamedConstructor&MixMeIn extends self::NoUnnamedConstructor implements self::MixMeIn /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor _() → self::_Foo&NoUnnamedConstructor&MixMeIn*
+    : super self::NoUnnamedConstructor::_()
     ;
 }
-class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+class Foo extends self::_Foo&NoUnnamedConstructor&MixMeIn {
   synthetic constructor •() → self::Foo*
     : invalid-initializer
     ;
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 762a17d..f805d8e 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -16,6 +16,13 @@
 const_functions/const_functions_list: SemiFuzzCrash
 generic_metadata/typedef_generic_types_in_arguments_and_bounds: SemiFuzzCrash
 
+dart2js/mixin_from_opt_in/main: SemiFuzzFailure # seems like the difference between normal and no-link version: it goes from InstanceInvocation to InvalidExpression
+dart2js/mixin_from_opt_in/main.no_link: SemiFuzzFailure # seems like the difference between normal and no-link version: it goes from InstanceInvocation to InvalidExpression
+late_lowering/private_members: SemiFuzzFailure # Reproduced in https://dart-review.googlesource.com/c/sdk/+/242285
+macros/multiple_imports: SemiFuzzFailure # probably augment imports that isn't split correctly.
+nnbd/constants: SemiFuzzFailure # Reproduced in https://dart-review.googlesource.com/c/sdk/+/242441
+nnbd/flutter_issue64155: SemiFuzzFailure # Reproduced in https://dart-review.googlesource.com/c/sdk/+/242443
+
 # These tests have "privacy issues" and isn't compatiable with splitting files (fuzzing):
 dart2js/mixin_default_values/main: semiFuzzFailureOnForceRebuildBodies # private method
 dartdevc/factory_patch/main: semiFuzzFailureOnForceRebuildBodies # needs custom libraries.json (and platform?) not setup here
@@ -32,6 +39,7 @@
 nnbd/nullable_extension: semiFuzzFailureOnForceRebuildBodies # unnamed extension
 nnbd/nullable_setter: semiFuzzFailureOnForceRebuildBodies # unnamed extension
 none/mixin_super: semiFuzzFailureOnForceRebuildBodies # has private name mixin
+dart2js/tear_off_patch/main: semiFuzzFailureOnForceRebuildBodies # needs custom libraries.json (and platform?) not setup here
 
 constructor_tearoffs/call_instantiation: TypeCheckError
 constructor_tearoffs/lowering/invalid_redirect: VerificationError
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 6097d2c..68ae6c1 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -10,6 +10,32 @@
 no_such_method_forwarders/abstract_override_abstract_different_type: SemiFuzzFailure
 no_such_method_forwarders/abstract_override_with_different_signature: SemiFuzzFailure
 
+dart2js/tear_off_patch/main: semiFuzzFailureOnForceRebuildBodies # needs custom libraries.json (and platform?) not setup here
+general/constants/with_unevaluated_agnostic/various_2: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242441
+general/flutter_issue64155: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242443
+general/no_such_method_forwarder: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242444
+general/tear_off_patch/main: semiFuzzFailureOnForceRebuildBodies # needs custom libraries.json (and platform?) not setup here
+general/with_dependencies/issue_43084/issue_43084: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242543
+late_lowering/issue41436b: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242445
+late_lowering/issue41436c/issue41436c: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242445
+late_lowering/late_override: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242445
+late_lowering/private_members: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242285
+macros/multiple_imports: SemiFuzzFailure # probably augment imports that isn't split correctly.
+nnbd_mixed/const_canonical_type: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242441
+nnbd_mixed/hierarchy/in_dill_out_in/in_out_in: SemiFuzzFailure # lots of stuff --- not digging in for now
+nnbd_mixed/hierarchy/in_out_dill_in/in_out_in: SemiFuzzFailure # lots of stuff --- not digging in for now
+nnbd_mixed/hierarchy/in_out_in: SemiFuzzFailure # lots of stuff --- not digging in for now
+nnbd_mixed/issue43988/main: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242540 and https://dart-review.googlesource.com/c/sdk/+/242446
+nnbd_mixed/issue43988/main.no_link: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242540 and https://dart-review.googlesource.com/c/sdk/+/242446
+nnbd_mixed/member_inheritance_from_opt_in: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242446
+nnbd/constants: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242441
+nnbd/flutter_issue64155: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242443
+no_such_method_forwarders/abstract_accessors_from_field_one_defined: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242444
+no_such_method_forwarders/abstract_accessors_from_field_with_substitution: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242444
+no_such_method_forwarders/abstract_accessors_from_field: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242444
+no_such_method_forwarders/default_argument_values: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242444
+variance/generic_covariance_sound_variance: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242444
+
 dart2js/flutter_issue94561/main: SemiFuzzFailure
 dart2js/flutter_issue94561/main.no_link: SemiFuzzFailure
 dart2js/late_fields: SemiFuzzFailure
diff --git a/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart b/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
index df2501c..6df8f38 100644
--- a/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
+++ b/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
@@ -233,8 +233,7 @@
         instrumentation: instrumentationListener,
         removeViaComments: removeViaComments,
         warnOnWeakCode: warnOnWeakCode);
-    Future<void> _forEachPath(
-        void Function(ResolvedUnitResult) callback) async {
+    Future<void> forEachPath(void Function(ResolvedUnitResult) callback) async {
       for (var testPath in testPaths) {
         var result = await driver!.currentSession.getResolvedUnit(testPath!)
             as ResolvedUnitResult;
@@ -242,10 +241,10 @@
       }
     }
 
-    await _forEachPath(migration.prepareInput);
+    await forEachPath(migration.prepareInput);
     expect(migration.unmigratedDependencies, isEmpty);
-    await _forEachPath(migration.processInput);
-    await _forEachPath(migration.finalizeInput);
+    await forEachPath(migration.processInput);
+    await forEachPath(migration.finalizeInput);
     migration.finish();
     // Build the migration info.
     var info = instrumentationListener.data;
diff --git a/runtime/tests/vm/dart/regress_48323_1_test.dart b/runtime/tests/vm/dart/regress_48323_1_test.dart
new file mode 100644
index 0000000..d9c7595
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_48323_1_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/48323.
+// Verifies that class finalization doesn't crash when seeing
+// superclass with type arguments which were not finalized yet.
+
+abstract class GraphNode extends Comparable<dynamic> {
+  int compareTo(dynamic other) => 0;
+}
+
+abstract class StreamNode<T> extends GraphNode {}
+
+class TransformNode<S, T> extends StreamNode<T> {}
+
+main() {
+  print(TransformNode());
+}
diff --git a/runtime/tests/vm/dart_2/regress_48323_1_test.dart b/runtime/tests/vm/dart_2/regress_48323_1_test.dart
new file mode 100644
index 0000000..c71670b
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_48323_1_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/48323.
+// Verifies that class finalization doesn't crash when seeing
+// superclass with type arguments which were not finalized yet.
+
+// @dart = 2.9
+
+abstract class GraphNode extends Comparable<dynamic> {
+  int compareTo(dynamic other) => 0;
+}
+
+abstract class StreamNode<T> extends GraphNode {}
+
+class TransformNode<S, T> extends StreamNode<T> {}
+
+main() {
+  print(TransformNode());
+}
diff --git a/runtime/vm/app_snapshot.h b/runtime/vm/app_snapshot.h
index ce084c0..118ca9c 100644
--- a/runtime/vm/app_snapshot.h
+++ b/runtime/vm/app_snapshot.h
@@ -324,6 +324,9 @@
   void Write(T value) {
     BaseWriteStream::Raw<sizeof(T), T>::Write(stream_, value);
   }
+  void WriteRefId(intptr_t value) {
+    stream_->WriteRefId(value);
+  }
   void WriteUnsigned(intptr_t value) { stream_->WriteUnsigned(value); }
   void WriteUnsigned64(uint64_t value) { stream_->WriteUnsigned(value); }
 
@@ -341,7 +344,7 @@
 
   void WriteRootRef(ObjectPtr object, const char* name = nullptr) {
     intptr_t id = RefId(object);
-    WriteUnsigned(id);
+    WriteRefId(id);
     if (profile_writer_ != nullptr) {
       profile_writer_->AddRoot(GetProfileId(object), name);
     }
@@ -359,7 +362,7 @@
 
   void WriteElementRef(ObjectPtr object, intptr_t index) {
     AttributeElementRef(object, index);
-    WriteUnsigned(RefId(object));
+    WriteRefId(RefId(object));
   }
 
   void AttributePropertyRef(ObjectPtr object, const char* property) {
@@ -369,12 +372,12 @@
 
   void WritePropertyRef(ObjectPtr object, const char* property) {
     AttributePropertyRef(object, property);
-    WriteUnsigned(RefId(object));
+    WriteRefId(RefId(object));
   }
 
   void WriteOffsetRef(ObjectPtr object, intptr_t offset) {
     intptr_t id = RefId(object);
-    WriteUnsigned(id);
+    WriteRefId(id);
     if (profile_writer_ != nullptr) {
       if (auto const property = offsets_table_->FieldNameForOffset(
               object_currently_writing_.cid_, offset)) {
@@ -634,6 +637,7 @@
   T Read() {
     return ReadStream::Raw<sizeof(T), T>::Read(&stream_);
   }
+  intptr_t ReadRefId() { return stream_.ReadRefId(); }
   intptr_t ReadUnsigned() { return stream_.ReadUnsigned(); }
   uint64_t ReadUnsigned64() { return stream_.ReadUnsigned<uint64_t>(); }
   void ReadBytes(uint8_t* addr, intptr_t len) { stream_.ReadBytes(addr, len); }
@@ -673,7 +677,7 @@
   static intptr_t CodeIndexToClusterIndex(const InstructionsTable& table,
                                           intptr_t code_index);
 
-  ObjectPtr ReadRef() { return Ref(ReadUnsigned()); }
+  ObjectPtr ReadRef() { return Ref(ReadRefId()); }
 
   template <typename T, typename... P>
   void ReadFromTo(T obj, P&&... params) {
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc
index fd70709..cc1c65b 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.cc
+++ b/runtime/vm/compiler/assembler/assembler_riscv.cc
@@ -3704,8 +3704,33 @@
   lx(FP, Address(SP, 0 * target::kWordSize));
   lx(RA, Address(SP, 1 * target::kWordSize));
   addi(SP, SP, 2 * target::kWordSize);
+}
 
-  // TODO(riscv): When we know the stack depth, we can avoid updating SP twice.
+void Assembler::LeaveDartFrame(intptr_t fp_sp_dist) {
+  intptr_t pp_offset =
+      target::frame_layout.saved_caller_pp_from_fp * target::kWordSize -
+      fp_sp_dist;
+  intptr_t fp_offset =
+      target::frame_layout.saved_caller_fp_from_fp * target::kWordSize -
+      fp_sp_dist;
+  intptr_t ra_offset =
+      target::frame_layout.saved_caller_pc_from_fp * target::kWordSize -
+      fp_sp_dist;
+  if (!IsITypeImm(pp_offset) || !IsITypeImm(fp_offset) ||
+      !IsITypeImm(ra_offset)) {
+    // Shorter to update SP twice than generate large immediates.
+    LeaveDartFrame();
+    return;
+  }
+
+  if (!FLAG_precompiled_mode) {
+    lx(PP, Address(SP, pp_offset));
+    subi(PP, PP, kHeapObjectTag);
+  }
+  set_constant_pool_allowed(false);
+  lx(FP, Address(SP, fp_offset));
+  lx(RA, Address(SP, ra_offset));
+  addi(SP, SP, -fp_sp_dist);
 }
 
 void Assembler::CallRuntime(const RuntimeEntry& entry,
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.h b/runtime/vm/compiler/assembler/assembler_riscv.h
index 44424ae..985ce81 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.h
+++ b/runtime/vm/compiler/assembler/assembler_riscv.h
@@ -1233,6 +1233,7 @@
   void EnterDartFrame(intptr_t frame_size, Register new_pp = kNoRegister);
   void EnterOsrFrame(intptr_t extra_size, Register new_pp = kNoRegister);
   void LeaveDartFrame();
+  void LeaveDartFrame(intptr_t fp_sp_dist);
 
   // For non-leaf runtime calls. For leaf runtime calls, use LeafRuntimeScope,
   void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index eabdbb0..6f556e5 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -1584,7 +1584,8 @@
 
 // Allocate a register that is not explictly blocked.
 static Register AllocateFreeRegister(bool* blocked_registers) {
-  for (intptr_t regno = 0; regno < kNumberOfCpuRegisters; regno++) {
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+    intptr_t regno = (i + kRegisterAllocationBias) % kNumberOfCpuRegisters;
     if (!blocked_registers[regno]) {
       blocked_registers[regno] = true;
       return static_cast<Register>(regno);
@@ -1615,22 +1616,6 @@
   bool blocked_registers[kNumberOfCpuRegisters];
   bool blocked_fpu_registers[kNumberOfFpuRegisters];
 
-  // Connect input with peephole output for some special cases. All other
-  // cases are handled by simply allocating registers and generating code.
-  if (top_of_stack_ != nullptr) {
-    const intptr_t p = locs->input_count() - 1;
-    Location peephole = top_of_stack_->locs()->out(0);
-    if ((instr->RequiredInputRepresentation(p) == kTagged) &&
-        (locs->in(p).IsUnallocated() || locs->in(p).IsConstant())) {
-      // If input is unallocated, match with an output register, if set. Also,
-      // if input is a direct constant, but the peephole output is a register,
-      // use that register to avoid wasting the already generated code.
-      if (peephole.IsRegister()) {
-        locs->set_in(p, Location::RegisterLocation(peephole.reg()));
-      }
-    }
-  }
-
   // Block all registers globally reserved by the assembler, etc and mark
   // the rest as free.
   for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
@@ -1671,6 +1656,23 @@
     }
   }
 
+  // Connect input with peephole output for some special cases. All other
+  // cases are handled by simply allocating registers and generating code.
+  if (top_of_stack_ != nullptr) {
+    const intptr_t p = locs->input_count() - 1;
+    Location peephole = top_of_stack_->locs()->out(0);
+    if ((instr->RequiredInputRepresentation(p) == kTagged) &&
+        (locs->in(p).IsUnallocated() || locs->in(p).IsConstant())) {
+      // If input is unallocated, match with an output register, if set. Also,
+      // if input is a direct constant, but the peephole output is a register,
+      // use that register to avoid wasting the already generated code.
+      if (peephole.IsRegister() && !blocked_registers[peephole.reg()]) {
+        locs->set_in(p, Location::RegisterLocation(peephole.reg()));
+        blocked_registers[peephole.reg()] = true;
+      }
+    }
+  }
+
   if (locs->out(0).IsRegister()) {
     // Fixed output registers are allowed to overlap with
     // temps and inputs.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
index 8671e2e..46a6ba5 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
@@ -346,14 +346,16 @@
     }
 
     __ Comment("Initialize spill slots");
+    const intptr_t fp_to_sp_delta =
+        num_locals + compiler::target::frame_layout.dart_fixed_frame_size;
     for (intptr_t i = 0; i < num_locals; ++i) {
       const intptr_t slot_index =
           compiler::target::frame_layout.FrameSlotForVariableIndex(-i);
       Register value_reg =
           slot_index == args_desc_slot ? ARGS_DESC_REG : NULL_REG;
-      __ StoreToOffset(value_reg, FP, slot_index * kWordSize);
-      // TODO(riscv): Using an SP-relative address instead of an FP-relative
-      // address would allow for compressed instructions.
+      // SP-relative addresses allow for compressed instructions.
+      __ StoreToOffset(value_reg, SP,
+                       (slot_index + fp_to_sp_delta) * kWordSize);
     }
   }
 
diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc
index b24fdb4..a2d70f7 100644
--- a/runtime/vm/compiler/backend/il_riscv.cc
+++ b/runtime/vm/compiler/backend/il_riscv.cc
@@ -469,14 +469,14 @@
     return;
   }
 
-#if defined(DEBUG)
-  compiler::Label stack_ok;
-  __ Comment("Stack Check");
   const intptr_t fp_sp_dist =
       (compiler::target::frame_layout.first_local_from_fp + 1 -
        compiler->StackSize()) *
       kWordSize;
   ASSERT(fp_sp_dist <= 0);
+#if defined(DEBUG)
+  compiler::Label stack_ok;
+  __ Comment("Stack Check");
   __ sub(TMP, SP, FP);
   __ CompareImmediate(TMP, fp_sp_dist);
   __ BranchIf(EQ, &stack_ok, compiler::Assembler::kNearJump);
@@ -487,7 +487,7 @@
   if (yield_index() != UntaggedPcDescriptors::kInvalidYieldIndex) {
     compiler->EmitYieldPositionMetadata(source(), yield_index());
   }
-  __ LeaveDartFrame();  // Disallows constant pool use.
+  __ LeaveDartFrame(fp_sp_dist);  // Disallows constant pool use.
   __ ret();
   // This ReturnInstr may be emitted out of order by the optimizer. The next
   // block may be a target expecting a properly set constant pool pointer.
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index 266b485..de3c5b1 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -2185,7 +2185,8 @@
     TRACE_ALLOC(THR_Print("found hint %s for v%" Pd ": free until %" Pd "\n",
                           hint.Name(), unallocated->vreg(), free_until));
   } else {
-    for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
+    for (intptr_t i = 0; i < NumberOfRegisters(); ++i) {
+      intptr_t reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
       if (!blocked_registers_[reg] && (registers_[reg]->length() == 0)) {
         candidate = reg;
         free_until = kMaxPosition;
@@ -2196,7 +2197,8 @@
 
   ASSERT(0 <= kMaxPosition);
   if (free_until != kMaxPosition) {
-    for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
+    for (intptr_t i = 0; i < NumberOfRegisters(); ++i) {
+      intptr_t reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
       if (blocked_registers_[reg] || (reg == candidate)) continue;
       const intptr_t intersection =
           FirstIntersectionWithAllocated(reg, unallocated);
@@ -2258,7 +2260,8 @@
                             unallocated->vreg(),
                             extra_loop_info_[loop_info->id()]->start,
                             extra_loop_info_[loop_info->id()]->end));
-      for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
+      for (intptr_t i = 0; i < NumberOfRegisters(); ++i) {
+        intptr_t reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
         if (blocked_registers_[reg] || (reg == candidate) ||
             used_on_backedge[reg]) {
           continue;
@@ -2371,7 +2374,8 @@
   intptr_t free_until = 0;
   intptr_t blocked_at = kMaxPosition;
 
-  for (int reg = 0; reg < NumberOfRegisters(); ++reg) {
+  for (int i = 0; i < NumberOfRegisters(); ++i) {
+    int reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
     if (blocked_registers_[reg]) continue;
     if (UpdateFreeUntil(reg, unallocated, &free_until, &blocked_at)) {
       candidate = reg;
@@ -2581,7 +2585,8 @@
 }
 
 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) {
-  for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) {
+  for (intptr_t i = 0; i < NumberOfRegisters(); ++i) {
+    intptr_t reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
     if (registers_[reg]->is_empty()) continue;
 
     intptr_t first_evicted = -1;
@@ -2704,7 +2709,8 @@
   ASSERT(unallocated_.is_empty());
   unallocated_.AddArray(unallocated);
 
-  for (intptr_t reg = 0; reg < number_of_registers; reg++) {
+  for (intptr_t i = 0; i < NumberOfRegisters(); ++i) {
+    intptr_t reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
     blocked_registers_[reg] = blocked_registers[reg];
     ASSERT(registers_[reg]->is_empty());
 
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 48fa007..e3dc87a 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -574,6 +574,8 @@
     kAllCpuRegistersList & ~kReservedCpuRegisters;
 constexpr int kNumberOfDartAvailableCpuRegs =
     kNumberOfCpuRegisters - kNumberOfReservedCpuRegisters;
+// No reason to prefer certain registers on ARM.
+constexpr int kRegisterAllocationBias = 0;
 const intptr_t kStoreBufferWrapperSize = 24;
 // Registers available to Dart that are not preserved by runtime calls.
 const RegList kDartVolatileCpuRegs =
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index b37fd6b..03fc499 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -431,6 +431,8 @@
     kAllCpuRegistersList & ~kReservedCpuRegisters;
 constexpr int kNumberOfDartAvailableCpuRegs =
     kNumberOfCpuRegisters - kNumberOfReservedCpuRegisters;
+// No reason to prefer certain registers on ARM64.
+constexpr int kRegisterAllocationBias = 0;
 // Registers available to Dart that are not preserved by runtime calls.
 const RegList kDartVolatileCpuRegs =
     kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 5d77faa..ab67693 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -31,7 +31,7 @@
   kNoRegister = -1,  // Signals an illegal register.
 };
 
-// Low and high bytes registers of the the first four general purpose registers.
+// Low and high bytes registers of the first four general purpose registers.
 // The other four general purpose registers do not have byte registers.
 enum ByteRegister {
   AL = 0,
@@ -278,6 +278,8 @@
 // CPU registers available to Dart allocator.
 const RegList kDartAvailableCpuRegs =
     kAllCpuRegistersList & ~kReservedCpuRegisters;
+// No reason to prefer certain registers on IA32.
+constexpr int kRegisterAllocationBias = 0;
 
 const RegList kAbiPreservedCpuRegs = (1 << EDI) | (1 << ESI) | (1 << EBX);
 
diff --git a/runtime/vm/constants_riscv.h b/runtime/vm/constants_riscv.h
index 375abfb..707caf7 100644
--- a/runtime/vm/constants_riscv.h
+++ b/runtime/vm/constants_riscv.h
@@ -411,6 +411,8 @@
 constexpr RegList kDartAvailableCpuRegs =
     kAllCpuRegistersList & ~kReservedCpuRegisters;
 constexpr int kNumberOfDartAvailableCpuRegs = 18;
+// Registers X8-15 (S0-1,A0-5) have more compressed instructions available.
+constexpr int kRegisterAllocationBias = 8;
 // Registers available to Dart that are not preserved by runtime calls.
 constexpr RegList kDartVolatileCpuRegs =
     kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 0c9652b..9b8e5c2 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -355,6 +355,8 @@
     kAllCpuRegistersList & ~kReservedCpuRegisters;
 constexpr int kNumberOfDartAvailableCpuRegs =
     kNumberOfCpuRegisters - kNumberOfReservedCpuRegisters;
+// Low numbered registers sometimes require fewer prefixes.
+constexpr int kRegisterAllocationBias = 0;
 constexpr int kStoreBufferWrapperSize = 13;
 
 #if defined(DART_TARGET_OS_WINDOWS)
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index c0c642f..09ec2e7 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -98,6 +98,30 @@
     return Read<T>(kEndUnsignedByteMarker);
   }
 
+  intptr_t ReadRefId() {
+    const int8_t* cursor = reinterpret_cast<const int8_t*>(current_);
+    intptr_t result = 0;
+    intptr_t byte;
+    // clang-format off
+#define STAGE                                                                  \
+    byte = *cursor++;              /* ldrsb byte, [result], 1  */              \
+    result = byte + (result << 7); /* add result, byte, result lsl 7 */        \
+    if (byte < 0) goto done;       /* tbnz byte, 63, done */
+    STAGE  // 0-7
+    STAGE  // 8-14
+    STAGE  // 15-21
+    STAGE  // 22-28
+#undef STAGE
+    ASSERT(byte < 0);  // 256MB is enough for anyone...
+    // clang-format on
+  done:
+    current_ = reinterpret_cast<const uint8_t*>(cursor);
+    // With big-endian order and the has-more marker being 0, the correction
+    // factor to remove the last-byte marker is a constant, which can be folded
+    // in to subsequent load offsets.
+    return result + 128;
+  }
+
   intptr_t Position() const { return current_ - buffer_; }
   void SetPosition(intptr_t value) {
     ASSERT((end_ - buffer_) >= value);
@@ -374,6 +398,21 @@
     WriteByte(static_cast<uint8_t>(value + kEndUnsignedByteMarker));
   }
 
+  void WriteRefId(intptr_t value) {
+    ASSERT(Utils::IsUint(28, value));  // 256MB is enough for anyone...
+    EnsureSpace(4);
+    if ((value >> 21) != 0) {
+      *current_++ = (value >> 21) & 127;
+    }
+    if ((value >> 14) != 0) {
+      *current_++ = (value >> 14) & 127;
+    }
+    if ((value >> 7) != 0) {
+      *current_++ = (value >> 7) & 127;
+    }
+    *current_++ = ((value >> 0) & 127) | 128;
+  }
+
   void WriteBytes(const void* addr, intptr_t len) {
     if (len != 0) {
       EnsureSpace(len);
diff --git a/runtime/vm/frame_layout.h b/runtime/vm/frame_layout.h
index d410e93..e09a757 100644
--- a/runtime/vm/frame_layout.h
+++ b/runtime/vm/frame_layout.h
@@ -42,6 +42,12 @@
   // The offset (in words) from FP to the saved pool (if applicable).
   int saved_caller_pp_from_fp;
 
+  // The offset (in words) from FP to the saved FP.
+  int saved_caller_fp_from_fp;
+
+  // The offset (in words) from FP to the saved return address.
+  int saved_caller_pc_from_fp;
+
   // The offset (in words) from FP to the code object (if applicable).
   int code_from_fp;
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 1ae59b4..bc8a1fe 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3364,8 +3364,11 @@
     for (; i < num_overlapping_type_args; i++) {
       sup_type_arg = sup_type_args.TypeAt(sup_type_args_length -
                                           num_overlapping_type_args + i);
-      ASSERT(!sup_type_arg.IsNull());
-      if (!sup_type_arg.IsTypeParameter()) break;
+      // 'sup_type_arg' can be null if type arguments are currently being
+      // finalized in ClassFinalizer::ExpandAndFinalizeTypeArguments.
+      // Type arguments which are not filled yet do not correspond to
+      // the type parameters and cannot be reused.
+      if (sup_type_arg.IsNull() || !sup_type_arg.IsTypeParameter()) break;
       // The only type parameters appearing in the type arguments of the super
       // type are those declared by this class. Their finalized indices depend
       // on the number of type arguments being computed here. Therefore, they
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index ca98fb9..295226f 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -118,7 +118,7 @@
   }
 
   // There is an idiom where static utility classes are given a private
-  // constructor to prevent the the class from being instantiated. Ignore these
+  // constructor to prevent the class from being instantiated. Ignore these
   // constructors so that they don't lower the coverage rate. See #47021.
   SafepointReadRwLocker ml(thread_, thread_->isolate_group()->program_lock());
   if (func.kind() == UntaggedFunction::kConstructor &&
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 0297144..7a43ea7 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -34,6 +34,8 @@
     /*.first_local_from_fp = */ -1,
     /*.dart_fixed_frame_size = */ -1,
     /*.saved_caller_pp_from_fp = */ -1,
+    /*.saved_caller_fp_from_fp = */ -1,
+    /*.saved_caller_pc_from_fp = */ -1,
     /*.code_from_fp = */ -1,
     /*.exit_link_slot_from_entry_fp = */ -1,
 };
@@ -46,6 +48,8 @@
     /*.first_local_from_fp = */ kFirstLocalSlotFromFp,
     /*.dart_fixed_frame_size = */ kDartFrameFixedSize,
     /*.saved_caller_pp_from_fp = */ kSavedCallerPpSlotFromFp,
+    /*.saved_caller_fp_from_fp = */ kSavedCallerFpSlotFromFp,
+    /*.saved_caller_pc_from_fp = */ kSavedCallerPcSlotFromFp,
     /*.code_from_fp = */ kPcMarkerSlotFromFp,
     /*.exit_link_slot_from_entry_fp = */ kExitLinkSlotFromEntryFp,
 };
@@ -60,7 +64,9 @@
     /*.dart_fixed_frame_size =*/kDartFrameFixedSize -
         2,                              // No saved CODE, PP slots.
     /*.saved_caller_pp_from_fp = */ 0,  // No saved PP slot.
-    /*.code_from_fp = */ 0,             // No saved CODE
+    /*.saved_caller_fp_from_fp = */ kSavedCallerFpSlotFromFp,
+    /*.saved_caller_pc_from_fp = */ kSavedCallerPcSlotFromFp,
+    /*.code_from_fp = */ 0,  // No saved CODE
     /*.exit_link_slot_from_entry_fp = */ kExitLinkSlotFromEntryFp,
 };
 
diff --git a/sdk/lib/_internal/vm/lib/collection_patch.dart b/sdk/lib/_internal/vm/lib/collection_patch.dart
index 942dc83..0647441 100644
--- a/sdk/lib/_internal/vm/lib/collection_patch.dart
+++ b/sdk/lib/_internal/vm/lib/collection_patch.dart
@@ -239,6 +239,28 @@
     _buckets = newBuckets;
   }
 
+  @override
+  V update(K key, V update(V value), {V Function()? ifAbsent}) {
+    final hashCode = key.hashCode;
+    final buckets = _buckets;
+    final length = buckets.length;
+    final index = hashCode & (length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && entry.key == key) {
+        return entry.value = update(entry.value);
+      }
+      entry = entry.next;
+    }
+    if (ifAbsent != null) {
+      V newValue = ifAbsent();
+      _addEntry(buckets, index, length, key, newValue, hashCode);
+      return newValue;
+    } else {
+      throw ArgumentError.value(key, "key", "Key not in map.");
+    }
+  }
+
   Set<K> _newKeySet() => new _HashSet<K>();
 }
 
@@ -429,6 +451,28 @@
     return null;
   }
 
+  @override
+  V update(K key, V update(V value), {V Function()? ifAbsent}) {
+    final hashCode = identityHashCode(key);
+    final buckets = _buckets;
+    final length = buckets.length;
+    final index = hashCode & (length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && identical(entry.key, key)) {
+        return entry.value = update(entry.value);
+      }
+      entry = entry.next;
+    }
+    if (ifAbsent != null) {
+      V newValue = ifAbsent();
+      _addEntry(buckets, index, length, key, newValue, hashCode);
+      return newValue;
+    } else {
+      throw ArgumentError.value(key, "key", "Key not in map.");
+    }
+  }
+
   Set<K> _newKeySet() => new _IdentityHashSet<K>();
 }
 
diff --git a/sdk/lib/_internal/vm/lib/finalizer_patch.dart b/sdk/lib/_internal/vm/lib/finalizer_patch.dart
index 417344f..18a030d 100644
--- a/sdk/lib/_internal/vm/lib/finalizer_patch.dart
+++ b/sdk/lib/_internal/vm/lib/finalizer_patch.dart
@@ -24,7 +24,7 @@
   ///
   /// This is fine as a non-atomic operation, because the GC only looks at
   /// finalizer instances when it process their entries. By preventing inlining
-  /// we ensure the the finalizer to have been fully initialized by the time
+  /// we ensure the finalizer to have been fully initialized by the time
   /// any [attach] on it is called.
   ///
   /// Alternatively, we could make it a recognized method and add a reachability
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 43e377a..e17cc71 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -563,7 +563,7 @@
 /// an existing zone which was created earlier using [Zone.fork].
 ///
 /// Developers can create a new zone that overrides some of the functionality of
-/// an existing zone. For example, custom zones can replace of modify the
+/// an existing zone. For example, custom zones can replace or modify the
 /// behavior of `print`, timers, microtasks or how uncaught errors are handled.
 ///
 /// The [Zone] class is not subclassable, but users can provide custom zones by
diff --git a/sdk/lib/core/weak.dart b/sdk/lib/core/weak.dart
index 3c8f968..660a5eb 100644
--- a/sdk/lib/core/weak.dart
+++ b/sdk/lib/core/weak.dart
@@ -173,7 +173,7 @@
 
   /// Attaches this finalizer to [value].
   ///
-  /// When [value] is longer accessible to the program,
+  /// When [value] is no longer accessible to the program,
   /// while still having an attachement to this finalizer,
   /// the callback of this finalizer *may* be called
   /// with [finalizationToken] as argument.
diff --git a/tests/language/implicit_creation/implicit_const_context_not_test.dart b/tests/language/implicit_creation/implicit_const_context_not_test.dart
index 7d69c0a..83d75ea 100644
--- a/tests/language/implicit_creation/implicit_const_context_not_test.dart
+++ b/tests/language/implicit_creation/implicit_const_context_not_test.dart
@@ -25,7 +25,7 @@
   const C.c2() : v = const C();
   const C.c3() : v = const C(C());
 
-  // Expression in redirecting generative const constuctor.
+  // Expression in redirecting generative const constructor.
   const C.r1() : this(C()); //# 3: compile-time error
   const C.r2() : this(const C());
   const C.r3() : this(const C(C()));
diff --git a/tests/language/inference_update_1/write_capture_deferral_disabled_test.dart b/tests/language/inference_update_1/write_capture_deferral_disabled_test.dart
index 1083524..80c63a8 100644
--- a/tests/language/inference_update_1/write_capture_deferral_disabled_test.dart
+++ b/tests/language/inference_update_1/write_capture_deferral_disabled_test.dart
@@ -52,4 +52,19 @@
   }
 }
 
+class B {
+  B(Object? x, void Function() g, Object? y);
+  B.redirectingConstructorInvocation(int? i)
+      : this(i!, () {
+          i = null;
+        }, i..expectStaticType<Exactly<int?>>());
+}
+
+class C extends B {
+  C.superConstructorInvocation(int? i)
+      : super(i!, () {
+          i = null;
+        }, i..expectStaticType<Exactly<int?>>());
+}
+
 main() {}
diff --git a/tests/language/inference_update_1/write_capture_deferral_enabled_test.dart b/tests/language/inference_update_1/write_capture_deferral_enabled_test.dart
index 3a93caa..1a9a79f6 100644
--- a/tests/language/inference_update_1/write_capture_deferral_enabled_test.dart
+++ b/tests/language/inference_update_1/write_capture_deferral_enabled_test.dart
@@ -52,4 +52,19 @@
   }
 }
 
+class B {
+  B(Object? x, void Function() g, Object? y);
+  B.redirectingConstructorInvocation(int? i)
+      : this(i!, () {
+          i = null;
+        }, i..expectStaticType<Exactly<int>>());
+}
+
+class C extends B {
+  C.superConstructorInvocation(int? i)
+      : super(i!, () {
+          i = null;
+        }, i..expectStaticType<Exactly<int>>());
+}
+
 main() {}
diff --git a/tests/language_2/implicit_creation/implicit_const_context_not_test.dart b/tests/language_2/implicit_creation/implicit_const_context_not_test.dart
index 8f8d999..26f7240 100644
--- a/tests/language_2/implicit_creation/implicit_const_context_not_test.dart
+++ b/tests/language_2/implicit_creation/implicit_const_context_not_test.dart
@@ -27,7 +27,7 @@
   const C.c2() : v = const C();
   const C.c3() : v = const C(C());
 
-  // Expression in redirecting generative const constuctor.
+  // Expression in redirecting generative const constructor.
   const C.r1() : this(C()); //# 3: compile-time error
   const C.r2() : this(const C());
   const C.r3() : this(const C(C()));
diff --git a/tools/VERSION b/tools/VERSION
index 8165b14..d6b04d4 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 66
+PRERELEASE 67
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index 417b548..df62eb3 100644
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -49,6 +49,23 @@
     platform('pkg/_fe_analyzer_shared/test/inheritance'),
   ];
 
+  // Validate that all the given directories exist.
+  var hasMissingDirectories = false;
+  for (var path in [
+    ...packageDirs,
+    ...cfePackageDirs,
+    ...feAnalyzerSharedPackageDirs
+  ]) {
+    if (!Directory(join(repoRoot, path)).existsSync()) {
+      stderr.writeln("Unable to locate directory: '$path'.");
+      hasMissingDirectories = true;
+    }
+  }
+
+  if (hasMissingDirectories) {
+    exit(1);
+  }
+
   var packages = <Package>[
     ...makePackageConfigs(packageDirs),
     ...makeCfePackageConfigs(cfePackageDirs),