Version 2.12.0-113.0.dev

Merge commit 'd86f0e2836d0941776f911dfc86ff444121fd29d' into 'dev'
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 3af28cb..0bce9d2 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  1.32.0
+  1.32.1
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -235,6 +235,11 @@
   the server so clients should ensure unknown values are handled gracefully, either
   ignoring the item or treating it with some default/fallback handling.
 </p>
+<h3>Changelog</h3>
+<h4>1.32.1</h4>
+<ul>
+  <li>Added <tt>CompletionSuggestionKind.PACKAGE_NAME</tt> for Pub package name completions in <tt>pubspec.yaml</tt></li>
+</ul>
 <h3>Domains</h3>
 <p>
   For convenience, the API is divided into domains. Each domain is specified
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index cdccff0..7636ffc 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.32.0';
+const String PROTOCOL_VERSION = '1.32.1';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 56c7ee0..145b8bf 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -74,14 +74,22 @@
         RegExp(r'[$}\\]'), // Replace any of $ } \
         (c) => '\\${c[0]}', // Prefix with a backslash
       );
+
   // Snippets syntax is documented in the LSP spec:
-  // https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/#snippet-syntax
+  // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax
   //
   // $1, $2, etc. are used for tab stops and ${1:foo} inserts a placeholder of foo.
 
   final output = [];
   var offset = 0;
-  var tabStopNumber = 1;
+
+  // When there's only a single tabstop, it should be ${0} as this is treated
+  // specially as the final cursor position (if we use 1, the editor will insert
+  // a 0 at the end of the string which is not what we expect).
+  // When there are multiple, start with ${1} since these are placeholders the
+  // user can tab through and the editor-inserted ${0} at the end is expected.
+  var tabStopNumber = offsetLengthPairs.length <= 2 ? 0 : 1;
+
   for (var i = 0; i < offsetLengthPairs.length; i += 2) {
     final pairOffset = offsetLengthPairs[i];
     final pairLength = offsetLengthPairs[i + 1];
@@ -852,9 +860,11 @@
               suggestion.defaultArgumentListString,
               suggestion.defaultArgumentListTextRanges,
             )
-          : '\${1:}'; // No required params still gets a tabstop in the parens.
+          : '\${0:}'; // No required params still gets a tabstop in the parens.
       insertText += '($functionCallSuffix)';
-    } else if (suggestion.selectionOffset != 0) {
+    } else if (suggestion.selectionOffset != 0 &&
+        // We don't need a tabstop if the selection is the end of the string.
+        suggestion.selectionOffset != suggestion.completion.length) {
       insertTextFormat = lsp.InsertTextFormat.Snippet;
       insertText = buildSnippetStringWithTabStops(
         suggestion.completion,
diff --git a/pkg/analysis_server/test/lsp/completion_dart_test.dart b/pkg/analysis_server/test/lsp/completion_dart_test.dart
index e1591e8..304bbbb 100644
--- a/pkg/analysis_server/test/lsp/completion_dart_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_dart_test.dart
@@ -145,7 +145,7 @@
     final item = res.singleWhere((c) => c.label == 'myFunction(…)');
     // With no required params, there should still be parens and a tabstop inside.
     expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
-    expect(item.insertText, equals(r'myFunction(${1:})'));
+    expect(item.insertText, equals(r'myFunction(${0:})'));
     expect(item.textEdit.newText, equals(item.insertText));
     expect(
       item.textEdit.range,
@@ -170,10 +170,10 @@
     await openFile(mainFileUri, withoutMarkers(content));
     final res = await getCompletion(mainFileUri, positionFromMarker(content));
     final item = res.singleWhere((c) => c.label == 'min(…)');
-    // Ensure the snippet does not include the parens/args as it doesn't
-    // make sense in the show clause. There will still be a trailing tabstop.
-    expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
-    expect(item.insertText, equals(r'min${1:}'));
+    // The insert text should be a simple string with no parens/args and
+    // no need for snippets.
+    expect(item.insertTextFormat, isNull);
+    expect(item.insertText, equals(r'min'));
     expect(item.textEdit.newText, equals(item.insertText));
   }
 
@@ -540,7 +540,7 @@
     expect(updated, contains('one: '));
   }
 
-  Future<void> test_namedArg_snippetStringSelection() async {
+  Future<void> test_namedArg_snippetStringSelection_endOfString() async {
     final content = '''
     class A { const A({int one}); }
     @A(^)
@@ -554,11 +554,43 @@
     final res = await getCompletion(mainFileUri, positionFromMarker(content));
     expect(res.any((c) => c.label == 'one: '), isTrue);
     final item = res.singleWhere((c) => c.label == 'one: ');
+    // As the selection is the end of the string, there's no need for a snippet
+    // here. Since the insert text is also the same as the label, it does not
+    // need to be provided.
+    expect(item.insertTextFormat, isNull);
+    expect(item.insertText, isNull);
+    expect(item.textEdit.newText, equals('one: '));
+    expect(
+      item.textEdit.range,
+      equals(Range(
+          start: positionFromMarker(content),
+          end: positionFromMarker(content))),
+    );
+  }
+
+  Future<void>
+      test_namedArgTrailing_snippetStringSelection_insideString() async {
+    final content = '''
+    main({int one, int two}) {
+      main(
+        ^
+        two: 2,
+      );
+    }
+    ''';
+
+    await initialize(
+        textDocumentCapabilities: withCompletionItemSnippetSupport(
+            emptyTextDocumentClientCapabilities));
+    await openFile(mainFileUri, withoutMarkers(content));
+    final res = await getCompletion(mainFileUri, positionFromMarker(content));
+    expect(res.any((c) => c.label == 'one: '), isTrue);
+    final item = res.singleWhere((c) => c.label == 'one: ');
     // Ensure the snippet comes through in the expected format with the expected
     // placeholder.
     expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
-    expect(item.insertText, equals(r'one: ${1:}'));
-    expect(item.textEdit.newText, equals(r'one: ${1:}'));
+    expect(item.insertText, equals(r'one: ${0:},'));
+    expect(item.textEdit.newText, equals(r'one: ${0:},'));
     expect(
       item.textEdit.range,
       equals(Range(
diff --git a/pkg/analysis_server/test/lsp/mapping_test.dart b/pkg/analysis_server/test/lsp/mapping_test.dart
index 72bf3f6..9d88d76 100644
--- a/pkg/analysis_server/test/lsp/mapping_test.dart
+++ b/pkg/analysis_server/test/lsp/mapping_test.dart
@@ -76,7 +76,7 @@
 
   Future<void> test_tabStopsInSnippets_contains() async {
     var result = lsp.buildSnippetStringWithTabStops('a, b, c', [3, 1]);
-    expect(result, equals(r'a, ${1:b}, c'));
+    expect(result, equals(r'a, ${0:b}, c'));
   }
 
   Future<void> test_tabStopsInSnippets_empty() async {
@@ -86,13 +86,13 @@
 
   Future<void> test_tabStopsInSnippets_endsWith() async {
     var result = lsp.buildSnippetStringWithTabStops('a, b', [3, 1]);
-    expect(result, equals(r'a, ${1:b}'));
+    expect(result, equals(r'a, ${0:b}'));
   }
 
   Future<void> test_tabStopsInSnippets_escape() async {
     var result = lsp.buildSnippetStringWithTabStops(
         r'te$tstri}ng, te$tstri}ng, te$tstri}ng', [13, 11]);
-    expect(result, equals(r'te\$tstri\}ng, ${1:te\$tstri\}ng}, te\$tstri\}ng'));
+    expect(result, equals(r'te\$tstri\}ng, ${0:te\$tstri\}ng}, te\$tstri\}ng'));
   }
 
   Future<void> test_tabStopsInSnippets_multiple() async {
@@ -103,6 +103,6 @@
 
   Future<void> test_tabStopsInSnippets_startsWith() async {
     var result = lsp.buildSnippetStringWithTabStops('a, b', [0, 1]);
-    expect(result, equals(r'${1:a}, b'));
+    expect(result, equals(r'${0:a}, b'));
   }
 }
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index 2e467ab..1d1665c 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -54,14 +54,19 @@
     return io.exit(1);
   }
 
+  var options = CompletionMetricsOptions(
+      availableSuggestions: result[AVAILABLE_SUGGESTIONS],
+      overlay: result[OVERLAY],
+      printMissedCompletionDetails: result[PRINT_MISSED_COMPLETION_DETAILS],
+      printMissedCompletionSummary: result[PRINT_MISSED_COMPLETION_SUMMARY],
+      printMissingInformation: result[PRINT_MISSING_INFORMATION],
+      printMrrByLocation: result[PRINT_MRR_BY_LOCATION],
+      printSlowestResults: result[PRINT_SLOWEST_RESULTS],
+      printWorstResults: result[PRINT_WORST_RESULTS]);
   var root = result.rest[0];
   print('Analyzing root: "$root"');
   var stopwatch = Stopwatch()..start();
-  var code = await CompletionMetricsComputer(root,
-          availableSuggestions: result[AVAILABLE_SUGGESTIONS],
-          overlay: result[OVERLAY],
-          verbose: result[VERBOSE])
-      .compute();
+  var code = await CompletionMetricsComputer(root, options).compute();
   stopwatch.stop();
 
   var duration = Duration(milliseconds: stopwatch.elapsedMilliseconds);
@@ -86,8 +91,34 @@
 /// completion offset should be removed.
 const String OVERLAY_REMOVE_TOKEN = 'remove-token';
 
-/// A flag that causes additional output to be produced.
-const String VERBOSE = 'verbose';
+/// A flag that causes detailed information to be printed every time a
+/// completion request fails to produce a suggestions matching the expected
+/// suggestion.
+const String PRINT_MISSED_COMPLETION_DETAILS =
+    'print-missed-completion-details';
+
+/// A flag that causes summary information to be printed about the times that a
+/// completion request failed to produce a suggestions matching the expected
+/// suggestion.
+const String PRINT_MISSED_COMPLETION_SUMMARY =
+    'print-missed-completion-summary';
+
+/// A flag that causes information to be printed about places where no
+/// completion location was computed and about information that's missing in the
+/// completion tables.
+const String PRINT_MISSING_INFORMATION = 'print-missing-information';
+
+/// A flag that causes information to be printed about the mrr score achieved at
+/// each completion location.
+const String PRINT_MRR_BY_LOCATION = 'print-mrr-by-location';
+
+/// A flag that causes information to be printed about the completion requests
+/// that were the slowest to return suggestions.
+const String PRINT_SLOWEST_RESULTS = 'print-slowest-results';
+
+/// A flag that causes information to be printed about the completion requests
+/// that had the worst mrr scores.
+const String PRINT_WORST_RESULTS = 'print-worst-results';
 
 /// A [Counter] to track the performance of each of the completion strategies
 /// that are being compared.
@@ -96,26 +127,21 @@
 /// Create a parser that can be used to parse the command-line arguments.
 ArgParser createArgParser() {
   return ArgParser()
+    ..addFlag(AVAILABLE_SUGGESTIONS,
+        abbr: 'a',
+        help:
+            'Use the available suggestions feature in the Analysis Server when '
+            'computing the set of code completions. With this feature enabled, '
+            'completion will match the support in the Dart Plugin for '
+            'IntelliJ, without this enabled the completion support matches the '
+            'support in LSP.',
+        defaultsTo: false,
+        negatable: false)
     ..addOption(
       'help',
       abbr: 'h',
       help: 'Print this help message.',
     )
-    ..addFlag(
-      VERBOSE,
-      abbr: 'v',
-      help: 'Print additional information about the analysis',
-      negatable: false,
-    )
-    ..addFlag(AVAILABLE_SUGGESTIONS,
-        abbr: 'a',
-        help: 'Use the available suggestions feature in the Analysis Server '
-            'when computing the set of code completions. With this feature '
-            'enabled, completion will match the support in the Dart Plugin for '
-            'IntelliJ, without this enabled the completion support matches '
-            'the support in LSP.',
-        defaultsTo: false,
-        negatable: false)
     ..addOption(OVERLAY,
         allowed: [
           OVERLAY_NONE,
@@ -125,9 +151,46 @@
         defaultsTo: OVERLAY_NONE,
         help:
             'Before attempting a completion at the location of each token, the '
-            'token can be removed, or the rest of the file can be removed to test '
-            'code completion with diverse methods. The default mode is to '
-            'complete at the start of the token without modifying the file.');
+            'token can be removed, or the rest of the file can be removed to '
+            'test code completion with diverse methods. The default mode is to '
+            'complete at the start of the token without modifying the file.')
+    ..addFlag(PRINT_MISSED_COMPLETION_DETAILS,
+        defaultsTo: false,
+        help:
+            'Print detailed information every time a completion request fails '
+            'to produce a suggestions matching the expected suggestion.',
+        negatable: false)
+    ..addFlag(PRINT_MISSED_COMPLETION_SUMMARY,
+        defaultsTo: false,
+        help: 'Print summary information about the times that a completion '
+            'request failed to produce a suggestions matching the expected '
+            'suggestion.',
+        negatable: false)
+    ..addFlag(PRINT_MISSING_INFORMATION,
+        defaultsTo: false,
+        help: 'Print information about places where no completion location was '
+            'computed and about information that is missing in the completion '
+            'tables.',
+        negatable: false)
+    ..addFlag(PRINT_MRR_BY_LOCATION,
+        defaultsTo: false,
+        help:
+            'Print information about the mrr score achieved at each completion '
+            'location. This can help focus efforts to improve the overall '
+            'score by pointing out the locations that are causing the biggest '
+            'impact.',
+        negatable: false)
+    ..addFlag(PRINT_SLOWEST_RESULTS,
+        defaultsTo: false,
+        help: 'Print information about the completion requests that were the '
+            'slowest to return suggestions.',
+        negatable: false)
+    ..addFlag(PRINT_WORST_RESULTS,
+        defaultsTo: false,
+        help:
+            'Print information about the completion requests that had the worst '
+            'mrr scores.',
+        negatable: false);
 }
 
 /// Print usage information for this tool.
@@ -446,11 +509,7 @@
 class CompletionMetricsComputer {
   final String rootPath;
 
-  final bool availableSuggestions;
-
-  final String overlay;
-
-  final bool verbose;
+  final CompletionMetricsOptions options;
 
   ResolvedUnitResult _resolvedUnitResult;
 
@@ -465,13 +524,7 @@
 
   int overlayModificationStamp = 0;
 
-  CompletionMetricsComputer(this.rootPath,
-      {@required this.availableSuggestions,
-      @required this.overlay,
-      @required this.verbose})
-      : assert(overlay == OVERLAY_NONE ||
-            overlay == OVERLAY_REMOVE_TOKEN ||
-            overlay == OVERLAY_REMOVE_REST_OF_FILE);
+  CompletionMetricsComputer(this.rootPath, this.options);
 
   Future<int> compute() async {
     resultCode = 0;
@@ -485,6 +538,7 @@
     for (var context in collection.contexts) {
       await _computeInContext(context.contextRoot);
     }
+    printComparison();
     for (var metrics in targetMetrics) {
       printMetrics(metrics);
 
@@ -493,11 +547,15 @@
       rankComparison.printCounterValues();
       print('====================');
 
-      if (verbose) {
-        printWorstResults(metrics);
-        printSlowestResults(metrics);
+      if (options.printMissingInformation) {
         printMissingInformation(metrics);
       }
+      if (options.printSlowestResults) {
+        printSlowestResults(metrics);
+      }
+      if (options.printWorstResults) {
+        printWorstResults(metrics);
+      }
     }
     return resultCode;
   }
@@ -561,12 +619,42 @@
     }
   }
 
+  void printComparison() {
+    List<String> toRow(Iterable<MeanReciprocalRankComputer> computers) {
+      return [
+        computers.first.name,
+        for (var computer in computers) (1 / computer.mrr).toStringAsFixed(3),
+      ];
+    }
+
+    var buffer = StringBuffer();
+    var table = [
+      ['', for (var metrics in targetMetrics) metrics.name],
+      toRow(targetMetrics.map((metrics) => metrics.mrrComputer)),
+      toRow(targetMetrics.map((metrics) => metrics.successfulMrrComputer)),
+      toRow(targetMetrics.map((metrics) => metrics.instanceMemberMrrComputer)),
+      toRow(targetMetrics.map((metrics) => metrics.staticMemberMrrComputer)),
+      toRow(targetMetrics.map((metrics) => metrics.typeRefMrrComputer)),
+      toRow(targetMetrics.map((metrics) => metrics.localRefMrrComputer)),
+      toRow(targetMetrics.map((metrics) => metrics.paramRefMrrComputer)),
+      toRow(targetMetrics.map((metrics) => metrics.topLevelMrrComputer)),
+    ];
+    for (var i = 1; i < table[0].length; i++) {
+      rightJustifyColumn(i, table);
+    }
+    buffer.writeTable(table);
+
+    print('');
+    print('Comparison of inverse mean reciprocal ranks (lower is better)');
+    print('');
+    print(buffer.toString());
+  }
+
   void printMetrics(CompletionMetrics metrics) {
-    print('');
-    print('');
     print('====================');
     print('Completion metrics for ${metrics.name}:');
-    if (verbose) {
+    print('');
+    if (options.printMissedCompletionSummary) {
       metrics.completionMissedTokenCounter.printCounterValues();
       print('');
 
@@ -577,31 +665,39 @@
       print('');
     }
 
-    metrics.mrrComputer.printMean();
-    print('');
+    List<String> toRow(MeanReciprocalRankComputer computer) {
+      return [
+        computer.name,
+        computer.mrr.toStringAsFixed(6),
+        (1 / computer.mrr).toStringAsFixed(3),
+        computer.mrr_5.toStringAsFixed(6),
+        (1 / computer.mrr_5).toStringAsFixed(3),
+        computer.count.toString(),
+      ];
+    }
 
-    metrics.successfulMrrComputer.printMean();
-    print('');
+    var buffer = StringBuffer();
+    var table = [
+      ['', 'mrr', 'inverse mrr', 'mrr_5', 'inverse mrr_5', 'count'],
+      toRow(metrics.mrrComputer),
+      toRow(metrics.successfulMrrComputer),
+      toRow(metrics.instanceMemberMrrComputer),
+      toRow(metrics.staticMemberMrrComputer),
+      toRow(metrics.typeRefMrrComputer),
+      toRow(metrics.localRefMrrComputer),
+      toRow(metrics.paramRefMrrComputer),
+      toRow(metrics.topLevelMrrComputer),
+    ];
+    rightJustifyColumn(2, table);
+    rightJustifyColumn(4, table);
+    rightJustifyColumn(5, table);
+    buffer.writeTable(table);
 
-    metrics.instanceMemberMrrComputer.printMean();
+    print('Mean Reciprocal Rank');
     print('');
+    print(buffer.toString());
 
-    metrics.staticMemberMrrComputer.printMean();
-    print('');
-
-    metrics.typeRefMrrComputer.printMean();
-    print('');
-
-    metrics.localRefMrrComputer.printMean();
-    print('');
-
-    metrics.paramRefMrrComputer.printMean();
-    print('');
-
-    metrics.topLevelMrrComputer.printMean();
-    print('');
-
-    if (verbose) {
+    if (options.printMrrByLocation) {
       var lines = <LocationTableLine>[];
       for (var entry in metrics.locationMrrComputers.entries) {
         var count = entry.value.count;
@@ -807,7 +903,7 @@
     // suggestions if doComputeCompletionsFromAnalysisServer is true.
     DeclarationsTracker declarationsTracker;
     protocol.CompletionAvailableSuggestionsParams availableSuggestionsParams;
-    if (availableSuggestions) {
+    if (options.availableSuggestions) {
       declarationsTracker = DeclarationsTracker(
           MemoryByteStore(), PhysicalResourceProvider.INSTANCE);
       declarationsTracker.addContext(context);
@@ -852,9 +948,11 @@
 
             // If an overlay option is being used, compute the overlay file, and
             // have the context reanalyze the file
-            if (overlay != OVERLAY_NONE) {
+            if (options.overlay != OVERLAY_NONE) {
               var overlayContents = _getOverlayContents(
-                  _resolvedUnitResult.content, expectedCompletion, overlay);
+                  _resolvedUnitResult.content,
+                  expectedCompletion,
+                  options.overlay);
 
               _provider.setOverlay(filePath,
                   content: overlayContents,
@@ -921,7 +1019,7 @@
               var rank = await handleExpectedCompletion(
                   listener: listener,
                   metrics: metrics,
-                  printMissedCompletions: verbose);
+                  printMissedCompletions: options.printMissedCompletionDetails);
               if (bestRank < 0 || rank < bestRank) {
                 bestRank = rank;
                 bestName = metrics.name;
@@ -932,7 +1030,7 @@
 
             // If an overlay option is being used, remove the overlay applied
             // earlier
-            if (overlay != OVERLAY_NONE) {
+            if (options.overlay != OVERLAY_NONE) {
               _provider.removeOverlay(filePath);
             }
           }
@@ -1061,6 +1159,56 @@
   }
 }
 
+/// The options specified on the command-line.
+class CompletionMetricsOptions {
+  /// A flag indicating whether available suggestions should be enabled for this
+  /// run.
+  final bool availableSuggestions;
+
+  /// The overlay mode that should be used.
+  final String overlay;
+
+  /// A flag indicating whether information should be printed every time a
+  /// completion request fails to produce a suggestions matching the expected
+  /// suggestion.
+  final bool printMissedCompletionDetails;
+
+  /// A flag indicating whether information should be printed every time a
+  /// completion request fails to produce a suggestions matching the expected
+  /// suggestion.
+  final bool printMissedCompletionSummary;
+
+  /// A flag indicating whether information should be printed about places where
+  /// no completion location was computed and about information that's missing
+  /// in the completion tables.
+  final bool printMissingInformation;
+
+  /// A flag indicating whether information should be printed about the mrr
+  /// score achieved at each completion location.
+  final bool printMrrByLocation;
+
+  /// A flag indicating whether information should be printed about the
+  /// completion requests that were the slowest to return suggestions.
+  final bool printSlowestResults;
+
+  /// A flag indicating whether information should be printed about the
+  /// completion requests that had the worst mrr scores.
+  final bool printWorstResults;
+
+  CompletionMetricsOptions(
+      {@required this.availableSuggestions,
+      @required this.overlay,
+      @required this.printMissedCompletionDetails,
+      @required this.printMissedCompletionSummary,
+      @required this.printMissingInformation,
+      @required this.printMrrByLocation,
+      @required this.printSlowestResults,
+      @required this.printWorstResults})
+      : assert(overlay == OVERLAY_NONE ||
+            overlay == OVERLAY_REMOVE_TOKEN ||
+            overlay == OVERLAY_REMOVE_REST_OF_FILE);
+}
+
 /// The result of a single completion.
 class CompletionResult {
   final Place place;
diff --git a/pkg/analysis_server/tool/code_completion/metrics_util.dart b/pkg/analysis_server/tool/code_completion/metrics_util.dart
index cadc262..6078af8d 100644
--- a/pkg/analysis_server/tool/code_completion/metrics_util.dart
+++ b/pkg/analysis_server/tool/code_completion/metrics_util.dart
@@ -76,8 +76,13 @@
   void printCounterValues() {
     print('Counts for \'$name\' (total = $_totalCount):');
     if (_totalCount > 0) {
-      _buckets.forEach((id, count) =>
-          print('[$id] $count (${printPercentage(count / _totalCount, 2)})'));
+      var entries = _buckets.entries.toList();
+      entries.sort((first, second) => second.value - first.value);
+      for (var entry in entries) {
+        var id = entry.key;
+        var count = entry.value;
+        print('[$id] $count (${printPercentage(count / _totalCount, 2)})');
+      }
     } else {
       print('<no counts>');
     }
diff --git a/pkg/analysis_server/tool/code_completion/output_utilities.dart b/pkg/analysis_server/tool/code_completion/output_utilities.dart
index 00ed748..71660df 100644
--- a/pkg/analysis_server/tool/code_completion/output_utilities.dart
+++ b/pkg/analysis_server/tool/code_completion/output_utilities.dart
@@ -4,6 +4,26 @@
 
 import 'dart:math' as math;
 
+/// Given a [table] represented as a list of rows, right justify all of the
+/// cells in the given [column], except for the first row under the assumption
+/// that the first row contains headers.
+void rightJustifyColumn(int column, List<List<String>> table) {
+  var width = 0;
+  for (var i = 0; i < table.length; i++) {
+    var row = table[i];
+    width = math.max(width, row[column].length);
+  }
+  for (var i = 1; i < table.length; i++) {
+    var row = table[i];
+    var cellValue = row[column];
+    var length = cellValue.length;
+    if (length < width) {
+      var padding = ' ' * (width - length);
+      row[column] = '$padding$cellValue';
+    }
+  }
+}
+
 extension OutputUtilities on StringSink {
   /// Write the given [table].
   ///
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 8b49fc8..57cd829 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  <version>1.32.0</version>
+  <version>1.32.1</version>
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -133,6 +133,11 @@
   the server so clients should ensure unknown values are handled gracefully, either
   ignoring the item or treating it with some default/fallback handling.
 </p>
+<h3>Changelog</h3>
+<h4>1.32.1</h4>
+<ul>
+  <li>Added <tt>CompletionSuggestionKind.PACKAGE_NAME</tt> for Pub package name completions in <tt>pubspec.yaml</tt></li>
+</ul>
 <h3>Domains</h3>
 <p>
   For convenience, the API is divided into domains. Each domain is specified
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index cdccff0..7636ffc 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.32.0';
+const String PROTOCOL_VERSION = '1.32.1';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
index 2cb1bde..941812a 100644
--- a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
+++ b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
@@ -2,6 +2,8 @@
 // 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:math' show max;
+
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -50,15 +52,7 @@
   /// Return the interfaces that are directly implemented by this class.
   List<InstantiatedClass> get interfaces {
     var interfaces = element.interfaces;
-
-    var result = List<InstantiatedClass>(interfaces.length);
-    for (var i = 0; i < interfaces.length; i++) {
-      var interface = interfaces[i];
-      var substituted = _substitution.substituteType(interface);
-      result[i] = InstantiatedClass.of(substituted);
-    }
-
-    return result;
+    return _toInstantiatedClasses(interfaces);
   }
 
   /// Return `true` if this type represents the type 'Function' defined in the
@@ -67,6 +61,12 @@
     return element.name == 'Function' && element.library.isDartCore;
   }
 
+  /// Return the mixin that are directly implemented by this class.
+  List<InstantiatedClass> get mixins {
+    var mixins = element.mixins;
+    return _toInstantiatedClasses(mixins);
+  }
+
   /// Return the superclass of this type, or `null` if this type represents
   /// the class 'Object'.
   InstantiatedClass get superclass {
@@ -84,15 +84,7 @@
   /// the type for the class `Object`.
   List<InstantiatedClass> get superclassConstraints {
     var constraints = element.superclassConstraints;
-
-    var result = List<InstantiatedClass>(constraints.length);
-    for (var i = 0; i < constraints.length; i++) {
-      var constraint = constraints[i];
-      var substituted = _substitution.substituteType(constraint);
-      result[i] = InstantiatedClass.of(substituted);
-    }
-
-    return result;
+    return _toInstantiatedClasses(constraints);
   }
 
   @visibleForTesting
@@ -139,6 +131,19 @@
       nullabilitySuffix: nullability,
     );
   }
+
+  List<InstantiatedClass> _toInstantiatedClasses(
+    List<InterfaceType> interfaces,
+  ) {
+    var result = List<InstantiatedClass>(interfaces.length);
+    for (var i = 0; i < interfaces.length; i++) {
+      var interface = interfaces[i];
+      var substituted = _substitution.substituteType(interface);
+      result[i] = InstantiatedClass.of(substituted);
+    }
+
+    return result;
+  }
 }
 
 class InterfaceLeastUpperBoundHelper {
@@ -277,11 +282,7 @@
   /// Object.
   @visibleForTesting
   static int computeLongestInheritancePathToObject(ClassElement element) {
-    return _computeLongestInheritancePathToObject(
-      element,
-      0,
-      <ClassElement>{},
-    );
+    return _computeLongestInheritancePathToObject(element, <ClassElement>{});
   }
 
   /// Add all of the superinterfaces of the given [type] to the given [set].
@@ -295,6 +296,14 @@
       }
     }
 
+    for (var mixin in type.mixins) {
+      if (!mixin.isDartCoreFunction) {
+        if (set.add(mixin)) {
+          _addSuperinterfaces(set, mixin);
+        }
+      }
+    }
+
     for (var constraint in type.superclassConstraints) {
       if (!constraint.isDartCoreFunction) {
         if (set.add(constraint)) {
@@ -333,47 +342,53 @@
   /// is used to prevent infinite recursion in the case of a cyclic type
   /// structure.
   static int _computeLongestInheritancePathToObject(
-      ClassElement element, int depth, Set<ClassElement> visitedElements) {
+      ClassElement element, Set<ClassElement> visitedElements) {
     // Object case
     if (element.isDartCoreObject || visitedElements.contains(element)) {
-      return depth;
+      return 0;
     }
-    int longestPath = 1;
+    int longestPath = 0;
     try {
       visitedElements.add(element);
-      int pathLength;
 
       // loop through each of the superinterfaces recursively calling this
       // method and keeping track of the longest path to return
       for (InterfaceType interface in element.superclassConstraints) {
-        pathLength = _computeLongestInheritancePathToObject(
-            interface.element, depth + 1, visitedElements);
-        if (pathLength > longestPath) {
-          longestPath = pathLength;
-        }
+        var pathLength = _computeLongestInheritancePathToObject(
+            interface.element, visitedElements);
+        longestPath = max(longestPath, 1 + pathLength);
       }
 
       // loop through each of the superinterfaces recursively calling this
       // method and keeping track of the longest path to return
       for (InterfaceType interface in element.interfaces) {
-        pathLength = _computeLongestInheritancePathToObject(
-            interface.element, depth + 1, visitedElements);
-        if (pathLength > longestPath) {
-          longestPath = pathLength;
-        }
+        var pathLength = _computeLongestInheritancePathToObject(
+            interface.element, visitedElements);
+        longestPath = max(longestPath, 1 + pathLength);
       }
 
-      // finally, perform this same check on the super type
-      // TODO(brianwilkerson) Does this also need to add in the number of mixin
-      // classes?
-      InterfaceType supertype = element.supertype;
-      if (supertype != null) {
-        pathLength = _computeLongestInheritancePathToObject(
-            supertype.element, depth + 1, visitedElements);
-        if (pathLength > longestPath) {
-          longestPath = pathLength;
-        }
+      var supertype = element.supertype;
+      if (supertype == null) {
+        return longestPath;
       }
+
+      var superLength = _computeLongestInheritancePathToObject(
+          supertype.element, visitedElements);
+
+      var mixins = element.mixins;
+      for (var i = 0; i < mixins.length; i++) {
+        // class _X&S&M extends S implements M {}
+        // So, we choose the maximum length from S and M.
+        var mixinLength = _computeLongestInheritancePathToObject(
+          mixins[i].element,
+          visitedElements,
+        );
+        superLength = max(superLength, mixinLength);
+        // For this synthetic class representing the mixin application.
+        superLength++;
+      }
+
+      longestPath = max(longestPath, 1 + superLength);
     } finally {
       visitedElements.remove(element);
     }
diff --git a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
index 30418ae..d99c0e8 100644
--- a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
+++ b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
@@ -15,16 +15,104 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(InterfaceLeastUpperBoundHelperTest);
+    defineReflectiveTests(PathToObjectTest);
+    defineReflectiveTests(SuperinterfaceSetTest);
   });
 }
 
 @reflectiveTest
-class InterfaceLeastUpperBoundHelperTest extends AbstractTypeSystemTest {
+class PathToObjectTest extends AbstractTypeSystemTest {
   @override
   final TestTypeProvider typeProvider = TestTypeProvider();
 
-  void test_computeLongestInheritancePathToObject_multipleInterfacePaths() {
+  void test_class_mixins1() {
+    var M1 = mixin_(name: 'M1');
+    expect(_longestPathToObject(M1), 1);
+
+    var A = class_(name: 'A');
+    expect(_longestPathToObject(A), 1);
+
+    // class _X&A&M1 extends A implements M1 {}
+    //    length: 2
+    // class X extends _X&A&M1 {}
+    //    length: 3
+    var X = class_(
+      name: 'X',
+      superType: interfaceTypeNone(A),
+      mixins: [
+        interfaceTypeNone(M1),
+      ],
+    );
+
+    expect(_longestPathToObject(X), 3);
+  }
+
+  void test_class_mixins2() {
+    var M1 = mixin_(name: 'M1');
+    var M2 = mixin_(name: 'M2');
+    expect(_longestPathToObject(M1), 1);
+    expect(_longestPathToObject(M2), 1);
+
+    var A = class_(name: 'A');
+    expect(_longestPathToObject(A), 1);
+
+    // class _X&A&M1 extends A implements M1 {}
+    //    length: 2
+    // class _X&A&M1&M2 extends _X&A&M1 implements M2 {}
+    //    length: 3
+    // class X extends _X&A&M1&M2 {}
+    //    length: 4
+    var X = class_(
+      name: 'X',
+      superType: interfaceTypeNone(A),
+      mixins: [
+        interfaceTypeNone(M1),
+        interfaceTypeNone(M2),
+      ],
+    );
+
+    expect(_longestPathToObject(X), 4);
+  }
+
+  void test_class_mixins_longerViaSecondMixin() {
+    var I1 = class_(name: 'I1');
+    var I2 = class_(name: 'I2', superType: interfaceTypeNone(I1));
+    var I3 = class_(name: 'I3', superType: interfaceTypeNone(I2));
+
+    expect(_longestPathToObject(I1), 1);
+    expect(_longestPathToObject(I2), 2);
+    expect(_longestPathToObject(I3), 3);
+
+    var M1 = mixin_(name: 'M1');
+    var M2 = mixin_(
+      name: 'M2',
+      interfaces: [interfaceTypeNone(I3)],
+    );
+    expect(_longestPathToObject(M1), 1);
+    expect(_longestPathToObject(M2), 4);
+
+    var A = class_(name: 'A'); // length: 1
+    expect(_longestPathToObject(A), 1);
+
+    // class _X&A&M1 extends A implements M1 {}
+    //    length: 2
+    // class _X&A&M1&M2 extends _X&A&M1 implements M2 {}
+    //    length: 5 = max(1 + _X&A&M1, 1 + M2)
+    // class X extends _X&A&M1&M2 {}
+    //    length: 6
+    var X = class_(
+      name: 'X',
+      superType: interfaceTypeNone(A),
+      mixins: [
+        interfaceTypeNone(M1),
+        interfaceTypeNone(M2),
+      ],
+    );
+
+    expect(_longestPathToObject(X), 6);
+  }
+
+  void test_class_multipleInterfacePaths() {
     //
     //   Object
     //     |
@@ -55,7 +143,7 @@
     expect(_longestPathToObject(classE), 4);
   }
 
-  void test_computeLongestInheritancePathToObject_multipleSuperclassPaths() {
+  void test_class_multipleSuperclassPaths() {
     //
     //   Object
     //     |
@@ -84,11 +172,11 @@
     expect(_longestPathToObject(classE), 4);
   }
 
-  void test_computeLongestInheritancePathToObject_object() {
+  void test_class_object() {
     expect(_longestPathToObject(typeProvider.objectType.element), 0);
   }
 
-  void test_computeLongestInheritancePathToObject_recursion() {
+  void test_class_recursion() {
     ClassElementImpl classA = ElementFactory.classElement2("A");
     ClassElementImpl classB =
         ElementFactory.classElement("B", interfaceTypeStar(classA));
@@ -96,7 +184,7 @@
     expect(_longestPathToObject(classA), 2);
   }
 
-  void test_computeLongestInheritancePathToObject_singleInterfacePath() {
+  void test_class_singleInterfacePath() {
     //
     //   Object
     //     |
@@ -116,7 +204,7 @@
     expect(_longestPathToObject(classC), 3);
   }
 
-  void test_computeLongestInheritancePathToObject_singleSuperclassPath() {
+  void test_class_singleSuperclassPath() {
     //
     //   Object
     //     |
@@ -136,7 +224,138 @@
     expect(_longestPathToObject(classC), 3);
   }
 
-  void test_computeSuperinterfaceSet_genericInterfacePath() {
+  void test_mixin_constraints_interfaces_allSame() {
+    var A = class_(name: 'A');
+    var B = class_(name: 'B');
+    var I = class_(name: 'I');
+    var J = class_(name: 'J');
+    expect(_longestPathToObject(A), 1);
+    expect(_longestPathToObject(B), 1);
+    expect(_longestPathToObject(I), 1);
+    expect(_longestPathToObject(J), 1);
+
+    // The interface of M is:
+    // class _M&A&A implements A, B, I, J {}
+    var M = mixin_(
+      name: 'M',
+      constraints: [
+        interfaceTypeNone(A),
+        interfaceTypeNone(B),
+      ],
+      interfaces: [
+        interfaceTypeNone(I),
+        interfaceTypeNone(J),
+      ],
+    );
+    expect(_longestPathToObject(M), 2);
+  }
+
+  void test_mixin_longerConstraint_1() {
+    var A1 = class_(name: 'A1');
+    var A = class_(
+      name: 'A',
+      superType: interfaceTypeNone(A1),
+    );
+    var B = class_(name: 'B');
+    var I = class_(name: 'I');
+    var J = class_(name: 'J');
+    expect(_longestPathToObject(A), 2);
+    expect(_longestPathToObject(B), 1);
+    expect(_longestPathToObject(I), 1);
+    expect(_longestPathToObject(J), 1);
+
+    // The interface of M is:
+    // class _M&A&A implements A, B, I, J {}
+    var M = mixin_(
+      name: 'M',
+      constraints: [
+        interfaceTypeNone(A),
+        interfaceTypeNone(B),
+      ],
+      interfaces: [
+        interfaceTypeNone(I),
+        interfaceTypeNone(J),
+      ],
+    );
+    expect(_longestPathToObject(M), 3);
+  }
+
+  void test_mixin_longerConstraint_2() {
+    var A = class_(name: 'A');
+    var B1 = class_(name: 'B1');
+    var B = class_(
+      name: 'B',
+      interfaces: [
+        interfaceTypeNone(B1),
+      ],
+    );
+    var I = class_(name: 'I');
+    var J = class_(name: 'J');
+    expect(_longestPathToObject(A), 1);
+    expect(_longestPathToObject(B), 2);
+    expect(_longestPathToObject(I), 1);
+    expect(_longestPathToObject(J), 1);
+
+    // The interface of M is:
+    // class _M&A&A implements A, B, I, J {}
+    var M = mixin_(
+      name: 'M',
+      constraints: [
+        interfaceTypeNone(A),
+        interfaceTypeNone(B),
+      ],
+      interfaces: [
+        interfaceTypeNone(I),
+        interfaceTypeNone(J),
+      ],
+    );
+    expect(_longestPathToObject(M), 3);
+  }
+
+  void test_mixin_longerInterface_1() {
+    var A = class_(name: 'A');
+    var B = class_(name: 'B');
+    var I1 = class_(name: 'I1');
+    var I = class_(
+      name: 'I',
+      interfaces: [
+        interfaceTypeNone(I1),
+      ],
+    );
+    var J = class_(name: 'J');
+    expect(_longestPathToObject(A), 1);
+    expect(_longestPathToObject(B), 1);
+    expect(_longestPathToObject(I), 2);
+    expect(_longestPathToObject(J), 1);
+
+    // The interface of M is:
+    // class _M&A&A implements A, B, I, J {}
+    var M = mixin_(
+      name: 'M',
+      constraints: [
+        interfaceTypeNone(A),
+        interfaceTypeNone(B),
+      ],
+      interfaces: [
+        interfaceTypeNone(I),
+        interfaceTypeNone(J),
+      ],
+    );
+    expect(_longestPathToObject(M), 3);
+  }
+
+  int _longestPathToObject(ClassElement element) {
+    return InterfaceLeastUpperBoundHelper.computeLongestInheritancePathToObject(
+        element);
+  }
+}
+
+@reflectiveTest
+class SuperinterfaceSetTest extends AbstractTypeSystemTest {
+  @override
+  final TestTypeProvider typeProvider = TestTypeProvider();
+
+  void test_genericInterfacePath() {
     //
     //  A
     //  | implements
@@ -200,7 +419,7 @@
     );
   }
 
-  void test_computeSuperinterfaceSet_genericSuperclassPath() {
+  void test_genericSuperclassPath() {
     //
     //  A
     //  |
@@ -261,7 +480,7 @@
     );
   }
 
-  void test_computeSuperinterfaceSet_mixin_constraints() {
+  void test_mixin_constraints() {
     var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var classA = ElementFactory.classElement3(name: 'A');
@@ -291,7 +510,7 @@
     );
   }
 
-  void test_computeSuperinterfaceSet_mixin_constraints_object() {
+  void test_mixin_constraints_object() {
     var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var mixinM = mixin_(name: 'M');
@@ -303,7 +522,7 @@
     );
   }
 
-  void test_computeSuperinterfaceSet_mixin_interfaces() {
+  void test_mixin_interfaces() {
     var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var classA = ElementFactory.classElement3(name: 'A');
@@ -333,7 +552,7 @@
     );
   }
 
-  void test_computeSuperinterfaceSet_multipleInterfacePaths() {
+  void test_multipleInterfacePaths() {
     var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var classA = ElementFactory.classElement3(name: 'A');
@@ -379,7 +598,7 @@
     );
   }
 
-  void test_computeSuperinterfaceSet_multipleSuperclassPaths() {
+  void test_multipleSuperclassPaths() {
     var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var classA = ElementFactory.classElement3(name: 'A');
@@ -425,7 +644,7 @@
     );
   }
 
-  void test_computeSuperinterfaceSet_recursion() {
+  void test_recursion() {
     var classA = ElementFactory.classElement3(name: 'A');
     var instA = InstantiatedClass(classA, const []);
 
@@ -448,7 +667,7 @@
     );
   }
 
-  void test_computeSuperinterfaceSet_singleInterfacePath() {
+  void test_singleInterfacePath() {
     var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var classA = ElementFactory.classElement3(name: 'A');
@@ -485,7 +704,7 @@
     );
   }
 
-  void test_computeSuperinterfaceSet_singleSuperclassPath() {
+  void test_singleSuperclassPath() {
     //
     //  A
     //  |
@@ -529,11 +748,6 @@
     );
   }
 
-  int _longestPathToObject(ClassElement element) {
-    return InterfaceLeastUpperBoundHelper.computeLongestInheritancePathToObject(
-        element);
-  }
-
   Set<InstantiatedClass> _superInterfaces(InstantiatedClass type) {
     var helper = InterfaceLeastUpperBoundHelper(typeSystem);
     return helper.computeSuperinterfaceSet(type);
diff --git a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
index 3372610..77f2918 100644
--- a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
+++ b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
@@ -2214,6 +2214,73 @@
     assertLUB(aNone, aNone, aNone);
   }
 
+  void test_sharedMixin1() {
+    // mixin M {}
+    // class B with M {}
+    // class C with M {}
+
+    var M = mixin_(name: 'M');
+    var M_none = interfaceTypeNone(M);
+
+    var B = class_(name: 'B', mixins: [M_none]);
+    var B_none = interfaceTypeNone(B);
+
+    var C = class_(name: 'C', mixins: [M_none]);
+    var C_none = interfaceTypeNone(C);
+
+    _checkLeastUpperBound(B_none, C_none, M_none);
+  }
+
+  void test_sharedMixin2() {
+    // mixin M1 {}
+    // mixin M2 {}
+    // mixin M3 {}
+    // class A with M1, M2 {}
+    // class B with M1, M3 {}
+
+    var M1 = mixin_(name: 'M1');
+    var M1_none = interfaceTypeNone(M1);
+
+    var M2 = mixin_(name: 'M2');
+    var M2_none = interfaceTypeNone(M2);
+
+    var M3 = mixin_(name: 'M3');
+    var M3_none = interfaceTypeNone(M3);
+
+    var A = class_(name: 'A', mixins: [M1_none, M2_none]);
+    var A_none = interfaceTypeNone(A);
+
+    var B = class_(name: 'B', mixins: [M1_none, M3_none]);
+    var B_none = interfaceTypeNone(B);
+
+    _checkLeastUpperBound(A_none, B_none, M1_none);
+  }
+
+  void test_sharedMixin3() {
+    // mixin M1 {}
+    // mixin M2 {}
+    // mixin M3 {}
+    // class A with M2, M1 {}
+    // class B with M3, M1 {}
+
+    var M1 = mixin_(name: 'M1');
+    var M1_none = interfaceTypeNone(M1);
+
+    var M2 = mixin_(name: 'M2');
+    var M2_none = interfaceTypeNone(M2);
+
+    var M3 = mixin_(name: 'M3');
+    var M3_none = interfaceTypeNone(M3);
+
+    var A = class_(name: 'A', mixins: [M2_none, M1_none]);
+    var A_none = interfaceTypeNone(A);
+
+    var B = class_(name: 'B', mixins: [M3_none, M1_none]);
+    var B_none = interfaceTypeNone(B);
+
+    _checkLeastUpperBound(A_none, B_none, M1_none);
+  }
+
   void test_sharedSuperclass1() {
     // class A {}
     // class B extends A {}
diff --git a/pkg/analyzer_plugin/CHANGELOG.md b/pkg/analyzer_plugin/CHANGELOG.md
index 8f0d5e3..2b49d2b 100644
--- a/pkg/analyzer_plugin/CHANGELOG.md
+++ b/pkg/analyzer_plugin/CHANGELOG.md
@@ -1,10 +1,10 @@
-## 0.3.1-dev
+## 0.4.0
 - Deprecated the class `DartChangeBuilder` and enhanced `ChangeBuilder` to be
   the replacement for it.
 - Deprecated the method `ChangeBuilder.addFileEdit` and introduced
   `ChangeBuilder.addDartFileEdit` and `ChangeBuilder.addGenericFileEdit` to be
   the replacements for it.
-- Bump maximum supported version of the analyzer to `<0.41.0`.
+- Changed the support version range of the analyzer to `>=0.41.0 <0.42.0`.
 
 ## 0.3.0
 - Removed deprecated `Plugin.getResolveResult`. Use `getResolvedUnitResult`.
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index b48c87b..2401bdb 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -1,6 +1,6 @@
 name: analyzer_plugin
 description: A framework and support code for building plugins for the analysis server.
-version: 0.3.0
+version: 0.4.0
 author: Dart Team <misc@dartlang.org>
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_plugin
 
@@ -8,7 +8,7 @@
   sdk: '>=2.9.0 <3.0.0'
 
 dependencies:
-  analyzer: '>=0.39.12 <0.41.0'
+  analyzer: '>=0.41.0 <0.42.0'
   dart_style: '^1.2.0'
   meta: ^1.2.3
   pub_semver: '^1.3.2'
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 85cca3c..eb037e7 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -1339,7 +1339,8 @@
         createIsSetRead: () => _createFieldGet(_lateIsSetField),
         createIsSetWrite: (Expression value) =>
             _createFieldSet(_lateIsSetField, value),
-        isSetEncoding: isSetEncoding);
+        isSetEncoding: isSetEncoding,
+        forField: true);
   }
 
   @override
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 c2d9461..de26ae2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -5838,17 +5838,30 @@
                       createIsSetRead: createIsSetRead,
                       isSetEncoding: isSetEncoding,
                       forField: false)
-                  : late_lowering.createGetterWithInitializer(
-                      inferrer.coreTypes,
-                      fileOffset,
-                      node.name,
-                      node.type,
-                      node.initializer,
-                      createVariableRead: createVariableRead,
-                      createVariableWrite: createVariableWrite,
-                      createIsSetRead: createIsSetRead,
-                      createIsSetWrite: createIsSetWrite,
-                      isSetEncoding: isSetEncoding),
+                  : (node.isFinal
+                      ? late_lowering.createGetterWithInitializerWithRecheck(
+                          inferrer.coreTypes,
+                          fileOffset,
+                          node.name,
+                          node.type,
+                          node.initializer,
+                          createVariableRead: createVariableRead,
+                          createVariableWrite: createVariableWrite,
+                          createIsSetRead: createIsSetRead,
+                          createIsSetWrite: createIsSetWrite,
+                          isSetEncoding: isSetEncoding,
+                          forField: false)
+                      : late_lowering.createGetterWithInitializer(
+                          inferrer.coreTypes,
+                          fileOffset,
+                          node.name,
+                          node.type,
+                          node.initializer,
+                          createVariableRead: createVariableRead,
+                          createVariableWrite: createVariableWrite,
+                          createIsSetRead: createIsSetRead,
+                          createIsSetWrite: createIsSetWrite,
+                          isSetEncoding: isSetEncoding)),
               returnType: node.type))
         ..fileOffset = fileOffset;
       getVariable.type =
diff --git a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
index a2c6f50..ce8d986 100644
--- a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
@@ -16,13 +16,10 @@
 const String lateLocalSetterSuffix = '#set';
 
 /// Creates the body for the synthesized getter used to encode the lowering
-/// of a late non-final field with an initializer or a late local with an
-/// initializer.
+/// of a late non-final field or local with an initializer.
 ///
-/// Late final field needs to detect writes during initialization and therefore
-/// uses [createGetterWithInitializerWithRecheck] instead. Late final locals
-/// cannot have writes during initialization since they are not in scope in
-/// their own initializer.
+/// Late final fields and locals need to detect writes during initialization and
+/// therefore uses [createGetterWithInitializerWithRecheck] instead.
 Statement createGetterWithInitializer(CoreTypes coreTypes, int fileOffset,
     String name, DartType type, Expression initializer,
     {Expression createVariableRead({bool needsPromotion}),
@@ -120,23 +117,23 @@
 }
 
 /// Creates the body for the synthesized getter used to encode the lowering
-/// of a late final field with an initializer.
-///
-/// A late final field needs to detect writes during initialization for
-/// which a `LateInitializationError` should be thrown. Late final locals
-/// cannot have writes during initialization since they are not in scope in
-/// their own initializer.
+/// of a late final field or local with an initializer.
 Statement createGetterWithInitializerWithRecheck(CoreTypes coreTypes,
     int fileOffset, String name, DartType type, Expression initializer,
     {Expression createVariableRead({bool needsPromotion}),
     Expression createVariableWrite(Expression value),
     Expression createIsSetRead(),
     Expression createIsSetWrite(Expression value),
-    IsSetEncoding isSetEncoding}) {
+    IsSetEncoding isSetEncoding,
+    bool forField}) {
+  assert(forField != null);
+  Constructor constructor = forField
+      ? coreTypes.lateInitializationFieldAssignedDuringInitializationConstructor
+      : coreTypes
+          .lateInitializationLocalAssignedDuringInitializationConstructor;
   Expression exception = new Throw(
       new ConstructorInvocation(
-          coreTypes
-              .lateInitializationFieldAssignedDuringInitializationConstructor,
+          constructor,
           new Arguments(
               <Expression>[new StringLiteral(name)..fileOffset = fileOffset])
             ..fileOffset = fileOffset)
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index 68fdfc8..a15a5c9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -289,7 +289,9 @@
           origin: remoteContext);
     }
 
-    bool isTypeCast = localContext != null &&
+    // TODO(johnniwinther): This check wasn't called from InterfaceType and
+    // is currently very broken. Disabling for now.
+    /*bool isTypeCast = localContext != null &&
         localContext is AsExpression &&
         localContext.isTypeError;
     // Don't check cases like foo(x as{TypeError} T).  In cases where foo comes
@@ -329,7 +331,7 @@
             "Found a legacy type '${node}' in an opted-in library.",
             origin: remoteContext);
       }
-    }
+    }*/
 
     super.defaultDartType(node);
   }
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart b/pkg/front_end/testcases/late_lowering/issue44372.dart
new file mode 100644
index 0000000..2550604
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2020, 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.
+
+main(List<String> args) {
+  late int Function() recursiveInitLocal;
+  late final int local = recursiveInitLocal();
+
+  bool doRecursiveInitLocal = true;
+  recursiveInitLocal = () {
+    print('Executing initializer');
+    if (doRecursiveInitLocal) {
+      doRecursiveInitLocal = false;
+      print('Trigger recursive initialization');
+      int val = local;
+      print('Final local has value $val');
+      print('Returning 4 from initializer');
+      return 4;
+    }
+    print('Returning 3 from initializer');
+    return 3;
+  };
+
+  throws(() {
+    int val = local;
+    print('Final local has value $val');
+  }, "Read local");
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+  dynamic value;
+  try {
+    value = f();
+  } on LateInitializationError catch (e) {
+    print(e);
+    return;
+  }
+  throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.outline.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.outline.expect
new file mode 100644
index 0000000..cd8b66b
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.outline.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args) → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → dynamic f, core::String message) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.expect
new file mode 100644
index 0000000..016d6f4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method main(core::List<core::String> args) → dynamic {
+  () →? core::int recursiveInitLocal;
+  function #recursiveInitLocal#get() → () → core::int
+    return let final () →? core::int #t1 = recursiveInitLocal in #t1.==(null) ?{() → core::int} throw new _in::LateError::localNI("recursiveInitLocal") : #t1{() → core::int};
+  function #recursiveInitLocal#set(() → core::int #t2) → dynamic
+    return recursiveInitLocal = #t2;
+  final core::int? local;
+  function #local#get() → core::int
+    return let final core::int? #t3 = local in #t3.==(null) ?{core::int} let final core::int #t4 = #recursiveInitLocal#get.call().call() in local.==(null) ?{core::int} local = #t4 : throw new _in::LateError::localADI("local") : #t3{core::int};
+  core::bool doRecursiveInitLocal = true;
+  #recursiveInitLocal#set.call(() → core::int {
+    core::print("Executing initializer");
+    if(doRecursiveInitLocal) {
+      doRecursiveInitLocal = false;
+      core::print("Trigger recursive initialization");
+      core::int val = #local#get.call();
+      core::print("Final local has value ${val}");
+      core::print("Returning 4 from initializer");
+      return 4;
+    }
+    core::print("Returning 3 from initializer");
+    return 3;
+  });
+  self::throws(() → Null {
+    core::int val = #local#get.call();
+    core::print("Final local has value ${val}");
+  }, "Read local");
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+  dynamic value;
+  try {
+    value = f.call();
+  }
+  on core::LateInitializationError catch(final core::LateInitializationError e) {
+    core::print(e);
+    return;
+  }
+  throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.transformed.expect
new file mode 100644
index 0000000..016d6f4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.transformed.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method main(core::List<core::String> args) → dynamic {
+  () →? core::int recursiveInitLocal;
+  function #recursiveInitLocal#get() → () → core::int
+    return let final () →? core::int #t1 = recursiveInitLocal in #t1.==(null) ?{() → core::int} throw new _in::LateError::localNI("recursiveInitLocal") : #t1{() → core::int};
+  function #recursiveInitLocal#set(() → core::int #t2) → dynamic
+    return recursiveInitLocal = #t2;
+  final core::int? local;
+  function #local#get() → core::int
+    return let final core::int? #t3 = local in #t3.==(null) ?{core::int} let final core::int #t4 = #recursiveInitLocal#get.call().call() in local.==(null) ?{core::int} local = #t4 : throw new _in::LateError::localADI("local") : #t3{core::int};
+  core::bool doRecursiveInitLocal = true;
+  #recursiveInitLocal#set.call(() → core::int {
+    core::print("Executing initializer");
+    if(doRecursiveInitLocal) {
+      doRecursiveInitLocal = false;
+      core::print("Trigger recursive initialization");
+      core::int val = #local#get.call();
+      core::print("Final local has value ${val}");
+      core::print("Returning 4 from initializer");
+      return 4;
+    }
+    core::print("Returning 3 from initializer");
+    return 3;
+  });
+  self::throws(() → Null {
+    core::int val = #local#get.call();
+    core::print("Final local has value ${val}");
+  }, "Read local");
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+  dynamic value;
+  try {
+    value = f.call();
+  }
+  on core::LateInitializationError catch(final core::LateInitializationError e) {
+    core::print(e);
+    return;
+  }
+  throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.textual_outline.expect
new file mode 100644
index 0000000..59d6aea
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+main(List<String> args) {}
+expect(expected, actual) {}
+throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..52b9bda
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+expect(expected, actual) {}
+main(List<String> args) {}
+throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.expect
new file mode 100644
index 0000000..515c1f2
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.expect
@@ -0,0 +1,60 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method main(core::List<core::String> args) → dynamic {
+  () →? core::int recursiveInitLocal;
+  core::bool #recursiveInitLocal#isSet = false;
+  function #recursiveInitLocal#get() → () → core::int
+    return #recursiveInitLocal#isSet ?{() → core::int} recursiveInitLocal{() → core::int} : throw new _in::LateError::localNI("recursiveInitLocal");
+  function #recursiveInitLocal#set(() → core::int #t1) → dynamic {
+    #recursiveInitLocal#isSet = true;
+    return recursiveInitLocal = #t1;
+  }
+  final core::int? local;
+  core::bool #local#isSet = false;
+  function #local#get() → core::int {
+    if(!#local#isSet) {
+      final core::int #t2 = #recursiveInitLocal#get.call().call();
+      if(#local#isSet)
+        throw new _in::LateError::localADI("local");
+      local = #t2;
+      #local#isSet = true;
+    }
+    return local{core::int};
+  }
+  core::bool doRecursiveInitLocal = true;
+  #recursiveInitLocal#set.call(() → core::int {
+    core::print("Executing initializer");
+    if(doRecursiveInitLocal) {
+      doRecursiveInitLocal = false;
+      core::print("Trigger recursive initialization");
+      core::int val = #local#get.call();
+      core::print("Final local has value ${val}");
+      core::print("Returning 4 from initializer");
+      return 4;
+    }
+    core::print("Returning 3 from initializer");
+    return 3;
+  });
+  self::throws(() → Null {
+    core::int val = #local#get.call();
+    core::print("Final local has value ${val}");
+  }, "Read local");
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+  dynamic value;
+  try {
+    value = f.call();
+  }
+  on core::LateInitializationError catch(final core::LateInitializationError e) {
+    core::print(e);
+    return;
+  }
+  throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.transformed.expect
new file mode 100644
index 0000000..515c1f2
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.transformed.expect
@@ -0,0 +1,60 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method main(core::List<core::String> args) → dynamic {
+  () →? core::int recursiveInitLocal;
+  core::bool #recursiveInitLocal#isSet = false;
+  function #recursiveInitLocal#get() → () → core::int
+    return #recursiveInitLocal#isSet ?{() → core::int} recursiveInitLocal{() → core::int} : throw new _in::LateError::localNI("recursiveInitLocal");
+  function #recursiveInitLocal#set(() → core::int #t1) → dynamic {
+    #recursiveInitLocal#isSet = true;
+    return recursiveInitLocal = #t1;
+  }
+  final core::int? local;
+  core::bool #local#isSet = false;
+  function #local#get() → core::int {
+    if(!#local#isSet) {
+      final core::int #t2 = #recursiveInitLocal#get.call().call();
+      if(#local#isSet)
+        throw new _in::LateError::localADI("local");
+      local = #t2;
+      #local#isSet = true;
+    }
+    return local{core::int};
+  }
+  core::bool doRecursiveInitLocal = true;
+  #recursiveInitLocal#set.call(() → core::int {
+    core::print("Executing initializer");
+    if(doRecursiveInitLocal) {
+      doRecursiveInitLocal = false;
+      core::print("Trigger recursive initialization");
+      core::int val = #local#get.call();
+      core::print("Final local has value ${val}");
+      core::print("Returning 4 from initializer");
+      return 4;
+    }
+    core::print("Returning 3 from initializer");
+    return 3;
+  });
+  self::throws(() → Null {
+    core::int val = #local#get.call();
+    core::print("Final local has value ${val}");
+  }, "Read local");
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+  dynamic value;
+  try {
+    value = f.call();
+  }
+  on core::LateInitializationError catch(final core::LateInitializationError e) {
+    core::print(e);
+    return;
+  }
+  throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect
index 8a5dd62..ff4583f 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {
   core::int? lateLocalInit;
@@ -9,7 +10,7 @@
   }
   final core::int? lateLocal;
   function #lateLocal#get() → core::int
-    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} lateLocal = initLateLocal.call(123) : #t1{core::int};
+    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} let final core::int #t2 = initLateLocal.call(123) in lateLocal.==(null) ?{core::int} lateLocal = #t2 : throw new _in::LateError::localADI("lateLocal") : #t1{core::int};
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
@@ -22,7 +23,10 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T% {
       if(!#lateGenericLocal#isSet) {
-        lateGenericLocal = initLateGenericLocal.call(value);
+        final T% #t3 = initLateGenericLocal.call(value);
+        if(#lateGenericLocal#isSet)
+          throw new _in::LateError::localADI("lateGenericLocal");
+        lateGenericLocal = #t3;
         #lateGenericLocal#isSet = true;
       }
       return lateGenericLocal{T%};
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect
index 8a5dd62..ff4583f 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {
   core::int? lateLocalInit;
@@ -9,7 +10,7 @@
   }
   final core::int? lateLocal;
   function #lateLocal#get() → core::int
-    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} lateLocal = initLateLocal.call(123) : #t1{core::int};
+    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} let final core::int #t2 = initLateLocal.call(123) in lateLocal.==(null) ?{core::int} lateLocal = #t2 : throw new _in::LateError::localADI("lateLocal") : #t1{core::int};
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
@@ -22,7 +23,10 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T% {
       if(!#lateGenericLocal#isSet) {
-        lateGenericLocal = initLateGenericLocal.call(value);
+        final T% #t3 = initLateGenericLocal.call(value);
+        if(#lateGenericLocal#isSet)
+          throw new _in::LateError::localADI("lateGenericLocal");
+        lateGenericLocal = #t3;
         #lateGenericLocal#isSet = true;
       }
       return lateGenericLocal{T%};
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
index 76adb10..5125e21 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {
   core::int? lateLocalInit;
@@ -11,7 +12,10 @@
   core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int {
     if(!#lateLocal#isSet) {
-      lateLocal = initLateLocal.call(123);
+      final core::int #t1 = initLateLocal.call(123);
+      if(#lateLocal#isSet)
+        throw new _in::LateError::localADI("lateLocal");
+      lateLocal = #t1;
       #lateLocal#isSet = true;
     }
     return lateLocal{core::int};
@@ -28,7 +32,10 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T% {
       if(!#lateGenericLocal#isSet) {
-        lateGenericLocal = initLateGenericLocal.call(value);
+        final T% #t2 = initLateGenericLocal.call(value);
+        if(#lateGenericLocal#isSet)
+          throw new _in::LateError::localADI("lateGenericLocal");
+        lateGenericLocal = #t2;
         #lateGenericLocal#isSet = true;
       }
       return lateGenericLocal{T%};
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
index 76adb10..5125e21 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {
   core::int? lateLocalInit;
@@ -11,7 +12,10 @@
   core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int {
     if(!#lateLocal#isSet) {
-      lateLocal = initLateLocal.call(123);
+      final core::int #t1 = initLateLocal.call(123);
+      if(#lateLocal#isSet)
+        throw new _in::LateError::localADI("lateLocal");
+      lateLocal = #t1;
       #lateLocal#isSet = true;
     }
     return lateLocal{core::int};
@@ -28,7 +32,10 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T% {
       if(!#lateGenericLocal#isSet) {
-        lateGenericLocal = initLateGenericLocal.call(value);
+        final T% #t2 = initLateGenericLocal.call(value);
+        if(#lateGenericLocal#isSet)
+          throw new _in::LateError::localADI("lateGenericLocal");
+        lateGenericLocal = #t2;
         #lateGenericLocal#isSet = true;
       }
       return lateGenericLocal{T%};
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect
index ffb22f1..6292291 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {
   core::int? lateLocalInit;
@@ -11,7 +12,10 @@
   core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int? {
     if(!#lateLocal#isSet) {
-      lateLocal = initLateLocal.call(123);
+      final core::int? #t1 = initLateLocal.call(123);
+      if(#lateLocal#isSet)
+        throw new _in::LateError::localADI("lateLocal");
+      lateLocal = #t1;
       #lateLocal#isSet = true;
     }
     return lateLocal;
@@ -28,7 +32,10 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T? {
       if(!#lateGenericLocal#isSet) {
-        lateGenericLocal = initLateGenericLocal.call(value);
+        final T? #t2 = initLateGenericLocal.call(value);
+        if(#lateGenericLocal#isSet)
+          throw new _in::LateError::localADI("lateGenericLocal");
+        lateGenericLocal = #t2;
         #lateGenericLocal#isSet = true;
       }
       return lateGenericLocal;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect
index ffb22f1..6292291 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {
   core::int? lateLocalInit;
@@ -11,7 +12,10 @@
   core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int? {
     if(!#lateLocal#isSet) {
-      lateLocal = initLateLocal.call(123);
+      final core::int? #t1 = initLateLocal.call(123);
+      if(#lateLocal#isSet)
+        throw new _in::LateError::localADI("lateLocal");
+      lateLocal = #t1;
       #lateLocal#isSet = true;
     }
     return lateLocal;
@@ -28,7 +32,10 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T? {
       if(!#lateGenericLocal#isSet) {
-        lateGenericLocal = initLateGenericLocal.call(value);
+        final T? #t2 = initLateGenericLocal.call(value);
+        if(#lateGenericLocal#isSet)
+          throw new _in::LateError::localADI("lateGenericLocal");
+        lateGenericLocal = #t2;
         #lateGenericLocal#isSet = true;
       }
       return lateGenericLocal;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect
index ffb22f1..6292291 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {
   core::int? lateLocalInit;
@@ -11,7 +12,10 @@
   core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int? {
     if(!#lateLocal#isSet) {
-      lateLocal = initLateLocal.call(123);
+      final core::int? #t1 = initLateLocal.call(123);
+      if(#lateLocal#isSet)
+        throw new _in::LateError::localADI("lateLocal");
+      lateLocal = #t1;
       #lateLocal#isSet = true;
     }
     return lateLocal;
@@ -28,7 +32,10 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T? {
       if(!#lateGenericLocal#isSet) {
-        lateGenericLocal = initLateGenericLocal.call(value);
+        final T? #t2 = initLateGenericLocal.call(value);
+        if(#lateGenericLocal#isSet)
+          throw new _in::LateError::localADI("lateGenericLocal");
+        lateGenericLocal = #t2;
         #lateGenericLocal#isSet = true;
       }
       return lateGenericLocal;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect
index ffb22f1..6292291 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {
   core::int? lateLocalInit;
@@ -11,7 +12,10 @@
   core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int? {
     if(!#lateLocal#isSet) {
-      lateLocal = initLateLocal.call(123);
+      final core::int? #t1 = initLateLocal.call(123);
+      if(#lateLocal#isSet)
+        throw new _in::LateError::localADI("lateLocal");
+      lateLocal = #t1;
       #lateLocal#isSet = true;
     }
     return lateLocal;
@@ -28,7 +32,10 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T? {
       if(!#lateGenericLocal#isSet) {
-        lateGenericLocal = initLateGenericLocal.call(value);
+        final T? #t2 = initLateGenericLocal.call(value);
+        if(#lateGenericLocal#isSet)
+          throw new _in::LateError::localADI("lateGenericLocal");
+        lateGenericLocal = #t2;
         #lateGenericLocal#isSet = true;
       }
       return lateGenericLocal;
diff --git a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.expect
index b67f124..1bb57d1 100644
--- a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.expect
@@ -110,29 +110,32 @@
   core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      nullableInitializedFinalLocal = 0;
+      final core::int? #t26 = 0;
+      if(#nullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nullableInitializedFinalLocal");
+      nullableInitializedFinalLocal = #t26;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return nullableInitializedFinalLocal;
   }
   final core::int? nonNullableInitializedFinalLocal;
   function #nonNullableInitializedFinalLocal#get() → core::int
-    return let final core::int? #t26 = nonNullableInitializedFinalLocal in #t26.==(null) ?{core::int} nonNullableInitializedFinalLocal = 0 : #t26{core::int};
+    return let final core::int? #t27 = nonNullableInitializedFinalLocal in #t27.==(null) ?{core::int} let final core::int #t28 = 0 in nonNullableInitializedFinalLocal.==(null) ?{core::int} nonNullableInitializedFinalLocal = #t28 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t27{core::int};
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t27 = self::_#uninitializedNonFinalTopLevelField in #t27.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t27{core::int};
-static set uninitializedNonFinalTopLevelField(core::int #t28) → void
-  self::_#uninitializedNonFinalTopLevelField = #t28;
+  return let final core::int? #t29 = self::_#uninitializedNonFinalTopLevelField in #t29.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t29{core::int};
+static set uninitializedNonFinalTopLevelField(core::int #t30) → void
+  self::_#uninitializedNonFinalTopLevelField = #t30;
 static get uninitializedFinalTopLevelField() → core::int
-  return let final core::int? #t29 = self::_#uninitializedFinalTopLevelField in #t29.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t29{core::int};
-static set uninitializedFinalTopLevelField(core::int #t30) → void
+  return let final core::int? #t31 = self::_#uninitializedFinalTopLevelField in #t31.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t31{core::int};
+static set uninitializedFinalTopLevelField(core::int #t32) → void
   if(self::_#uninitializedFinalTopLevelField.==(null))
-    self::_#uninitializedFinalTopLevelField = #t30;
+    self::_#uninitializedFinalTopLevelField = #t32;
   else
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
 static get initializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#initializedNonFinalTopLevelField in #t31.==(null) ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t31{core::int};
-static set initializedNonFinalTopLevelField(core::int #t32) → void
-  self::_#initializedNonFinalTopLevelField = #t32;
+  return let final core::int? #t33 = self::_#initializedNonFinalTopLevelField in #t33.==(null) ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t33{core::int};
+static set initializedNonFinalTopLevelField(core::int #t34) → void
+  self::_#initializedNonFinalTopLevelField = #t34;
 static get initializedFinalTopLevelField() → core::int
-  return let final core::int? #t33 = self::_#initializedFinalTopLevelField in #t33.==(null) ?{core::int} let final core::int #t34 = 0 in self::_#initializedFinalTopLevelField.==(null) ?{core::int} self::_#initializedFinalTopLevelField = #t34 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t33{core::int};
+  return let final core::int? #t35 = self::_#initializedFinalTopLevelField in #t35.==(null) ?{core::int} let final core::int #t36 = 0 in self::_#initializedFinalTopLevelField.==(null) ?{core::int} self::_#initializedFinalTopLevelField = #t36 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t35{core::int};
diff --git a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.transformed.expect
index b3a9855..a71870d 100644
--- a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.strong.transformed.expect
@@ -110,36 +110,40 @@
   core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      nullableInitializedFinalLocal = 0;
+      final core::int? #t26 = 0;
+      if(#nullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nullableInitializedFinalLocal");
+      nullableInitializedFinalLocal = #t26;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return nullableInitializedFinalLocal;
   }
   final core::int? nonNullableInitializedFinalLocal;
   function #nonNullableInitializedFinalLocal#get() → core::int
-    return let final core::int? #t26 = nonNullableInitializedFinalLocal in #t26.==(null) ?{core::int} nonNullableInitializedFinalLocal = 0 : #t26{core::int};
+    return let final core::int? #t27 = nonNullableInitializedFinalLocal in #t27.==(null) ?{core::int} let final core::int #t28 = 0 in nonNullableInitializedFinalLocal.==(null) ?{core::int} nonNullableInitializedFinalLocal = #t28 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t27{core::int};
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t27 = self::_#uninitializedNonFinalTopLevelField in #t27.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t27{core::int};
-static set uninitializedNonFinalTopLevelField(core::int #t28) → void
-  self::_#uninitializedNonFinalTopLevelField = #t28;
+  return let final core::int? #t29 = self::_#uninitializedNonFinalTopLevelField in #t29.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t29{core::int};
+static set uninitializedNonFinalTopLevelField(core::int #t30) → void
+  self::_#uninitializedNonFinalTopLevelField = #t30;
 static get uninitializedFinalTopLevelField() → core::int
-  return let final core::int? #t29 = self::_#uninitializedFinalTopLevelField in #t29.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t29{core::int};
-static set uninitializedFinalTopLevelField(core::int #t30) → void
+  return let final core::int? #t31 = self::_#uninitializedFinalTopLevelField in #t31.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t31{core::int};
+static set uninitializedFinalTopLevelField(core::int #t32) → void
   if(self::_#uninitializedFinalTopLevelField.==(null))
-    self::_#uninitializedFinalTopLevelField = #t30;
+    self::_#uninitializedFinalTopLevelField = #t32;
   else
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
 static get initializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#initializedNonFinalTopLevelField in #t31.==(null) ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t31{core::int};
-static set initializedNonFinalTopLevelField(core::int #t32) → void
-  self::_#initializedNonFinalTopLevelField = #t32;
+  return let final core::int? #t33 = self::_#initializedNonFinalTopLevelField in #t33.==(null) ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t33{core::int};
+static set initializedNonFinalTopLevelField(core::int #t34) → void
+  self::_#initializedNonFinalTopLevelField = #t34;
 static get initializedFinalTopLevelField() → core::int
-  return let final core::int? #t33 = self::_#initializedFinalTopLevelField in #t33.==(null) ?{core::int} let final core::int #t34 = 0 in self::_#initializedFinalTopLevelField.==(null) ?{core::int} self::_#initializedFinalTopLevelField = #t34 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t33{core::int};
+  return let final core::int? #t35 = self::_#initializedFinalTopLevelField in #t35.==(null) ?{core::int} let final core::int #t36 = 0 in self::_#initializedFinalTopLevelField.==(null) ?{core::int} self::_#initializedFinalTopLevelField = #t36 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t35{core::int};
 
 
 Extra constant evaluation status:
 Evaluated: VariableGet @ org-dartlang-testcase:///late_lowering_bitmasks.dart:30:25 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///late_lowering_bitmasks.dart:35:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_lowering_bitmasks.dart:18:18 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///late_lowering_bitmasks.dart:24:16 -> IntConstant(0)
-Extra constant evaluation: evaluated: 224, effectively constant: 3
+Extra constant evaluation: evaluated: 235, effectively constant: 4
diff --git a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.expect
index 0bc36f5..e5d34d1 100644
--- a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.expect
@@ -174,7 +174,10 @@
   core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      nullableInitializedFinalLocal = 0;
+      final core::int? #t23 = 0;
+      if(#nullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nullableInitializedFinalLocal");
+      nullableInitializedFinalLocal = #t23;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return nullableInitializedFinalLocal;
@@ -183,45 +186,48 @@
   core::bool #nonNullableInitializedFinalLocal#isSet = false;
   function #nonNullableInitializedFinalLocal#get() → core::int {
     if(!#nonNullableInitializedFinalLocal#isSet) {
-      nonNullableInitializedFinalLocal = 0;
+      final core::int #t24 = 0;
+      if(#nonNullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nonNullableInitializedFinalLocal");
+      nonNullableInitializedFinalLocal = #t24;
       #nonNullableInitializedFinalLocal#isSet = true;
     }
     return nonNullableInitializedFinalLocal{core::int};
   }
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t23 = self::_#uninitializedNonFinalTopLevelField in #t23{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
-static set uninitializedNonFinalTopLevelField(core::int #t24) → void {
+  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedNonFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
+static set uninitializedNonFinalTopLevelField(core::int #t26) → void {
   self::_#uninitializedNonFinalTopLevelField#isSet = true;
-  self::_#uninitializedNonFinalTopLevelField = #t24;
+  self::_#uninitializedNonFinalTopLevelField = #t26;
 }
 static get uninitializedFinalTopLevelField() → core::int
-  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
-static set uninitializedFinalTopLevelField(core::int #t26) → void
+  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t27 = self::_#uninitializedFinalTopLevelField in #t27{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
+static set uninitializedFinalTopLevelField(core::int #t28) → void
   if(self::_#uninitializedFinalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
   else {
     self::_#uninitializedFinalTopLevelField#isSet = true;
-    self::_#uninitializedFinalTopLevelField = #t26;
+    self::_#uninitializedFinalTopLevelField = #t28;
   }
 static get initializedNonFinalTopLevelField() → core::int {
   if(!self::_#initializedNonFinalTopLevelField#isSet) {
     self::_#initializedNonFinalTopLevelField = 0;
     self::_#initializedNonFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t27 = self::_#initializedNonFinalTopLevelField in #t27{core::int};
+  return let final core::int? #t29 = self::_#initializedNonFinalTopLevelField in #t29{core::int};
 }
-static set initializedNonFinalTopLevelField(core::int #t28) → void {
+static set initializedNonFinalTopLevelField(core::int #t30) → void {
   self::_#initializedNonFinalTopLevelField#isSet = true;
-  self::_#initializedNonFinalTopLevelField = #t28;
+  self::_#initializedNonFinalTopLevelField = #t30;
 }
 static get initializedFinalTopLevelField() → core::int {
   if(!self::_#initializedFinalTopLevelField#isSet) {
-    final core::int #t29 = 0;
+    final core::int #t31 = 0;
     if(self::_#initializedFinalTopLevelField#isSet)
       throw new _in::LateError::fieldADI("initializedFinalTopLevelField");
-    self::_#initializedFinalTopLevelField = #t29;
+    self::_#initializedFinalTopLevelField = #t31;
     self::_#initializedFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t30 = self::_#initializedFinalTopLevelField in #t30{core::int};
+  return let final core::int? #t32 = self::_#initializedFinalTopLevelField in #t32{core::int};
 }
diff --git a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.transformed.expect
index 0bc36f5..e5d34d1 100644
--- a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.weak.transformed.expect
@@ -174,7 +174,10 @@
   core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      nullableInitializedFinalLocal = 0;
+      final core::int? #t23 = 0;
+      if(#nullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nullableInitializedFinalLocal");
+      nullableInitializedFinalLocal = #t23;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return nullableInitializedFinalLocal;
@@ -183,45 +186,48 @@
   core::bool #nonNullableInitializedFinalLocal#isSet = false;
   function #nonNullableInitializedFinalLocal#get() → core::int {
     if(!#nonNullableInitializedFinalLocal#isSet) {
-      nonNullableInitializedFinalLocal = 0;
+      final core::int #t24 = 0;
+      if(#nonNullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nonNullableInitializedFinalLocal");
+      nonNullableInitializedFinalLocal = #t24;
       #nonNullableInitializedFinalLocal#isSet = true;
     }
     return nonNullableInitializedFinalLocal{core::int};
   }
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t23 = self::_#uninitializedNonFinalTopLevelField in #t23{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
-static set uninitializedNonFinalTopLevelField(core::int #t24) → void {
+  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedNonFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
+static set uninitializedNonFinalTopLevelField(core::int #t26) → void {
   self::_#uninitializedNonFinalTopLevelField#isSet = true;
-  self::_#uninitializedNonFinalTopLevelField = #t24;
+  self::_#uninitializedNonFinalTopLevelField = #t26;
 }
 static get uninitializedFinalTopLevelField() → core::int
-  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
-static set uninitializedFinalTopLevelField(core::int #t26) → void
+  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t27 = self::_#uninitializedFinalTopLevelField in #t27{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
+static set uninitializedFinalTopLevelField(core::int #t28) → void
   if(self::_#uninitializedFinalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
   else {
     self::_#uninitializedFinalTopLevelField#isSet = true;
-    self::_#uninitializedFinalTopLevelField = #t26;
+    self::_#uninitializedFinalTopLevelField = #t28;
   }
 static get initializedNonFinalTopLevelField() → core::int {
   if(!self::_#initializedNonFinalTopLevelField#isSet) {
     self::_#initializedNonFinalTopLevelField = 0;
     self::_#initializedNonFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t27 = self::_#initializedNonFinalTopLevelField in #t27{core::int};
+  return let final core::int? #t29 = self::_#initializedNonFinalTopLevelField in #t29{core::int};
 }
-static set initializedNonFinalTopLevelField(core::int #t28) → void {
+static set initializedNonFinalTopLevelField(core::int #t30) → void {
   self::_#initializedNonFinalTopLevelField#isSet = true;
-  self::_#initializedNonFinalTopLevelField = #t28;
+  self::_#initializedNonFinalTopLevelField = #t30;
 }
 static get initializedFinalTopLevelField() → core::int {
   if(!self::_#initializedFinalTopLevelField#isSet) {
-    final core::int #t29 = 0;
+    final core::int #t31 = 0;
     if(self::_#initializedFinalTopLevelField#isSet)
       throw new _in::LateError::fieldADI("initializedFinalTopLevelField");
-    self::_#initializedFinalTopLevelField = #t29;
+    self::_#initializedFinalTopLevelField = #t31;
     self::_#initializedFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t30 = self::_#initializedFinalTopLevelField in #t30{core::int};
+  return let final core::int? #t32 = self::_#initializedFinalTopLevelField in #t32{core::int};
 }
diff --git a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.expect b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.expect
index d63b6e3..df92880 100644
--- a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.expect
@@ -106,29 +106,32 @@
   core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      nullableInitializedFinalLocal = 0;
+      final core::int? #t24 = 0;
+      if(#nullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nullableInitializedFinalLocal");
+      nullableInitializedFinalLocal = #t24;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return nullableInitializedFinalLocal;
   }
   final core::int? nonNullableInitializedFinalLocal;
   function #nonNullableInitializedFinalLocal#get() → core::int
-    return let final core::int? #t24 = nonNullableInitializedFinalLocal in #t24.==(null) ?{core::int} nonNullableInitializedFinalLocal = 0 : #t24{core::int};
+    return let final core::int? #t25 = nonNullableInitializedFinalLocal in #t25.==(null) ?{core::int} let final core::int #t26 = 0 in nonNullableInitializedFinalLocal.==(null) ?{core::int} nonNullableInitializedFinalLocal = #t26 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t25{core::int};
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t25 = self::_#uninitializedNonFinalTopLevelField in #t25.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t25{core::int};
-static set uninitializedNonFinalTopLevelField(core::int #t26) → void
-  self::_#uninitializedNonFinalTopLevelField = #t26;
+  return let final core::int? #t27 = self::_#uninitializedNonFinalTopLevelField in #t27.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t27{core::int};
+static set uninitializedNonFinalTopLevelField(core::int #t28) → void
+  self::_#uninitializedNonFinalTopLevelField = #t28;
 static get uninitializedFinalTopLevelField() → core::int
-  return let final core::int? #t27 = self::_#uninitializedFinalTopLevelField in #t27.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t27{core::int};
-static set uninitializedFinalTopLevelField(core::int #t28) → void
+  return let final core::int? #t29 = self::_#uninitializedFinalTopLevelField in #t29.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t29{core::int};
+static set uninitializedFinalTopLevelField(core::int #t30) → void
   if(self::_#uninitializedFinalTopLevelField.==(null))
-    self::_#uninitializedFinalTopLevelField = #t28;
+    self::_#uninitializedFinalTopLevelField = #t30;
   else
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
 static get initializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t29 = self::_#initializedNonFinalTopLevelField in #t29.==(null) ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t29{core::int};
-static set initializedNonFinalTopLevelField(core::int #t30) → void
-  self::_#initializedNonFinalTopLevelField = #t30;
+  return let final core::int? #t31 = self::_#initializedNonFinalTopLevelField in #t31.==(null) ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t31{core::int};
+static set initializedNonFinalTopLevelField(core::int #t32) → void
+  self::_#initializedNonFinalTopLevelField = #t32;
 static get initializedFinalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#initializedFinalTopLevelField in #t31.==(null) ?{core::int} let final core::int #t32 = 0 in self::_#initializedFinalTopLevelField.==(null) ?{core::int} self::_#initializedFinalTopLevelField = #t32 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t31{core::int};
+  return let final core::int? #t33 = self::_#initializedFinalTopLevelField in #t33.==(null) ?{core::int} let final core::int #t34 = 0 in self::_#initializedFinalTopLevelField.==(null) ?{core::int} self::_#initializedFinalTopLevelField = #t34 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t33{core::int};
diff --git a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.transformed.expect
index 23aeb4d..c2964fd 100644
--- a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.strong.transformed.expect
@@ -106,36 +106,40 @@
   core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      nullableInitializedFinalLocal = 0;
+      final core::int? #t24 = 0;
+      if(#nullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nullableInitializedFinalLocal");
+      nullableInitializedFinalLocal = #t24;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return nullableInitializedFinalLocal;
   }
   final core::int? nonNullableInitializedFinalLocal;
   function #nonNullableInitializedFinalLocal#get() → core::int
-    return let final core::int? #t24 = nonNullableInitializedFinalLocal in #t24.==(null) ?{core::int} nonNullableInitializedFinalLocal = 0 : #t24{core::int};
+    return let final core::int? #t25 = nonNullableInitializedFinalLocal in #t25.==(null) ?{core::int} let final core::int #t26 = 0 in nonNullableInitializedFinalLocal.==(null) ?{core::int} nonNullableInitializedFinalLocal = #t26 : throw new _in::LateError::localADI("nonNullableInitializedFinalLocal") : #t25{core::int};
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t25 = self::_#uninitializedNonFinalTopLevelField in #t25.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t25{core::int};
-static set uninitializedNonFinalTopLevelField(core::int #t26) → void
-  self::_#uninitializedNonFinalTopLevelField = #t26;
+  return let final core::int? #t27 = self::_#uninitializedNonFinalTopLevelField in #t27.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField") : #t27{core::int};
+static set uninitializedNonFinalTopLevelField(core::int #t28) → void
+  self::_#uninitializedNonFinalTopLevelField = #t28;
 static get uninitializedFinalTopLevelField() → core::int
-  return let final core::int? #t27 = self::_#uninitializedFinalTopLevelField in #t27.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t27{core::int};
-static set uninitializedFinalTopLevelField(core::int #t28) → void
+  return let final core::int? #t29 = self::_#uninitializedFinalTopLevelField in #t29.==(null) ?{core::int} throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField") : #t29{core::int};
+static set uninitializedFinalTopLevelField(core::int #t30) → void
   if(self::_#uninitializedFinalTopLevelField.==(null))
-    self::_#uninitializedFinalTopLevelField = #t28;
+    self::_#uninitializedFinalTopLevelField = #t30;
   else
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
 static get initializedNonFinalTopLevelField() → core::int
-  return let final core::int? #t29 = self::_#initializedNonFinalTopLevelField in #t29.==(null) ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t29{core::int};
-static set initializedNonFinalTopLevelField(core::int #t30) → void
-  self::_#initializedNonFinalTopLevelField = #t30;
+  return let final core::int? #t31 = self::_#initializedNonFinalTopLevelField in #t31.==(null) ?{core::int} self::_#initializedNonFinalTopLevelField = 0 : #t31{core::int};
+static set initializedNonFinalTopLevelField(core::int #t32) → void
+  self::_#initializedNonFinalTopLevelField = #t32;
 static get initializedFinalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#initializedFinalTopLevelField in #t31.==(null) ?{core::int} let final core::int #t32 = 0 in self::_#initializedFinalTopLevelField.==(null) ?{core::int} self::_#initializedFinalTopLevelField = #t32 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t31{core::int};
+  return let final core::int? #t33 = self::_#initializedFinalTopLevelField in #t33.==(null) ?{core::int} let final core::int #t34 = 0 in self::_#initializedFinalTopLevelField.==(null) ?{core::int} self::_#initializedFinalTopLevelField = #t34 : throw new _in::LateError::fieldADI("initializedFinalTopLevelField") : #t33{core::int};
 
 
 Extra constant evaluation status:
 Evaluated: VariableGet @ org-dartlang-testcase:///main.dart:30:25 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///main.dart:35:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///main.dart:18:18 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///main.dart:24:16 -> IntConstant(0)
-Extra constant evaluation: evaluated: 212, effectively constant: 3
+Extra constant evaluation: evaluated: 223, effectively constant: 4
diff --git a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.expect b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.expect
index 91d5d03..e3cd765 100644
--- a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.expect
@@ -167,7 +167,10 @@
   core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      nullableInitializedFinalLocal = 0;
+      final core::int? #t21 = 0;
+      if(#nullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nullableInitializedFinalLocal");
+      nullableInitializedFinalLocal = #t21;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return nullableInitializedFinalLocal;
@@ -176,45 +179,48 @@
   core::bool #nonNullableInitializedFinalLocal#isSet = false;
   function #nonNullableInitializedFinalLocal#get() → core::int {
     if(!#nonNullableInitializedFinalLocal#isSet) {
-      nonNullableInitializedFinalLocal = 0;
+      final core::int #t22 = 0;
+      if(#nonNullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nonNullableInitializedFinalLocal");
+      nonNullableInitializedFinalLocal = #t22;
       #nonNullableInitializedFinalLocal#isSet = true;
     }
     return nonNullableInitializedFinalLocal{core::int};
   }
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t21 = self::_#uninitializedNonFinalTopLevelField in #t21{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
-static set uninitializedNonFinalTopLevelField(core::int #t22) → void {
+  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t23 = self::_#uninitializedNonFinalTopLevelField in #t23{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
+static set uninitializedNonFinalTopLevelField(core::int #t24) → void {
   self::_#uninitializedNonFinalTopLevelField#isSet = true;
-  self::_#uninitializedNonFinalTopLevelField = #t22;
+  self::_#uninitializedNonFinalTopLevelField = #t24;
 }
 static get uninitializedFinalTopLevelField() → core::int
-  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t23 = self::_#uninitializedFinalTopLevelField in #t23{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
-static set uninitializedFinalTopLevelField(core::int #t24) → void
+  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
+static set uninitializedFinalTopLevelField(core::int #t26) → void
   if(self::_#uninitializedFinalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
   else {
     self::_#uninitializedFinalTopLevelField#isSet = true;
-    self::_#uninitializedFinalTopLevelField = #t24;
+    self::_#uninitializedFinalTopLevelField = #t26;
   }
 static get initializedNonFinalTopLevelField() → core::int {
   if(!self::_#initializedNonFinalTopLevelField#isSet) {
     self::_#initializedNonFinalTopLevelField = 0;
     self::_#initializedNonFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t25 = self::_#initializedNonFinalTopLevelField in #t25{core::int};
+  return let final core::int? #t27 = self::_#initializedNonFinalTopLevelField in #t27{core::int};
 }
-static set initializedNonFinalTopLevelField(core::int #t26) → void {
+static set initializedNonFinalTopLevelField(core::int #t28) → void {
   self::_#initializedNonFinalTopLevelField#isSet = true;
-  self::_#initializedNonFinalTopLevelField = #t26;
+  self::_#initializedNonFinalTopLevelField = #t28;
 }
 static get initializedFinalTopLevelField() → core::int {
   if(!self::_#initializedFinalTopLevelField#isSet) {
-    final core::int #t27 = 0;
+    final core::int #t29 = 0;
     if(self::_#initializedFinalTopLevelField#isSet)
       throw new _in::LateError::fieldADI("initializedFinalTopLevelField");
-    self::_#initializedFinalTopLevelField = #t27;
+    self::_#initializedFinalTopLevelField = #t29;
     self::_#initializedFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t28 = self::_#initializedFinalTopLevelField in #t28{core::int};
+  return let final core::int? #t30 = self::_#initializedFinalTopLevelField in #t30{core::int};
 }
diff --git a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.transformed.expect
index 91d5d03..e3cd765 100644
--- a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.weak.transformed.expect
@@ -167,7 +167,10 @@
   core::bool #nullableInitializedFinalLocal#isSet = false;
   function #nullableInitializedFinalLocal#get() → core::int? {
     if(!#nullableInitializedFinalLocal#isSet) {
-      nullableInitializedFinalLocal = 0;
+      final core::int? #t21 = 0;
+      if(#nullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nullableInitializedFinalLocal");
+      nullableInitializedFinalLocal = #t21;
       #nullableInitializedFinalLocal#isSet = true;
     }
     return nullableInitializedFinalLocal;
@@ -176,45 +179,48 @@
   core::bool #nonNullableInitializedFinalLocal#isSet = false;
   function #nonNullableInitializedFinalLocal#get() → core::int {
     if(!#nonNullableInitializedFinalLocal#isSet) {
-      nonNullableInitializedFinalLocal = 0;
+      final core::int #t22 = 0;
+      if(#nonNullableInitializedFinalLocal#isSet)
+        throw new _in::LateError::localADI("nonNullableInitializedFinalLocal");
+      nonNullableInitializedFinalLocal = #t22;
       #nonNullableInitializedFinalLocal#isSet = true;
     }
     return nonNullableInitializedFinalLocal{core::int};
   }
 }
 static get uninitializedNonFinalTopLevelField() → core::int
-  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t21 = self::_#uninitializedNonFinalTopLevelField in #t21{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
-static set uninitializedNonFinalTopLevelField(core::int #t22) → void {
+  return self::_#uninitializedNonFinalTopLevelField#isSet ?{core::int} let final core::int? #t23 = self::_#uninitializedNonFinalTopLevelField in #t23{core::int} : throw new _in::LateError::fieldNI("uninitializedNonFinalTopLevelField");
+static set uninitializedNonFinalTopLevelField(core::int #t24) → void {
   self::_#uninitializedNonFinalTopLevelField#isSet = true;
-  self::_#uninitializedNonFinalTopLevelField = #t22;
+  self::_#uninitializedNonFinalTopLevelField = #t24;
 }
 static get uninitializedFinalTopLevelField() → core::int
-  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t23 = self::_#uninitializedFinalTopLevelField in #t23{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
-static set uninitializedFinalTopLevelField(core::int #t24) → void
+  return self::_#uninitializedFinalTopLevelField#isSet ?{core::int} let final core::int? #t25 = self::_#uninitializedFinalTopLevelField in #t25{core::int} : throw new _in::LateError::fieldNI("uninitializedFinalTopLevelField");
+static set uninitializedFinalTopLevelField(core::int #t26) → void
   if(self::_#uninitializedFinalTopLevelField#isSet)
     throw new _in::LateError::fieldAI("uninitializedFinalTopLevelField");
   else {
     self::_#uninitializedFinalTopLevelField#isSet = true;
-    self::_#uninitializedFinalTopLevelField = #t24;
+    self::_#uninitializedFinalTopLevelField = #t26;
   }
 static get initializedNonFinalTopLevelField() → core::int {
   if(!self::_#initializedNonFinalTopLevelField#isSet) {
     self::_#initializedNonFinalTopLevelField = 0;
     self::_#initializedNonFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t25 = self::_#initializedNonFinalTopLevelField in #t25{core::int};
+  return let final core::int? #t27 = self::_#initializedNonFinalTopLevelField in #t27{core::int};
 }
-static set initializedNonFinalTopLevelField(core::int #t26) → void {
+static set initializedNonFinalTopLevelField(core::int #t28) → void {
   self::_#initializedNonFinalTopLevelField#isSet = true;
-  self::_#initializedNonFinalTopLevelField = #t26;
+  self::_#initializedNonFinalTopLevelField = #t28;
 }
 static get initializedFinalTopLevelField() → core::int {
   if(!self::_#initializedFinalTopLevelField#isSet) {
-    final core::int #t27 = 0;
+    final core::int #t29 = 0;
     if(self::_#initializedFinalTopLevelField#isSet)
       throw new _in::LateError::fieldADI("initializedFinalTopLevelField");
-    self::_#initializedFinalTopLevelField = #t27;
+    self::_#initializedFinalTopLevelField = #t29;
     self::_#initializedFinalTopLevelField#isSet = true;
   }
-  return let final core::int? #t28 = self::_#initializedFinalTopLevelField in #t28{core::int};
+  return let final core::int? #t30 = self::_#initializedFinalTopLevelField in #t30{core::int};
 }
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.expect
index 9f76172..9d4ef45 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.expect
@@ -42,14 +42,14 @@
       throw new _in::LateError::localAI("nonNullableFinalTopLevelLocal");
   final core::int? nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = null : #t13{core::int?};
+    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(nullableFinalTopLevelLocalWithInitializer) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = #t14 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t13;
   final core::int? nonNullableFinalTopLevelLocalWithInitializer;
   function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int? #t14 = nonNullableFinalTopLevelLocalWithInitializer in #t14.==(null) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = 0 : #t14{core::int};
+    return let final core::int? #t15 = nonNullableFinalTopLevelLocalWithInitializer in #t15.==(null) ?{core::int} let final core::int #t16 = 0 in nonNullableFinalTopLevelLocalWithInitializer.==(null) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = #t16 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t15{core::int};
   Null neverLocal;
   function #neverLocal#get() → Never
-    return let final Never? #t15 = neverLocal in #t15.==(null) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t15{Never};
-  function #neverLocal#set(Never #t16) → dynamic
-    return neverLocal = #t16;
+    return let final Never? #t17 = neverLocal in #t17.==(null) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t17{Never};
+  function #neverLocal#set(Never #t18) → dynamic
+    return neverLocal = #t18;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.transformed.expect
index 9f76172..1dfd282 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.transformed.expect
@@ -42,14 +42,20 @@
       throw new _in::LateError::localAI("nonNullableFinalTopLevelLocal");
   final core::int? nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = null : #t13{core::int?};
+    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(nullableFinalTopLevelLocalWithInitializer) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = #t14 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t13;
   final core::int? nonNullableFinalTopLevelLocalWithInitializer;
   function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int? #t14 = nonNullableFinalTopLevelLocalWithInitializer in #t14.==(null) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = 0 : #t14{core::int};
+    return let final core::int? #t15 = nonNullableFinalTopLevelLocalWithInitializer in #t15.==(null) ?{core::int} let final core::int #t16 = 0 in nonNullableFinalTopLevelLocalWithInitializer.==(null) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = #t16 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t15{core::int};
   Null neverLocal;
   function #neverLocal#get() → Never
-    return let final Never? #t15 = neverLocal in #t15.==(null) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t15{Never};
-  function #neverLocal#set(Never #t16) → dynamic
-    return neverLocal = #t16;
+    return let final Never? #t17 = neverLocal in #t17.==(null) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t17{Never};
+  function #neverLocal#set(Never #t18) → dynamic
+    return neverLocal = #t18;
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:12:19 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:13:18 -> IntConstant(0)
+Extra constant evaluation: evaluated: 108, effectively constant: 2
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.expect
index c2d22e5..9a53f0d 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.expect
@@ -42,14 +42,14 @@
       throw new _in::LateError::localAI("nonNullableFinalTopLevelLocal");
   final core::int? nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = null : #t13{core::int?};
+    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(nullableFinalTopLevelLocalWithInitializer) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = #t14 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t13;
   final core::int? nonNullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int>();
   function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int? #t14 = nonNullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t14) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = 0 : #t14{core::int};
+    return let final core::int #t15 = nonNullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t15) ?{core::int} let final core::int #t16 = 0 in _in::isSentinel(nonNullableFinalTopLevelLocalWithInitializer) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = #t16 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t15;
   Null neverLocal = _in::createSentinel<Never>();
   function #neverLocal#get() → Never
-    return let final Never? #t15 = neverLocal in _in::isSentinel(#t15) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t15{Never};
-  function #neverLocal#set(Never #t16) → dynamic
-    return neverLocal = #t16;
+    return let final Never? #t17 = neverLocal in _in::isSentinel(#t17) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t17{Never};
+  function #neverLocal#set(Never #t18) → dynamic
+    return neverLocal = #t18;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.transformed.expect
index c2d22e5..b4188db 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.transformed.expect
@@ -42,14 +42,20 @@
       throw new _in::LateError::localAI("nonNullableFinalTopLevelLocal");
   final core::int? nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
   function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
-    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = null : #t13{core::int?};
+    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(nullableFinalTopLevelLocalWithInitializer) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = #t14 : throw new _in::LateError::localADI("nullableFinalTopLevelLocalWithInitializer") : #t13;
   final core::int? nonNullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int>();
   function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
-    return let final core::int? #t14 = nonNullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t14) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = 0 : #t14{core::int};
+    return let final core::int #t15 = nonNullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t15) ?{core::int} let final core::int #t16 = 0 in _in::isSentinel(nonNullableFinalTopLevelLocalWithInitializer) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = #t16 : throw new _in::LateError::localADI("nonNullableFinalTopLevelLocalWithInitializer") : #t15;
   Null neverLocal = _in::createSentinel<Never>();
   function #neverLocal#get() → Never
-    return let final Never? #t15 = neverLocal in _in::isSentinel(#t15) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t15{Never};
-  function #neverLocal#set(Never #t16) → dynamic
-    return neverLocal = #t16;
+    return let final Never? #t17 = neverLocal in _in::isSentinel(#t17) ?{Never} throw new _in::LateError::localNI("neverLocal") : #t17{Never};
+  function #neverLocal#set(Never #t18) → dynamic
+    return neverLocal = #t18;
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:12:19 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:13:18 -> IntConstant(0)
+Extra constant evaluation: evaluated: 113, effectively constant: 2
diff --git a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart
new file mode 100644
index 0000000..7980d5f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, 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.
+
+// @dart=2.9
+
+import 'typedef_from_opt_in_lib.dart';
+
+Handler method1() => (Request r) async => new Response();
+
+Typedef method2() => (r) => 0;
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.textual_outline.expect
new file mode 100644
index 0000000..90cf0f0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+// @dart = 2.9
+import 'typedef_from_opt_in_lib.dart';
+
+Handler method1() => (Request r) async => new Response();
+Typedef method2() => (r) => 0;
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..90cf0f0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+// @dart = 2.9
+import 'typedef_from_opt_in_lib.dart';
+
+Handler method1() => (Request r) async => new Response();
+Typedef method2() => (r) => 0;
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.expect
new file mode 100644
index 0000000..95d0805
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "typedef_from_opt_in_lib.dart" as typ;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///typedef_from_opt_in_lib.dart";
+
+static method method1() → (typ::Request) →* FutureOr<typ::Response>
+  return (typ::Request* r) → asy::Future<typ::Response*>* async => new typ::Response::•();
+static method method2() → (core::int?) →* core::int
+  return (core::int* r) → core::int* => 0;
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef Handler = (typ::Request) → FutureOr<typ::Response>;
+typedef Typedef = (core::int?) → core::int;
+class Request extends core::Object {
+  synthetic constructor •() → typ::Request
+    : super core::Object::•()
+    ;
+}
+class Response extends core::Object {
+  synthetic constructor •() → typ::Response
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
new file mode 100644
index 0000000..504f220
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
@@ -0,0 +1,58 @@
+library;
+import self as self;
+import "typedef_from_opt_in_lib.dart" as typ;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///typedef_from_opt_in_lib.dart";
+
+static method method1() → (typ::Request) →* FutureOr<typ::Response>
+  return (typ::Request* r) → asy::Future<typ::Response*>* /* originally async */ {
+    final asy::_Future<typ::Response*>* :async_future = new asy::_Future::•<typ::Response*>();
+    core::bool* :is_sync = false;
+    FutureOr<typ::Response*>* :return_value;
+    (dynamic) →* dynamic :async_op_then;
+    (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+    core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L1:
+        {
+          :return_value = new typ::Response::•();
+          break #L1;
+        }
+        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        return;
+      }
+      on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+        asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+      }
+    :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+    :async_op.call();
+    :is_sync = true;
+    return :async_future;
+  };
+static method method2() → (core::int?) →* core::int
+  return (core::int* r) → core::int* => 0;
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef Handler = (typ::Request) → FutureOr<typ::Response>;
+typedef Typedef = (core::int?) → core::int;
+class Request extends core::Object {
+  synthetic constructor •() → typ::Request
+    : super core::Object::•()
+    ;
+}
+class Response extends core::Object {
+  synthetic constructor •() → typ::Response
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in_lib.dart b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in_lib.dart
new file mode 100644
index 0000000..851b087
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in_lib.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, 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:async';
+
+class Request {}
+
+class Response {}
+
+typedef Handler = FutureOr<Response> Function(Request request);
+
+typedef Typedef = int Function(int?);
diff --git a/pkg/frontend_server/README.md b/pkg/frontend_server/README.md
new file mode 100644
index 0000000..afebf6c
--- /dev/null
+++ b/pkg/frontend_server/README.md
@@ -0,0 +1,19 @@
+The frontend_server package is used by both the flutter command line tool and the frontend_server_client package (used by webdev and package:test).
+
+## API Stability
+
+Changes to the command line API or behavior should be tested against the follwing test suites (in addition to normal HHH testing):
+  * flutter_tools: https://github.com/flutter/flutter/tree/master/packages/flutter_tools
+  * frontend_server_client: https://github.com/dart-lang/webdev/tree/master/frontend_server_client
+
+Otherwise these changes will need to be carefully coordinated with the flutter tooling and frontend_server_client teams.
+
+This API stability does not cover any of the source code APIs.
+
+
+### Stable subset
+
+* The frontend_server kernel compilation and expression evaluation for kernel should be considered "stable".
+* The frontend_server JavaScript compilation is semi-stable, but clients should anticipate coordinated breaking changes in the future.
+* The frontend_server JavaScript expression evaluation is experimental and is expected to change significantly from Dec 2020 through the end of 2021.
+* Specific flags like the --flutter-widget-cache may be added for experimentation and should not be considered stable.
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index 8dadff5..e7c5646 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -95,6 +95,7 @@
   Procedure _awaitHelperProcedure;
   Procedure _boolFromEnvironment;
   Constructor _lateInitializationFieldAssignedDuringInitializationConstructor;
+  Constructor _lateInitializationLocalAssignedDuringInitializationConstructor;
   Constructor _lateInitializationFieldNotInitializedConstructor;
   Constructor _lateInitializationLocalNotInitializedConstructor;
   Constructor _lateInitializationFieldAlreadyInitializedConstructor;
@@ -1220,6 +1221,12 @@
         index.getMember('dart:_internal', 'LateError', 'fieldADI');
   }
 
+  Constructor
+      get lateInitializationLocalAssignedDuringInitializationConstructor {
+    return _lateInitializationLocalAssignedDuringInitializationConstructor ??=
+        index.getMember('dart:_internal', 'LateError', 'localADI');
+  }
+
   Constructor get lateInitializationFieldNotInitializedConstructor {
     return _lateInitializationFieldNotInitializedConstructor ??=
         index.getMember('dart:_internal', 'LateError', 'fieldNI');
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index cc2d51b..5f0d085 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -815,6 +815,7 @@
       }
       problem(currentParent, "Type $node references an anonymous mixin class.");
     }
+    defaultDartType(node);
   }
 
   @override
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 4ebbbef..afa2668 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1148,10 +1148,9 @@
 }
 
 ErrorPtr ClassFinalizer::AllocateFinalizeClass(const Class& cls) {
+  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
   ASSERT(cls.is_finalized());
-  if (cls.is_allocate_finalized()) {
-    return Error::null();
-  }
+  ASSERT(!cls.is_allocate_finalized());
 
   Thread* thread = Thread::Current();
   HANDLESCOPE(thread);
@@ -1200,7 +1199,10 @@
 }
 
 ErrorPtr ClassFinalizer::LoadClassMembers(const Class& cls) {
+  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
   ASSERT(Thread::Current()->IsMutatorThread());
+  ASSERT(!cls.is_finalized());
+
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 6f83c62..2b0c369 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1700,10 +1700,16 @@
   // TODO(http://dartbug.com/16615): Validate isolate parameter.
   Isolate* iso = reinterpret_cast<Isolate*>(isolate);
   if (!Thread::EnterIsolate(iso)) {
-    FATAL(
-        "Unable to Enter Isolate : "
-        "Multiple mutators entering an isolate / "
-        "Dart VM is shutting down");
+    if (iso->IsScheduled()) {
+      FATAL(
+          "Isolate %s is already scheduled on mutator thread %p, "
+          "failed to schedule from os thread 0x%" Px "\n",
+          iso->name(), iso->scheduled_mutator_thread(),
+          OSThread::ThreadIdToIntPtr(OSThread::GetCurrentThreadId()));
+    } else {
+      FATAL("Unable to enter isolate %s as Dart VM is shutting down",
+            iso->name());
+    }
   }
   // A Thread structure has been associated to the thread, we do the
   // safepoint transition explicitly here instead of using the
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 3a3cbf8..e88229a 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -812,7 +812,8 @@
     return thread == nullptr ? nullptr : thread->isolate();
   }
 
-  bool IsScheduled() { return scheduled_mutator_thread_ != nullptr; }
+  bool IsScheduled() { return scheduled_mutator_thread() != nullptr; }
+  Thread* scheduled_mutator_thread() const { return scheduled_mutator_thread_; }
 
   // Register a newly introduced class.
   void RegisterClass(const Class& cls);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 87ca73b..803e75c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4260,7 +4260,6 @@
 // Ensure that top level parsing of the class has been done.
 ErrorPtr Class::EnsureIsFinalized(Thread* thread) const {
   ASSERT(!IsNull());
-  // Finalized classes have already been parsed.
   if (is_finalized()) {
     return Error::null();
   }
@@ -4290,7 +4289,6 @@
 // this class is ready to be allocated.
 ErrorPtr Class::EnsureIsAllocateFinalized(Thread* thread) const {
   ASSERT(!IsNull());
-  // Finalized classes have already been parsed.
   if (is_allocate_finalized()) {
     return Error::null();
   }
@@ -4298,6 +4296,10 @@
     Compiler::AbortBackgroundCompilation(
         DeoptId::kNone, "Class allocate finalization while compiling");
   }
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+  if (is_allocate_finalized()) {
+    return Error::null();
+  }
   ASSERT(thread->IsMutatorThread());
   ASSERT(thread != NULL);
   Error& error = Error::Handle(thread->zone(), EnsureIsFinalized(thread));
diff --git a/sdk/lib/internal/errors.dart b/sdk/lib/internal/errors.dart
index 3fe6e40..8b93cd1 100644
--- a/sdk/lib/internal/errors.dart
+++ b/sdk/lib/internal/errors.dart
@@ -17,6 +17,10 @@
       : _message =
             "Field '$fieldName' has been assigned during initialization.";
 
+  LateError.localADI(String localName)
+      : _message =
+            "Local '$localName' has been assigned during initialization.";
+
   @pragma("vm:entry-point")
   LateError.fieldNI(String fieldName)
       : _message = "Field '${fieldName}' has not been initialized.";
diff --git a/tests/language/type_variable/scope_test.dart b/tests/language/type_variable/scope_test.dart
index 3be94a3..2a68d15 100644
--- a/tests/language/type_variable/scope_test.dart
+++ b/tests/language/type_variable/scope_test.dart
@@ -43,6 +43,8 @@
   // [cfe] Type variables can't be used in static members.
   //                 ^
   // [cfe] Verification of the generated program failed:
+  //                 ^
+  // [cfe] Verification of the generated program failed:
 
   static
   Foo<T>
diff --git a/tools/VERSION b/tools/VERSION
index ac2b734..5397bdc 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 112
+PRERELEASE 113
 PRERELEASE_PATCH 0
\ No newline at end of file