Version 2.15.0-261.0.dev

Merge commit 'ed0131bc7c149fe752743264463cb87c79d0c27b' into 'dev'
diff --git a/pkg/_js_interop_checks/pubspec.yaml b/pkg/_js_interop_checks/pubspec.yaml
index bae1992..53c668a 100644
--- a/pkg/_js_interop_checks/pubspec.yaml
+++ b/pkg/_js_interop_checks/pubspec.yaml
@@ -6,7 +6,10 @@
   sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
-  _fe_analyzer_shared:
-    path: ../_fe_analyzer_shared
+  _fe_analyzer_shared: any
   kernel:
     path: ../kernel
+
+dependency_overrides:
+  _fe_analyzer_shared:
+    path: ../_fe_analyzer_shared
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index 5051a51..b9c27ec 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -70,7 +70,7 @@
       var lineInfo = resolvedUnit.lineInfo;
       var offset = lineInfo.getOffsetOfLine(line) + column;
 
-      _dartCompletionRequest = DartCompletionRequest.from(
+      _dartCompletionRequest = DartCompletionRequest(
         resolvedUnit: resolvedUnit,
         offset: offset,
       );
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index cfb6da5..4434ecc 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -33,6 +33,9 @@
 /// Instances of the class [CompletionDomainHandler] implement a
 /// [RequestHandler] that handles requests in the completion domain.
 class CompletionDomainHandler extends AbstractRequestHandler {
+  /// The time budget for a completion request.
+  static const Duration _budgetDuration = Duration(milliseconds: 100);
+
   /// The maximum number of performance measurements to keep.
   static const int performanceListMaxLength = 50;
 
@@ -66,11 +69,13 @@
   /// [results]. Subclasses should override this method, append at least one
   /// result to the [controller], and close the controller stream once complete.
   Future<List<CompletionSuggestion>> computeSuggestions({
+    required CompletionBudget budget,
     required OperationPerformanceImpl performance,
     required DartCompletionRequest request,
     Set<ElementKind>? includedElementKinds,
     Set<String>? includedElementNames,
     List<IncludedSuggestionRelevanceTag>? includedSuggestionRelevanceTags,
+    List<Uri>? librariesToImport,
   }) async {
     //
     // Allow plugins to start computing fixes.
@@ -88,6 +93,7 @@
         includedElementKinds: includedElementKinds,
         includedElementNames: includedElementNames,
         includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
+        librariesToImport: librariesToImport,
       );
 
       try {
@@ -106,7 +112,7 @@
     //
     if (requestToPlugins != null) {
       await performance.runAsync('waitForPlugins', (_) async {
-        await _addPluginSuggestions(requestToPlugins, suggestions);
+        await _addPluginSuggestions(budget, requestToPlugins, suggestions);
       });
     }
 
@@ -207,6 +213,8 @@
 
   /// Implement the 'completion.getSuggestions2' request.
   void getSuggestions2(Request request) async {
+    var budget = CompletionBudget(_budgetDuration);
+
     var params = CompletionGetSuggestions2Params.fromRequest(request);
     var file = params.file;
     var offset = params.offset;
@@ -244,7 +252,7 @@
     recordRequest(completionPerformance, file, resolvedUnit.content, offset);
 
     await completionPerformance.runRequestOperation((performance) async {
-      var completionRequest = DartCompletionRequest.from(
+      var completionRequest = DartCompletionRequest(
         resolvedUnit: resolvedUnit,
         offset: offset,
         dartdocDirectiveInfo: server.getDartdocDirectiveInfoFor(
@@ -253,9 +261,12 @@
         documentationCache: server.getDocumentationCacheFor(resolvedUnit),
       );
 
+      var librariesToImport = <Uri>[];
       var suggestions = await computeSuggestions(
+        budget: budget,
         performance: performance,
         request: completionRequest,
+        librariesToImport: librariesToImport,
       );
 
       performance.run('filter', (performance) {
@@ -276,7 +287,7 @@
           completionRequest.replacementOffset,
           completionRequest.replacementLength,
           lengthRestricted,
-          [], // TODO(scheglov)
+          librariesToImport.map((e) => '$e').toList(),
           isIncomplete,
         ).toResponse(request.id),
       );
@@ -326,6 +337,8 @@
 
   /// Process a `completion.getSuggestions` request.
   Future<void> processRequest(Request request) async {
+    var budget = CompletionBudget(_budgetDuration);
+
     final performance = this.performance = CompletionPerformance();
 
     await performance.runRequestOperation((perf) async {
@@ -392,7 +405,7 @@
         return;
       }
 
-      var completionRequest = DartCompletionRequest.from(
+      var completionRequest = DartCompletionRequest(
         resolvedUnit: resolvedUnit,
         offset: offset,
         dartdocDirectiveInfo: server.getDartdocDirectiveInfoFor(
@@ -423,6 +436,7 @@
       // Compute suggestions in the background
       try {
         var suggestions = await computeSuggestions(
+          budget: budget,
           performance: perf,
           request: completionRequest,
           includedElementKinds: includedElementKinds,
@@ -550,13 +564,15 @@
 
   /// Add the completions produced by plugins to the server-generated list.
   Future<void> _addPluginSuggestions(
+    CompletionBudget budget,
     _RequestToPlugins requestToPlugins,
     List<CompletionSuggestion> suggestions,
   ) async {
     var responses = await waitForResponses(
       requestToPlugins.futures,
       requestParameters: requestToPlugins.parameters,
-      timeout: 100,
+      // TODO(scheglov) pass Duration
+      timeout: budget.left.inMilliseconds,
     );
     for (var response in responses) {
       var result = plugin.CompletionGetSuggestionsResult.fromResponse(response);
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index 1f20a26..c130a8a 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -69,7 +69,7 @@
       return RuntimeCompletionResult([], []);
     }
 
-    var dartRequest = DartCompletionRequest.from(
+    var dartRequest = DartCompletionRequest(
       resolvedUnit: targetResult,
       offset: targetOffset,
     );
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 0142b07..c853df6b 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -208,7 +208,7 @@
     server.performanceStats.completion.add(performance);
 
     return await performance.runRequestOperation((perf) async {
-      final completionRequest = DartCompletionRequest.from(
+      final completionRequest = DartCompletionRequest(
         resolvedUnit: unit,
         offset: offset,
         dartdocDirectiveInfo: server.getDartdocDirectiveInfoFor(unit),
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index a26115a..77455f0 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -19,6 +19,7 @@
 import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/local_reference_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/named_constructor_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/not_imported_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/override_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/redirecting_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/relevance_tables.g.dart';
@@ -44,6 +45,19 @@
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
 import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
 
+/// Class that tracks how much time budget we have left.
+class CompletionBudget {
+  final Duration _budget;
+  final Stopwatch _timer = Stopwatch()..start();
+
+  CompletionBudget(this._budget);
+
+  Duration get left {
+    var result = _budget - _timer.elapsed;
+    return result.isNegative ? Duration.zero : result;
+  }
+}
+
 /// [DartCompletionManager] determines if a completion request is Dart specific
 /// and forwards those requests to all [DartCompletionContributor]s.
 class DartCompletionManager {
@@ -67,16 +81,22 @@
   /// suggestions, or `null` if no notification should occur.
   final SuggestionListener? listener;
 
+  /// If specified, will be filled with URIs of libraries that are not yet
+  /// imported, but could be imported into the requested target. Corresponding
+  /// [CompletionSuggestion] will have the import index into this list.
+  final List<Uri>? librariesToImport;
+
   /// Initialize a newly created completion manager. The parameters
   /// [includedElementKinds], [includedElementNames], and
   /// [includedSuggestionRelevanceTags] must either all be `null` or must all be
   /// non-`null`.
-  DartCompletionManager(
-      {this.includedElementKinds,
-      this.includedElementNames,
-      this.includedSuggestionRelevanceTags,
-      this.listener})
-      : assert((includedElementKinds != null &&
+  DartCompletionManager({
+    this.includedElementKinds,
+    this.includedElementNames,
+    this.includedSuggestionRelevanceTags,
+    this.listener,
+    this.librariesToImport,
+  }) : assert((includedElementKinds != null &&
                 includedElementNames != null &&
                 includedSuggestionRelevanceTags != null) ||
             (includedElementKinds == null &&
@@ -133,6 +153,13 @@
       );
     }
 
+    final librariesToImport = this.librariesToImport;
+    if (librariesToImport != null) {
+      contributors.add(
+        NotImportedContributor(request, builder, librariesToImport),
+      );
+    }
+
     try {
       for (var contributor in contributors) {
         await performance.runAsync(
@@ -283,6 +310,47 @@
 
   bool _aborted = false;
 
+  factory DartCompletionRequest({
+    required ResolvedUnitResult resolvedUnit,
+    required int offset,
+    DartdocDirectiveInfo? dartdocDirectiveInfo,
+    CompletionPreference completionPreference = CompletionPreference.insert,
+    DocumentationCache? documentationCache,
+  }) {
+    var target = CompletionTarget.forOffset(resolvedUnit.unit, offset);
+    var dotTarget = _dotTarget(target);
+
+    var featureComputer = FeatureComputer(
+      resolvedUnit.typeSystem,
+      resolvedUnit.typeProvider,
+    );
+
+    var contextType = featureComputer.computeContextType(
+      target.containingNode,
+      offset,
+    );
+
+    var opType = OpType.forCompletion(target, offset);
+    if (contextType != null && contextType.isVoid) {
+      opType.includeVoidReturnSuggestions = true;
+    }
+
+    return DartCompletionRequest._(
+      completionPreference: completionPreference,
+      contextType: contextType,
+      dartdocDirectiveInfo: dartdocDirectiveInfo ?? DartdocDirectiveInfo(),
+      documentationCache: documentationCache,
+      dotTarget: dotTarget,
+      featureComputer: featureComputer,
+      offset: offset,
+      opType: opType,
+      replacementRange: target.computeReplacementRange(offset),
+      result: resolvedUnit,
+      source: resolvedUnit.unit.declaredElement!.source,
+      target: target,
+    );
+  }
+
   DartCompletionRequest._({
     required this.completionPreference,
     required this.contextType,
@@ -389,48 +457,6 @@
     }
   }
 
-  /// Return a newly created completion request in [resolvedUnit] at [offset].
-  static DartCompletionRequest from({
-    required ResolvedUnitResult resolvedUnit,
-    required int offset,
-    DartdocDirectiveInfo? dartdocDirectiveInfo,
-    CompletionPreference completionPreference = CompletionPreference.insert,
-    DocumentationCache? documentationCache,
-  }) {
-    var target = CompletionTarget.forOffset(resolvedUnit.unit, offset);
-    var dotTarget = _dotTarget(target);
-
-    var featureComputer = FeatureComputer(
-      resolvedUnit.typeSystem,
-      resolvedUnit.typeProvider,
-    );
-
-    var contextType = featureComputer.computeContextType(
-      target.containingNode,
-      offset,
-    );
-
-    var opType = OpType.forCompletion(target, offset);
-    if (contextType != null && contextType.isVoid) {
-      opType.includeVoidReturnSuggestions = true;
-    }
-
-    return DartCompletionRequest._(
-      completionPreference: completionPreference,
-      contextType: contextType,
-      dartdocDirectiveInfo: dartdocDirectiveInfo ?? DartdocDirectiveInfo(),
-      documentationCache: documentationCache,
-      dotTarget: dotTarget,
-      featureComputer: featureComputer,
-      offset: offset,
-      opType: opType,
-      replacementRange: target.computeReplacementRange(offset),
-      result: resolvedUnit,
-      source: resolvedUnit.unit.declaredElement!.source,
-      target: target,
-    );
-  }
-
   /// TODO(scheglov) Should this be a property of [CompletionTarget]?
   static Expression? _dotTarget(CompletionTarget target) {
     var node = target.containingNode;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
new file mode 100644
index 0000000..e6415d0
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
@@ -0,0 +1,181 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart'
+    show SuggestionBuilder;
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/src/dart/analysis/file_state.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
+import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/lint/pub.dart';
+import 'package:analyzer/src/workspace/pub.dart';
+import 'package:collection/collection.dart';
+
+/// A contributor of suggestions from not yet imported libraries.
+class NotImportedContributor extends DartCompletionContributor {
+  final List<Uri> librariesToImport;
+
+  NotImportedContributor(
+    DartCompletionRequest request,
+    SuggestionBuilder builder,
+    this.librariesToImport,
+  ) : super(request, builder);
+
+  @override
+  Future<void> computeSuggestions() async {
+    if (!request.includeIdentifiers) {
+      return;
+    }
+
+    var session = request.result.session as AnalysisSessionImpl;
+    var analysisDriver = session.getDriver(); // ignore: deprecated_member_use
+
+    var fsState = analysisDriver.fsState;
+    var filter = _buildFilter(fsState);
+
+    await analysisDriver.discoverAvailableFiles();
+
+    var knownFiles = fsState.knownFiles.toList();
+    for (var file in knownFiles) {
+      if (!filter.shouldInclude(file)) {
+        continue;
+      }
+
+      var elementResult = await session.getLibraryByUri(file.uriStr);
+      if (elementResult is! LibraryElementResult) {
+        continue;
+      }
+
+      var newSuggestions = builder.markSuggestions();
+
+      _buildSuggestions(
+        elementResult.element.exportNamespace,
+      );
+
+      newSuggestions.setLibraryUriToImportIndex(() {
+        librariesToImport.add(file.uri);
+        return librariesToImport.length - 1;
+      });
+    }
+  }
+
+  _Filter _buildFilter(FileSystemState fsState) {
+    var file = fsState.getFileForPath(request.result.path);
+    var workspacePackage = file.workspacePackage;
+    if (workspacePackage is PubWorkspacePackage) {
+      return _PubFilter(workspacePackage, file.path);
+    } else {
+      return _AnyFilter();
+    }
+  }
+
+  void _buildSuggestions(Namespace namespace) {
+    var visitor = LibraryElementSuggestionBuilder(request, builder);
+    for (var element in namespace.definedNames.values) {
+      element.accept(visitor);
+    }
+  }
+}
+
+class _AnyFilter implements _Filter {
+  @override
+  bool shouldInclude(FileState file) => true;
+}
+
+abstract class _Filter {
+  bool shouldInclude(FileState file);
+}
+
+class _PubFilter implements _Filter {
+  final PubWorkspacePackage targetPackage;
+  final String? targetPackageName;
+  final bool targetInLib;
+  final Set<String> dependencies;
+
+  factory _PubFilter(PubWorkspacePackage package, String path) {
+    var inLib = package.workspace.provider
+        .getFolder(package.root)
+        .getChildAssumingFolder('lib')
+        .contains(path);
+
+    var dependencies = <String>{};
+    var pubspec = package.pubspec;
+    if (pubspec != null) {
+      dependencies.addAll(pubspec.dependencies.names);
+      if (!inLib) {
+        dependencies.addAll(pubspec.devDependencies.names);
+      }
+    }
+
+    return _PubFilter._(
+      targetPackage: package,
+      targetPackageName: pubspec?.name?.value.text,
+      targetInLib: inLib,
+      dependencies: dependencies,
+    );
+  }
+
+  _PubFilter._({
+    required this.targetPackage,
+    required this.targetPackageName,
+    required this.targetInLib,
+    required this.dependencies,
+  });
+
+  @override
+  bool shouldInclude(FileState file) {
+    var uri = file.uri;
+    if (uri.isScheme('dart')) {
+      return true;
+    }
+
+    // Normally only package URIs are available.
+    // But outside of lib/ we allow any files of this package.
+    if (!uri.isScheme('package')) {
+      if (targetInLib) {
+        return false;
+      } else {
+        var filePackage = file.workspacePackage;
+        return filePackage is PubWorkspacePackage &&
+            filePackage.root == targetPackage.root;
+      }
+    }
+
+    // Sanity check.
+    var uriPathSegments = uri.pathSegments;
+    if (uriPathSegments.length < 2) {
+      return false;
+    }
+
+    // Any `package:` library from the same package.
+    var packageName = uriPathSegments[0];
+    if (packageName == targetPackageName) {
+      return true;
+    }
+
+    // If not the same package, must be public.
+    if (uriPathSegments[1] == 'src') {
+      return false;
+    }
+
+    return dependencies.contains(packageName);
+  }
+}
+
+extension on PSDependencyList? {
+  List<String> get names {
+    final self = this;
+    if (self == null) {
+      return const [];
+    } else {
+      return self
+          .map((dependency) => dependency.name?.text)
+          .whereNotNull()
+          .toList();
+    }
+  }
+}
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 8783ddd..06ce9e7 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
@@ -138,6 +138,54 @@
   }
 }
 
+class NewSuggestionsProcessor {
+  final SuggestionBuilder _builder;
+  final Set<protocol.CompletionSuggestion> _current = Set.identity();
+
+  NewSuggestionsProcessor._(this._builder) {
+    _current.addAll(_builder._suggestionMap.values);
+  }
+
+  /// Update suggestions added since this marker was created.
+  void setLibraryUriToImportIndex(int Function() produce) {
+    int? libraryUriToImportIndex;
+    var suggestionMap = _builder._suggestionMap;
+    for (var entry in suggestionMap.entries.toList()) {
+      var suggestion = entry.value;
+      if (!_current.contains(suggestion)) {
+        libraryUriToImportIndex ??= produce();
+        suggestionMap[entry.key] = protocol.CompletionSuggestion(
+          suggestion.kind,
+          suggestion.relevance,
+          suggestion.completion,
+          suggestion.selectionOffset,
+          suggestion.selectionLength,
+          suggestion.isDeprecated,
+          suggestion.isPotential,
+          displayText: suggestion.displayText,
+          replacementOffset: suggestion.replacementOffset,
+          replacementLength: suggestion.replacementLength,
+          docSummary: suggestion.docSummary,
+          docComplete: suggestion.docComplete,
+          declaringType: suggestion.declaringType,
+          defaultArgumentListString: suggestion.defaultArgumentListString,
+          defaultArgumentListTextRanges:
+              suggestion.defaultArgumentListTextRanges,
+          element: suggestion.element,
+          returnType: suggestion.returnType,
+          parameterNames: suggestion.parameterNames,
+          parameterTypes: suggestion.parameterTypes,
+          requiredParameterCount: suggestion.requiredParameterCount,
+          hasNamedParameters: suggestion.hasNamedParameters,
+          parameterName: suggestion.parameterName,
+          parameterType: suggestion.parameterType,
+          libraryUriToImportIndex: libraryUriToImportIndex,
+        );
+      }
+    }
+  }
+}
+
 /// An object used to build a list of suggestions in response to a single
 /// completion request.
 class SuggestionBuilder {
@@ -216,6 +264,11 @@
   bool get _isNonNullableByDefault =>
       request.libraryElement.isNonNullableByDefault;
 
+  /// Return an object that knows which suggestions exist, and which are new.
+  NewSuggestionsProcessor markSuggestions() {
+    return NewSuggestionsProcessor._(this);
+  }
+
   /// Add a suggestion for an [accessor] declared within a class or extension.
   /// If the accessor is being invoked with a target of `super`, then the
   /// [containingMemberName] should be the name of the member containing the
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index b0adedf..4536f8b 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -10,9 +10,11 @@
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
 import 'package:analysis_server/src/utilities/mocks.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/service.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
+import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
@@ -47,8 +49,12 @@
 
   String get testPackageLibPath => '$testPackageRootPath/lib';
 
+  Folder get testPackageRoot => getFolder(testPackageRootPath);
+
   String get testPackageRootPath => '$workspaceRootPath/test';
 
+  String get testPackageTestPath => '$testPackageRootPath/test';
+
   String get workspaceRootPath => '/home';
 
   Future<void> setRoots({
@@ -75,6 +81,8 @@
       root: sdkRoot,
     );
 
+    writeTestPackageConfig();
+
     server = AnalysisServer(
       serverChannel,
       resourceProvider,
@@ -85,6 +93,441 @@
     );
   }
 
+  Future<void> test_notImported_pub_dependencies_inLib() async {
+    // TODO(scheglov) Switch to PubspecYamlFileConfig
+    newPubspecYamlFile(testPackageRootPath, r'''
+name: test
+dependencies:
+  aaa: any
+dev_dependencies:
+  bbb: any
+''');
+
+    var aaaRoot = getFolder('$workspaceRootPath/packages/aaa');
+    newFile('${aaaRoot.path}/lib/f.dart', content: '''
+class A01 {}
+''');
+    newFile('${aaaRoot.path}/lib/src/f.dart', content: '''
+class A02 {}
+''');
+
+    var bbbRoot = getFolder('$workspaceRootPath/packages/bbb');
+    newFile('${bbbRoot.path}/lib/f.dart', content: '''
+class A03 {}
+''');
+    newFile('${bbbRoot.path}/lib/src/f.dart', content: '''
+class A04 {}
+''');
+
+    writeTestPackageConfig(
+      config: PackageConfigFileBuilder()
+        ..add(name: 'aaa', rootPath: aaaRoot.path)
+        ..add(name: 'bbb', rootPath: bbbRoot.path),
+    );
+
+    await _configureWithWorkspaceRoot();
+
+    var responseValidator = await _getTestCodeSuggestions('''
+void f() {
+  A0^
+}
+''');
+
+    responseValidator
+      ..assertComplete()
+      ..assertReplacementBack(2)
+      ..assertLibrariesToImport(includes: [
+        'package:aaa/f.dart',
+      ], excludes: [
+        'dart:core',
+        'package:bbb/f.dart',
+        'package:test/test.dart',
+      ]);
+
+    var classes = responseValidator.suggestions.withElementClass();
+    classes.assertCompletions(['A01']);
+    classes.withCompletion('A01').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:aaa/f.dart');
+  }
+
+  Future<void> test_notImported_pub_dependencies_inTest() async {
+    // TODO(scheglov) Switch to PubspecYamlFileConfig
+    newPubspecYamlFile(testPackageRootPath, r'''
+name: test
+dependencies:
+  aaa: any
+dev_dependencies:
+  bbb: any
+''');
+
+    var aaaRoot = getFolder('$workspaceRootPath/packages/aaa');
+    newFile('${aaaRoot.path}/lib/f.dart', content: '''
+class A01 {}
+''');
+    newFile('${aaaRoot.path}/lib/src/f.dart', content: '''
+class A02 {}
+''');
+
+    var bbbRoot = getFolder('$workspaceRootPath/packages/bbb');
+    newFile('${bbbRoot.path}/lib/f.dart', content: '''
+class A03 {}
+''');
+    newFile('${bbbRoot.path}/lib/src/f.dart', content: '''
+class A04 {}
+''');
+
+    writeTestPackageConfig(
+      config: PackageConfigFileBuilder()
+        ..add(name: 'aaa', rootPath: aaaRoot.path)
+        ..add(name: 'bbb', rootPath: bbbRoot.path),
+    );
+
+    await _configureWithWorkspaceRoot();
+
+    var test_path = '$testPackageTestPath/test.dart';
+    var responseValidator = await _getCodeSuggestions(
+      path: test_path,
+      content: '''
+void f() {
+  A0^
+}
+''',
+    );
+
+    responseValidator
+      ..assertComplete()
+      ..assertReplacementBack(2)
+      ..assertLibrariesToImport(includes: [
+        'package:aaa/f.dart',
+        'package:bbb/f.dart',
+      ], excludes: [
+        'dart:core',
+        'package:test/test.dart',
+      ]);
+
+    var classes = responseValidator.suggestions.withElementClass();
+    classes.assertCompletions(['A01', 'A03']);
+    classes.withCompletion('A01').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:aaa/f.dart');
+    classes.withCompletion('A03').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:bbb/f.dart');
+  }
+
+  /// TODO(scheglov) Only lib/ libraries in lib/, no test/.
+  /// TODO(scheglov) Suggestions from available Pub packages.
+  Future<void> test_notImported_pub_this() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+class A01 {}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+class A02 {}
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var responseValidator = await _getTestCodeSuggestions('''
+void f() {
+  A0^
+}
+''');
+
+    responseValidator
+      ..assertComplete()
+      ..assertReplacementBack(2)
+      ..assertLibrariesToImport(includes: [
+        'dart:async',
+        'dart:math',
+        'package:test/a.dart',
+        'package:test/b.dart',
+      ], excludes: [
+        'dart:core',
+        'package:test/test.dart',
+      ]);
+
+    var classes = responseValidator.suggestions.withElementClass();
+    classes.assertCompletions(['A01', 'A02']);
+    classes.withCompletion('A01').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:test/a.dart');
+    classes.withCompletion('A02').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:test/b.dart');
+  }
+
+  Future<void> test_notImported_pub_this_hasImport() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+class A01 {}
+class A02 {}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+class A03 {}
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var responseValidator = await _getTestCodeSuggestions('''
+import 'a.dart';
+
+void f() {
+  A0^
+}
+''');
+
+    responseValidator
+      ..assertComplete()
+      ..assertReplacementBack(2)
+      ..assertLibrariesToImport(includes: [
+        'dart:async',
+        'dart:math',
+        'package:test/b.dart',
+      ], excludes: [
+        'dart:core',
+        'package:test/a.dart',
+        'package:test/test.dart',
+      ]);
+
+    var classes = responseValidator.suggestions.withElementClass();
+    classes.assertCompletions(['A01', 'A02', 'A03']);
+    classes.withCompletion('A01').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport(isNull);
+    classes.withCompletion('A02').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport(isNull);
+    classes.withCompletion('A03').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:test/b.dart');
+  }
+
+  Future<void> test_notImported_pub_this_hasImport_hasShow() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+class A01 {}
+class A02 {}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+class A03 {}
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var responseValidator = await _getTestCodeSuggestions('''
+import 'a.dart' show A01;
+
+void f() {
+  A0^
+}
+''');
+
+    responseValidator
+      ..assertComplete()
+      ..assertReplacementBack(2)
+      ..assertLibrariesToImport(includes: [
+        'dart:async',
+        'dart:math',
+        'package:test/a.dart',
+        'package:test/b.dart',
+      ], excludes: [
+        'dart:core',
+        'package:test/test.dart',
+      ]);
+
+    var classes = responseValidator.suggestions.withElementClass();
+    classes.assertCompletions(['A01', 'A02', 'A03']);
+    classes.withCompletion('A01').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport(isNull);
+    classes.withCompletion('A02').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:test/a.dart');
+    classes.withCompletion('A03').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:test/b.dart');
+  }
+
+  Future<void> test_notImported_pub_this_inLib_excludesTest() async {
+    // TODO(scheglov) Switch to PubspecYamlFileConfig
+    newPubspecYamlFile(testPackageRootPath, r'''
+name: test
+''');
+
+    newFile('$testPackageLibPath/a.dart', content: '''
+class A01 {}
+''');
+
+    var b = newFile('$testPackageTestPath/b.dart', content: '''
+class A02 {}
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var responseValidator = await _getTestCodeSuggestions('''
+void f() {
+  A0^
+}
+''');
+
+    responseValidator
+      ..assertComplete()
+      ..assertReplacementBack(2)
+      ..assertLibrariesToImport(includes: [
+        'package:test/a.dart',
+      ], excludes: [
+        'dart:core',
+        'package:test/test.dart',
+        toUriStr(b.path),
+      ]);
+
+    var classes = responseValidator.suggestions.withElementClass();
+    classes.assertCompletions(['A01']);
+    classes.withCompletion('A01').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:test/a.dart');
+  }
+
+  Future<void> test_notImported_pub_this_inLib_includesThisSrc() async {
+    // TODO(scheglov) Switch to PubspecYamlFileConfig
+    newPubspecYamlFile(testPackageRootPath, r'''
+name: test
+''');
+
+    newFile('$testPackageLibPath/f.dart', content: '''
+class A01 {}
+''');
+
+    newFile('$testPackageLibPath/src/f.dart', content: '''
+class A02 {}
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var responseValidator = await _getTestCodeSuggestions('''
+void f() {
+  A0^
+}
+''');
+
+    responseValidator
+      ..assertComplete()
+      ..assertReplacementBack(2)
+      ..assertLibrariesToImport(includes: [
+        'package:test/f.dart',
+        'package:test/src/f.dart',
+      ], excludes: [
+        'dart:core',
+        'package:test/test.dart',
+      ]);
+
+    var classes = responseValidator.suggestions.withElementClass();
+    classes.assertCompletions(['A01', 'A02']);
+    classes.withCompletion('A01').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:test/f.dart');
+    classes.withCompletion('A02').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:test/src/f.dart');
+  }
+
+  Future<void> test_notImported_pub_this_inTest_includesTest() async {
+    // TODO(scheglov) Switch to PubspecYamlFileConfig
+    newPubspecYamlFile(testPackageRootPath, r'''
+name: test
+''');
+
+    newFile('$testPackageLibPath/a.dart', content: '''
+class A01 {}
+''');
+
+    var b = newFile('$testPackageTestPath/b.dart', content: '''
+class A02 {}
+''');
+    var b_uriStr = toUriStr(b.path);
+
+    await _configureWithWorkspaceRoot();
+
+    var test_path = '$testPackageTestPath/test.dart';
+    var responseValidator = await _getCodeSuggestions(
+      path: test_path,
+      content: '''
+void f() {
+  A0^
+}
+''',
+    );
+
+    responseValidator
+      ..assertComplete()
+      ..assertReplacementBack(2)
+      ..assertLibrariesToImport(includes: [
+        'package:test/a.dart',
+        b_uriStr,
+      ], excludes: [
+        'dart:core',
+        toUriStr(test_path),
+      ]);
+
+    var classes = responseValidator.suggestions.withElementClass();
+    classes.assertCompletions(['A01', 'A02']);
+    classes.withCompletion('A01').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:test/a.dart');
+    classes.withCompletion('A02').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport(b_uriStr);
+  }
+
+  Future<void> test_notImported_pub_this_inTest_includesThisSrc() async {
+    // TODO(scheglov) Switch to PubspecYamlFileConfig
+    newPubspecYamlFile(testPackageRootPath, r'''
+name: test
+''');
+
+    newFile('$testPackageLibPath/f.dart', content: '''
+class A01 {}
+''');
+
+    newFile('$testPackageLibPath/src/f.dart', content: '''
+class A02 {}
+''');
+
+    await _configureWithWorkspaceRoot();
+
+    var test_path = '$testPackageTestPath/test.dart';
+    var responseValidator = await _getCodeSuggestions(
+      path: test_path,
+      content: '''
+void f() {
+  A0^
+}
+''',
+    );
+
+    responseValidator
+      ..assertComplete()
+      ..assertReplacementBack(2)
+      ..assertLibrariesToImport(includes: [
+        'package:test/f.dart',
+        'package:test/src/f.dart',
+      ], excludes: [
+        'dart:core',
+        'package:test/test.dart',
+      ]);
+
+    var classes = responseValidator.suggestions.withElementClass();
+    classes.assertCompletions(['A01', 'A02']);
+    classes.withCompletion('A01').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:test/f.dart');
+    classes.withCompletion('A02').assertSingle()
+      ..assertClass()
+      ..assertLibraryToImport('package:test/src/f.dart');
+  }
+
   Future<void> test_numResults_class_methods() async {
     await _configureWithWorkspaceRoot();
 
@@ -464,11 +907,59 @@
     suggestionsValidator.assertCompletions(['foo02', 'foo01']);
   }
 
+  void writePackageConfig(Folder root, PackageConfigFileBuilder config) {
+    newPackageConfigJsonFile(
+      root.path,
+      content: config.toContent(toUriStr: toUriStr),
+    );
+  }
+
+  void writeTestPackageConfig({
+    PackageConfigFileBuilder? config,
+    String? languageVersion,
+  }) {
+    if (config == null) {
+      config = PackageConfigFileBuilder();
+    } else {
+      config = config.copy();
+    }
+
+    config.add(
+      name: 'test',
+      rootPath: testPackageRootPath,
+      languageVersion: languageVersion,
+    );
+
+    writePackageConfig(testPackageRoot, config);
+  }
+
   Future<void> _configureWithWorkspaceRoot() async {
     await setRoots(included: [workspaceRootPath], excluded: []);
     await server.onAnalysisComplete;
   }
 
+  Future<CompletionGetSuggestions2ResponseValidator> _getCodeSuggestions({
+    required String path,
+    required String content,
+    int maxResults = 1 << 10,
+  }) async {
+    var completionOffset = content.indexOf('^');
+    expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
+
+    var nextOffset = content.indexOf('^', completionOffset + 1);
+    expect(nextOffset, equals(-1), reason: 'too many ^');
+
+    newFile(path,
+        content: content.substring(0, completionOffset) +
+            content.substring(completionOffset + 1));
+
+    return await _getSuggestions(
+      path: path,
+      completionOffset: completionOffset,
+      maxResults: maxResults,
+    );
+  }
+
   Future<CompletionGetSuggestions2ResponseValidator> _getSuggestions({
     required String path,
     required int completionOffset,
@@ -489,19 +980,9 @@
     String content, {
     int maxResults = 1 << 10,
   }) async {
-    var completionOffset = content.indexOf('^');
-    expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
-
-    var nextOffset = content.indexOf('^', completionOffset + 1);
-    expect(nextOffset, equals(-1), reason: 'too many ^');
-
-    var testFile = newFile(testFilePath,
-        content: content.substring(0, completionOffset) +
-            content.substring(completionOffset + 1));
-
-    return await _getSuggestions(
-      path: testFile.path,
-      completionOffset: completionOffset,
+    return _getCodeSuggestions(
+      path: testFilePath,
+      content: content,
       maxResults: maxResults,
     );
   }
@@ -1413,7 +1894,10 @@
   );
 
   SuggestionsValidator get suggestions {
-    return SuggestionsValidator(result.suggestions);
+    return SuggestionsValidator(
+      result.suggestions,
+      libraryUrisToImport: result.libraryUrisToImport,
+    );
   }
 
   void assertComplete() {
@@ -1428,6 +1912,18 @@
     expect(result.isIncomplete, isTrue);
   }
 
+  void assertLibrariesToImport({
+    required List<String> includes,
+    List<String>? excludes,
+  }) {
+    expect(result.libraryUrisToImport, containsAll(includes));
+    if (excludes != null) {
+      for (var exclude in excludes) {
+        expect(result.libraryUrisToImport, isNot(contains(exclude)));
+      }
+    }
+  }
+
   void assertReplacement(int offset, int length) {
     expect(result.replacementOffset, offset);
     expect(result.replacementLength, length);
@@ -1440,8 +1936,12 @@
 
 class SingleSuggestionValidator {
   final CompletionSuggestion suggestion;
+  final List<String>? libraryUrisToImport;
 
-  SingleSuggestionValidator(this.suggestion);
+  SingleSuggestionValidator(
+    this.suggestion, {
+    this.libraryUrisToImport,
+  });
 
   void assertClass() {
     expect(suggestion.kind, CompletionSuggestionKind.INVOCATION);
@@ -1458,6 +1958,15 @@
     expect(suggestion.element?.kind, ElementKind.GETTER);
   }
 
+  void assertLibraryToImport(Object matcher) {
+    final libraryUrisToImport = this.libraryUrisToImport;
+    final index = suggestion.libraryUriToImportIndex;
+    var libraryUri = libraryUrisToImport != null && index != null
+        ? libraryUrisToImport[index]
+        : null;
+    expect(libraryUri, matcher);
+  }
+
   void assertMethod() {
     expect(suggestion.kind, CompletionSuggestionKind.INVOCATION);
     expect(suggestion.element?.kind, ElementKind.METHOD);
@@ -1471,8 +1980,12 @@
 
 class SuggestionsValidator {
   final List<CompletionSuggestion> suggestions;
+  final List<String>? libraryUrisToImport;
 
-  SuggestionsValidator(this.suggestions);
+  SuggestionsValidator(
+    this.suggestions, {
+    this.libraryUrisToImport,
+  });
 
   int get length => suggestions.length;
 
@@ -1495,7 +2008,10 @@
 
   SingleSuggestionValidator assertSingle() {
     assertLength(1);
-    return SingleSuggestionValidator(suggestions.single);
+    return SingleSuggestionValidator(
+      suggestions.single,
+      libraryUrisToImport: libraryUrisToImport,
+    );
   }
 
   SuggestionsValidator withCompletion(String completion) {
@@ -1503,6 +2019,7 @@
       suggestions.where((suggestion) {
         return suggestion.completion == completion;
       }).toList(),
+      libraryUrisToImport: libraryUrisToImport,
     );
   }
 
@@ -1519,6 +2036,7 @@
       suggestions.where((suggestion) {
         return suggestion.element?.kind == kind;
       }).toList(),
+      libraryUrisToImport: libraryUrisToImport,
     );
   }
 }
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index b1d9045..4926490 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -533,7 +533,7 @@
     return await CompletionPerformance().runRequestOperation(
       (performance) async {
         // Build the request
-        var request = DartCompletionRequest.from(
+        var request = DartCompletionRequest(
           resolvedUnit: result,
           offset: completionOffset,
           dartdocDirectiveInfo: dartdocInfo,
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
index 882d459..972198c 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -52,7 +52,7 @@
     // Build the request
     var resolvedUnit =
         await session.getResolvedUnit(testFile) as ResolvedUnitResult;
-    request = DartCompletionRequest.from(
+    request = DartCompletionRequest(
       resolvedUnit: resolvedUnit,
       offset: completionOffset,
     );
diff --git a/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart b/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
index 009797d..8c8bc43 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/suggestion_builder_test.dart
@@ -27,7 +27,7 @@
   }
 
   Future<CompletionSuggestion> forTopLevelFunction(String functionName) async {
-    var request = DartCompletionRequest.from(
+    var request = DartCompletionRequest(
       resolvedUnit: testAnalysisResult,
       offset: 0,
     );
diff --git a/pkg/analysis_server/test/stress/completion/completion_runner.dart b/pkg/analysis_server/test/stress/completion/completion_runner.dart
index 25770fe..f54299e 100644
--- a/pkg/analysis_server/test/stress/completion/completion_runner.dart
+++ b/pkg/analysis_server/test/stress/completion/completion_runner.dart
@@ -98,7 +98,7 @@
           }
 
           timer.start();
-          var dartRequest = DartCompletionRequest.from(
+          var dartRequest = DartCompletionRequest(
             resolvedUnit: result,
             offset: offset,
           );
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index fe1e019..7284e5d 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1366,7 +1366,7 @@
             {required MetricsSuggestionListener listener,
             required CompletionMetrics metrics}) async {
           var stopwatch = Stopwatch()..start();
-          var request = DartCompletionRequest.from(
+          var request = DartCompletionRequest(
             resolvedUnit: resolvedUnitResult,
             offset: expectedCompletion.offset,
             documentationCache: documentationCache,
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index e146cf2..468934b 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -682,27 +682,37 @@
     if (functionResult == null) {
       return functionResult;
     }
+
+    // Report an error if any of the _inferred_ type argument types refer to a
+    // type parameter. If, however, `node.typeArguments` is not `null`, then
+    // any type parameters contained therein are reported as non-constant in
+    // [ConstantVerifier].
+    if (node.typeArguments == null &&
+        (node.typeArgumentTypes?.any(hasTypeParameterReference) ?? false)) {
+      _error(node, null);
+    }
+
     var typeArgumentList = node.typeArguments;
     if (typeArgumentList == null) {
-      return functionResult;
-    } else {
-      var typeArguments = <DartType>[];
-      for (var typeArgument in typeArgumentList.arguments) {
-        var object = typeArgument.accept(this);
-        if (object == null) {
-          return null;
-        }
-        var typeArgumentType = object.toTypeValue();
-        if (typeArgumentType == null) {
-          return null;
-        }
-        // TODO(srawlins): Test type alias types (`typedef i = int`) used as
-        // type arguments. Possibly change implementation based on
-        // canonicalization rules.
-        typeArguments.add(typeArgumentType);
-      }
-      return _dartObjectComputer.typeInstantiate(functionResult, typeArguments);
+      return _instantiateFunctionType(node, functionResult);
     }
+
+    var typeArguments = <DartType>[];
+    for (var typeArgument in typeArgumentList.arguments) {
+      var object = typeArgument.accept(this);
+      if (object == null) {
+        return null;
+      }
+      var typeArgumentType = object.toTypeValue();
+      if (typeArgumentType == null) {
+        return null;
+      }
+      // TODO(srawlins): Test type alias types (`typedef i = int`) used as
+      // type arguments. Possibly change implementation based on
+      // canonicalization rules.
+      typeArguments.add(typeArgumentType);
+    }
+    return _dartObjectComputer.typeInstantiate(functionResult, typeArguments);
   }
 
   @override
@@ -1000,7 +1010,7 @@
   DartObjectImpl? visitSimpleIdentifier(SimpleIdentifier node) {
     var value = _lexicalEnvironment?[node.name];
     if (value != null) {
-      return _instantiateFunctionType(node, value);
+      return _instantiateFunctionTypeForSimpleIdentifier(node, value);
     }
 
     return _getConstantValue(node, node);
@@ -1212,6 +1222,8 @@
     var variableElement =
         element is PropertyAccessorElement ? element.variable : element;
 
+    // TODO(srawlins): Remove this check when [FunctionReference]s are inserted
+    // for generic function instantiation for pre-constructor-references code.
     if (node is SimpleIdentifier &&
         (node.tearOffTypeArgumentTypes?.any(hasTypeParameterReference) ??
             false)) {
@@ -1230,7 +1242,7 @@
         if (value == null) {
           return value;
         }
-        return _instantiateFunctionType(identifier, value);
+        return _instantiateFunctionTypeForSimpleIdentifier(identifier, value);
       }
     } else if (variableElement is ConstructorElement) {
       return DartObjectImpl(
@@ -1246,7 +1258,7 @@
           function.type,
           FunctionState(function),
         );
-        return _instantiateFunctionType(identifier, rawType);
+        return _instantiateFunctionTypeForSimpleIdentifier(identifier, rawType);
       }
     } else if (variableElement is ClassElement) {
       var type = variableElement.instantiate(
@@ -1305,12 +1317,41 @@
     return null;
   }
 
+  /// If the type of [value] is a generic [FunctionType], and [node] has type
+  /// argument types, returns [value] type-instantiated with those [node]'s
+  /// type argument types, otherwise returns [value].
+  DartObjectImpl? _instantiateFunctionType(
+      FunctionReference node, DartObjectImpl value) {
+    var functionElement = value.toFunctionValue();
+    if (functionElement is! ExecutableElement) {
+      return value;
+    }
+    var valueType = functionElement.type;
+    if (valueType.typeFormals.isNotEmpty) {
+      var typeArgumentTypes = node.typeArgumentTypes;
+      if (typeArgumentTypes != null && typeArgumentTypes.isNotEmpty) {
+        var instantiatedType =
+            functionElement.type.instantiate(typeArgumentTypes);
+        var substitution = _substitution;
+        if (substitution != null) {
+          instantiatedType =
+              substitution.substituteType(instantiatedType) as FunctionType;
+        }
+        return value.typeInstantiate(
+            typeSystem, instantiatedType, typeArgumentTypes);
+      }
+    }
+    return value;
+  }
+
   /// If the type of [value] is a generic [FunctionType], and [node] is a
   /// [SimpleIdentifier] with tear-off type argument types, returns [value]
   /// type-instantiated with those [node]'s tear-off type argument types,
   /// otherwise returns [value].
-  DartObjectImpl? _instantiateFunctionType(
+  DartObjectImpl? _instantiateFunctionTypeForSimpleIdentifier(
       SimpleIdentifier node, DartObjectImpl value) {
+    // TODO(srawlins): When all code uses [FunctionReference]s generated via
+    // generic function instantiation, remove this method and all call sites.
     var functionElement = value.toFunctionValue();
     if (functionElement is! ExecutableElement) {
       return value;
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 1678bf8..549136f 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -4188,12 +4188,17 @@
   /// this variable is not a subject of type inference, or there was no error.
   TopLevelInferenceError? typeInferenceError;
 
+  /// If this method is a synthetic element which is based on another method
+  /// with some modifications (such as making some parameters covariant),
+  /// this field contains the base method.
+  MethodElement? prototype;
+
   /// Initialize a newly created method element to have the given [name] at the
   /// given [offset].
   MethodElementImpl(String name, int offset) : super(name, offset);
 
   @override
-  MethodElement get declaration => this;
+  MethodElement get declaration => prototype ?? this;
 
   @override
   String get displayName {
@@ -4988,6 +4993,11 @@
   @override
   late PropertyInducingElement variable;
 
+  /// If this method is a synthetic element which is based on another method
+  /// with some modifications (such as making some parameters covariant),
+  /// this field contains the base method.
+  PropertyAccessorElement? prototype;
+
   /// Initialize a newly created property accessor element to have the given
   /// [name] and [offset].
   PropertyAccessorElementImpl(String name, int offset) : super(name, offset);
@@ -5020,7 +5030,7 @@
   }
 
   @override
-  PropertyAccessorElement get declaration => this;
+  PropertyAccessorElement get declaration => prototype ?? this;
 
   @override
   String get identifier {
diff --git a/pkg/analyzer/lib/src/dart/element/extensions.dart b/pkg/analyzer/lib/src/dart/element/extensions.dart
index 2b9767d..6eaa94a 100644
--- a/pkg/analyzer/lib/src/dart/element/extensions.dart
+++ b/pkg/analyzer/lib/src/dart/element/extensions.dart
@@ -53,12 +53,16 @@
 
 extension ParameterElementExtensions on ParameterElement {
   /// Return [ParameterElement] with the specified properties replaced.
-  ParameterElement copyWith({DartType? type, ParameterKind? kind}) {
+  ParameterElement copyWith({
+    DartType? type,
+    ParameterKind? kind,
+    bool? isCovariant,
+  }) {
     return ParameterElementImpl.synthetic(
       name,
       type ?? this.type,
       // ignore: deprecated_member_use_from_same_package
       kind ?? parameterKind,
-    )..isExplicitlyCovariant = isCovariant;
+    )..isExplicitlyCovariant = isCovariant ?? this.isCovariant;
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index b19d846..cf52a23 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/extensions.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
@@ -626,6 +627,11 @@
       }
     }
 
+    implemented = implemented.map<Name, ExecutableElement>((key, value) {
+      var result = _inheritCovariance(element, namedCandidates, key, value);
+      return MapEntry(key, result);
+    });
+
     return Interface._(
       interface,
       declared,
@@ -697,6 +703,102 @@
     );
   }
 
+  /// If a candidate from [namedCandidates] has covariant parameters, return
+  /// a copy of the [executable] with the corresponding parameters marked
+  /// covariant. If there are no covariant parameters, or parameters to
+  /// update are already covariant, return the [executable] itself.
+  ExecutableElement _inheritCovariance(
+    ClassElement class_,
+    Map<Name, List<ExecutableElement>> namedCandidates,
+    Name name,
+    ExecutableElement executable,
+  ) {
+    if (executable.enclosingElement == class_) {
+      return executable;
+    }
+
+    var parameters = executable.parameters;
+    if (parameters.isEmpty) {
+      return executable;
+    }
+
+    var candidates = namedCandidates[name];
+    if (candidates == null) {
+      return executable;
+    }
+
+    // Find parameters that are covariant (by declaration) in any overridden.
+    Set<_ParameterDesc>? covariantParameters;
+    for (var candidate in candidates) {
+      var parameters = candidate.parameters;
+      for (var i = 0; i < parameters.length; i++) {
+        var parameter = parameters[i];
+        if (parameter.isCovariant) {
+          covariantParameters ??= {};
+          covariantParameters.add(
+            _ParameterDesc(i, parameter),
+          );
+        }
+      }
+    }
+
+    if (covariantParameters == null) {
+      return executable;
+    }
+
+    // Update covariance of the parameters of the chosen executable.
+    List<ParameterElement>? transformedParameters;
+    for (var index = 0; index < parameters.length; index++) {
+      var parameter = parameters[index];
+      var shouldBeCovariant = covariantParameters.contains(
+        _ParameterDesc(index, parameter),
+      );
+      if (parameter.isCovariant != shouldBeCovariant) {
+        transformedParameters ??= parameters.toList();
+        transformedParameters[index] = parameter.copyWith(
+          isCovariant: shouldBeCovariant,
+        );
+      }
+    }
+
+    if (transformedParameters == null) {
+      return executable;
+    }
+
+    if (executable is MethodElement) {
+      var result = MethodElementImpl(executable.name, -1);
+      result.enclosingElement = class_;
+      result.isSynthetic = true;
+      result.parameters = transformedParameters;
+      result.prototype = executable;
+      result.returnType = executable.returnType;
+      result.typeParameters = executable.typeParameters;
+      return result;
+    }
+
+    if (executable is PropertyAccessorElement) {
+      assert(executable.isSetter);
+      var result = PropertyAccessorElementImpl(executable.name, -1);
+      result.enclosingElement = class_;
+      result.isSynthetic = true;
+      result.parameters = transformedParameters;
+      result.prototype = executable;
+      result.returnType = executable.returnType;
+
+      var field = executable.variable;
+      var resultField = FieldElementImpl(field.name, -1);
+      resultField.enclosingElement = class_;
+      resultField.getter = field.getter;
+      resultField.setter = executable;
+      resultField.type = executable.parameters[0].type;
+      result.variable = resultField;
+
+      return result;
+    }
+
+    return executable;
+  }
+
   /// Given one or more [validOverrides], merge them into a single resulting
   /// signature. This signature always exists.
   ExecutableElement _topMerge(
@@ -907,3 +1009,34 @@
   @override
   String toString() => libraryUri != null ? '$libraryUri::$name' : name;
 }
+
+class _ParameterDesc {
+  final int? index;
+  final String? name;
+
+  factory _ParameterDesc(int index, ParameterElement element) {
+    return element.isNamed
+        ? _ParameterDesc.name(element.name)
+        : _ParameterDesc.index(index);
+  }
+
+  _ParameterDesc.index(int index)
+      : index = index,
+        name = null;
+
+  _ParameterDesc.name(String name)
+      : index = null,
+        name = name;
+
+  @override
+  int get hashCode {
+    return index?.hashCode ?? name?.hashCode ?? 0;
+  }
+
+  @override
+  bool operator ==(other) {
+    return other is _ParameterDesc &&
+        other.index == index &&
+        other.name == name;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index 6257b73..da8742a 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -242,15 +242,21 @@
       if (node.function is ConstructorReference) {
         node.staticType = DynamicTypeImpl.instance;
       } else {
-        var typeArguments = _checkTypeArguments(
-          // `node.typeArguments`, coming from the parser, is never null.
-          node.typeArguments!, name, rawType.typeFormals,
-          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
-        );
+        var typeArguments = node.typeArguments;
+        if (typeArguments == null) {
+          node.staticType = rawType;
+        } else {
+          var typeArgumentTypes = _checkTypeArguments(
+            typeArguments,
+            name,
+            rawType.typeFormals,
+            CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
+          );
 
-        var invokeType = rawType.instantiate(typeArguments);
-        node.typeArgumentTypes = typeArguments;
-        node.staticType = invokeType;
+          var invokeType = rawType.instantiate(typeArgumentTypes);
+          node.typeArgumentTypes = typeArgumentTypes;
+          node.staticType = invokeType;
+        }
       }
     } else {
       if (_resolver.isConstructorTearoffsEnabled) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
index 14d554a..eb97c1f 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
@@ -83,8 +83,15 @@
       type = result.functionTypeCallType!;
     }
 
-    type = _inferenceHelper.inferTearOff(node, identifier, type);
-
+    if (!_resolver.isConstructorTearoffsEnabled) {
+      // Only perform a generic function instantiation on a [PrefixedIdentifier]
+      // in pre-constructor-tearoffs code. In constructor-tearoffs-enabled code,
+      // generic function instantiation is performed at assignability check
+      // sites.
+      // TODO(srawlins): Switch all resolution to use the latter method, in a
+      // breaking change release.
+      type = _inferenceHelper.inferTearOff(node, identifier, type);
+    }
     _recordStaticType(identifier, type);
     _recordStaticType(node, type);
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
index bb564f7..1f9befa 100644
--- a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
@@ -12,7 +12,6 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
-import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
 import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -25,8 +24,6 @@
 
   ErrorReporter get _errorReporter => _resolver.errorReporter;
 
-  InvocationInferenceHelper get _inferenceHelper => _resolver.inferenceHelper;
-
   TypeProviderImpl get _typeProvider => _resolver.typeProvider;
 
   void resolve(SimpleIdentifierImpl node) {
@@ -259,7 +256,17 @@
     } else {
       staticType = DynamicTypeImpl.instance;
     }
-    staticType = _inferenceHelper.inferTearOff(node, node, staticType);
+
+    if (!_resolver.isConstructorTearoffsEnabled) {
+      // Only perform a generic function instantiation on a [PrefixedIdentifier]
+      // in pre-constructor-tearoffs code. In constructor-tearoffs-enabled code,
+      // generic function instantiation is performed at assignability check
+      // sites.
+      // TODO(srawlins): Switch all resolution to use the latter method, in a
+      // breaking change release.
+      staticType =
+          _resolver.inferenceHelper.inferTearOff(node, node, staticType);
+    }
     _recordStaticType(node, staticType);
   }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
index 8542adc..ca56632 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
@@ -65,17 +65,14 @@
       _resolver.flowAnalysis.flow?.lateInitializer_end();
     }
 
+    initializer = _resolver.insertImplicitCallReference(initializer);
+
     // Initializers of top-level variables and fields are already included
     // into elements during linking.
     if (element is ConstLocalVariableElementImpl) {
       element.constantInitializer = initializer;
     }
 
-    var callReference = _resolver.insertImplicitCallReference(initializer);
-    if (callReference != initializer) {
-      initializer = callReference;
-    }
-
     _resolver.checkForInvalidAssignment(node.name, initializer,
         whyNotPromoted: whyNotPromoted);
   }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 8b33178..5f87d47 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -7,7 +7,6 @@
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -19,6 +18,7 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/ast_factory.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -628,6 +628,62 @@
     return null;
   }
 
+  /// If generic function instantiation should be performed on `expression`,
+  /// inserts a [FunctionReference] node which wraps [expression].
+  ///
+  /// If an [FunctionReference] is inserted, returns it; otherwise, returns
+  /// [expression].
+  ExpressionImpl insertGenericFunctionInstantiation(Expression expression) {
+    expression as ExpressionImpl;
+    if (!isConstructorTearoffsEnabled) {
+      // Temporarily, only create [ImplicitCallReference] nodes under the
+      // 'constructor-tearoffs' feature.
+      // TODO(srawlins): When we are ready to make a breaking change release to
+      // the analyzer package, remove this exception.
+      return expression;
+    }
+
+    var staticType = expression.staticType;
+    var context = InferenceContext.getContext(expression);
+    if (context == null ||
+        staticType is! FunctionType ||
+        staticType.typeFormals.isEmpty) {
+      return expression;
+    }
+
+    context = typeSystem.flatten(context);
+    if (context is! FunctionType || context.typeFormals.isNotEmpty) {
+      return expression;
+    }
+
+    List<DartType> typeArgumentTypes =
+        typeSystem.inferFunctionTypeInstantiation(
+      context,
+      staticType,
+      errorReporter: errorReporter,
+      errorNode: expression,
+      // If the constructor-tearoffs feature is enabled, then so is
+      // generic-metadata.
+      genericMetadataIsEnabled: true,
+    )!;
+    if (typeArgumentTypes.isNotEmpty) {
+      staticType = staticType.instantiate(typeArgumentTypes);
+    }
+
+    var parent = expression.parent;
+    var genericFunctionInstantiation = astFactory.functionReference(
+      function: expression,
+      typeArguments: null,
+    );
+    NodeReplacer.replace(expression, genericFunctionInstantiation,
+        parent: parent);
+
+    genericFunctionInstantiation.typeArgumentTypes = typeArgumentTypes;
+    genericFunctionInstantiation.staticType = staticType;
+
+    return genericFunctionInstantiation;
+  }
+
   /// If `expression` should be treated as `expression.call`, inserts an
   /// [ImplicitCallReferece] node which wraps [expression].
   ///
@@ -667,6 +723,7 @@
       typeArgumentTypes = typeSystem.inferFunctionTypeInstantiation(
         context,
         callMethodType,
+        errorReporter: errorReporter,
         errorNode: expression,
         // If the constructor-tearoffs feature is enabled, then so is
         // generic-metadata.
@@ -683,7 +740,7 @@
       staticElement: callMethod,
       typeArguments: null,
       typeArgumentTypes: typeArgumentTypes,
-    ) as ImplicitCallReferenceImpl;
+    );
     NodeReplacer.replace(expression, callReference, parent: parent);
 
     callReference.staticType = callMethodType;
@@ -1060,6 +1117,7 @@
   void visitAsExpression(AsExpression node) {
     super.visitAsExpression(node);
     flowAnalysis.asExpression(node);
+    insertGenericFunctionInstantiation(node);
   }
 
   @override
@@ -1095,6 +1153,7 @@
   @override
   void visitAssignmentExpression(AssignmentExpression node) {
     _assignmentExpressionResolver.resolve(node as AssignmentExpressionImpl);
+    insertGenericFunctionInstantiation(node);
   }
 
   @override
@@ -1105,11 +1164,13 @@
       InferenceContext.setType(node.expression, futureUnion);
     }
     super.visitAwaitExpression(node);
+    insertGenericFunctionInstantiation(node);
   }
 
   @override
   void visitBinaryExpression(BinaryExpression node) {
     _binaryExpressionResolver.resolve(node as BinaryExpressionImpl);
+    insertGenericFunctionInstantiation(node);
   }
 
   @override
@@ -1540,6 +1601,7 @@
     _enclosingFunction = node.declaredElement;
 
     _functionExpressionResolver.resolve(node);
+    insertGenericFunctionInstantiation(node);
 
     _enclosingFunction = outerFunction;
   }
@@ -1551,6 +1613,7 @@
     _functionExpressionInvocationResolver.resolve(
         node as FunctionExpressionInvocationImpl, whyNotPromotedList);
     nullShortingTermination(node);
+    insertGenericFunctionInstantiation(node);
     checkForArgumentTypesNotAssignableInList(
         node.argumentList, whyNotPromotedList);
   }
@@ -1681,6 +1744,7 @@
       type = DynamicTypeImpl.instance;
     }
     inferenceHelper.recordStaticType(node, type);
+    insertGenericFunctionInstantiation(node);
 
     nullShortingTermination(node);
   }
@@ -1786,6 +1850,7 @@
     } else {
       nullShortingTermination(node);
     }
+    insertGenericFunctionInstantiation(node);
     checkForArgumentTypesNotAssignableInList(
         node.argumentList, whyNotPromotedList);
   }
@@ -1849,16 +1914,19 @@
   @override
   void visitPostfixExpression(PostfixExpression node) {
     _postfixExpressionResolver.resolve(node as PostfixExpressionImpl);
+    insertGenericFunctionInstantiation(node);
   }
 
   @override
   void visitPrefixedIdentifier(covariant PrefixedIdentifierImpl node) {
     _prefixedIdentifierResolver.resolve(node);
+    insertGenericFunctionInstantiation(node);
   }
 
   @override
   void visitPrefixExpression(PrefixExpression node) {
     _prefixExpressionResolver.resolve(node as PrefixExpressionImpl);
+    insertGenericFunctionInstantiation(node);
   }
 
   @override
@@ -1888,10 +1956,19 @@
       type = DynamicTypeImpl.instance;
     }
 
-    type = inferenceHelper.inferTearOff(node, propertyName, type);
+    if (!isConstructorTearoffsEnabled) {
+      // Only perform a generic function instantiation on a [PrefixedIdentifier]
+      // in pre-constructor-tearoffs code. In constructor-tearoffs-enabled code,
+      // generic function instantiation is performed at assignability check
+      // sites.
+      // TODO(srawlins): Switch all resolution to use the latter method, in a
+      // breaking change release.
+      type = inferenceHelper.inferTearOff(node, propertyName, type);
+    }
 
     inferenceHelper.recordStaticType(propertyName, type);
     inferenceHelper.recordStaticType(node, type);
+    insertGenericFunctionInstantiation(node);
 
     nullShortingTermination(node);
   }
@@ -1950,6 +2027,7 @@
   @override
   void visitSimpleIdentifier(covariant SimpleIdentifierImpl node) {
     _simpleIdentifierResolver.resolve(node);
+    insertGenericFunctionInstantiation(node);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/summary2/reference.dart b/pkg/analyzer/lib/src/summary2/reference.dart
index 8c305bd..aea331f 100644
--- a/pkg/analyzer/lib/src/summary2/reference.dart
+++ b/pkg/analyzer/lib/src/summary2/reference.dart
@@ -56,19 +56,32 @@
 
   /// Return the child with the given name, or `null` if does not exist.
   Reference? operator [](String name) {
+    name = _rewriteDartUi(name);
     return _children?[name];
   }
 
   /// Return the child with the given name, create if does not exist yet.
   Reference getChild(String name) {
+    name = _rewriteDartUi(name);
     var map = _children ??= <String, Reference>{};
     return map[name] ??= Reference._(this, name);
   }
 
   Reference? removeChild(String name) {
+    name = _rewriteDartUi(name);
     return _children?.remove(name);
   }
 
   @override
   String toString() => parent == null ? 'root' : '$parent::$name';
+
+  /// TODO(scheglov) Remove it, once when the actual issue is fixed.
+  /// https://buganizer.corp.google.com/issues/203423390
+  static String _rewriteDartUi(String name) {
+    const srcPrefix = 'dart:ui/src/ui/';
+    if (name.startsWith(srcPrefix)) {
+      return 'dart:ui/${name.substring(srcPrefix.length)}';
+    }
+    return name;
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
index b8af67e..ba5aa89 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
@@ -838,6 +838,48 @@
     );
   }
 
+  test_getMember_method_covariantByDeclaration_inherited() async {
+    await resolveTestCode('''
+abstract class A {
+  void foo(covariant num a);
+}
+
+abstract class B extends A {
+  void foo(int a);
+}
+''');
+    var member = manager.getMember2(
+      findElement.classOrMixin('B'),
+      Name(null, 'foo'),
+    )!;
+    // TODO(scheglov) It would be nice to use `_assertGetMember`.
+    // But we need a way to check covariance.
+    // Maybe check the element display string, not the type.
+    expect(member.parameters[0].isCovariant, isTrue);
+  }
+
+  test_getMember_method_covariantByDeclaration_merged() async {
+    await resolveTestCode('''
+class A {
+  void foo(covariant num a) {}
+}
+
+class B {
+  void foo(int a) {}
+}
+
+class C extends B implements A {}
+''');
+    var member = manager.getMember2(
+      findElement.classOrMixin('C'),
+      Name(null, 'foo'),
+      concrete: true,
+    )!;
+    // TODO(scheglov) It would be nice to use `_assertGetMember`.
+    expect(member.declaration, same(findElement.method('foo', of: 'B')));
+    expect(member.parameters[0].isCovariant, isTrue);
+  }
+
   test_getMember_preferLatest_mixin() async {
     await resolveTestCode('''
 class A {
@@ -909,6 +951,48 @@
     );
   }
 
+  test_getMember_setter_covariantByDeclaration_inherited() async {
+    await resolveTestCode('''
+abstract class A {
+  set foo(covariant num a);
+}
+
+abstract class B extends A {
+  set foo(int a);
+}
+''');
+    var member = manager.getMember2(
+      findElement.classOrMixin('B'),
+      Name(null, 'foo='),
+    )!;
+    // TODO(scheglov) It would be nice to use `_assertGetMember`.
+    // But we need a way to check covariance.
+    // Maybe check the element display string, not the type.
+    expect(member.parameters[0].isCovariant, isTrue);
+  }
+
+  test_getMember_setter_covariantByDeclaration_merged() async {
+    await resolveTestCode('''
+class A {
+  set foo(covariant num a) {}
+}
+
+class B {
+  set foo(int a) {}
+}
+
+class C extends B implements A {}
+''');
+    var member = manager.getMember2(
+      findElement.classOrMixin('C'),
+      Name(null, 'foo='),
+      concrete: true,
+    )!;
+    // TODO(scheglov) It would be nice to use `_assertGetMember`.
+    expect(member.declaration, same(findElement.setter('foo', of: 'B')));
+    expect(member.parameters[0].isCovariant, isTrue);
+  }
+
   test_getMember_super_abstract() async {
     await resolveTestCode('''
 abstract class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 814951e..fe578e8 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -416,7 +416,7 @@
 
 mixin WithoutConstructorTearoffsMixin on PubPackageResolutionTest {
   @override
-  String? get testPackageLanguageVersion => '2.13';
+  String? get testPackageLanguageVersion => '2.14';
 }
 
 mixin WithoutNullSafetyMixin on PubPackageResolutionTest {
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
index 2ccdb48..fc226d1 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -10,6 +10,8 @@
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(
+        FunctionReferenceResolution_genericFunctionInstantiationTest);
     defineReflectiveTests(FunctionReferenceResolutionTest);
     defineReflectiveTests(
         FunctionReferenceResolutionWithoutConstructorTearoffsTest);
@@ -17,6 +19,262 @@
 }
 
 @reflectiveTest
+class FunctionReferenceResolution_genericFunctionInstantiationTest
+    extends PubPackageResolutionTest {
+  test_asExpression() async {
+    await assertNoErrorsInCode('''
+void Function(int) foo(void Function<T>(T) f) {
+  return (f as dynamic) as void Function<T>(T);
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('as void Function<T>(T);'),
+        null,
+        'void Function(int)');
+  }
+
+  test_assignmentExpression() async {
+    await assertNoErrorsInCode('''
+late void Function<T>(T) g;
+void Function(int) foo(void Function<T>(T) f) {
+  return g = f;
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('g = f;'), null, 'void Function(int)');
+  }
+
+  test_assignmentExpression_compound() async {
+    await assertNoErrorsInCode('''
+extension on void Function<T>(T) {
+  void Function<T>(T) operator +(int i) {
+    return this;
+  }
+}
+
+void Function(int) foo(void Function<T>(T) f) {
+  return f += 1;
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('f += 1'), null, 'void Function(int)');
+  }
+
+  test_awaitExpression() async {
+    await assertNoErrorsInCode('''
+Future<void Function(int)> foo(Future<void Function<T>(T)> f) async {
+  return await f;
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('await f'), null, 'void Function(int)');
+  }
+
+  test_binaryExpression() async {
+    await assertNoErrorsInCode('''
+class C {
+  void Function<T>(T) operator +(int i) {
+    return <T>(T a) {};
+  }
+}
+
+void Function(int) foo(C c) {
+  return c + 1;
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('c + 1'), null, 'void Function(int)');
+  }
+
+  test_cascadeExpression() async {
+    await assertNoErrorsInCode('''
+void Function(int) foo(void Function<T>(T) f) {
+  return f..toString();
+}
+''');
+
+    assertFunctionReference(findNode.functionReference('f..toString()'), null,
+        'void Function(int)');
+  }
+
+  test_constructorReference() async {
+    await assertNoErrorsInCode('''
+class C<T> {
+  C(T a);
+}
+C<int> Function(int) foo() {
+  return C.new;
+}
+''');
+
+    // TODO(srawlins): Leave the constructor reference uninstantiated, then
+    // perform generic function instantiation as a wrapping node.
+    assertConstructorReference(
+        findNode.constructorReference('C.new'),
+        findElement.unnamedConstructor('C'),
+        findElement.class_('C'),
+        'C<int> Function(int)');
+  }
+
+  test_functionExpression() async {
+    await assertNoErrorsInCode('''
+Null Function(int) foo() {
+  return <T>(T a) {};
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('<T>(T a) {};'), null, 'Null Function(int)');
+  }
+
+  test_functionExpressionInvocation() async {
+    await assertNoErrorsInCode('''
+void Function(int) foo(void Function<T>(T) Function() f) {
+  return (f)();
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('(f)()'), null, 'void Function(int)');
+  }
+
+  test_functionReference() async {
+    await assertNoErrorsInCode('''
+typedef Fn = void Function<U>(U);
+
+void Function(int) foo(Fn f) {
+  return f;
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('f;'), null, 'void Function(int)');
+  }
+
+  test_implicitCallReference() async {
+    await assertNoErrorsInCode('''
+class C {
+  void call<T>(T a) {}
+}
+
+void Function(int) foo(C c) {
+  return c;
+}
+''');
+
+    assertImplicitCallReference(findNode.implicitCallReference('c;'),
+        findElement.method('call'), 'void Function(int)');
+  }
+
+  test_indexExpression() async {
+    await assertNoErrorsInCode('''
+void Function(int) foo(List<void Function<T>(T)> f) {
+  return f[0];
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('f[0];'), null, 'void Function(int)');
+  }
+
+  test_methodInvocation() async {
+    await assertNoErrorsInCode('''
+class C {
+  late void Function<T>(T) f;
+  void Function<T>(T) m() => f;
+}
+
+void Function(int) foo(C c) {
+  return c.m();
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('c.m();'), null, 'void Function(int)');
+  }
+
+  test_postfixExpression_compound() async {
+    await assertNoErrorsInCode('''
+extension on void Function<T>(T) {
+  void Function<T>(T) operator +(int i) {
+    return this;
+  }
+}
+
+void Function(int) foo(void Function<T>(T) f) {
+  return f++;
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('f++'), null, 'void Function(int)');
+  }
+
+  test_prefixedIdentifier() async {
+    await assertNoErrorsInCode('''
+class C {
+  late void Function<T>(T) f;
+}
+
+void Function(int) foo(C c) {
+  return c.f;
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('c.f;'), null, 'void Function(int)');
+  }
+
+  test_prefixExpression_compound() async {
+    await assertNoErrorsInCode('''
+extension on void Function<T>(T) {
+  void Function<T>(T) operator +(int i) {
+    return this;
+  }
+}
+
+void Function(int) foo(void Function<T>(T) f) {
+  return ++f;
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('++f'), null, 'void Function(int)');
+  }
+
+  test_propertyAccess() async {
+    await assertNoErrorsInCode('''
+class C {
+  late void Function<T>(T) f;
+}
+
+void Function(int) foo(C c) {
+  return (c).f;
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('(c).f;'), null, 'void Function(int)');
+  }
+
+  test_simpleIdentifier() async {
+    await assertNoErrorsInCode('''
+void Function(int) foo(void Function<T>(T) f) {
+  return f;
+}
+''');
+
+    assertFunctionReference(
+        findNode.functionReference('f;'), null, 'void Function(int)');
+  }
+}
+
+@reflectiveTest
 class FunctionReferenceResolutionTest extends PubPackageResolutionTest {
   test_constructorFunction_named() async {
     await assertNoErrorsInCode('''
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 6f09001..bed3b36 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -360,7 +360,9 @@
 
   void assertFunctionReference(
       FunctionReference node, Element? expectedElement, String expectedType) {
-    assertElement(node, expectedElement);
+    if (expectedElement != null) {
+      assertElement(node, expectedElement);
+    }
     assertType(node, expectedType);
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/tear_off_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/tear_off_test.dart
index 85fe012..84e3362 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/tear_off_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/tear_off_test.dart
@@ -32,7 +32,6 @@
       'f; // 1',
       findElement.topFunction('f'),
       'T Function<T>(T)',
-      [],
     );
   }
 
@@ -51,68 +50,94 @@
       'f; // 1',
       findElement.topFunction('f'),
       'int Function(int)',
-      [],
     );
   }
 
-  test_notEmpty() async {
-    await assertErrorsInCode('''
-T f<T>(T x) => x;
-
+  test_notEmpty_instanceMethod() async {
+    await assertNoErrorsInCode('''
 class C {
   T f<T>(T x) => x;
-  static T g<T>(T x) => x;
+}
+
+int Function(int) test() {
+  return new C().f;
+}
+''');
+    _assertGenericFunctionInstantiation(
+      'f;',
+      findElement.method('f', of: 'C'),
+      'int Function(int)',
+      ['int'],
+    );
+  }
+
+  test_notEmpty_localFunction() async {
+    await assertNoErrorsInCode('''
+int Function(int) test() {
+  T f<T>(T x) => x;
+  return f;
+}
+''');
+    _assertGenericFunctionInstantiation(
+      'f;',
+      findElement.localFunction('f'),
+      'int Function(int)',
+      ['int'],
+    );
+  }
+
+  test_notEmpty_staticMethod() async {
+    await assertNoErrorsInCode('''
+class C {
+  static T f<T>(T x) => x;
+}
+
+int Function(int) test() {
+  return C.f;
+}
+''');
+    _assertGenericFunctionInstantiation(
+      'f;',
+      findElement.method('f', of: 'C'),
+      'int Function(int)',
+      ['int'],
+    );
+  }
+
+  test_notEmpty_superMethod() async {
+    await assertNoErrorsInCode('''
+class C {
+  T f<T>(T x) => x;
 }
 
 class D extends C {
-  void test() {
-    int Function(int) func;
-    func = super.f; // 1
+  int Function(int) test() {
+    return super.f;
   }
 }
+''');
+    _assertGenericFunctionInstantiation(
+      'f;',
+      findElement.method('f', of: 'C'),
+      'int Function(int)',
+      ['int'],
+    );
+  }
 
-void test() {
-  T h<T>(T x) => x;
-  int Function(int) func;
-  func = f; // 2
-  func = new C().f; // 3
-  func = C.g; // 4
-  func = h; // 5
+  test_notEmpty_topLevelFunction() async {
+    await assertNoErrorsInCode('''
+T f<T>(T x) => x;
+
+int Function(int) test() {
+  return f;
 }
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 137, 4),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 229, 4),
-    ]);
-    _assertTearOff(
-      'f; // 1',
-      findElement.method('f', of: 'C'),
-      'int Function(int)',
-      ['int'],
-    );
-    _assertTearOff(
-      'f; // 2',
+''');
+    _assertGenericFunctionInstantiation(
+      'f;',
       findElement.topFunction('f'),
       'int Function(int)',
       ['int'],
     );
-    _assertTearOff(
-      'f; // 3',
-      findElement.method('f', of: 'C'),
-      'int Function(int)',
-      ['int'],
-    );
-    _assertTearOff(
-      'g; // 4',
-      findElement.method('g', of: 'C'),
-      'int Function(int)',
-      ['int'],
-    );
-    _assertTearOff(
-      'h; // 5',
-      findElement.localFunction('h'),
-      'int Function(int)',
-      ['int'],
-    );
   }
 
   test_null_notTearOff() async {
@@ -127,7 +152,6 @@
       'f(0);',
       findElement.topFunction('f'),
       'T Function<T>(T)',
-      null,
     );
     assertInvokeType(
       findNode.methodInvocation('f(0)'),
@@ -135,19 +159,30 @@
     );
   }
 
-  void _assertTearOff(
+  void _assertGenericFunctionInstantiation(
     String search,
     ExecutableElement element,
     String type,
     List<String>? typeArguments,
   ) {
-    var id = findNode.simple(search);
+    var id = findNode.functionReference(search);
     assertElement(id, element);
     assertType(id, type);
     if (typeArguments != null) {
-      assertElementTypes(id.tearOffTypeArgumentTypes, typeArguments);
+      assertElementTypes(id.typeArgumentTypes, typeArguments);
     } else {
-      expect(id.tearOffTypeArgumentTypes, isNull);
+      expect(id.typeArgumentTypes, isNull);
     }
   }
+
+  void _assertTearOff(
+    String search,
+    ExecutableElement element,
+    String type,
+  ) {
+    var id = findNode.simple(search);
+    assertElement(id, element);
+    assertType(id, type);
+    expect(id.tearOffTypeArgumentTypes, isNull);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
index 2de6c7e..a303efd 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
@@ -20,24 +20,14 @@
 class InvalidAssignment_ImplicitCallReferenceTest
     extends PubPackageResolutionTest {
   test_invalid_genericBoundedCall_nonGenericContext() async {
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode('''
 class C {
   T call<T extends num>(T t) => t;
 }
 
 String Function(String) f = C();
-''');
-  }
-
-  test_invalid_genericCall() async {
-    await assertErrorsInCode('''
-class C {
-  T call<T>(T t) => t;
-}
-
-void Function() f = C();
 ''', [
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 56, 3),
+      error(CompileTimeErrorCode.COULD_NOT_INFER, 76, 3),
     ]);
   }
 
@@ -57,6 +47,18 @@
     ]);
   }
 
+  test_invalid_genericCall_nonGenericContext() async {
+    await assertErrorsInCode('''
+class C {
+  T call<T>(T t) => t;
+}
+
+void Function() f = C();
+''', [
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 56, 3),
+    ]);
+  }
+
   test_invalid_genericCall_nonGenericContext_withoutConstructorTearoffs() async {
     await assertErrorsInCode('''
 // @dart=2.12
@@ -349,6 +351,20 @@
     ]);
   }
 
+  test_functionTearoff_genericInstantiation() async {
+    await assertNoErrorsInCode('''
+int Function() foo(int Function<T extends int>() f) {
+  return f;
+}
+''');
+
+    assertFunctionReference(
+      findNode.functionReference('f;'),
+      findElement.parameter('f'),
+      'int Function()',
+    );
+  }
+
   test_functionTearoff_inferredTypeArgs() async {
     await assertNoErrorsInCode('''
 void f<T>(T a) {}
@@ -524,6 +540,38 @@
     ]);
   }
 
+  test_functionInstantiation_topLevelVariable_genericContext_assignable() async {
+    await assertNoErrorsInCode('''
+T f<T>(T a) => a;
+U Function<U>(U) foo = f;
+''');
+  }
+
+  test_functionInstantiation_topLevelVariable_genericContext_nonAssignable() async {
+    await assertErrorsInCode('''
+T f<T>(T a) => a;
+U Function<U>(U, int) foo = f;
+''', [
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 46, 1),
+    ]);
+  }
+
+  test_functionInstantiation_topLevelVariable_nonGenericContext_assignable() async {
+    await assertNoErrorsInCode('''
+T f<T>(T a) => a;
+int Function(int) foo = f;
+''');
+  }
+
+  test_functionInstantiation_topLevelVariable_nonGenericContext_nonAssignable() async {
+    await assertErrorsInCode('''
+T f<T>(T a) => a;
+int Function(int, int) foo = f;
+''', [
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 47, 1),
+    ]);
+  }
+
   test_implicitlyImplementFunctionViaCall_1() async {
     // issue 18341
     //
@@ -983,6 +1031,20 @@
 @reflectiveTest
 class InvalidAssignmentWithoutNullSafetyTest extends PubPackageResolutionTest
     with InvalidAssignmentTestCases, WithoutNullSafetyMixin {
+  test_functionTearoff_genericInstantiation() async {
+    await assertNoErrorsInCode('''
+int Function() foo(int Function<T extends int>() f) {
+  return f;
+}
+''');
+
+    assertSimpleIdentifier(
+      findNode.simple('f;'),
+      element: findElement.parameter('f'),
+      type: 'int Function()',
+    );
+  }
+
   test_ifNullAssignment() async {
     await assertErrorsInCode('''
 void f(int i) {
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_implementation_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_implementation_override_test.dart
index d8c60f6..a4d4a40 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_implementation_override_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_implementation_override_test.dart
@@ -120,6 +120,26 @@
       error(CompileTimeErrorCode.INVALID_OVERRIDE, 94, 1),
     ]);
   }
+
+  test_method_covariant_inheritance_merge() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+class B extends A {}
+
+class C {
+  /// Not covariant-by-declaration here.
+  void foo(B b) {}
+}
+
+abstract class I {
+  /// Is covariant-by-declaration here.
+  void foo(covariant A a);
+}
+
+/// Is covariant-by-declaration here.
+class D extends C implements I {}
+''');
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
index 76204ef..8d45f28 100644
--- a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
@@ -23,6 +23,42 @@
 var v = const <String?>[null];
 ''');
   }
+
+  test_nonConst_genericFunction_genericContext() async {
+    await assertNoErrorsInCode('''
+List<U Function<U>(U)> foo(T Function<T>(T a) f) {
+  return [f];
+}
+''');
+  }
+
+  test_nonConst_genericFunction_genericContext_nonAssignable() async {
+    await assertErrorsInCode('''
+List<U Function<U>(U, int)> foo(T Function<T>(T a) f) {
+  return [f];
+}
+''', [
+      error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 66, 1),
+    ]);
+  }
+
+  test_nonConst_genericFunction_nonGenericContext() async {
+    await assertNoErrorsInCode('''
+List<int Function(int)> foo(T Function<T>(T a) f) {
+  return [f];
+}
+''');
+  }
+
+  test_nonConst_genericFunction_nonGenericContext_nonAssignable() async {
+    await assertErrorsInCode('''
+List<int Function(int, int)> foo(T Function<T>(T a) f) {
+  return [f];
+}
+''', [
+      error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 67, 1),
+    ]);
+  }
 }
 
 mixin ListElementTypeNotAssignableTestCases on PubPackageResolutionTest {
diff --git a/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
index 5f7f7cb..89bab3f 100644
--- a/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
@@ -258,6 +258,42 @@
 ''');
   }
 
+  test_function_sync_block_genericFunction__to_genericFunction() async {
+    await assertNoErrorsInCode('''
+U Function<U>(U) foo(T Function<T>(T a) f) {
+  return f;
+}
+''');
+  }
+
+  test_function_sync_block_genericFunction__to_genericFunction_notAssignable() async {
+    await assertErrorsInCode('''
+U Function<U>(U, int) foo(T Function<T>(T a) f) {
+  return f;
+}
+''', [
+      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 59, 1),
+    ]);
+  }
+
+  test_function_sync_block_genericFunction__to_nonGenericFunction() async {
+    await assertNoErrorsInCode('''
+int Function(int) foo(T Function<T>(T a) f) {
+  return f;
+}
+''');
+  }
+
+  test_function_sync_block_genericFunction__to_nonGenericFunction_notAssignable() async {
+    await assertErrorsInCode('''
+int Function(int, int) foo(T Function<T>(T a) f) {
+  return f;
+}
+''', [
+      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 60, 1),
+    ]);
+  }
+
   test_function_sync_block_int__to_num() async {
     await assertNoErrorsInCode(r'''
 num f(int a) {
@@ -352,6 +388,34 @@
 ''');
   }
 
+  test_function_sync_expression_genericFunction__to_genericFunction() async {
+    await assertNoErrorsInCode('''
+U Function<U>(U) foo(T Function<T>(T a) f) => f;
+''');
+  }
+
+  test_function_sync_expression_genericFunction__to_genericFunction_notAssignable() async {
+    await assertErrorsInCode('''
+U Function<U>(U, int) foo(T Function<T>(T a) f) => f;
+''', [
+      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 51, 1),
+    ]);
+  }
+
+  test_function_sync_expression_genericFunction__to_nonGenericFunction() async {
+    await assertNoErrorsInCode('''
+int Function(int) foo(T Function<T>(T a) f) => f;
+''');
+  }
+
+  test_function_sync_expression_genericFunction__to_nonGenericFunction_notAssignable() async {
+    await assertErrorsInCode('''
+int Function(int, int) foo(T Function<T>(T a) f) => f;
+''', [
+      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 52, 1),
+    ]);
+  }
+
   test_function_sync_expression_int__to_void() async {
     await assertNoErrorsInCode('''
 void f() => 42;
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 60a785c..25f182d 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -6526,6 +6526,41 @@
 ''');
   }
 
+  test_const_functionExpression_typeArgumentTypes() async {
+    var library = await checkLibrary('''
+void f<T>(T a) {}
+
+const void Function(int) v = f;
+''');
+    checkElementText(library, '''
+library
+  definingUnit
+    topLevelVariables
+      static const v @44
+        type: void Function(int)
+        constantInitializer
+          FunctionReference
+            function: SimpleIdentifier
+              staticElement: self::@function::f
+              staticType: void Function<T>(T)
+              token: f @48
+            staticType: void Function(int)
+            typeArgumentTypes
+              int
+    accessors
+      synthetic static get v @-1
+        returnType: void Function(int)
+    functions
+      f @5
+        typeParameters
+          covariant T @7
+        parameters
+          requiredPositional a @12
+            type: T
+        returnType: void
+''');
+  }
+
   test_const_functionReference() async {
     var library = await checkLibrary(r'''
 void f<T>(T a) {}
@@ -10475,39 +10510,6 @@
 ''');
   }
 
-  test_const_simpleIdentifier_tearOffTypeArgumentTypes() async {
-    var library = await checkLibrary(r'''
-void f<T>(T a) {}
-
-const void Function(int) v = f;
-''');
-    checkElementText(library, r'''
-library
-  definingUnit
-    topLevelVariables
-      static const v @44
-        type: void Function(int)
-        constantInitializer
-          SimpleIdentifier
-            staticElement: self::@function::f
-            staticType: void Function(int)
-            tearOffTypeArgumentTypes
-              int
-            token: f @48
-    accessors
-      synthetic static get v @-1
-        returnType: void Function(int)
-    functions
-      f @5
-        typeParameters
-          covariant T @7
-        parameters
-          requiredPositional a @12
-            type: T
-        returnType: void
-''');
-  }
-
   test_const_topLevel_binary() async {
     var library = await checkLibrary(r'''
 const vEqual = 1 == 2;
@@ -14065,12 +14067,14 @@
                   aliasArguments
                     dynamic
                 constantInitializer
-                  SimpleIdentifier
-                    staticElement: self::@function::defaultF
+                  FunctionReference
+                    function: SimpleIdentifier
+                      staticElement: self::@function::defaultF
+                      staticType: void Function<T>(T)
+                      token: defaultF @93
                     staticType: void Function(dynamic)
-                    tearOffTypeArgumentTypes
+                    typeArgumentTypes
                       dynamic
-                    token: defaultF @93
         accessors
           synthetic get f @-1
             returnType: void Function(dynamic)
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index ad1c27b..bbee8a4 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -9,6 +9,7 @@
 # NOTE: `pub get / pub upgrade` are generally not needed when working on this
 # package. The `.packages` file in the repository root will be used by default.
 dependencies:
+  _fe_analyzer_shared: any
   # Published packages - repo version ensured via dependency_overrides
   collection: any
   crypto: any
@@ -20,8 +21,6 @@
     path: ../kernel
 
   # Unpublished packages that can be used via path dependency
-  _fe_analyzer_shared:
-    path: ../_fe_analyzer_shared
   _js_interop_checks:
     path: ../_js_interop_checks
   js_ast:
diff --git a/pkg/dartdev/pubspec.yaml b/pkg/dartdev/pubspec.yaml
index 9fbdb4b..0145fab 100644
--- a/pkg/dartdev/pubspec.yaml
+++ b/pkg/dartdev/pubspec.yaml
@@ -34,6 +34,8 @@
   usage: any
 
 dev_dependencies:
+  expect:
+    path: ../expect
   lints: any
   pub_semver: any
   test: any
diff --git a/pkg/dartdev/test/regress_46364_test.dart b/pkg/dartdev/test/regress_46364_test.dart
new file mode 100644
index 0000000..09edc21
--- /dev/null
+++ b/pkg/dartdev/test/regress_46364_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+import 'package:path/path.dart' as p;
+
+// Copied from package:io
+Future<void> copyPath(String from, String to) async {
+  await Directory(to).create(recursive: true);
+  await for (final file in Directory(from).list(recursive: true)) {
+    final copyTo = p.join(to, p.relative(file.path, from: from));
+    if (file is Directory) {
+      await Directory(copyTo).create(recursive: true);
+    } else if (file is File) {
+      await File(file.path).copy(copyTo);
+    } else if (file is Link) {
+      await Link(copyTo).create(await file.target(), recursive: true);
+    }
+  }
+}
+
+Future<void> main() async {
+  final exePath = Platform.resolvedExecutable;
+  final sdkDir = p.dirname(p.dirname(exePath));
+  // Try to run the VM located on a path with % encoded characters. The VM
+  // should not try and resolve the path as a URI for SDK artifacts (e.g.,
+  // dartdev.dart.snapshot).
+  final d = Directory.systemTemp.createTempSync('dart_symlink%3A');
+  try {
+    await copyPath(sdkDir, d.path);
+    final path = '${d.path}/bin/dart';
+    final result = await Process.run(path, ['help']);
+    Expect.equals(result.exitCode, 0);
+  } finally {
+    await d.delete(recursive: true);
+  }
+}
diff --git a/pkg/dev_compiler/analysis_options.yaml b/pkg/dev_compiler/analysis_options.yaml
index 4c72ad8..c1925c0 100644
--- a/pkg/dev_compiler/analysis_options.yaml
+++ b/pkg/dev_compiler/analysis_options.yaml
@@ -1,10 +1,15 @@
-include: package:pedantic/analysis_options.1.11.0.yaml
+include: package:lints/recommended.yaml
 
 analyzer:
   strong-mode:
     implicit-casts: false
   errors:
     todo: ignore
+    avoid_function_literals_in_foreach_calls: ignore
+    avoid_renaming_method_parameters: ignore
+    constant_identifier_names: ignore
+    implementation_imports: ignore
+    prefer_void_to_null: ignore
   exclude:
     - doc/api/**
     - gen/**
@@ -15,7 +20,10 @@
 
 linter:
   rules:
-    # Not enforced by pedantic at any version.
+    # Not enforced by lints at any version.
+    - always_declare_return_types
     - directives_ordering
-    - prefer_null_aware_operators
-    - prefer_typing_uninitialized_variables
+    - omit_local_variable_types
+    - prefer_single_quotes
+    - prefer_relative_imports
+    - unawaited_futures
diff --git a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
index d9ff9c1..06d5941 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
@@ -322,9 +322,7 @@
   /// Compute fresh IDs to avoid
   static int _uniqueId = 0;
 
-  MetaLetVariable(String displayName)
-      : displayName = displayName,
-        super(displayName + '@${++_uniqueId}');
+  MetaLetVariable(this.displayName) : super(displayName + '@${++_uniqueId}');
 }
 
 class _VariableUseCounter extends BaseVisitor<void> {
diff --git a/pkg/dev_compiler/lib/src/compiler/module_builder.dart b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
index 922b17f..9761f01 100644
--- a/pkg/dev_compiler/lib/src/compiler/module_builder.dart
+++ b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
@@ -5,11 +5,11 @@
 // @dart = 2.9
 
 import 'package:args/args.dart' show ArgParser, ArgResults;
-import 'package:dev_compiler/src/compiler/shared_compiler.dart';
 import 'package:path/path.dart' as p;
 
 import '../js_ast/js_ast.dart';
 import 'js_names.dart';
+import 'shared_compiler.dart';
 
 /// The module format to emit.
 enum ModuleFormat {
diff --git a/pkg/dev_compiler/lib/src/compiler/module_containers.dart b/pkg/dev_compiler/lib/src/compiler/module_containers.dart
index 0040d60..a669e71 100644
--- a/pkg/dev_compiler/lib/src/compiler/module_containers.dart
+++ b/pkg/dev_compiler/lib/src/compiler/module_containers.dart
@@ -9,7 +9,7 @@
 import '../js_ast/js_ast.dart' show js;
 
 /// Defines how to emit a value of a table
-typedef _emitValue<K> = js_ast.Expression Function(K, ModuleItemData);
+typedef _EmitValue<K> = js_ast.Expression Function(K, ModuleItemData);
 
 /// Represents a top-level property hoisted to a top-level object.
 class ModuleItemData {
@@ -125,7 +125,7 @@
   /// necessary.
   ///
   /// Uses [emitValue] to emit the values in the table.
-  List<js_ast.Statement> emit({_emitValue<K> emitValue});
+  List<js_ast.Statement> emit({_EmitValue<K> emitValue});
 }
 
 /// Associates a [K] with a container-unique JS key and arbitrary JS value.
@@ -184,7 +184,7 @@
   }
 
   @override
-  List<js_ast.Statement> emit({_emitValue<K> emitValue}) {
+  List<js_ast.Statement> emit({_EmitValue<K> emitValue}) {
     var containersToProperties = <js_ast.Identifier, List<js_ast.Property>>{};
     moduleItems.forEach((k, v) {
       if (!incrementalMode && _noEmit.contains(k)) return;
@@ -240,7 +240,7 @@
   }
 
   @override
-  List<js_ast.Statement> emit({_emitValue<K> emitValue}) {
+  List<js_ast.Statement> emit({_EmitValue<K> emitValue}) {
     var properties = List<js_ast.Expression>.filled(length, null);
 
     // If the entire array holds just one value, generate a short initializer.
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index 3a60942..ee52937 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -28,7 +28,7 @@
 
   /// Holds all top-level JS symbols (used for caching or indexing fields).
   final _symbolContainer = ModuleItemContainer<js_ast.Identifier>.asObject('S',
-      keyToString: (js_ast.Identifier i) => '${i.name}');
+      keyToString: (js_ast.Identifier i) => i.name);
 
   ModuleItemContainer<js_ast.Identifier> get symbolContainer =>
       _symbolContainer;
diff --git a/pkg/dev_compiler/lib/src/js_ast/builder.dart b/pkg/dev_compiler/lib/src/js_ast/builder.dart
index 0e0077a..1621087 100644
--- a/pkg/dev_compiler/lib/src/js_ast/builder.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/builder.dart
@@ -4,9 +4,10 @@
 
 // @dart = 2.9
 
-// ignore_for_file: slash_for_doc_comments, unnecessary_new
 // ignore_for_file: always_declare_return_types, prefer_single_quotes
+// ignore_for_file: non_constant_identifier_names
 // ignore_for_file: prefer_collection_literals, omit_local_variable_types
+// ignore_for_file: slash_for_doc_comments, unnecessary_new
 // ignore_for_file: unnecessary_brace_in_string_interps
 
 // Utilities for building JS ASTs at runtime.  Contains a builder class
diff --git a/pkg/dev_compiler/lib/src/js_ast/nodes.dart b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
index d721e6e..8618c7e 100644
--- a/pkg/dev_compiler/lib/src/js_ast/nodes.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
@@ -4,10 +4,11 @@
 
 // @dart = 2.9
 
-// ignore_for_file: slash_for_doc_comments, prefer_single_quotes
 // ignore_for_file: always_declare_return_types, prefer_final_fields
 // ignore_for_file: always_require_non_null_named_parameters
 // ignore_for_file: omit_local_variable_types, unnecessary_this
+// ignore_for_file: prefer_initializing_formals
+// ignore_for_file: slash_for_doc_comments, prefer_single_quotes
 
 part of js_ast;
 
diff --git a/pkg/dev_compiler/lib/src/js_ast/printer.dart b/pkg/dev_compiler/lib/src/js_ast/printer.dart
index c6d7581..ff54cdb 100644
--- a/pkg/dev_compiler/lib/src/js_ast/printer.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/printer.dart
@@ -4,10 +4,11 @@
 
 // @dart = 2.9
 
-// ignore_for_file: slash_for_doc_comments, unnecessary_const
 // ignore_for_file: always_declare_return_types, prefer_single_quotes
 // ignore_for_file: prefer_collection_literals, omit_local_variable_types
 // ignore_for_file: prefer_final_fields
+// ignore_for_file: prefer_initializing_formals
+// ignore_for_file: slash_for_doc_comments, unnecessary_const
 // ignore_for_file: use_function_type_syntax_for_parameters
 
 part of js_ast;
diff --git a/pkg/dev_compiler/lib/src/js_ast/template.dart b/pkg/dev_compiler/lib/src/js_ast/template.dart
index d421d6a..bcba9f0 100644
--- a/pkg/dev_compiler/lib/src/js_ast/template.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/template.dart
@@ -4,9 +4,10 @@
 
 // @dart = 2.9
 
-// ignore_for_file: slash_for_doc_comments, omit_local_variable_types
 // ignore_for_file: always_declare_return_types, prefer_collection_literals
+// ignore_for_file: avoid_returning_null_for_void
 // ignore_for_file: prefer_single_quotes, prefer_generic_function_type_aliases
+// ignore_for_file: slash_for_doc_comments, omit_local_variable_types
 // ignore_for_file: unnecessary_this
 
 part of js_ast;
diff --git a/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart b/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart
index 54fd3b5..a293c28 100644
--- a/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart
+++ b/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart
@@ -9,9 +9,9 @@
 import 'dart:io';
 
 import 'package:async/async.dart';
-import 'package:dev_compiler/src/kernel/retry_timeout_client.dart';
 import 'package:front_end/src/api_prototype/file_system.dart';
-import 'package:pedantic/pedantic.dart';
+
+import 'retry_timeout_client.dart';
 
 /// A wrapper around asset server that redirects file read requests
 /// to http get requests to the asset server.
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index ed6fa697..ba81acf 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -2278,11 +2278,12 @@
 
       // Helper functions to test if a constructor invocation is internal and
       // should be eagerly evaluated.
-      var isInternalConstructor = (ConstructorInvocation node) {
+      bool isInternalConstructor(ConstructorInvocation node) {
         var type = node.getStaticType(_staticTypeContext) as InterfaceType;
         var library = type.classNode.enclosingLibrary;
         return isSdkInternalRuntime(library);
-      };
+      }
+
       for (var field in fields) {
         _staticTypeContext.enterMember(field);
         var init = field.initializer;
@@ -2824,9 +2825,9 @@
       // type arguments are applied.
       if (type.typeParameters.isNotEmpty) return true;
 
-      return (_canEmitTypeAtTopLevel(type.returnType) &&
+      return _canEmitTypeAtTopLevel(type.returnType) &&
           type.positionalParameters.every(_canEmitTypeAtTopLevel) &&
-          type.namedParameters.every((n) => _canEmitTypeAtTopLevel(n.type)));
+          type.namedParameters.every((n) => _canEmitTypeAtTopLevel(n.type));
     }
     if (type is TypedefType) {
       return type.typeArguments.every(_canEmitTypeAtTopLevel);
@@ -3667,6 +3668,7 @@
             _cacheUri(location?.file?.toString()),
             js.number(location?.line ?? -1),
             js.number(location?.column ?? -1),
+            // ignore: unnecessary_string_interpolations
             js.escapedString('${p.name}')
           ])
         ]);
@@ -5082,10 +5084,10 @@
       if (parent.name.text == '&' && parent.arguments.positional.length == 1) {
         var left = getInvocationReceiver(parent);
         var right = parent.arguments.positional[0];
-        final MAX = (1 << width) - 1;
+        final max = (1 << width) - 1;
         if (left != null) {
-          if (_asIntInRange(right, 0, MAX) != null) return true;
-          if (_asIntInRange(left, 0, MAX) != null) return true;
+          if (_asIntInRange(right, 0, max) != null) return true;
+          if (_asIntInRange(left, 0, max) != null) return true;
         }
       }
       return _parentMasksToWidth(parent, width);
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
index 0a1e1c2..4e2cd32 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
@@ -10,10 +10,6 @@
     show Code, Message, PlainAndColorizedString;
 import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
     show DiagnosticMessage, DiagnosticMessageHandler;
-import 'package:dev_compiler/dev_compiler.dart';
-import 'package:dev_compiler/src/compiler/js_names.dart' as js_ast;
-import 'package:dev_compiler/src/compiler/module_builder.dart';
-import 'package:dev_compiler/src/js_ast/js_ast.dart' as js_ast;
 import 'package:front_end/src/api_unstable/ddc.dart';
 import 'package:kernel/ast.dart'
     show
@@ -36,6 +32,11 @@
         VisitorNullMixin,
         VisitorVoidMixin;
 
+import '../../dev_compiler.dart';
+import '../compiler/js_names.dart' as js_ast;
+import '../compiler/module_builder.dart';
+import '../js_ast/js_ast.dart' as js_ast;
+
 DiagnosticMessage _createInternalError(Uri uri, int line, int col, String msg) {
   return Message(Code<String>('Expression Compiler Internal error'),
           problemMessage: msg)
@@ -453,7 +454,7 @@
 
     var imports = <js_ast.ModuleItem>[];
     var jsFun = _kernel2jsCompiler.emitFunctionIncremental(imports,
-        scope.library, scope.cls, procedure.function, '$debugProcedureName');
+        scope.library, scope.cls, procedure.function, debugProcedureName);
 
     _log('Generated JavaScript for expression');
 
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
index 6f11aa6..1068a8a 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
@@ -11,9 +11,6 @@
 
 import 'package:args/args.dart';
 import 'package:build_integration/file_system/multi_root.dart';
-import 'package:dev_compiler/dev_compiler.dart';
-import 'package:dev_compiler/src/kernel/target.dart'
-    show sdkLibraryEnvironmentDefines;
 import 'package:front_end/src/api_prototype/file_system.dart';
 import 'package:front_end/src/api_unstable/ddc.dart';
 import 'package:kernel/ast.dart' show Component, Library;
@@ -24,9 +21,11 @@
 import 'package:kernel/target/targets.dart' show TargetFlags;
 import 'package:meta/meta.dart';
 
+import '../../dev_compiler.dart';
 import '../compiler/js_names.dart';
 import 'asset_file_system.dart';
 import 'command.dart';
+import 'target.dart' show sdkLibraryEnvironmentDefines;
 
 /// The service that handles expression compilation requests from
 /// the debugger.
diff --git a/pkg/dev_compiler/lib/src/kernel/module_metadata.dart b/pkg/dev_compiler/lib/src/kernel/module_metadata.dart
index 416f0d8..0ed050a 100644
--- a/pkg/dev_compiler/lib/src/kernel/module_metadata.dart
+++ b/pkg/dev_compiler/lib/src/kernel/module_metadata.dart
@@ -144,10 +144,10 @@
     if (!libraries.containsKey(library.importUri)) {
       libraries[library.importUri] = library;
     } else {
-      throw ('Metadata creation error: '
+      throw 'Metadata creation error: '
           'Cannot add library $library with uri ${library.importUri}: '
           'another library "${libraries[library.importUri]}" is found '
-          'with the same uri');
+          'with the same uri';
     }
   }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart b/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart
index dfaa3d9..ce67906 100644
--- a/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart
+++ b/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart
@@ -8,8 +8,6 @@
 import 'dart:io';
 import 'dart:math';
 
-import 'package:pedantic/pedantic.dart';
-
 /// An HTTP client wrapper that times out connections and requests and
 /// automatically retries failing requests.
 class RetryTimeoutClient {
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
index e0271f3..f8e49e9 100644
--- a/pkg/dev_compiler/pubspec.yaml
+++ b/pkg/dev_compiler/pubspec.yaml
@@ -6,8 +6,7 @@
   sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
-  _fe_analyzer_shared:
-    path: ../_fe_analyzer_shared
+  _fe_analyzer_shared: any
   _js_interop_checks:
     path: ../_js_interop_checks
   args: any
@@ -21,10 +20,8 @@
     path: ../front_end
   kernel:
     path: ../kernel
-  meta:
-    path: ../meta
+  meta: any
   path: any
-  pedantic: ^1.11.0
   source_maps: any
   source_span: any
 
@@ -32,18 +29,16 @@
   browser_launcher: ^1.0.0
   expect:
     path: ../expect
-  http_multi_server:
-    path: ../../third_party/pkg/http_multi_server
-  js:
-    path: ../js
+  http_multi_server: any
+  js: any
+  lints: ^1.0.0
   modular_test:
     path: ../modular_test
   package_config: any
   sourcemap_testing:
     path: ../sourcemap_testing
   stack_trace: any
-  shelf:
-    path: ../../third_party/pkg/shelf
+  shelf: any
   test: any
   testing:
     path: ../testing
@@ -51,3 +46,14 @@
     path: ../vm
   webkit_inspection_protocol: ^1.0.0
 
+dependency_overrides:
+  _fe_analyzer_shared:
+    path: ../_fe_analyzer_shared
+  js:
+    path: ../js
+  meta:
+    path: ../meta
+  shelf:
+    path: ../../third_party/pkg/shelf
+  http_multi_server:
+    path: ../../third_party/pkg/http_multi_server
diff --git a/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart b/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart
index ca481dc..77b6904 100644
--- a/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart
@@ -208,17 +208,17 @@
         () async {
       var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
 
-      var elapsedReadAsString = () async {
+      Future<int> elapsedReadAsString() async {
         var stopwatch = Stopwatch()..start();
         await expectLater(entity.readAsString(), isNotNull);
         return stopwatch.elapsedMilliseconds;
-      };
+      }
 
-      var elapsedReadAsBytesAndDecode = () async {
+      Future<int> elapsedReadAsBytesAndDecode() async {
         var stopwatch = Stopwatch()..start();
         await expectLater(utf8.decode(await entity.readAsBytes()), isNotNull);
         return stopwatch.elapsedMilliseconds;
-      };
+      }
 
       await expectLater(await elapsedReadAsString(),
           lessThan(await elapsedReadAsBytesAndDecode()));
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
index c121403..7eaac57 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
@@ -520,7 +520,7 @@
       await driver.check(
           breakpointId: 'bp',
           expression: 'typo',
-          expectedError: "Undefined name \'typo\'");
+          expectedError: "Undefined name 'typo'");
     });
 
     test('local', () async {
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart
index 8e8f1bf..bc5786d 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart
@@ -120,7 +120,7 @@
     var component = await compiler.computeDelta();
     component.computeCanonicalNames();
     // Initialize DDC.
-    var moduleName = '${p.basenameWithoutExtension(output.toFilePath())}';
+    var moduleName = p.basenameWithoutExtension(output.toFilePath());
 
     var classHierarchy = compiler.getClassHierarchy();
     var compilerOptions = SharedCompilerOptions(
@@ -157,7 +157,7 @@
     var codeBytes = utf8.encode(code.code);
     var sourceMapBytes = utf8.encode(json.encode(code.sourceMap));
 
-    File('${output.toFilePath()}').writeAsBytesSync(codeBytes);
+    File(output.toFilePath()).writeAsBytesSync(codeBytes);
     File('${output.toFilePath()}.map').writeAsBytesSync(sourceMapBytes);
 
     // Save the expression evaluator for future evaluations.
@@ -438,7 +438,7 @@
 
     final scriptController = StreamController<wip.ScriptParsedEvent>();
     var scriptSub = debugger.onScriptParsed.listen((event) {
-      if ('${event.script.url}' == '$output') {
+      if (event.script.url == '$output') {
         scriptController.add(event);
       }
     });
@@ -569,7 +569,7 @@
       var response = await connection.runtime
           .getProperties(scope.object, ownProperties: true);
       for (var prop in response) {
-        var propKey = '${prop.name}';
+        var propKey = prop.name;
         var propValue = '${prop.value.value}';
         if (prop.value.type == 'string') {
           propValue = "'$propValue'";
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
index 4a98206..66db5dd 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
@@ -218,7 +218,7 @@
   String _normalize(String text) {
     return text
         .replaceAll(RegExp('\'.*foo.dart\''), '\'foo.dart\'')
-        .replaceAll(RegExp('\".*foo.dart\"'), '\'foo.dart\'');
+        .replaceAll(RegExp('".*foo.dart"'), '\'foo.dart\'');
   }
 
   Matcher _matches(String text) {
@@ -281,7 +281,7 @@
                 expression: 'Directory.systemTemp',
                 expectedResult: '''
             (function() {
-              const dart_sdk = ${options.loadModule}(\'dart_sdk\');
+              const dart_sdk = ${options.loadModule}('dart_sdk');
               const io = dart_sdk.io;
               return io.Directory.systemTemp;
             }(
@@ -296,7 +296,7 @@
                 expression: 'p.Directory.systemTemp',
                 expectedResult: '''
             (function() {
-              const dart_sdk = ${options.loadModule}(\'dart_sdk\');
+              const dart_sdk = ${options.loadModule}('dart_sdk');
               const io = dart_sdk.io;
               return io.Directory.systemTemp;
             }(
@@ -313,7 +313,7 @@
                 expression: 'p.utf8.decoder',
                 expectedResult: '''
             (function() {
-              const dart_sdk = ${options.loadModule}(\'dart_sdk\');
+              const dart_sdk = ${options.loadModule}('dart_sdk');
               const convert = dart_sdk.convert;
               return convert.utf8.decoder;
             }(
@@ -543,7 +543,7 @@
                 expression: 'Directory.systemTemp',
                 expectedResult: '''
             (function() {
-              const dart_sdk = ${options.loadModule}(\'dart_sdk\');
+              const dart_sdk = ${options.loadModule}('dart_sdk');
               const io = dart_sdk.io;
               return io.Directory.systemTemp;
             }(
@@ -558,7 +558,7 @@
                 expression: 'p.Directory.systemTemp',
                 expectedResult: '''
             (function() {
-              const dart_sdk = ${options.loadModule}(\'dart_sdk\');
+              const dart_sdk = ${options.loadModule}('dart_sdk');
               const io = dart_sdk.io;
               return io.Directory.systemTemp;
             }(
@@ -575,7 +575,7 @@
                 expression: 'p.utf8.decoder',
                 expectedResult: '''
             (function() {
-              const dart_sdk = ${options.loadModule}(\'dart_sdk\');
+              const dart_sdk = ${options.loadModule}('dart_sdk');
               const convert = dart_sdk.convert;
               return convert.utf8.decoder;
             }(
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_shared.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_shared.dart
index cd8a9ef..a1631cf 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_shared.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_shared.dart
@@ -19,7 +19,6 @@
 import 'package:front_end/src/compute_platform_binaries_location.dart';
 import 'package:http_multi_server/http_multi_server.dart';
 import 'package:path/path.dart' as p;
-import 'package:pedantic/pedantic.dart';
 import 'package:shelf/shelf.dart';
 import 'package:shelf/shelf_io.dart';
 import 'package:test/test.dart';
@@ -1008,7 +1007,7 @@
       if (config.soundNullSafety) '--sound-null-safety',
       if (!config.soundNullSafety) '--no-sound-null-safety',
       '--modules',
-      '${config.moduleFormat}',
+      config.moduleFormat,
     ];
 
     var exitCode = await runProcess(dart, args, config.rootPath);
@@ -1037,7 +1036,7 @@
       if (config.soundNullSafety) '--sound-null-safety',
       if (!config.soundNullSafety) '--no-sound-null-safety',
       '--modules',
-      '${config.moduleFormat}',
+      config.moduleFormat,
     ];
 
     exitCode = await runProcess(dart, args, config.rootPath);
@@ -1069,7 +1068,7 @@
       if (config.soundNullSafety) '--sound-null-safety',
       if (!config.soundNullSafety) '--no-sound-null-safety',
       '--modules',
-      '${config.moduleFormat}',
+      config.moduleFormat,
     ];
 
     exitCode = await runProcess(dart, args, config.rootPath);
@@ -1104,7 +1103,7 @@
       if (config.soundNullSafety) '--sound-null-safety',
       if (!config.soundNullSafety) '--no-sound-null-safety',
       '--modules',
-      '${config.moduleFormat}',
+      config.moduleFormat,
     ];
 
     return await runProcess(dart, args, config.rootPath);
diff --git a/pkg/dev_compiler/test/modular_suite.dart b/pkg/dev_compiler/test/modular_suite.dart
index fde41a3..77ee34f 100644
--- a/pkg/dev_compiler/test/modular_suite.dart
+++ b/pkg/dev_compiler/test/modular_suite.dart
@@ -128,11 +128,11 @@
         '${toUri(sdkModule, dillId)}',
         '--exclude-non-sources',
       ],
-      ...(transitiveDependencies
+      ...transitiveDependencies
           .where((m) => !m.isSdk)
-          .expand((m) => ['--input-summary', '${toUri(m, dillId)}'])),
-      ...(sources.expand((String uri) => ['--source', uri])),
-      ...(flags.expand((String flag) => ['--enable-experiment', flag])),
+          .expand((m) => ['--input-summary', '${toUri(m, dillId)}']),
+      ...sources.expand((String uri) => ['--source', uri]),
+      ...flags.expand((String flag) => ['--enable-experiment', flag]),
     ];
 
     var result =
@@ -211,9 +211,9 @@
       ...sources,
       ...extraArgs,
       for (String flag in flags) '--enable-experiment=$flag',
-      ...(transitiveDependencies
+      ...transitiveDependencies
           .where((m) => !m.isSdk)
-          .expand((m) => ['-s', '${toUri(m, dillId)}=${m.name}'])),
+          .expand((m) => ['-s', '${toUri(m, dillId)}=${m.name}']),
       '-o',
       '$output',
     ];
diff --git a/pkg/dev_compiler/test/modular_suite_nnbd.dart b/pkg/dev_compiler/test/modular_suite_nnbd.dart
index e00e185..2cba274 100644
--- a/pkg/dev_compiler/test/modular_suite_nnbd.dart
+++ b/pkg/dev_compiler/test/modular_suite_nnbd.dart
@@ -126,15 +126,15 @@
         '${toUri(sdkModule, dillId)}',
         '--exclude-non-sources',
       ],
-      ...(transitiveDependencies
+      ...transitiveDependencies
           .where((m) => !m.isSdk)
-          .expand((m) => ['--input-summary', '${toUri(m, dillId)}'])),
-      ...(sources.expand((String uri) => ['--source', uri])),
+          .expand((m) => ['--input-summary', '${toUri(m, dillId)}']),
+      ...sources.expand((String uri) => ['--source', uri]),
       // TODO(40266) After unfork of dart:_runtime only need experiment when
       // compiling SDK. For now always use the Null Safety experiment.
       '--enable-experiment',
       'non-nullable',
-      ...(flags.expand((String flag) => ['--enable-experiment', flag])),
+      ...flags.expand((String flag) => ['--enable-experiment', flag]),
     ];
 
     var result =
@@ -215,9 +215,9 @@
       '--enable-experiment',
       'non-nullable',
       for (String flag in flags) '--enable-experiment=$flag',
-      ...(transitiveDependencies
+      ...transitiveDependencies
           .where((m) => !m.isSdk)
-          .expand((m) => ['-s', '${toUri(m, dillId)}=${m.name}'])),
+          .expand((m) => ['-s', '${toUri(m, dillId)}=${m.name}']),
       '-o',
       '$output',
     ];
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index da8d7c6..901ca21 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -530,7 +530,7 @@
 /// Given the Dart [code], expects all the expressions inferred to be not-null.
 Future expectAllNotNull(String code) async {
   code = '// @dart = 2.9\n$code';
-  var result = (await kernelCompile(code));
+  var result = await kernelCompile(code);
   result.component.accept(ExpectAllNotNull(result.librariesFromDill));
 }
 
diff --git a/pkg/dev_compiler/test/sourcemap/testfiles/multiple_debugger_calls.dart b/pkg/dev_compiler/test/sourcemap/testfiles/multiple_debugger_calls.dart
index f976b63..7ce45b4 100644
--- a/pkg/dev_compiler/test/sourcemap/testfiles/multiple_debugger_calls.dart
+++ b/pkg/dev_compiler/test/sourcemap/testfiles/multiple_debugger_calls.dart
@@ -30,4 +30,4 @@
   foo(/*s:8*/ debugger());
 }
 
-void foo(bool _) => null;
+void foo(bool _) {}
diff --git a/pkg/dev_compiler/test/worker/worker_test.dart b/pkg/dev_compiler/test/worker/worker_test.dart
index b03c32f..84111ba 100644
--- a/pkg/dev_compiler/test/worker/worker_test.dart
+++ b/pkg/dev_compiler/test/worker/worker_test.dart
@@ -378,7 +378,7 @@
 }
 
 Future<WorkResponse> _readResponse(MessageGrouper messageGrouper) async {
-  var buffer = (await messageGrouper.next) as List<int>;
+  var buffer = await messageGrouper.next as List<int>;
   try {
     return WorkResponse.fromBuffer(buffer);
   } catch (_) {
diff --git a/pkg/expect/pubspec.yaml b/pkg/expect/pubspec.yaml
index f84f8c9..70c2817 100644
--- a/pkg/expect/pubspec.yaml
+++ b/pkg/expect/pubspec.yaml
@@ -12,5 +12,8 @@
   sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
-  meta:
-    path: ../meta
+  meta: any
+
+dependency_overrides:
+ meta:
+  path: ../meta
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index c71dda4..1031699 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -37,6 +37,7 @@
 import '../source/source_class_builder.dart';
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 import '../type_inference/type_schema.dart';
+import '../type_inference/type_inferrer.dart';
 import '../util/helpers.dart' show DelayedActionPerformer;
 
 import 'builder.dart';
@@ -68,8 +69,8 @@
   void injectInvalidInitializer(Message message, int charOffset, int length,
       ExpressionGeneratorHelper helper);
 
-  void addInitializer(
-      Initializer initializer, ExpressionGeneratorHelper helper);
+  void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
+      {required InitializerInferenceResult? inferenceResult});
 
   void prepareInitializers();
 
@@ -328,8 +329,8 @@
   }
 
   @override
-  void addInitializer(
-      Initializer initializer, ExpressionGeneratorHelper helper) {
+  void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
+      {required InitializerInferenceResult? inferenceResult}) {
     List<Initializer> initializers = _constructor.initializers;
     if (initializer is SuperInitializer) {
       if (superInitializer != null) {
@@ -342,6 +343,7 @@
             "super".length,
             helper);
       } else {
+        inferenceResult?.applyResult(initializers, _constructor);
         initializers.add(initializer..parent = _constructor);
         superInitializer = initializer;
       }
@@ -373,9 +375,11 @@
           error.parent = _constructor;
           initializers[i] = error;
         }
+        inferenceResult?.applyResult(initializers, _constructor);
         initializers.add(initializer..parent = _constructor);
         redirectingInitializer = initializer;
       } else {
+        inferenceResult?.applyResult(initializers, _constructor);
         initializers.add(initializer..parent = _constructor);
         redirectingInitializer = initializer;
       }
@@ -391,6 +395,7 @@
       injectInvalidInitializer(messageSuperInitializerNotLast,
           initializer.fileOffset, noLength, helper);
     } else {
+      inferenceResult?.applyResult(initializers, _constructor);
       initializers.add(initializer..parent = _constructor);
     }
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index b13e27c..6f08b8b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -112,7 +112,7 @@
 import '../source/value_kinds.dart';
 
 import '../type_inference/type_inferrer.dart'
-    show TypeInferrer, InferredFunctionBody;
+    show TypeInferrer, InferredFunctionBody, InitializerInferenceResult;
 import '../type_inference/type_schema.dart' show UnknownType;
 
 import '../util/helpers.dart' show DelayedActionPerformer;
@@ -960,7 +960,7 @@
                   formal: formal);
             }
             for (Initializer initializer in initializers) {
-              member.addInitializer(initializer, this);
+              member.addInitializer(initializer, this, inferenceResult: null);
             }
           }
         }
@@ -1648,12 +1648,16 @@
       }
     }
     if (_initializers != null) {
+      Map<Initializer, InitializerInferenceResult> inferenceResults =
+          <Initializer, InitializerInferenceResult>{};
       for (Initializer initializer in _initializers!) {
-        typeInferrer.inferInitializer(this, initializer);
+        inferenceResults[initializer] =
+            typeInferrer.inferInitializer(this, initializer);
       }
       if (!builder.isExternal) {
         for (Initializer initializer in _initializers!) {
-          builder.addInitializer(initializer, this);
+          builder.addInitializer(initializer, this,
+              inferenceResult: inferenceResults[initializer]!);
         }
       }
     }
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 57f6519..87a0d06 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -42,7 +42,7 @@
     implements
         ExpressionVisitor1<ExpressionInferenceResult, DartType>,
         StatementVisitor<StatementInferenceResult>,
-        InitializerVisitor<void> {
+        InitializerVisitor<InitializerInferenceResult> {
   final TypeInferrerImpl inferrer;
 
   Class? mapEntryClass;
@@ -326,23 +326,23 @@
     return _unhandledStatement(node);
   }
 
-  void _unhandledInitializer(Initializer node) {
+  Never _unhandledInitializer(Initializer node) {
     unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
         node.location!.file);
   }
 
   @override
-  void defaultInitializer(Initializer node) {
+  InitializerInferenceResult defaultInitializer(Initializer node) {
     _unhandledInitializer(node);
   }
 
   @override
-  void visitInvalidInitializer(InvalidInitializer node) {
+  InitializerInferenceResult visitInvalidInitializer(InvalidInitializer node) {
     _unhandledInitializer(node);
   }
 
   @override
-  void visitLocalInitializer(LocalInitializer node) {
+  InitializerInferenceResult visitLocalInitializer(LocalInitializer node) {
     _unhandledInitializer(node);
   }
 
@@ -488,11 +488,12 @@
   }
 
   @override
-  void visitAssertInitializer(AssertInitializer node) {
+  InitializerInferenceResult visitAssertInitializer(AssertInitializer node) {
     StatementInferenceResult result = inferrer.inferStatement(node.statement);
     if (result.hasChanged) {
       node.statement = (result.statement as AssertStatement)..parent = node;
     }
+    return const SuccessfulInitializerInferenceResult();
   }
 
   @override
@@ -1059,13 +1060,14 @@
   }
 
   @override
-  void visitFieldInitializer(FieldInitializer node) {
+  InitializerInferenceResult visitFieldInitializer(FieldInitializer node) {
     ExpressionInferenceResult initializerResult =
         inferrer.inferExpression(node.value, node.field.type, true);
     Expression initializer = inferrer.ensureAssignableResult(
         node.field.type, initializerResult,
         fileOffset: node.fileOffset);
     node.value = initializer..parent = node;
+    return const SuccessfulInitializerInferenceResult();
   }
 
   ForInResult handleForInDeclaringVariable(
@@ -1410,7 +1412,7 @@
     return new ExpressionInferenceResult(inferredType, node);
   }
 
-  void visitInvalidSuperInitializerJudgment(
+  InitializerInferenceResult visitInvalidSuperInitializerJudgment(
       InvalidSuperInitializerJudgment node) {
     Substitution substitution = Substitution.fromSupertype(
         inferrer.classHierarchy.getClassAsInstanceOf(
@@ -1420,9 +1422,12 @@
             .computeThisFunctionType(inferrer.library.nonNullable)
             .withoutTypeParameters) as FunctionType,
         inferrer.thisType!);
-    inferrer.inferInvocation(const UnknownType(), node.fileOffset, functionType,
-        node.argumentsJudgment,
-        skipTypeArgumentInference: true);
+    InvocationInferenceResult invocationInferenceResult =
+        inferrer.inferInvocation(const UnknownType(), node.fileOffset,
+            functionType, node.argumentsJudgment,
+            skipTypeArgumentInference: true);
+    return new InitializerInferenceResult.fromInvocationInferenceResult(
+        invocationInferenceResult);
   }
 
   ExpressionInferenceResult visitIfNullExpression(
@@ -1566,19 +1571,23 @@
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
-  void visitShadowInvalidInitializer(ShadowInvalidInitializer node) {
+  InitializerInferenceResult visitShadowInvalidInitializer(
+      ShadowInvalidInitializer node) {
     ExpressionInferenceResult initializerResult = inferrer.inferExpression(
         node.variable.initializer!, const UnknownType(), !inferrer.isTopLevel,
         isVoidAllowed: false);
     node.variable.initializer = initializerResult.expression
       ..parent = node.variable;
+    return const SuccessfulInitializerInferenceResult();
   }
 
-  void visitShadowInvalidFieldInitializer(ShadowInvalidFieldInitializer node) {
+  InitializerInferenceResult visitShadowInvalidFieldInitializer(
+      ShadowInvalidFieldInitializer node) {
     ExpressionInferenceResult initializerResult = inferrer.inferExpression(
         node.value, node.field.type, !inferrer.isTopLevel,
         isVoidAllowed: false);
     node.value = initializerResult.expression..parent = node;
+    return const SuccessfulInitializerInferenceResult();
   }
 
   @override
@@ -5850,7 +5859,8 @@
   }
 
   @override
-  void visitRedirectingInitializer(RedirectingInitializer node) {
+  InitializerInferenceResult visitRedirectingInitializer(
+      RedirectingInitializer node) {
     inferrer.inferConstructorParameterTypes(node.target);
     List<TypeParameter> classTypeParameters =
         node.target.enclosingClass.typeParameters;
@@ -5866,11 +5876,17 @@
             .computeThisFunctionType(inferrer.library.nonNullable),
         inferrer.coreTypes.thisInterfaceType(
             node.target.enclosingClass, inferrer.library.nonNullable));
-    inferrer.inferInvocation(const UnknownType(), node.fileOffset, functionType,
+    InvocationInferenceResult inferenceResult = inferrer.inferInvocation(
+        const UnknownType(),
+        node.fileOffset,
+        functionType,
         node.arguments as ArgumentsImpl,
-        skipTypeArgumentInference: true, staticTarget: node.target);
+        skipTypeArgumentInference: true,
+        staticTarget: node.target);
     ArgumentsImpl.removeNonInferrableArgumentTypes(
         node.arguments as ArgumentsImpl);
+    return new InitializerInferenceResult.fromInvocationInferenceResult(
+        inferenceResult);
   }
 
   @override
@@ -6080,7 +6096,7 @@
   }
 
   @override
-  void visitSuperInitializer(SuperInitializer node) {
+  InitializerInferenceResult visitSuperInitializer(SuperInitializer node) {
     inferrer.inferConstructorParameterTypes(node.target);
     Substitution substitution = Substitution.fromSupertype(
         inferrer.classHierarchy.getClassAsInstanceOf(
@@ -6090,9 +6106,15 @@
             .computeThisFunctionType(inferrer.library.nonNullable)
             .withoutTypeParameters) as FunctionType,
         inferrer.thisType!);
-    inferrer.inferInvocation(const UnknownType(), node.fileOffset, functionType,
+    InvocationInferenceResult inferenceResult = inferrer.inferInvocation(
+        const UnknownType(),
+        node.fileOffset,
+        functionType,
         node.arguments as ArgumentsImpl,
-        skipTypeArgumentInference: true, staticTarget: node.target);
+        skipTypeArgumentInference: true,
+        staticTarget: node.target);
+    return new InitializerInferenceResult.fromInvocationInferenceResult(
+        inferenceResult);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index 7560883..7239b43 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -891,7 +891,7 @@
       : super(variable);
 
   @override
-  void acceptInference(InferenceVisitor visitor) {
+  InitializerInferenceResult acceptInference(InferenceVisitor visitor) {
     return visitor.visitInvalidSuperInitializerJudgment(this);
   }
 
@@ -982,7 +982,7 @@
 abstract class InitializerJudgment implements Initializer {
   /// Performs type inference for whatever concrete type of
   /// [InitializerJudgment] this is.
-  void acceptInference(InferenceVisitor visitor);
+  InitializerInferenceResult acceptInference(InferenceVisitor visitor);
 }
 
 Expression? checkWebIntLiteralsErrorIfUnexact(
@@ -1089,7 +1089,7 @@
   ShadowInvalidInitializer(VariableDeclaration variable) : super(variable);
 
   @override
-  void acceptInference(InferenceVisitor visitor) {
+  InitializerInferenceResult acceptInference(InferenceVisitor visitor) {
     return visitor.visitShadowInvalidInitializer(this);
   }
 
@@ -1114,7 +1114,7 @@
   }
 
   @override
-  void acceptInference(InferenceVisitor visitor) {
+  InitializerInferenceResult acceptInference(InferenceVisitor visitor) {
     return visitor.visitShadowInvalidFieldInitializer(this);
   }
 
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 7e9d30a..93e1544 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
@@ -145,7 +145,8 @@
       DartType returnType, AsyncMarker asyncMarker, Statement body);
 
   /// Performs type inference on the given constructor initializer.
-  void inferInitializer(InferenceHelper helper, Initializer initializer);
+  InitializerInferenceResult inferInitializer(
+      InferenceHelper helper, Initializer initializer);
 
   /// Performs type inference on the given metadata annotations.
   void inferMetadata(
@@ -410,19 +411,22 @@
   }
 
   @override
-  void inferInitializer(InferenceHelper helper, Initializer initializer) {
+  InitializerInferenceResult inferInitializer(
+      InferenceHelper helper, Initializer initializer) {
     this.helper = helper;
     // Use polymorphic dispatch on [KernelInitializer] to perform whatever
     // kind of type inference is correct for this kind of initializer.
     // TODO(paulberry): experiment to see if dynamic dispatch would be better,
     // so that the type hierarchy will be simpler (which may speed up "is"
     // checks).
+    InitializerInferenceResult inferenceResult;
     if (initializer is InitializerJudgment) {
-      initializer.acceptInference(new InferenceVisitor(this));
+      inferenceResult = initializer.acceptInference(new InferenceVisitor(this));
     } else {
-      initializer.accept(new InferenceVisitor(this));
+      inferenceResult = initializer.accept(new InferenceVisitor(this));
     }
     this.helper = null;
+    return inferenceResult;
   }
 
   bool isDoubleContext(DartType typeContext) {
@@ -4905,11 +4909,9 @@
       if (expression is FactoryConstructorInvocation) {
         return _insertHoistedExpressions(expression, hoistedArguments);
       } else if (expression is TypeAliasedConstructorInvocation) {
-        // Should be unaliased at this point, the code is for completeness.
         return _insertHoistedExpressions(expression, hoistedArguments);
       } else if (expression is TypeAliasedFactoryInvocation) {
-        // Should be unaliased at this point, the code is for completeness.
-        return expression;
+        return _insertHoistedExpressions(expression, hoistedArguments);
       } else if (expression is ConstructorInvocation) {
         return _insertHoistedExpressions(expression, hoistedArguments);
       } else if (expression is DynamicInvocation) {
@@ -4982,6 +4984,78 @@
   }
 }
 
+abstract class InitializerInferenceResult {
+  /// Modifies list of initializers in-place to apply the inference result.
+  void applyResult(List<Initializer> initializers, TreeNode? parent);
+
+  factory InitializerInferenceResult.fromInvocationInferenceResult(
+      InvocationInferenceResult invocationInferenceResult) {
+    if (invocationInferenceResult is SuccessfulInferenceResult) {
+      return new SuccessfulInitializerInvocationInferenceResult
+          .fromSuccessfulInferenceResult(invocationInferenceResult);
+    } else {
+      return new WrapInProblemInitializerInferenceResult
+              .fromWrapInProblemInferenceResult(
+          invocationInferenceResult as WrapInProblemInferenceResult);
+    }
+  }
+}
+
+class SuccessfulInitializerInferenceResult
+    implements InitializerInferenceResult {
+  const SuccessfulInitializerInferenceResult();
+
+  @override
+  void applyResult(List<Initializer> initializers, TreeNode? parent) {}
+}
+
+class SuccessfulInitializerInvocationInferenceResult
+    implements InitializerInferenceResult {
+  final DartType inferredType;
+
+  final FunctionType functionType;
+
+  final List<VariableDeclaration>? hoistedArguments;
+
+  final DartType? inferredReceiverType;
+
+  SuccessfulInitializerInvocationInferenceResult(
+      {required this.inferredType,
+      required this.functionType,
+      required this.hoistedArguments,
+      required this.inferredReceiverType});
+
+  SuccessfulInitializerInvocationInferenceResult.fromSuccessfulInferenceResult(
+      SuccessfulInferenceResult successfulInferenceResult)
+      : this(
+            inferredType: successfulInferenceResult.inferredType,
+            functionType: successfulInferenceResult.functionType,
+            hoistedArguments: successfulInferenceResult.hoistedArguments,
+            inferredReceiverType:
+                successfulInferenceResult.inferredReceiverType);
+
+  @override
+  void applyResult(List<Initializer> initializers, TreeNode? parent) {
+    List<VariableDeclaration>? hoistedArguments = this.hoistedArguments;
+    if (hoistedArguments != null && hoistedArguments.isNotEmpty) {
+      for (VariableDeclaration hoistedArgument in hoistedArguments) {
+        initializers.add(new LocalInitializer(hoistedArgument)
+          ..parent = parent
+          ..fileOffset = hoistedArgument.fileOffset);
+      }
+    }
+  }
+}
+
+class WrapInProblemInitializerInferenceResult
+    implements InitializerInferenceResult {
+  WrapInProblemInitializerInferenceResult.fromWrapInProblemInferenceResult(
+      WrapInProblemInferenceResult wrapInProblemInferenceResult);
+
+  @override
+  void applyResult(List<Initializer> initializers, TreeNode? parent) {}
+}
+
 /// The result of inference of a property get expression.
 class PropertyGetInferenceResult {
   /// The main inference result.
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index 9e67ea3..4fff6ab 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -9,37 +9,43 @@
   sdk: '>=2.13.0 <3.0.0'
 
 dependencies:
-  _fe_analyzer_shared:
-    path: ../_fe_analyzer_shared
+  _fe_analyzer_shared: any
   kernel:
     path: ../kernel
-  package_config:
-    path: ../../third_party/pkg_tested/package_config
+  package_config: any
 
 dev_dependencies:
-  analyzer:
-    path: ../analyzer
-  args: '>=0.13.0 <2.0.0'
+  analyzer: any
+  args: ^2.0.0
   async_helper:
     path: ../async_helper
   build_integration:
     path: ../build_integration
   compiler:
     path: ../compiler
-  dart_style: '^1.0.7'
+  dart_style: ^2.0.0
   dev_compiler:
     path: ../dev_compiler
   expect:
     path: ../expect
-  json_rpc_2: ^2.0.9
-  path: '^1.3.9'
+  json_rpc_2: ^3.0.0
+  path: ^1.3.9
   test: ^1.3.4
   testing:
     path: ../testing
-  test_reflective_loader: ^0.1.0
+  test_reflective_loader: ^0.2.0
   vm:
     path: ../vm
+  vm_service: any
+  web_socket_channel: ^2.0.0
+  yaml: any
+
+dependency_overrides:
+  analyzer:
+    path: ../analyzer
+  _fe_analyzer_shared:
+    path: ../_fe_analyzer_shared
+  package_config:
+    path: ../../third_party/pkg_tested/package_config
   vm_service:
     path: ../vm_service
-  web_socket_channel: ^1.0.4
-  yaml: any
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart b/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart
index 2c51514..8d34e3c 100644
--- a/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart
+++ b/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart
@@ -1,3 +1,7 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 class A {
   A(int x, int y, {required int z});
 
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart.strong.transformed.expect b/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart.strong.transformed.expect
index 4cfee0f..c92ba29 100644
--- a/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart.strong.transformed.expect
@@ -78,44 +78,44 @@
 }
 
 Extra constant evaluation status:
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:77:15 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:77:21 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:78:18 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:17:18 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:27:7 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:27:13 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:28:10 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:32:13 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:32:19 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:33:16 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:35:13 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:35:19 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:36:16 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:40:9 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:40:15 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:41:12 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:43:9 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:43:15 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:44:12 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:48:5 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:48:11 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:49:8 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:53:5 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:53:11 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:54:8 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:57:14 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:57:17 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:57:23 -> IntConstant(3)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:58:14 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:58:23 -> IntConstant(3)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:58:20 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:59:20 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:59:23 -> IntConstant(3)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:59:17 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:63:9 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:63:15 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:64:12 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:68:9 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:68:15 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:69:12 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:81:15 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:81:21 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:82:18 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:21:18 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:31:7 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:31:13 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:32:10 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:36:13 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:36:19 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:37:16 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:39:13 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:39:19 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:40:16 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:44:9 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:44:15 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:45:12 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:47:9 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:47:15 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:48:12 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:52:5 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:52:11 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:53:8 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:57:5 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:57:11 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:58:8 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:61:14 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:61:17 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:61:23 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:62:14 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:62:23 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:62:20 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:63:20 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:63:23 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:63:17 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:67:9 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:67:15 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:68:12 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:72:9 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:72:15 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:73:12 -> IntConstant(1)
 Extra constant evaluation: evaluated: 155, effectively constant: 40
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart.weak.transformed.expect b/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart.weak.transformed.expect
index 4cfee0f..c92ba29 100644
--- a/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/named_arguments_anywhere/all_kinds.dart.weak.transformed.expect
@@ -78,44 +78,44 @@
 }
 
 Extra constant evaluation status:
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:77:15 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:77:21 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:78:18 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:17:18 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:27:7 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:27:13 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:28:10 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:32:13 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:32:19 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:33:16 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:35:13 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:35:19 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:36:16 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:40:9 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:40:15 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:41:12 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:43:9 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:43:15 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:44:12 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:48:5 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:48:11 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:49:8 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:53:5 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:53:11 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:54:8 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:57:14 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:57:17 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:57:23 -> IntConstant(3)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:58:14 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:58:23 -> IntConstant(3)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:58:20 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:59:20 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:59:23 -> IntConstant(3)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:59:17 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:63:9 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:63:15 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:64:12 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:68:9 -> IntConstant(1)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:68:15 -> IntConstant(2)
-Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:69:12 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:81:15 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:81:21 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:82:18 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:21:18 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:31:7 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:31:13 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:32:10 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:36:13 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:36:19 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:37:16 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:39:13 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:39:19 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:40:16 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:44:9 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:44:15 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:45:12 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:47:9 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:47:15 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:48:12 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:52:5 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:52:11 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:53:8 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:57:5 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:57:11 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:58:8 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:61:14 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:61:17 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:61:23 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:62:14 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:62:23 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:62:20 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:63:20 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:63:23 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:63:17 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:67:9 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:67:15 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:68:12 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:72:9 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:72:15 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///all_kinds.dart:73:12 -> IntConstant(1)
 Extra constant evaluation: evaluated: 155, effectively constant: 40
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart
new file mode 100644
index 0000000..ebb9e92
--- /dev/null
+++ b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  A(int x, bool y, {required String z});
+
+  A.foo() : this(42, z: "foo", false);
+
+  factory A.bar(int x, bool y, {required String z}) = A;
+}
+
+class B extends A {
+  B() : super(42, z: "foo", false);
+}
+
+test() {
+  new A.bar(42, false, z: "bar");
+  new A.bar(42, z: "bar", false);
+  new A.bar(z: "bar", 42, false);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.strong.expect b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.strong.expect
new file mode 100644
index 0000000..5b2dee8
--- /dev/null
+++ b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.strong.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •(core::int x, core::bool y, {required core::String z = #C2}) → self::A
+    : super core::Object::•()
+    ;
+  constructor foo() → self::A
+    : final core::int #t1 = 42, final core::String #t2 = "foo", this self::A::•(#t1, false, z: #t2)
+    ;
+  static factory bar(core::int x, core::bool y, {required core::String z = #C2}) → self::A
+    return new self::A::•(x, y, z: z);
+}
+class B extends self::A {
+  constructor •() → self::B
+    : final core::int #t3 = 42, final core::String #t4 = "foo", super self::A::•(#t3, false, z: #t4)
+    ;
+}
+static method test() → dynamic {
+  new self::A::•(42, false, z: "bar");
+  let final core::int #t5 = 42 in let final core::String #t6 = "bar" in new self::A::•(#t5, false, z: #t6);
+  let final core::String #t7 = "bar" in new self::A::•(42, false, z: #t7);
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::bar
+  #C2 = null
+}
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.strong.transformed.expect b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.strong.transformed.expect
new file mode 100644
index 0000000..06dd91e
--- /dev/null
+++ b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.strong.transformed.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •(core::int x, core::bool y, {required core::String z = #C2}) → self::A
+    : super core::Object::•()
+    ;
+  constructor foo() → self::A
+    : final core::int #t1 = 42, final core::String #t2 = "foo", this self::A::•(#t1, false, z: #t2)
+    ;
+  static factory bar(core::int x, core::bool y, {required core::String z = #C2}) → self::A
+    return new self::A::•(x, y, z: z);
+}
+class B extends self::A {
+  constructor •() → self::B
+    : final core::int #t3 = 42, final core::String #t4 = "foo", super self::A::•(#t3, false, z: #t4)
+    ;
+}
+static method test() → dynamic {
+  new self::A::•(42, false, z: "bar");
+  let final core::int #t5 = 42 in let final core::String #t6 = "bar" in new self::A::•(#t5, false, z: #t6);
+  let final core::String #t7 = "bar" in new self::A::•(42, false, z: #t7);
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::bar
+  #C2 = null
+}
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///redirecting_constructor_initializers.dart:19:13 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///redirecting_constructor_initializers.dart:19:20 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///redirecting_constructor_initializers.dart:20:16 -> StringConstant("bar")
+Extra constant evaluation: evaluated: 18, effectively constant: 3
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline.expect b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline.expect
new file mode 100644
index 0000000..4ca0a85
--- /dev/null
+++ b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+class A {
+  A(int x, bool y, {required String z});
+  A.foo() : this(42, z: "foo", false);
+  factory A.bar(int x, bool y, {required String z}) = A;
+}
+class B extends A {
+  B() : super(42, z: "foo", false);
+}
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.weak.expect b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.weak.expect
new file mode 100644
index 0000000..5b2dee8
--- /dev/null
+++ b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.weak.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •(core::int x, core::bool y, {required core::String z = #C2}) → self::A
+    : super core::Object::•()
+    ;
+  constructor foo() → self::A
+    : final core::int #t1 = 42, final core::String #t2 = "foo", this self::A::•(#t1, false, z: #t2)
+    ;
+  static factory bar(core::int x, core::bool y, {required core::String z = #C2}) → self::A
+    return new self::A::•(x, y, z: z);
+}
+class B extends self::A {
+  constructor •() → self::B
+    : final core::int #t3 = 42, final core::String #t4 = "foo", super self::A::•(#t3, false, z: #t4)
+    ;
+}
+static method test() → dynamic {
+  new self::A::•(42, false, z: "bar");
+  let final core::int #t5 = 42 in let final core::String #t6 = "bar" in new self::A::•(#t5, false, z: #t6);
+  let final core::String #t7 = "bar" in new self::A::•(42, false, z: #t7);
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::bar
+  #C2 = null
+}
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.weak.outline.expect b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.weak.outline.expect
new file mode 100644
index 0000000..ccf5a7c
--- /dev/null
+++ b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.weak.outline.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::bar]/*isLegacy*/;
+  constructor •(core::int x, core::bool y, {required core::String z}) → self::A
+    ;
+  constructor foo() → self::A
+    ;
+  static factory bar(core::int x, core::bool y, {required core::String z}) → self::A
+    return new self::A::•(x, y, z: z);
+}
+class B extends self::A {
+  constructor •() → self::B
+    ;
+}
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///redirecting_constructor_initializers.dart:5:7 -> ConstructorTearOffConstant(A.bar)
+Extra constant evaluation: evaluated: 6, effectively constant: 1
diff --git a/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.weak.transformed.expect b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.weak.transformed.expect
new file mode 100644
index 0000000..06dd91e
--- /dev/null
+++ b/pkg/front_end/testcases/named_arguments_anywhere/redirecting_constructor_initializers.dart.weak.transformed.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  constructor •(core::int x, core::bool y, {required core::String z = #C2}) → self::A
+    : super core::Object::•()
+    ;
+  constructor foo() → self::A
+    : final core::int #t1 = 42, final core::String #t2 = "foo", this self::A::•(#t1, false, z: #t2)
+    ;
+  static factory bar(core::int x, core::bool y, {required core::String z = #C2}) → self::A
+    return new self::A::•(x, y, z: z);
+}
+class B extends self::A {
+  constructor •() → self::B
+    : final core::int #t3 = 42, final core::String #t4 = "foo", super self::A::•(#t3, false, z: #t4)
+    ;
+}
+static method test() → dynamic {
+  new self::A::•(42, false, z: "bar");
+  let final core::int #t5 = 42 in let final core::String #t6 = "bar" in new self::A::•(#t5, false, z: #t6);
+  let final core::String #t7 = "bar" in new self::A::•(42, false, z: #t7);
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::bar
+  #C2 = null
+}
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///redirecting_constructor_initializers.dart:19:13 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///redirecting_constructor_initializers.dart:19:20 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///redirecting_constructor_initializers.dart:20:16 -> StringConstant("bar")
+Extra constant evaluation: evaluated: 18, effectively constant: 3
diff --git a/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.outline.expect
index 4789762..ed2219b 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.outline.expect
@@ -170,8 +170,8 @@
 Evaluated: SymbolLiteral @ org-dartlang-testcase:///mock_http_headers.dart:13:7 -> SymbolConstant(#noFolding)
 Evaluated: ListLiteral @ org-dartlang-testcase:///mock_http_headers.dart:13:7 -> ListConstant(const <Type*>[])
 Evaluated: MapLiteral @ org-dartlang-testcase:///mock_http_headers.dart:13:7 -> MapConstant(const <Symbol*, dynamic>{})
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:707:8 -> SymbolConstant(#clear)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:707:8 -> ListConstant(const <Type*>[])
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:707:8 -> ListConstant(const <dynamic>[])
-Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:707:8 -> MapConstant(const <Symbol*, dynamic>{})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:676:8 -> SymbolConstant(#clear)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:676:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:676:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:676:8 -> MapConstant(const <Symbol*, dynamic>{})
 Extra constant evaluation: evaluated: 268, effectively constant: 91
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 9306978..0c51eb2 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -74,10 +74,10 @@
 general/error_recovery/yield_not_in_generator: RuntimeError
 general/expressions: RuntimeError
 general/getter_vs_setter_type: TypeCheckError
+general/implement_semi_stub: TypeCheckError
+general/implicit_super_call: TypeCheckError
 general/incomplete_field_formal_parameter: RuntimeError
 general/infer_field_from_multiple: TypeCheckError
-general/implicit_super_call: TypeCheckError
-general/implement_semi_stub: TypeCheckError
 general/invalid_operator: TypeCheckError
 general/invalid_operator_override: TypeCheckError
 general/invocations: RuntimeError
@@ -135,6 +135,7 @@
 inference_new/infer_assign_to_index_this_upwards: TypeCheckError
 inference_new/infer_assign_to_index_upwards: TypeCheckError
 late_lowering/covariant_late_field: TypeCheckError
+named_arguments_anywhere/redirecting_constructor_initializers: Crash # Issue 47524.
 nnbd/covariant_late_field: TypeCheckError
 nnbd/getter_vs_setter_type: TypeCheckError
 nnbd/issue42603: TypeCheckError
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index decb8b5..260c55f 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -134,6 +134,7 @@
 late_lowering/override_getter_setter: FormatterCrash
 late_lowering/skip_late_final_uninitialized_instance_fields/main: FormatterCrash
 late_lowering/uninitialized_non_nullable_late_fields: FormatterCrash
+named_arguments_anywhere/redirecting_constructor_initializers: FormatterCrash
 nnbd/abstract_field_errors: FormatterCrash
 nnbd/covariant_late_field: FormatterCrash
 nnbd/duplicates_instance: FormatterCrash
diff --git a/pkg/status_file/pubspec.yaml b/pkg/status_file/pubspec.yaml
index 1536b63..5f9e8e2 100644
--- a/pkg/status_file/pubspec.yaml
+++ b/pkg/status_file/pubspec.yaml
@@ -5,7 +5,8 @@
   sdk: "^2.12.0"
 dependencies:
   path: "^1.4.0"
-  args: "^1.4.4"
+  args: ^2.0.0
+
 dev_dependencies:
   expect:
     path: ../expect
diff --git a/pkg/vm/lib/transformations/ffi/native.dart b/pkg/vm/lib/transformations/ffi/native.dart
index 2919bf1..51a4d71 100644
--- a/pkg/vm/lib/transformations/ffi/native.dart
+++ b/pkg/vm/lib/transformations/ffi/native.dart
@@ -118,7 +118,7 @@
         ffiReturnType,
         handleClass.getThisType(coreTypes, Nullability.nonNullable),
         SubtypeCheckMode.ignoringNullabilities)) {
-      return objectClass.getThisType(coreTypes, Nullability.nonNullable);
+      return objectClass.getThisType(coreTypes, dartReturnType.nullability);
     }
     return dartReturnType;
   }
@@ -293,7 +293,8 @@
         ffiFunctionType.returnType,
         handleClass.getThisType(coreTypes, Nullability.nonNullable),
         SubtypeCheckMode.ignoringNullabilities)) {
-      resultInitializer = AsExpression(invocation, dartFunctionType.returnType);
+      resultInitializer = StaticInvocation(unsafeCastMethod,
+          Arguments([invocation], types: [dartFunctionType.returnType]));
     }
 
     //   final T #t1 = foo(Pointer.fromAddress(_getNativeField(#t0)));
diff --git a/pkg/vm/pubspec.yaml b/pkg/vm/pubspec.yaml
index 20b2cd7..3ae9534 100644
--- a/pkg/vm/pubspec.yaml
+++ b/pkg/vm/pubspec.yaml
@@ -7,7 +7,7 @@
   sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
-  args: ^1.4.4
+  args: ^2.0.0
   build_integration:
     path: ../build_integration
   crypto: any
@@ -25,7 +25,3 @@
   path: any
   test: any
   web_socket_channel: any
-
-dependency_overrides:
-  front_end:
-    path: ../front_end
diff --git a/pkg/vm/test/transformations/ffinative_test.dart b/pkg/vm/test/transformations/ffi_test.dart
similarity index 96%
rename from pkg/vm/test/transformations/ffinative_test.dart
rename to pkg/vm/test/transformations/ffi_test.dart
index a6326a1..cda6097 100644
--- a/pkg/vm/test/transformations/ffinative_test.dart
+++ b/pkg/vm/test/transformations/ffi_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
diff --git a/pkg/vm/testcases/transformations/ffi/ffinative.dart b/pkg/vm/testcases/transformations/ffi/ffinative.dart
index 347ba00..d2d8c18 100644
--- a/pkg/vm/testcases/transformations/ffi/ffinative.dart
+++ b/pkg/vm/testcases/transformations/ffi/ffinative.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
diff --git a/pkg/vm/testcases/transformations/ffi/ffinative.dart.expect b/pkg/vm/testcases/transformations/ffi/ffinative.dart.expect
index 557aa76..b33994e 100644
--- a/pkg/vm/testcases/transformations/ffi/ffinative.dart.expect
+++ b/pkg/vm/testcases/transformations/ffi/ffinative.dart.expect
@@ -22,7 +22,7 @@
   static final field (self::NativeClassy, ffi::Pointer<ffi::Void>) → void _goodHasReceiverHandleAndPtr$FfiNative$Ptr = ffi::_asFunctionInternal<(self::NativeClassy, ffi::Pointer<ffi::Void>) → void, (ffi::Handle*, ffi::Pointer<ffi::Void*>*) →* ffi::Void*>(ffi::_fromAddress<ffi::NativeFunction<(ffi::Handle*, ffi::Pointer<ffi::Void*>*) →* ffi::Void*>*>(ffi::_ffi_resolver(#C1, #C4, #C5){(core::Object, core::Object, core::int) → core::int}), false)/*isLegacy*/;
   static final field (self::NativeClassy, self::NativeClassy) → void _goodHasReceiverHandleAndHandle$FfiNative$Ptr = ffi::_asFunctionInternal<(self::NativeClassy, self::NativeClassy) → void, (ffi::Handle*, ffi::Handle*) →* ffi::Void*>(ffi::_fromAddress<ffi::NativeFunction<(ffi::Handle*, ffi::Handle*) →* ffi::Void*>*>(ffi::_ffi_resolver(#C1, #C4, #C5){(core::Object, core::Object, core::int) → core::int}), false)/*isLegacy*/;
   static final field (ffi::Pointer<ffi::Void>, self::NativeClassy) → void _goodHasReceiverPtrAndHandle$FfiNative$Ptr = ffi::_asFunctionInternal<(ffi::Pointer<ffi::Void>, self::NativeClassy) → void, (ffi::Pointer<ffi::Void*>*, ffi::Handle*) →* ffi::Void*>(ffi::_fromAddress<ffi::NativeFunction<(ffi::Pointer<ffi::Void*>*, ffi::Handle*) →* ffi::Void*>*>(ffi::_ffi_resolver(#C1, #C4, #C5){(core::Object, core::Object, core::int) → core::int}), false)/*isLegacy*/;
-  static final field (ffi::Pointer<ffi::Void>, core::bool) → core::Object _meh$FfiNative$Ptr = ffi::_asFunctionInternal<(ffi::Pointer<ffi::Void>, core::bool) → core::Object, (ffi::Pointer<ffi::Void*>*, ffi::Bool*) →* ffi::Handle*>(ffi::_fromAddress<ffi::NativeFunction<(ffi::Pointer<ffi::Void*>*, ffi::Bool*) →* ffi::Handle*>*>(ffi::_ffi_resolver(#C1, #C4, #C5){(core::Object, core::Object, core::int) → core::int}), false)/*isLegacy*/;
+  static final field (ffi::Pointer<ffi::Void>, core::bool) → core::Object? _meh$FfiNative$Ptr = ffi::_asFunctionInternal<(ffi::Pointer<ffi::Void>, core::bool) → core::Object?, (ffi::Pointer<ffi::Void*>*, ffi::Bool*) →* ffi::Handle*>(ffi::_fromAddress<ffi::NativeFunction<(ffi::Pointer<ffi::Void*>*, ffi::Bool*) →* ffi::Handle*>*>(ffi::_ffi_resolver(#C1, #C4, #C5){(core::Object, core::Object, core::int) → core::int}), false)/*isLegacy*/;
   static final field (ffi::Pointer<ffi::Void>) → core::bool _blah$FfiNative$Ptr = ffi::_asFunctionInternal<(ffi::Pointer<ffi::Void>) → core::bool, (ffi::Pointer<ffi::Void*>*) →* ffi::Bool*>(ffi::_fromAddress<ffi::NativeFunction<(ffi::Pointer<ffi::Void*>*) →* ffi::Bool*>*>(ffi::_ffi_resolver(#C1, #C4, #C3){(core::Object, core::Object, core::int) → core::int}), false)/*isLegacy*/;
   synthetic constructor •() → self::NativeClassy
     : super nat::NativeFieldWrapperClass1::•()
@@ -56,7 +56,7 @@
     return block {
       final nat::NativeFieldWrapperClass1 #t10 = this;
       final core::bool #t11 = blah;
-      final core::String? #t12 = self::NativeClassy::_meh$FfiNative$Ptr(ffi::_fromAddress<ffi::Void>(nat::_getNativeField(#t10)), #t11){(ffi::Pointer<ffi::Void>, core::bool) → core::Object} as core::String?;
+      final core::String? #t12 = _in::unsafeCast<core::String?>(self::NativeClassy::_meh$FfiNative$Ptr(ffi::_fromAddress<ffi::Void>(nat::_getNativeField(#t10)), #t11){(ffi::Pointer<ffi::Void>, core::bool) → core::Object?});
       _in::reachabilityFence(#t10);
     } =>#t12;
   method blah() → core::bool
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index b6c27fa..701967b 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -231,9 +231,11 @@
 
 void DFE::ReadScript(const char* script_uri,
                      uint8_t** kernel_buffer,
-                     intptr_t* kernel_buffer_size) const {
+                     intptr_t* kernel_buffer_size,
+                     bool decode_uri) const {
   int64_t start = Dart_TimelineGetMicros();
-  if (!TryReadKernelFile(script_uri, kernel_buffer, kernel_buffer_size)) {
+  if (!TryReadKernelFile(script_uri, kernel_buffer, kernel_buffer_size,
+                         decode_uri)) {
     return;
   }
   if (!Dart_IsKernel(*kernel_buffer, *kernel_buffer_size)) {
@@ -274,9 +276,12 @@
 ///
 /// If successful, newly allocated buffer with file contents is returned in
 /// [buffer], file contents byte count - in [size].
-static bool TryReadFile(const char* script_uri, uint8_t** buffer,
-                        intptr_t* size) {
-  void* script_file = DartUtils::OpenFileUri(script_uri, false);
+static bool TryReadFile(const char* script_uri,
+                        uint8_t** buffer,
+                        intptr_t* size,
+                        bool decode_uri = true) {
+  void* script_file = decode_uri ? DartUtils::OpenFileUri(script_uri, false)
+                                 : DartUtils::OpenFile(script_uri, false);
   if (script_file == nullptr) {
     return false;
   }
@@ -417,12 +422,13 @@
 
 bool DFE::TryReadKernelFile(const char* script_uri,
                             uint8_t** kernel_ir,
-                            intptr_t* kernel_ir_size) {
+                            intptr_t* kernel_ir_size,
+                            bool decode_uri) {
   *kernel_ir = nullptr;
   *kernel_ir_size = -1;
 
   uint8_t* buffer;
-  if (!TryReadFile(script_uri, &buffer, kernel_ir_size)) {
+  if (!TryReadFile(script_uri, &buffer, kernel_ir_size, decode_uri)) {
     return false;
   }
 
diff --git a/runtime/bin/dfe.h b/runtime/bin/dfe.h
index 649cc32..038bca7 100644
--- a/runtime/bin/dfe.h
+++ b/runtime/bin/dfe.h
@@ -92,7 +92,8 @@
   // valid kernel file, false otherwise.
   void ReadScript(const char* script_uri,
                   uint8_t** kernel_buffer,
-                  intptr_t* kernel_buffer_size) const;
+                  intptr_t* kernel_buffer_size,
+                  bool decode_uri = true) const;
 
   bool KernelServiceDillAvailable() const;
 
@@ -103,7 +104,8 @@
   // was returned.
   static bool TryReadKernelFile(const char* script_uri,
                                 uint8_t** kernel_buffer,
-                                intptr_t* kernel_buffer_size);
+                                intptr_t* kernel_buffer_size,
+                                bool decode_uri = true);
 
   // We distinguish between "intent to use Dart frontend" vs "can actually
   // use Dart frontend". The method UseDartFrontend tells us about the
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 64f1715..4193965 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -431,8 +431,9 @@
   AppSnapshot* app_snapshot = NULL;
   // Kernel isolate uses an app snapshot or uses the dill file.
   if ((kernel_snapshot_uri != NULL) &&
-      (app_snapshot = Snapshot::TryReadAppSnapshot(kernel_snapshot_uri)) !=
-          NULL) {
+      (app_snapshot = Snapshot::TryReadAppSnapshot(
+           kernel_snapshot_uri, /*force_load_elf_from_memory=*/false,
+           /*decode_uri=*/false)) != nullptr) {
     const uint8_t* isolate_snapshot_data = NULL;
     const uint8_t* isolate_snapshot_instructions = NULL;
     const uint8_t* ignore_vm_snapshot_data;
@@ -603,8 +604,9 @@
   AppSnapshot* app_snapshot = nullptr;
   bool isolate_run_app_snapshot = true;
   if (dartdev_path.get() != nullptr &&
-      (app_snapshot = Snapshot::TryReadAppSnapshot(dartdev_path.get())) !=
-          nullptr) {
+      (app_snapshot = Snapshot::TryReadAppSnapshot(
+           dartdev_path.get(), /*force_load_elf_from_memory=*/false,
+           /*decode_uri=*/false)) != nullptr) {
     const uint8_t* isolate_snapshot_data = NULL;
     const uint8_t* isolate_snapshot_instructions = NULL;
     const uint8_t* ignore_vm_snapshot_data;
@@ -613,8 +615,8 @@
         &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
         &isolate_snapshot_data, &isolate_snapshot_instructions);
     isolate_group_data =
-        new IsolateGroupData(dartdev_path.get(), packages_config, app_snapshot,
-                             isolate_run_app_snapshot);
+        new IsolateGroupData(DART_DEV_ISOLATE_NAME, packages_config,
+                             app_snapshot, isolate_run_app_snapshot);
     isolate_data = new IsolateData(isolate_group_data);
     isolate = Dart_CreateIsolateGroup(
         DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
@@ -642,7 +644,7 @@
       uint8_t* application_kernel_buffer = NULL;
       intptr_t application_kernel_buffer_size = 0;
       dfe.ReadScript(dartdev_path.get(), &application_kernel_buffer,
-                     &application_kernel_buffer_size);
+                     &application_kernel_buffer_size, /*decode_uri=*/false);
       isolate_group_data->SetKernelBufferNewlyOwned(
           application_kernel_buffer, application_kernel_buffer_size);
 
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index cf9589a..754043a 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -330,13 +330,19 @@
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
 AppSnapshot* Snapshot::TryReadAppSnapshot(const char* script_uri,
-                                          bool force_load_elf_from_memory) {
-  auto decoded_path = File::UriToPath(script_uri);
-  if (decoded_path == nullptr) {
-    return nullptr;
+                                          bool force_load_elf_from_memory,
+                                          bool decode_uri) {
+  Utils::CStringUniquePtr decoded_path(nullptr, std::free);
+  const char* script_name = nullptr;
+  if (decode_uri) {
+    decoded_path = File::UriToPath(script_uri);
+    if (decoded_path == nullptr) {
+      return nullptr;
+    }
+    script_name = decoded_path.get();
+  } else {
+    script_name = script_uri;
   }
-
-  const char* script_name = decoded_path.get();
   if (File::GetType(nullptr, script_name, true) != File::kIsFile) {
     // If 'script_name' refers to a pipe, don't read to check for an app
     // snapshot since we cannot rewind if it isn't (and couldn't mmap it in
diff --git a/runtime/bin/snapshot_utils.h b/runtime/bin/snapshot_utils.h
index 57d8929..ed96fb1 100644
--- a/runtime/bin/snapshot_utils.h
+++ b/runtime/bin/snapshot_utils.h
@@ -41,7 +41,8 @@
   static AppSnapshot* TryReadAppendedAppSnapshotElf(const char* container_path);
   static AppSnapshot* TryReadAppSnapshot(
       const char* script_uri,
-      bool force_load_elf_from_memory = false);
+      bool force_load_elf_from_memory = false,
+      bool decode_uri = true);
   static void WriteAppSnapshot(const char* filename,
                                uint8_t* vm_data_buffer,
                                intptr_t vm_data_size,
diff --git a/runtime/observatory/tests/service/coverage_closure_call_test.dart b/runtime/observatory/tests/service/coverage_closure_call_test.dart
new file mode 100644
index 0000000..d7566a2
--- /dev/null
+++ b/runtime/observatory/tests/service/coverage_closure_call_test.dart
@@ -0,0 +1,115 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:developer';
+
+String leafFunction(void Function() f) {
+  f();
+  return "some constant";
+}
+
+void testFunction() {
+  debugger();
+  leafFunction(() {});
+  debugger();
+}
+
+bool allRangesCompiled(coverage) {
+  for (int i = 0; i < coverage['ranges'].length; i++) {
+    if (!coverage['ranges'][i]['compiled']) {
+      return false;
+    }
+  }
+  return true;
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    expect(stack['frames'][0].function.name, equals('testFunction'));
+
+    var root = isolate.rootLibrary;
+    await root.load();
+    var func = root.functions.singleWhere((f) => f.name == 'leafFunction');
+    await func.load();
+
+    var expectedRange = {
+      'scriptIndex': 0,
+      'startPos': 384,
+      'endPos': 458,
+      'compiled': true,
+      'coverage': {
+        'hits': [],
+        'misses': [384, 428]
+      }
+    };
+
+    var params = {
+      'reports': ['Coverage'],
+      'scriptId': func.location!.script.id,
+      'tokenPos': func.location!.tokenPos,
+      'endTokenPos': func.location!.endTokenPos,
+      'forceCompile': true
+    };
+    var report = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    expect(report['type'], equals('SourceReport'));
+    expect(report['ranges'].length, 1);
+    expect(report['ranges'][0], equals(expectedRange));
+    expect(report['scripts'].length, 1);
+    expect(report['scripts'][0]['uri'],
+        endsWith('coverage_closure_call_test.dart'));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    expect(stack['frames'][0].function.name, equals('testFunction'));
+
+    var root = isolate.rootLibrary;
+    await root.load();
+    var func = root.functions.singleWhere((f) => f.name == 'leafFunction');
+    await func.load();
+
+    var expectedRange = {
+      'scriptIndex': 0,
+      'startPos': 384,
+      'endPos': 458,
+      'compiled': true,
+      'coverage': {
+        'hits': [384, 428],
+        'misses': []
+      }
+    };
+
+    var params = {
+      'reports': ['Coverage'],
+      'scriptId': func.location!.script.id,
+      'tokenPos': func.location!.tokenPos,
+      'endTokenPos': func.location!.endTokenPos,
+      'forceCompile': true
+    };
+    var report = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    expect(report['type'], equals('SourceReport'));
+    expect(report['ranges'].length, 1);
+    expect(report['ranges'][0], equals(expectedRange));
+    expect(report['scripts'].length, 1);
+    expect(report['scripts'][0]['uri'],
+        endsWith('coverage_closure_call_test.dart'));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/vm/compiler/backend/block_scheduler.cc b/runtime/vm/compiler/backend/block_scheduler.cc
index 33dae39..7fb1408 100644
--- a/runtime/vm/compiler/backend/block_scheduler.cc
+++ b/runtime/vm/compiler/backend/block_scheduler.cc
@@ -63,7 +63,11 @@
     return;
   }
   Array& edge_counters = Array::Handle();
-  edge_counters ^= ic_data_array.At(0);
+  edge_counters ^=
+      ic_data_array.At(Function::ICDataArrayIndices::kEdgeCounters);
+  if (edge_counters.IsNull()) {
+    return;
+  }
 
   auto graph_entry = flow_graph->graph_entry();
   BlockEntryInstr* entry = graph_entry->normal_entry();
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 60fdf3a..50418b8 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -758,6 +758,10 @@
   // Nothing to do.
 }
 
+void ConstantPropagator::VisitRecordCoverage(RecordCoverageInstr* instr) {
+  // Nothing to do.
+}
+
 void ConstantPropagator::VisitOneByteStringFromCharCode(
     OneByteStringFromCharCodeInstr* instr) {
   const Object& o = instr->char_code()->definition()->constant_value();
diff --git a/runtime/vm/compiler/backend/flow_graph.h b/runtime/vm/compiler/backend/flow_graph.h
index fa930ed..5aeec58 100644
--- a/runtime/vm/compiler/backend/flow_graph.h
+++ b/runtime/vm/compiler/backend/flow_graph.h
@@ -506,6 +506,9 @@
 
   void CreateCommonConstants();
 
+  const Array& coverage_array() const { return *coverage_array_; }
+  void set_coverage_array(const Array& array) { coverage_array_ = &array; }
+
  private:
   friend class FlowGraphCompiler;  // TODO(ajcbik): restructure
   friend class FlowGraphChecker;
@@ -629,6 +632,8 @@
 
   intptr_t inlining_id_;
   bool should_print_;
+
+  const Array* coverage_array_ = &Array::empty_array();
 };
 
 class LivenessAnalysis : public ValueObject {
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 7f82524..8e7e24d 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -3002,6 +3002,11 @@
   return NULL;
 }
 
+Instruction* RecordCoverageInstr::Canonicalize(FlowGraph* flow_graph) {
+  ASSERT(!coverage_array_.IsNull());
+  return coverage_array_.At(coverage_index_) != Smi::New(0) ? nullptr : this;
+}
+
 Definition* BoxInstr::Canonicalize(FlowGraph* flow_graph) {
   if (input_use_list() == nullptr) {
     // Environments can accommodate any representation. No need to box.
@@ -6783,6 +6788,28 @@
   return locs;
 }
 
+LocationSummary* RecordCoverageInstr::MakeLocationSummary(Zone* zone,
+                                                          bool opt) const {
+  const intptr_t kNumInputs = 0;
+  const intptr_t kNumTemps = 2;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  locs->set_temp(0, Location::RequiresRegister());
+  locs->set_temp(1, Location::RequiresRegister());
+  return locs;
+}
+
+void RecordCoverageInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const auto array_temp = locs()->temp(0).reg();
+  const auto value_temp = locs()->temp(1).reg();
+
+  __ LoadObject(array_temp, coverage_array_);
+  __ LoadImmediate(value_temp, Smi::RawValue(1));
+  __ StoreFieldToOffset(value_temp, array_temp,
+                        Array::element_offset(coverage_index_),
+                        compiler::kObjectBytes);
+}
+
 #undef Z
 
 Representation FfiCallInstr::representation() const {
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index a6f9d2d..a211039 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -426,6 +426,7 @@
   M(RelationalOp, kNoGC)                                                       \
   M(NativeCall, _)                                                             \
   M(DebugStepCheck, _)                                                         \
+  M(RecordCoverage, kNoGC)                                                     \
   M(LoadIndexed, kNoGC)                                                        \
   M(LoadCodeUnits, kNoGC)                                                      \
   M(StoreIndexed, kNoGC)                                                       \
@@ -6017,6 +6018,31 @@
   DISALLOW_COPY_AND_ASSIGN(StoreIndexedInstr);
 };
 
+class RecordCoverageInstr : public TemplateInstruction<0, NoThrow> {
+ public:
+  RecordCoverageInstr(const Array& coverage_array,
+                      intptr_t coverage_index,
+                      const InstructionSource& source)
+      : TemplateInstruction(source),
+        coverage_array_(coverage_array),
+        coverage_index_(coverage_index),
+        token_pos_(source.token_pos) {}
+
+  DECLARE_INSTRUCTION(RecordCoverage)
+
+  virtual TokenPosition token_pos() const { return token_pos_; }
+  virtual bool ComputeCanDeoptimize() const { return false; }
+  virtual bool HasUnknownSideEffects() const { return false; }
+  virtual Instruction* Canonicalize(FlowGraph* flow_graph);
+
+ private:
+  const Array& coverage_array_;
+  const intptr_t coverage_index_;
+  const TokenPosition token_pos_;
+
+  DISALLOW_COPY_AND_ASSIGN(RecordCoverageInstr);
+};
+
 // Note overrideable, built-in: value ? false : true.
 class BooleanNegateInstr : public TemplateDefinition<1, NoThrow> {
  public:
@@ -6164,6 +6190,7 @@
  private:
   friend class BranchInstr;
   friend class IfThenElseInstr;
+  friend class RecordCoverageInstr;
 
   virtual void RawSetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
 };
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index b16a368..7b9bac9 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -1138,10 +1138,25 @@
   return call_hook;
 }
 
+static bool SupportsCoverage() {
+#if defined(PRODUCT)
+  return false;
+#else
+  return !CompilerState::Current().is_aot();
+#endif
+}
+
 Fragment BaseFlowGraphBuilder::ClosureCall(TokenPosition position,
                                            intptr_t type_args_len,
                                            intptr_t argument_count,
                                            const Array& argument_names) {
+  Fragment result;
+
+  if (SupportsCoverage()) {
+    const intptr_t coverage_index = GetCoverageIndexFor(position);
+    result <<= new (Z) RecordCoverageInstr(coverage_array(), coverage_index,
+                                           InstructionSource(position));
+  }
   const intptr_t total_count =
       (type_args_len > 0 ? 1 : 0) + argument_count +
       /*closure (bare instructions) or function (otherwise)*/ 1;
@@ -1150,7 +1165,8 @@
       new (Z) ClosureCallInstr(arguments, type_args_len, argument_names,
                                InstructionSource(position), GetNextDeoptId());
   Push(call);
-  return Fragment(call);
+  result <<= call;
+  return result;
 }
 
 void BaseFlowGraphBuilder::reset_context_depth_for_deopt_id(intptr_t deopt_id) {
@@ -1233,5 +1249,53 @@
   return Fragment(instr);
 }
 
+intptr_t BaseFlowGraphBuilder::GetCoverageIndexFor(TokenPosition token_pos) {
+  if (coverage_array_.IsNull()) {
+    // We have not yet created coverage_array, this is the first time
+    // we are building the graph for this function. Collect coverage
+    // positions.
+    for (intptr_t i = 0; i < coverage_array_positions_.length(); i++) {
+      if (coverage_array_positions_.At(i) == token_pos) {
+        return 2 * i + 1;
+      }
+    }
+    const auto index = 2 * coverage_array_positions_.length() + 1;
+    coverage_array_positions_.Add(token_pos);
+    return index;
+  }
+
+  for (intptr_t i = 0; i < coverage_array_.Length(); i += 2) {
+    if (TokenPosition::Deserialize(Smi::Value(
+            static_cast<SmiPtr>(coverage_array_.At(i)))) == token_pos) {
+      return i + 1;
+    }
+  }
+  // Reaching here indicates that the graph is constructed in an unstable way.
+  UNREACHABLE();
+  return 1;
+}
+
+void BaseFlowGraphBuilder::FinalizeCoverageArray() {
+  if (!coverage_array_.IsNull()) {
+    return;
+  }
+
+  if (coverage_array_positions_.is_empty()) {
+    coverage_array_ = Array::empty_array().ptr();
+    return;
+  }
+
+  coverage_array_ =
+      Array::New(coverage_array_positions_.length() * 2, Heap::kOld);
+
+  Smi& value = Smi::Handle();
+  for (intptr_t i = 0; i < coverage_array_positions_.length(); i++) {
+    value = Smi::New(coverage_array_positions_[i].Serialize());
+    coverage_array_.SetAt(2 * i, value);
+    value = Smi::New(0);  // no coverage recorded.
+    coverage_array_.SetAt(2 * i + 1, value);
+  }
+}
+
 }  // namespace kernel
 }  // namespace dart
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index 0a5339f..ee7e7ce 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -159,7 +159,15 @@
         saved_args_desc_array_(
             has_saved_args_desc_array()
                 ? Array::ZoneHandle(zone_, function_.saved_args_desc())
-                : Object::null_array()) {}
+                : Object::null_array()),
+        coverage_array_(
+            Array::ZoneHandle(parsed_function->function().GetCoverageArray())) {
+  }
+
+  const Array& coverage_array() const { return coverage_array_; }
+
+  intptr_t GetCoverageIndexFor(TokenPosition token_pos);
+  void FinalizeCoverageArray();
 
   Fragment LoadField(const Field& field, bool calls_initializer);
   Fragment LoadNativeField(const Slot& native_field,
@@ -496,6 +504,9 @@
   const bool inlining_unchecked_entry_;
   const Array& saved_args_desc_array_;
 
+  GrowableArray<TokenPosition> coverage_array_positions_;
+  Array& coverage_array_;
+
   friend class StreamingFlowGraphBuilder;
 
  private:
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
index 6bb19fa..85ba707 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
@@ -333,6 +333,7 @@
     kMatchAndMoveCheckNull,
     kMatchAndMoveLoadField,
     kMoveDebugStepChecks,
+    kMatchAndMoveRecordCoverage,
     kMatchAndMoveClosureCall,
     kMoveDebugStepChecks,
     kMatchReturn,
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 503e051..efd2f8e 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -772,7 +772,12 @@
 
   StreamingFlowGraphBuilder streaming_flow_graph_builder(
       this, kernel_data, kernel_data_program_offset);
-  return streaming_flow_graph_builder.BuildGraph();
+  auto result = streaming_flow_graph_builder.BuildGraph();
+
+  FinalizeCoverageArray();
+  result->set_coverage_array(coverage_array());
+
+  return result;
 }
 
 Fragment FlowGraphBuilder::NativeFunctionBody(const Function& function,
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index b750d2d..b85bfec 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -461,11 +461,10 @@
       }
     }
   } else {  // not optimized.
-    if (function.ic_data_array() == Array::null()) {
-      function.SaveICDataMap(
-          graph_compiler->deopt_id_to_ic_data(),
-          Array::Handle(zone, graph_compiler->edge_counters_array()));
-    }
+    function.SaveICDataMap(
+        graph_compiler->deopt_id_to_ic_data(),
+        Array::Handle(zone, graph_compiler->edge_counters_array()),
+        flow_graph->coverage_array());
     function.set_unoptimized_code(code);
     function.AttachCode(code);
     function.SetWasCompiled(true);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index cf8f107..e272c5c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -9937,25 +9937,37 @@
 
 void Function::SaveICDataMap(
     const ZoneGrowableArray<const ICData*>& deopt_id_to_ic_data,
-    const Array& edge_counters_array) const {
+    const Array& edge_counters_array,
+    const Array& coverage_array) const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
+  // Already installed nothing to do.
+  if (ic_data_array() != Array::null()) {
+    ASSERT(coverage_array.ptr() == GetCoverageArray());
+    return;
+  }
+
   // Compute number of ICData objects to save.
-  // Store edge counter array in the first slot.
-  intptr_t count = 1;
+  intptr_t count = 0;
   for (intptr_t i = 0; i < deopt_id_to_ic_data.length(); i++) {
     if (deopt_id_to_ic_data[i] != NULL) {
       count++;
     }
   }
-  const Array& array = Array::Handle(Array::New(count, Heap::kOld));
-  count = 1;
-  for (intptr_t i = 0; i < deopt_id_to_ic_data.length(); i++) {
+
+  // Compress sparse deopt_id_to_ic_data mapping into a linear sequence of
+  // ICData objects.
+  const Array& array = Array::Handle(
+      Array::New(ICDataArrayIndices::kFirstICData + count, Heap::kOld));
+  for (intptr_t i = 0, pos = ICDataArrayIndices::kFirstICData;
+       i < deopt_id_to_ic_data.length(); i++) {
     if (deopt_id_to_ic_data[i] != NULL) {
       ASSERT(i == deopt_id_to_ic_data[i]->deopt_id());
-      array.SetAt(count++, *deopt_id_to_ic_data[i]);
+      array.SetAt(pos++, *deopt_id_to_ic_data[i]);
     }
   }
-  array.SetAt(0, edge_counters_array);
+  array.SetAt(ICDataArrayIndices::kEdgeCounters, edge_counters_array);
+  // Preserve coverage_array which is stored early after graph construction.
+  array.SetAt(ICDataArrayIndices::kCoverageData, coverage_array);
   set_ic_data_array(array);
 #else   // DART_PRECOMPILED_RUNTIME
   UNREACHABLE();
@@ -9979,7 +9991,7 @@
   }
   const intptr_t saved_length = saved_ic_data.Length();
   ASSERT(saved_length > 0);
-  if (saved_length > 1) {
+  if (saved_length > ICDataArrayIndices::kFirstICData) {
     const intptr_t restored_length =
         ICData::Cast(Object::Handle(zone, saved_ic_data.At(saved_length - 1)))
             .deopt_id() +
@@ -9988,7 +10000,7 @@
     for (intptr_t i = 0; i < restored_length; i++) {
       (*deopt_id_to_ic_data)[i] = NULL;
     }
-    for (intptr_t i = 1; i < saved_length; i++) {
+    for (intptr_t i = ICDataArrayIndices::kFirstICData; i < saved_length; i++) {
       ICData& ic_data = ICData::ZoneHandle(zone);
       ic_data ^= saved_ic_data.At(i);
       if (clone_ic_data) {
@@ -10005,6 +10017,14 @@
 #endif  // DART_PRECOMPILED_RUNTIME
 }
 
+ArrayPtr Function::GetCoverageArray() const {
+  const Array& arr = Array::Handle(ic_data_array());
+  if (arr.IsNull()) {
+    return Array::null();
+  }
+  return Array::RawCast(arr.At(ICDataArrayIndices::kCoverageData));
+}
+
 void Function::set_ic_data_array(const Array& value) const {
   untag()->set_ic_data_array<std::memory_order_release>(value.ptr());
 }
@@ -10020,7 +10040,7 @@
 ICDataPtr Function::FindICData(intptr_t deopt_id) const {
   const Array& array = Array::Handle(ic_data_array());
   ICData& ic_data = ICData::Handle();
-  for (intptr_t i = 1; i < array.Length(); i++) {
+  for (intptr_t i = ICDataArrayIndices::kFirstICData; i < array.Length(); i++) {
     ic_data ^= array.At(i);
     if (ic_data.deopt_id() == deopt_id) {
       return ic_data.ptr();
@@ -10033,7 +10053,7 @@
                                     ICData::DeoptReasonId reason) {
   const Array& array = Array::Handle(ic_data_array());
   ICData& ic_data = ICData::Handle();
-  for (intptr_t i = 1; i < array.Length(); i++) {
+  for (intptr_t i = ICDataArrayIndices::kFirstICData; i < array.Length(); i++) {
     ic_data ^= array.At(i);
     if (ic_data.deopt_id() == deopt_id) {
       ic_data.AddDeoptReason(reason);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index ad0d7cd..df0932e 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -3675,16 +3675,31 @@
   // Works with map [deopt-id] -> ICData.
   void SaveICDataMap(
       const ZoneGrowableArray<const ICData*>& deopt_id_to_ic_data,
-      const Array& edge_counters_array) const;
+      const Array& edge_counters_array,
+      const Array& coverage_array) const;
   // Uses 'ic_data_array' to populate the table 'deopt_id_to_ic_data'. Clone
   // ic_data (array and descriptor) if 'clone_ic_data' is true.
   void RestoreICDataMap(ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data,
                         bool clone_ic_data) const;
 
+  // ic_data_array attached to the function stores edge counters in the
+  // first element, coverage data array in the second element and the rest
+  // are ICData objects.
+  struct ICDataArrayIndices {
+    static constexpr intptr_t kEdgeCounters = 0;
+    static constexpr intptr_t kCoverageData = 1;
+    static constexpr intptr_t kFirstICData = 2;
+  };
+
   ArrayPtr ic_data_array() const;
   void ClearICDataArray() const;
   ICDataPtr FindICData(intptr_t deopt_id) const;
 
+  // Coverage data array is a list of pairs:
+  //   element 2 * i + 0 is token position
+  //   element 2 * i + 1 is coverage hit (zero meaning code was not hit)
+  ArrayPtr GetCoverageArray() const;
+
   // Sets deopt reason in all ICData-s with given deopt_id.
   void SetDeoptReasonForAll(intptr_t deopt_id, ICData::DeoptReasonId reason);
 
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index cc089f2..5ed79a5 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -29,7 +29,8 @@
     return;
   }
   ASSERT(ic_data_array_.Length() > 0);
-  edge_counters_ ^= ic_data_array_.At(0);
+  edge_counters_ ^=
+      ic_data_array_.At(Function::ICDataArrayIndices::kEdgeCounters);
   if (edge_counters_.IsNull()) {
     return;
   }
@@ -98,7 +99,7 @@
                        ICData* ic_data) {
   // ic_data_array is sorted because of how it is constructed in
   // Function::SaveICDataMap.
-  intptr_t lo = 1;
+  intptr_t lo = Function::ICDataArrayIndices::kFirstICData;
   intptr_t hi = ic_data_array.Length() - 1;
   while (lo <= hi) {
     intptr_t mid = (hi - lo + 1) / 2 + lo;
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index f72a72e..ede8d64 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -263,6 +263,21 @@
     coverage[0] = kCoverageMiss;
   }
 
+  auto update_coverage = [&](TokenPosition token_pos, bool was_executed) {
+    if (!token_pos.IsWithin(begin_pos, end_pos)) {
+      return;
+    }
+
+    const intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
+    if (was_executed) {
+      coverage[token_offset] = kCoverageHit;
+    } else {
+      if (coverage[token_offset] == kCoverageNone) {
+        coverage[token_offset] = kCoverageMiss;
+      }
+    }
+  };
+
   PcDescriptors::Iterator iter(
       descriptors,
       UntaggedPcDescriptors::kIcCall | UntaggedPcDescriptors::kUnoptStaticCall);
@@ -272,19 +287,19 @@
     const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
     if (ic_data != NULL) {
       const TokenPosition& token_pos = iter.TokenPos();
-      if (!token_pos.IsWithin(begin_pos, end_pos)) {
-        // Does not correspond to a valid source position.
-        continue;
-      }
-      intptr_t count = ic_data->AggregateCount();
-      intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
-      if (count > 0) {
-        coverage[token_offset] = kCoverageHit;
-      } else {
-        if (coverage[token_offset] == kCoverageNone) {
-          coverage[token_offset] = kCoverageMiss;
-        }
-      }
+      update_coverage(token_pos, ic_data->AggregateCount() > 0);
+    }
+  }
+
+  // Merge the coverage from coverage_array attached to the function.
+  const Array& coverage_array = Array::Handle(function.GetCoverageArray());
+  if (!coverage_array.IsNull()) {
+    for (intptr_t i = 0; i < coverage_array.Length(); i += 2) {
+      const TokenPosition token_pos = TokenPosition::Deserialize(
+          Smi::Value(Smi::RawCast(coverage_array.At(i))));
+      const bool was_executed =
+          Smi::Value(Smi::RawCast(coverage_array.At(i + 1))) != 0;
+      update_coverage(token_pos, was_executed);
     }
   }
 
diff --git a/runtime/vm/source_report_test.cc b/runtime/vm/source_report_test.cc
index 5934703..00c4c2e 100644
--- a/runtime/vm/source_report_test.cc
+++ b/runtime/vm/source_report_test.cc
@@ -339,7 +339,7 @@
 
       // One range compiled with one hit (helper0).
       "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":73,\"compiled\":true,"
-      "\"coverage\":{\"hits\":[0],\"misses\":[]}},"
+      "\"coverage\":{\"hits\":[0,56],\"misses\":[]}},"
 
       // One range not compiled (helper1).
       "{\"scriptIndex\":0,\"startPos\":75,\"endPos\":86,\"compiled\":false},"
@@ -402,7 +402,7 @@
 
       // One range compiled with one hit (helper0).
       "{\"scriptIndex\":0,\"startPos\":0,\"endPos\":73,\"compiled\":true,"
-      "\"coverage\":{\"hits\":[0],\"misses\":[]}},"
+      "\"coverage\":{\"hits\":[0,56],\"misses\":[]}},"
 
       // Nested range compiled (nestedHelper0).
       "{\"scriptIndex\":0,\"startPos\":14,\"endPos\":31,\"compiled\":true,"
diff --git a/sdk/lib/_http/http.dart b/sdk/lib/_http/http.dart
index 4193db2..84cfbdf 100644
--- a/sdk/lib/_http/http.dart
+++ b/sdk/lib/_http/http.dart
@@ -4,6 +4,8 @@
 
 library dart._http;
 
+import 'dart:_internal'
+    show Since, valueOfNonNullableParamWithDefault, HttpStatus;
 import 'dart:async';
 import 'dart:collection'
     show
@@ -15,11 +17,9 @@
         UnmodifiableMapView;
 import 'dart:convert';
 import 'dart:developer' hide log;
-import 'dart:_internal'
-    show Since, valueOfNonNullableParamWithDefault, HttpStatus;
+import 'dart:io';
 import 'dart:isolate' show Isolate;
 import 'dart:math';
-import 'dart:io';
 import 'dart:typed_data';
 
 part 'crypto.dart';
@@ -35,35 +35,39 @@
 
 /// A server that delivers content, such as web pages, using the HTTP protocol.
 ///
-/// The HttpServer is a [Stream] that provides [HttpRequest] objects. Each
-/// HttpRequest has an associated [HttpResponse] object.
-/// The server responds to a request by writing to that HttpResponse object.
-/// The following example shows how to bind an HttpServer to an IPv6
+/// Note: [HttpServer] provides low-level HTTP functionality.
+/// We recommend users evaluate the high-level APIs discussed at
+/// [Write HTTP servers](https://dart.dev/tutorials/server/httpserver) on
+/// [dart.dev](https://dart.dev/).
+///
+/// `HttpServer` is a [Stream] that provides [HttpRequest] objects. Each
+/// `HttpRequest` has an associated [HttpResponse] object.
+/// The server responds to a request by writing to that [HttpResponse] object.
+/// The following example shows how to bind an `HttpServer` to an IPv6
 /// [InternetAddress] on port 80 (the standard port for HTTP servers)
 /// and how to listen for requests.
 /// Port 80 is the default HTTP port. However, on most systems accessing
 /// this requires super-user privileges. For local testing consider
 /// using a non-reserved port (1024 and above).
 ///
-///     import 'dart:io';
+/// ```dart
+/// import 'dart:io';
 ///
-///     main() {
-///       HttpServer
-///           .bind(InternetAddress.anyIPv6, 80)
-///           .then((server) {
-///             server.listen((HttpRequest request) {
-///               request.response.write('Hello, world!');
-///               request.response.close();
-///             });
-///           });
-///     }
+/// Future<void> main() async {
+///   var server = await HttpServer.bind(InternetAddress.anyIPv6, 80);
+///   await server.forEach((HttpRequest request) {
+///     request.response.write('Hello, world!');
+///     request.response.close();
+///   });
+/// }
+/// ```
 ///
 /// Incomplete requests, in which all or part of the header is missing, are
-/// ignored, and no exceptions or HttpRequest objects are generated for them.
-/// Likewise, when writing to an HttpResponse, any [Socket] exceptions are
+/// ignored, and no exceptions or [HttpRequest] objects are generated for them.
+/// Likewise, when writing to an [HttpResponse], any [Socket] exceptions are
 /// ignored and any future writes are ignored.
 ///
-/// The HttpRequest exposes the request headers and provides the request body,
+/// The [HttpRequest] exposes the request headers and provides the request body,
 /// if it exists, as a Stream of data. If the body is unread, it is drained
 /// when the server writes to the HttpResponse or closes it.
 ///
@@ -75,62 +79,27 @@
 /// chain and the private key are set in the [SecurityContext]
 /// object that is passed to [bindSecure].
 ///
-///     import 'dart:io';
-///     import "dart:isolate";
+/// ```dart
+/// import 'dart:io';
 ///
-///     main() {
-///       SecurityContext context = new SecurityContext();
-///       var chain =
-///           Platform.script.resolve('certificates/server_chain.pem')
-///           .toFilePath();
-///       var key =
-///           Platform.script.resolve('certificates/server_key.pem')
-///           .toFilePath();
-///       context.useCertificateChain(chain);
-///       context.usePrivateKey(key, password: 'dartdart');
+/// Future<void> main() async {
+///   var chain =
+///       Platform.script.resolve('certificates/server_chain.pem').toFilePath();
+///   var key = Platform.script.resolve('certificates/server_key.pem').toFilePath();
+///   var context = SecurityContext()
+///     ..useCertificateChain(chain)
+///     ..usePrivateKey(key, password: 'dartdart');
+///   var server =
+///       await HttpServer.bindSecure(InternetAddress.anyIPv6, 443, context);
+///   await server.forEach((HttpRequest request) {
+///     request.response.write('Hello, world!');
+///     request.response.close();
+///   });
+/// }
+/// ```
 ///
-///       HttpServer
-///           .bindSecure(InternetAddress.anyIPv6,
-///                       443,
-///                       context)
-///           .then((server) {
-///             server.listen((HttpRequest request) {
-///               request.response.write('Hello, world!');
-///               request.response.close();
-///             });
-///           });
-///     }
-///
-///  The certificates and keys are PEM files, which can be created and
-///  managed with the tools in OpenSSL.
-///
-/// ## Connect to a server socket
-///
-/// You can use the [listenOn] constructor to attach an HTTP server to
-/// a [ServerSocket].
-///
-///     import 'dart:io';
-///
-///     main() {
-///       ServerSocket.bind(InternetAddress.anyIPv6, 80)
-///         .then((serverSocket) {
-///           HttpServer httpserver = new HttpServer.listenOn(serverSocket);
-///           serverSocket.listen((Socket socket) {
-///             socket.write('Hello, client.');
-///           });
-///         });
-///     }
-///
-/// ## Other resources
-///
-/// * HttpServer is a Stream. Refer to the [Stream] class for information
-/// about the streaming qualities of an HttpServer.
-/// Pausing the subscription of the stream, pauses at the OS level.
-///
-/// * The [shelf](https://pub.dev/packages/shelf)
-/// package on pub.dev contains a set of high-level classes that,
-/// together with this class, makes it easy to provide content through HTTP
-/// servers.
+/// The certificates and keys are PEM files, which can be created and
+/// managed with the tools in OpenSSL.
 abstract class HttpServer implements Stream<HttpRequest> {
   /// Gets and sets the default value of the `Server` header for all responses
   /// generated by this [HttpServer].
@@ -206,7 +175,7 @@
   /// value of 0 (the default) a reasonable value will be chosen by
   /// the system.
   ///
-  /// The optional argument [shared] specifies whether additional HttpServer
+  /// The optional argument [shared] specifies whether additional `HttpServer`
   /// objects can bind to the same combination of `address`, `port` and `v6Only`.
   /// If `shared` is `true` and more `HttpServer`s from this isolate or other
   /// isolates are bound to the port, then the incoming connections will be
@@ -247,7 +216,7 @@
   /// certificates, getting them from a [SecurityContext], where they have been
   /// set using [SecurityContext.setClientAuthorities].
   ///
-  /// The optional argument [shared] specifies whether additional HttpServer
+  /// The optional argument [shared] specifies whether additional `HttpServer`
   /// objects can bind to the same combination of `address`, `port` and `v6Only`.
   /// If `shared` is `true` and more `HttpServer`s from this isolate or other
   /// isolates are bound to the port, then the incoming connections will be
@@ -727,7 +696,7 @@
 /// use code like this:
 ///
 ///     HttpClientRequest request = ...;
-///     var v = new HeaderValue("text/plain", {"q": "0.3"});
+///     var v = HeaderValue("text/plain", {"q": "0.3"});
 ///     request.headers.add(HttpHeaders.acceptHeader, v);
 ///     request.headers.add(HttpHeaders.acceptHeader, "text/html");
 ///
@@ -775,6 +744,7 @@
   String toString();
 }
 
+/// The [session][HttpRequest.session] of an [HttpRequest].
 abstract class HttpSession implements Map {
   /// The id of the current session.
   String get id;
@@ -949,11 +919,6 @@
 /// A server-side object
 /// that contains the content of and information about an HTTP request.
 ///
-/// __Note__: Check out the
-/// [http_server](https://pub.dev/packages/http_server)
-/// package, which makes working with the low-level
-/// dart:io HTTP server subsystem easier.
-///
 /// `HttpRequest` objects are generated by an [HttpServer],
 /// which listens for HTTP requests on a specific host and port.
 /// For each request received, the HttpServer, which is a [Stream],
@@ -1100,7 +1065,7 @@
 ///
 ///     HttpResponse response = ...
 ///     response.headers.contentType
-///         = new ContentType("application", "json", charset: "utf-8");
+///         = ContentType("application", "json", charset: "utf-8");
 ///     response.write(...);  // Strings written will be UTF-8 encoded.
 ///
 /// If no charset is provided the default of ISO-8859-1 (Latin 1) will
@@ -1202,8 +1167,15 @@
   HttpConnectionInfo? get connectionInfo;
 }
 
-/// A client that receives content, such as web pages, from
-/// a server using the HTTP protocol.
+/// An HTTP client for communicating with an HTTP server.
+///
+/// Sends HTTP requests to an HTTP server and receives responses.
+/// Maintains state, including session cookies and other cookies,
+/// between multiple requests to the same server.
+///
+/// Note: [HttpClient] provides low-level HTTP functionality.
+/// We recommend users start with more developer-friendly and composable APIs
+/// found in [`package:http`](https://pub.dev/packages/http).
 ///
 /// HttpClient contains a number of methods to send an [HttpClientRequest]
 /// to an Http server and receive an [HttpClientResponse] back.
@@ -1223,30 +1195,31 @@
 /// the second future, which is returned by close,
 /// completes with an [HttpClientResponse] object.
 /// This object provides access to the headers and body of the response.
-/// The body is available as a stream implemented by HttpClientResponse.
+/// The body is available as a stream implemented by `HttpClientResponse`.
 /// If a body is present, it must be read. Otherwise, it leads to resource
 /// leaks. Consider using [HttpClientResponse.drain] if the body is unused.
 ///
-///     HttpClient client = new HttpClient();
-///     client.getUrl(Uri.parse("http://www.example.com/"))
-///         .then((HttpClientRequest request) {
-///           // Optionally set up headers...
-///           // Optionally write to the request object...
-///           // Then call close.
-///           ...
-///           return request.close();
-///         })
-///         .then((HttpClientResponse response) {
-///           // Process the response.
-///           ...
-///         });
+/// ```dart
+/// var client = HttpClient();
+/// try {
+///   HttpClientRequest request = await client.get('localhost', 80, '/file.txt');
+///   // Optionally set up headers...
+///   // Optionally write to the request object...
+///   HttpClientResponse response = await request.close();
+///   // Process the response
+///   final stringData = await response.transform(utf8.decoder).join();
+///   print(stringData);
+/// } finally {
+///   client.close();
+/// }
+/// ```
 ///
 /// The future for [HttpClientRequest] is created by methods such as
 /// [getUrl] and [open].
 ///
 /// ## HTTPS connections
 ///
-/// An HttpClient can make HTTPS requests, connecting to a server using
+/// An `HttpClient` can make HTTPS requests, connecting to a server using
 /// the TLS (SSL) secure networking protocol. Calling [getUrl] with an
 /// https: scheme will work automatically, if the server's certificate is
 /// signed by a root CA (certificate authority) on the default list of
@@ -1259,7 +1232,7 @@
 ///
 /// ## Headers
 ///
-/// All HttpClient requests set the following header by default:
+/// All `HttpClient` requests set the following header by default:
 ///
 ///     Accept-Encoding: gzip
 ///
@@ -1270,23 +1243,22 @@
 ///
 ///      request.headers.removeAll(HttpHeaders.acceptEncodingHeader)
 ///
-/// ## Closing the HttpClient
+/// ## Closing the `HttpClient`
 ///
-/// The HttpClient supports persistent connections and caches network
+/// `HttpClient` supports persistent connections and caches network
 /// connections to reuse them for multiple requests whenever
 /// possible. This means that network connections can be kept open for
-/// some time after a request has completed. Use HttpClient.close
-/// to force the HttpClient object to shut down and to close the idle
+/// some time after a request has completed. Use [HttpClient.close]
+/// to force the `HttpClient` object to shut down and to close the idle
 /// network connections.
 ///
 /// ## Turning proxies on and off
 ///
-/// By default the HttpClient uses the proxy configuration available
+/// By default the `HttpClient` uses the proxy configuration available
 /// from the environment, see [findProxyFromEnvironment]. To turn off
-/// the use of proxies set the [findProxy] property to
-/// `null`.
+/// the use of proxies set the [findProxy] property to `null`.
 ///
-///     HttpClient client = new HttpClient();
+///     HttpClient client = HttpClient();
 ///     client.findProxy = null;
 abstract class HttpClient {
   static const int defaultHttpPort = 80;
@@ -1601,13 +1573,13 @@
   /// To activate this way of resolving proxies assign this function to
   /// the [findProxy] property on the [HttpClient].
   ///
-  ///     HttpClient client = new HttpClient();
+  ///     HttpClient client = HttpClient();
   ///     client.findProxy = HttpClient.findProxyFromEnvironment;
   ///
   /// If you don't want to use the system environment you can use a
   /// different one by wrapping the function.
   ///
-  ///     HttpClient client = new HttpClient();
+  ///     HttpClient client = HttpClient();
   ///     client.findProxy = (url) {
   ///       return HttpClient.findProxyFromEnvironment(
   ///           url, environment: {"http_proxy": ..., "no_proxy": ...});
@@ -1665,9 +1637,9 @@
   /// returned `false`
   ///
   /// If the callback returns true, the secure connection is accepted and the
-  /// [:Future<HttpClientRequest>:] that was returned from the call making the
+  /// `Future<HttpClientRequest>` that was returned from the call making the
   /// request completes with a valid HttpRequest object. If the callback returns
-  /// false, the [:Future<HttpClientRequest>:] completes with an exception.
+  /// false, the `Future<HttpClientRequest>` completes with an exception.
   ///
   /// If a bad certificate is received on a connection attempt, the library calls
   /// the function that was the value of badCertificateCallback at the time
@@ -1691,8 +1663,8 @@
 ///
 /// To set up a request, set the headers using the headers property
 /// provided in this class and write the data to the body of the request.
-/// HttpClientRequest is an [IOSink]. Use the methods from IOSink,
-/// such as writeCharCode(), to write the body of the HTTP
+/// `HttpClientRequest` is an [IOSink]. Use the methods from IOSink,
+/// such as `writeCharCode()`, to write the body of the HTTP
 /// request. When one of the IOSink methods is used for the first
 /// time, the request header is sent. Calling any methods that
 /// change the header after it is sent throws an exception.
@@ -1701,17 +1673,20 @@
 /// encoding used is determined from the "charset" parameter of
 /// the "Content-Type" header.
 ///
-///     HttpClientRequest request = ...
-///     request.headers.contentType
-///         = new ContentType("application", "json", charset: "utf-8");
-///     request.write(...);  // Strings written will be UTF-8 encoded.
+/// ```dart
+/// HttpClientRequest request = await client.get('localhost', 80, '/file.txt');
+/// request.headers.contentType =
+///     ContentType('application', 'json', charset: 'utf-8');
+/// request.write('text content👍🎯'); // Strings written will be UTF-8 encoded.
+/// ```
 ///
-/// If no charset is provided the default of ISO-8859-1 (Latin 1) is
-/// be used.
+/// If no charset is provided the default of ISO-8859-1 (Latin 1) is used.
 ///
-///     HttpClientRequest request = ...
-///     request.headers.add(HttpHeaders.contentTypeHeader, "text/plain");
-///     request.write(...);  // Strings written will be ISO-8859-1 encoded.
+/// ```dart
+/// HttpClientRequest request = await client.get('localhost', 80, '/file.txt');
+/// request.headers.add(HttpHeaders.contentTypeHeader, "text/plain");
+/// request.write('blåbærgrød'); // Strings written will be ISO-8859-1 encoded
+/// ```
 ///
 /// An exception is thrown if you use an unsupported encoding and the
 /// `write()` method being used takes a string parameter.
@@ -1825,17 +1800,21 @@
 
 /// HTTP response for a client connection.
 ///
-/// The body of a [HttpClientResponse] object is a
-/// [Stream] of data from the server. Listen to the body to handle
-/// the data and be notified when the entire body is received.
+/// The body of a [HttpClientResponse] object is a [Stream] of data from the
+/// server. Use [Stream] methods like [`transform`][Stream.transform] and
+/// [`join`][Stream.join] to access the data.
 ///
-///     new HttpClient().get('localhost', 80, '/file.txt')
-///          .then((HttpClientRequest request) => request.close())
-///          .then((HttpClientResponse response) {
-///            response.transform(utf8.decoder).listen((contents) {
-///              // handle data
-///            });
-///          });
+/// ```dart
+/// var client = HttpClient();
+/// try {
+///   HttpClientRequest request = await client.get('localhost', 80, '/file.txt');
+///   HttpClientResponse response = await request.close();
+///   final stringData = await response.transform(utf8.decoder).join();
+///   print(stringData);
+/// } finally {
+///   client.close();
+/// }
+/// ```
 abstract class HttpClientResponse implements Stream<List<int>> {
   /// Returns the status code.
   ///
@@ -2008,16 +1987,6 @@
   Uri get location;
 }
 
-/// When detaching a socket from either the [:HttpServer:] or the
-/// [:HttpClient:] due to a HTTP connection upgrade there might be
-/// unparsed data already read from the socket. This unparsed data
-/// together with the detached socket is returned in an instance of
-/// this class.
-abstract class DetachedSocket {
-  Socket get socket;
-  List<int> get unparsedData;
-}
-
 class HttpException implements IOException {
   final String message;
   final Uri? uri;
diff --git a/sdk/lib/_http/overrides.dart b/sdk/lib/_http/overrides.dart
index 5c49590..db464f8 100644
--- a/sdk/lib/_http/overrides.dart
+++ b/sdk/lib/_http/overrides.dart
@@ -26,7 +26,7 @@
 ///     // Operations will use MyHttpClient instead of the real HttpClient
 ///     // implementation whenever HttpClient is used.
 ///     ...
-///   }, createHttpClient: (SecurityContext c) => new MyHttpClient(c));
+///   }, createHttpClient: (SecurityContext c) => MyHttpClient(c));
 /// }
 /// ```
 abstract class HttpOverrides {
diff --git a/sdk/lib/cli/cli.dart b/sdk/lib/cli/cli.dart
index 223dd68..f43efeb 100644
--- a/sdk/lib/cli/cli.dart
+++ b/sdk/lib/cli/cli.dart
@@ -2,8 +2,14 @@
 // 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.
 
+/// Utilities for building CLI apps.
+///
+/// ## Deprecation notice
+///
+/// The functionality of this library is incomplete and may be removed in a
+/// later version. See [waitFor] for details.
+///
 /// {@category VM}
-/// {@nodoc}
 @Deprecated(
     "The functionality of this library is incomplete and may be removed in a later version")
 library dart.cli;
diff --git a/sdk/lib/cli/wait_for.dart b/sdk/lib/cli/wait_for.dart
index 29e5386..2aa8ff8 100644
--- a/sdk/lib/cli/wait_for.dart
+++ b/sdk/lib/cli/wait_for.dart
@@ -69,7 +69,32 @@
  * Suspends the stack, runs microtasks, and handles incoming events until
  * [future] completes.
  *
- * WARNING: EXPERIMENTAL. USE AT YOUR OWN RISK.
+ * ## Deprecation notice
+ *
+ * The `waitFor` feature is deprecated.
+ * The feature was intended to solve a particular problem for existing code,
+ * a problem introduced by a breaking change to the platform libraries.
+ * The `waitFor` function is not suitable for general use.
+ * The feature has shortcomings that can affect other code
+ * running in the same isolate, including:
+ *  * A function call that looks synchronous may cause other asynchronous
+ *    events to run before it returns.
+ *    This is something synchronous code can usually assume not to happen,
+ *    and some code may have been written to take advantage of that
+ *    assumed behavior. Such code can fail in unexpected ways.
+ *  * Multiple nested calls to `waitFor` may block each other
+ *    since the most recent call always needs to complete
+ *    before any other call can complete.
+ *    Judicious use of `waitFor` is necessary to avoid unexpected deadlocks
+ *    which wouldn't happen if using `await` instead.
+ *    If more than one library in the same program is using `waitFor`,
+ *    then it's hard to avoid or control whether such blocking will happen.
+ *
+ * The feature is not actively maintained.
+ * It will remain as-is to support the original problem it was added to solve,
+ * at least until that problem can be solved in some other way.
+ * 
+ * ## Call semantics
  *
  * This call does the following:
  * - While [future] is not completed:
@@ -111,30 +136,6 @@
  * Please be aware that nesting calls to [waitFor] can lead to deadlock if
  * subsequent calls block waiting for a condition that is only satisfied when
  * an earlier call returns.
- *
- * **NOTICE**
- * The `waitFor` feature is deprecated.
- * The feature was intended to solve a particular problem for existing code,
- * a problem introduced by a breaking change to the platform libraries.
- * The `waitFor` function is not suitable for general use.
- * The feature has shortcomings that can affect other code
- * running in the same isolate, including:
- *  * A function call that looks synchronous may cause other asynchronous
- *    events to run before it returns.
- *    This is something synchronous code can usually assume not to happen,
- *    and some code may have been written to take advantage of that
- *    assumed behavior. Such code can fail in unexpected ways.
- *  * Multiple nested calls to `waitFor` may block each other
- *    since the most recent call always needs to complete
- *    before any other call can complete.
- *    Judicious use of `waitFor` is necessary to avoid unexpected deadlocks
- *    which wouldn't happen if using `await` instead.
- *    If more than one library in the same program is using `waitFor`,
- *    then it's hard to avoid or control whether such blocking will happen.
- *
- * The feature is not actively maintained.
- * It will remain as-is to support the original problem it was added to solve,
- * at least until that problem can be solved in some other way.
  */
 @Deprecated(
     "This functionality is incomplete and may be removed in a later version")
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index f504810..dbecc26 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -62,16 +62,17 @@
 /// ```
 /// ## HttpServer and HttpClient
 ///
-/// The classes [HttpServer] and [HttpClient]
-/// provide HTTP server and HTTP client functionality.
+/// The classes [HttpClient] and [HttpServer] provide low-level HTTP
+/// functionality.
 ///
-/// The [HttpServer] class provides the basic functionality for
-/// implementing an HTTP server.
-/// For some higher-level building-blocks, we recommend that you try
-/// the [shelf](https://pub.dev/packages/shelf)
-/// pub package, which contains
-/// a set of high-level classes that, together with the [HttpServer] class
-/// in this library, make it easier to implement HTTP servers.
+/// Instead of using these classes directly, consider using more
+/// developer-friendly and composable APIs found in packages.
+///
+/// For HTTP clients, look at [`package:http`](https://pub.dev/packages/http).
+///
+/// For HTTP servers, look at
+/// [Write HTTP servers](https://dart.dev/tutorials/server/httpserver) on
+/// [dart.dev](https://dart.dev/).
 ///
 /// ## Process
 ///
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index f8283f9..d439fd4 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -582,7 +582,10 @@
   /// If the port is a native port -- one provided by [ReceivePort.sendPort] or
   /// [RawReceivePort.sendPort] -- the system may be able to send this final
   /// message more efficiently than normal port communication between live
-  /// isolates.
+  /// isolates. In these cases this final message object graph will be
+  /// reassigned to the receiving isolate without copying. Further, the
+  /// receiving isolate will in most cases be able to receive the message
+  /// in constant time.
   external static Never exit([SendPort? finalMessagePort, Object? message]);
 }
 
diff --git a/tools/VERSION b/tools/VERSION
index ea1d582..f8a05d9 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 260
+PRERELEASE 261
 PRERELEASE_PATCH 0
\ No newline at end of file