Version 2.8.0-dev.15.0

Merge commit 'eb9c26bd378fbe3a0ebd00ce91973b49814d32be' into dev
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 20db2ee..8c08a77 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2020-02-27T09:12:42.886102",
+  "generated": "2020-03-11T09:16:09.767708",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -57,12 +57,6 @@
       "languageVersion": "2.7"
     },
     {
-      "name": "analyzer_fe_comparison",
-      "rootUri": "../pkg/analyzer_fe_comparison",
-      "packageUri": "lib/",
-      "languageVersion": "2.0"
-    },
-    {
       "name": "analyzer_plugin",
       "rootUri": "../pkg/analyzer_plugin",
       "packageUri": "lib/",
diff --git a/.packages b/.packages
index b6c666c..a5ab646 100644
--- a/.packages
+++ b/.packages
@@ -13,7 +13,6 @@
 analysis_tool:pkg/analysis_tool/lib
 analyzer:pkg/analyzer/lib
 analyzer_cli:pkg/analyzer_cli/lib
-analyzer_fe_comparison:pkg/analyzer_fe_comparison/lib
 analyzer_plugin:pkg/analyzer_plugin/lib
 args:third_party/pkg/args/lib
 async:third_party/pkg/async/lib
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9146f83..8b44589 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -61,6 +61,11 @@
   `ProcessStartMode.inheritStdio`) upon accessing the `stdin`, `stdout`, and
   `stderr` getters. Previously these getters would all return `null`.
 
+* **Breaking change** [#40706](https://github.com/dart-lang/sdk/issues/40706):
+  The dummy object returned if `FileStat.stat()` and `FileStat.statSync()` fail
+  now contains Unix epoch timestamps instead of `null` for the `accessed`,
+  `changed`, and `modified` getters.
+
 #### `dart:mirrors`
 
 * Added `MirrorSystem.neverType`.
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index d715141..739dd20 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -1185,25 +1185,40 @@
       variableInfo[variable] ?? _freshVariableInfo;
 
   /// Updates the state to indicate that variables that are not definitely
-  /// unassigned in the [other] are also not definitely unassigned in the
-  /// result.
-  FlowModel<Variable, Type> joinUnassigned(FlowModel<Variable, Type> other) {
+  /// unassigned in the [other], or are [written], are also not definitely
+  /// unassigned in the result.
+  FlowModel<Variable, Type> joinUnassigned({
+    FlowModel<Variable, Type> other,
+    Iterable<Variable> written,
+  }) {
     Map<Variable, VariableModel<Type>> newVariableInfo;
 
-    for (Variable variable in other.variableInfo.keys) {
-      VariableModel<Type> otherInfo = other.variableInfo[variable];
-      if (otherInfo.unassigned) continue;
-
+    void markNotUnassigned(Variable variable) {
       VariableModel<Type> info = variableInfo[variable];
-      if (info == null) continue;
+      if (info == null) return;
 
       VariableModel<Type> newInfo = info.markNotUnassigned();
-      if (identical(newInfo, info)) continue;
+      if (identical(newInfo, info)) return;
 
       (newVariableInfo ??= new Map<Variable, VariableModel<Type>>.from(
           variableInfo))[variable] = newInfo;
     }
 
+    if (other != null) {
+      for (Variable variable in other.variableInfo.keys) {
+        VariableModel<Type> otherInfo = other.variableInfo[variable];
+        if (!otherInfo.unassigned) {
+          markNotUnassigned(variable);
+        }
+      }
+    }
+
+    if (written != null) {
+      for (Variable variable in written) {
+        markNotUnassigned(variable);
+      }
+    }
+
     if (newVariableInfo == null) return this;
 
     return FlowModel<Variable, Type>._(reachable, newVariableInfo);
@@ -2217,7 +2232,7 @@
     FlowModel<Variable, Type> falseCondition = context._conditionInfo.ifFalse;
 
     _current = _join(falseCondition, breakState);
-    _current = _current.joinUnassigned(afterUpdate);
+    _current = _current.joinUnassigned(other: afterUpdate);
   }
 
   @override
@@ -2256,6 +2271,9 @@
     _stack.add(new _SimpleContext(_current));
     _current = _current.removePromotedAll(_assignedVariables._anywhere._written,
         _assignedVariables._anywhere._captured);
+    _current = _current.joinUnassigned(
+      written: _assignedVariables._anywhere._written,
+    );
   }
 
   @override
@@ -2266,7 +2284,7 @@
     _SimpleContext<Variable, Type> context =
         _stack.removeLast() as _SimpleContext<Variable, Type>;
     _current = context._previous;
-    _current = _current.joinUnassigned(afterBody);
+    _current = _current.joinUnassigned(other: afterBody);
   }
 
   @override
@@ -2597,7 +2615,7 @@
         _stack.removeLast() as _WhileContext<Variable, Type>;
     var afterBody = _current;
     _current = _join(context._conditionInfo.ifFalse, context._breakModel);
-    _current = _current.joinUnassigned(afterBody);
+    _current = _current.joinUnassigned(other: afterBody);
   }
 
   @override
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index 18cf339..e3e5ffb 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -3565,7 +3565,7 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageFinalAndCovariantLateWithInitializer = const MessageCode(
     "FinalAndCovariantLateWithInitializer",
-    analyzerCodes: <String>["ParserErrorCode.FINAL_AND_COVARIANT"],
+    index: 101,
     message:
         r"""Members marked 'late' with an initializer can't be declared to be both 'final' and 'covariant'.""",
     tip:
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index 26608af..b18db89 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -4267,21 +4267,6 @@
     return isConditional;
   }
 
-  Token parseNullAwareBracketOrConditionalExpressionRest(
-      Token token, TypeParamOrArgInfo typeArg) {
-    Token question = token.next;
-    assert(optional('?', question));
-    Token bracket = question.next;
-    assert(optional('[', bracket));
-
-    bool isConditional = canParseAsConditional(question);
-    if (isConditional) {
-      return parseConditionalExpressionRest(token);
-    }
-    // It wasn't a conditional expression. Must be a null aware bracket then.
-    return parseArgumentOrIndexStar(token, typeArg, true);
-  }
-
   Token parseConditionalExpressionRest(Token token) {
     Token question = token = token.next;
     assert(optional('?', question));
@@ -4375,6 +4360,10 @@
               identical(type, TokenType.OPEN_SQUARE_BRACKET) ||
               identical(type, TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET)) {
             token = parseArgumentOrIndexStar(token, typeArg, false);
+          } else if (identical(type, TokenType.QUESTION)) {
+            // We have determined selector precedence so this is a null-aware
+            // bracket operator.
+            token = parseArgumentOrIndexStar(token, typeArg, true);
           } else if (identical(type, TokenType.INDEX)) {
             BeginToken replacement = link(
                 new BeginToken(TokenType.OPEN_SQUARE_BRACKET, next.charOffset,
@@ -4397,12 +4386,7 @@
         } else if (identical(type, TokenType.AS)) {
           token = parseAsOperatorRest(token);
         } else if (identical(type, TokenType.QUESTION)) {
-          if (optional('[', next.next)) {
-            token = parseNullAwareBracketOrConditionalExpressionRest(
-                token, typeArg);
-          } else {
-            token = parseConditionalExpressionRest(token);
-          }
+          token = parseConditionalExpressionRest(token);
         } else {
           if (level == EQUALITY_PRECEDENCE || level == RELATIONAL_PRECEDENCE) {
             // We don't allow (a == b == c) or (a < b < c).
@@ -4444,6 +4428,14 @@
         return SELECTOR_PRECEDENCE;
       }
       return POSTFIX_PRECEDENCE;
+    } else if (identical(type, TokenType.QUESTION) &&
+        optional('[', token.next)) {
+      // "?[" can be a null-aware bracket or a conditional. If it's a
+      // null-aware bracket it has selector precedence.
+      bool isConditional = canParseAsConditional(token);
+      if (!isConditional) {
+        return SELECTOR_PRECEDENCE;
+      }
     }
     return type.precedence;
   }
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/function_expression.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/function_expression.dart
index d614577..1bcbfc1 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/function_expression.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/function_expression.dart
@@ -2,29 +2,6 @@
 // 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.
 
-closure_read() {
-  late int v1, v2;
-
-  v1 = 0;
-
-  [0, 1, 2].forEach((t) {
-    v1;
-    /*unassigned*/ v2;
-  });
-}
-
-closure_write() {
-  late int v;
-
-  /*unassigned*/ v;
-
-  [0, 1, 2].forEach((t) {
-    v = t;
-  });
-
-  v;
-}
-
 localFunction_local() {
   late int v;
 
@@ -50,32 +27,21 @@
   }
 }
 
-localFunction_read() {
+readInClosure_writeInMain() {
   late int v1, v2, v3;
 
   v1 = 0;
 
-  void f() {
+  [0, 1, 2].forEach((t) {
     v1;
-    /*unassigned*/ v2;
-  }
+    v2;
+    /*unassigned*/ v3;
+  });
 
   v2 = 0;
 }
 
-localFunction_write() {
-  late int v;
-
-  /*unassigned*/ v;
-
-  void f() {
-    v = 0;
-  }
-
-  v;
-}
-
-writeCaptured() {
+readInLocal_writeInLocal() {
   late int v1, v2;
 
   void f() {
@@ -91,6 +57,46 @@
 
   g();
   f();
+}
+
+readInLocal_writeInMain() {
+  late int v1, v2, v3;
+
+  v1 = 0;
+
+  void f() {
+    v1;
+    v2;
+    /*unassigned*/ v3;
+  }
+
+  v2 = 0;
+  f();
+}
+
+readInMain_writeInClosure() {
+  late int v1, v2;
+
+  /*unassigned*/ v1;
+  /*unassigned*/ v2;
+
+  [0, 1, 2].forEach((t) {
+    v1 = t;
+  });
+
+  v1;
+  /*unassigned*/ v2;
+}
+
+readInMain_writeInLocal() {
+  late int v1, v2;
+
+  /*unassigned*/ v1;
+  /*unassigned*/ v2;
+
+  void f() {
+    v1 = 0;
+  }
 
   v1;
   /*unassigned*/ v2;
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
index 93374c3..f28c2e9 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -2118,76 +2118,110 @@
     });
 
     group('joinUnassigned', () {
-      test('unchanged', () {
-        var h = _Harness();
+      group('other', () {
+        test('unchanged', () {
+          var h = _Harness();
 
-        var a = _Var('a', _Type('int'));
-        var b = _Var('b', _Type('int'));
+          var a = _Var('a', _Type('int'));
+          var b = _Var('b', _Type('int'));
 
-        var s1 = FlowModel<_Var, _Type>(true)
-            .declare(a, false)
-            .declare(b, false)
-            .write(a, _Type('int'), h);
-        expect(s1.variableInfo, {
-          a: _matchVariableModel(assigned: true, unassigned: false),
-          b: _matchVariableModel(assigned: false, unassigned: true),
+          var s1 = FlowModel<_Var, _Type>(true)
+              .declare(a, false)
+              .declare(b, false)
+              .write(a, _Type('int'), h);
+          expect(s1.variableInfo, {
+            a: _matchVariableModel(assigned: true, unassigned: false),
+            b: _matchVariableModel(assigned: false, unassigned: true),
+          });
+
+          var s2 = s1.write(a, _Type('int'), h);
+          expect(s2.variableInfo, {
+            a: _matchVariableModel(assigned: true, unassigned: false),
+            b: _matchVariableModel(assigned: false, unassigned: true),
+          });
+
+          var s3 = s1.joinUnassigned(other: s2);
+          expect(s3, same(s1));
         });
 
-        var s2 = s1.write(a, _Type('int'), h);
-        expect(s2.variableInfo, {
-          a: _matchVariableModel(assigned: true, unassigned: false),
-          b: _matchVariableModel(assigned: false, unassigned: true),
-        });
+        test('changed', () {
+          var h = _Harness();
 
-        var s3 = s1.joinUnassigned(s2);
-        expect(s3, same(s1));
-      });
+          var a = _Var('a', _Type('int'));
+          var b = _Var('b', _Type('int'));
+          var c = _Var('c', _Type('int'));
 
-      test('written', () {
-        var h = _Harness();
+          var s1 = FlowModel<_Var, _Type>(true)
+              .declare(a, false)
+              .declare(b, false)
+              .declare(c, false)
+              .write(a, _Type('int'), h);
+          expect(s1.variableInfo, {
+            a: _matchVariableModel(assigned: true, unassigned: false),
+            b: _matchVariableModel(assigned: false, unassigned: true),
+            c: _matchVariableModel(assigned: false, unassigned: true),
+          });
 
-        var a = _Var('a', _Type('int'));
-        var b = _Var('b', _Type('int'));
-        var c = _Var('c', _Type('int'));
+          var s2 = s1.write(b, _Type('int'), h);
+          expect(s2.variableInfo, {
+            a: _matchVariableModel(assigned: true, unassigned: false),
+            b: _matchVariableModel(assigned: true, unassigned: false),
+            c: _matchVariableModel(assigned: false, unassigned: true),
+          });
 
-        var s1 = FlowModel<_Var, _Type>(true)
-            .declare(a, false)
-            .declare(b, false)
-            .declare(c, false)
-            .write(a, _Type('int'), h);
-        expect(s1.variableInfo, {
-          a: _matchVariableModel(assigned: true, unassigned: false),
-          b: _matchVariableModel(assigned: false, unassigned: true),
-          c: _matchVariableModel(assigned: false, unassigned: true),
-        });
-
-        var s2 = s1.write(b, _Type('int'), h);
-        expect(s2.variableInfo, {
-          a: _matchVariableModel(assigned: true, unassigned: false),
-          b: _matchVariableModel(assigned: true, unassigned: false),
-          c: _matchVariableModel(assigned: false, unassigned: true),
-        });
-
-        var s3 = s1.joinUnassigned(s2);
-        expect(s3.variableInfo, {
-          a: _matchVariableModel(assigned: true, unassigned: false),
-          b: _matchVariableModel(assigned: false, unassigned: false),
-          c: _matchVariableModel(assigned: false, unassigned: true),
+          var s3 = s1.joinUnassigned(other: s2);
+          expect(s3.variableInfo, {
+            a: _matchVariableModel(assigned: true, unassigned: false),
+            b: _matchVariableModel(assigned: false, unassigned: false),
+            c: _matchVariableModel(assigned: false, unassigned: true),
+          });
         });
       });
 
-      test('write captured', () {
-        var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
-            .tryPromote(h, objectQVar, _Type('int'))
-            .ifTrue
-            .tryPromote(h, intQVar, _Type('int'))
-            .ifTrue;
-        var s2 = s1.removePromotedAll([], [intQVar]);
-        expect(s2.reachable, true);
-        expect(s2.variableInfo, {
-          objectQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int']),
-          intQVar: _matchVariableModel(chain: null, ofInterest: isEmpty)
+      group('written', () {
+        test('unchanged', () {
+          var h = _Harness();
+
+          var a = _Var('a', _Type('int'));
+          var b = _Var('b', _Type('int'));
+
+          var s1 = FlowModel<_Var, _Type>(true)
+              .declare(a, false)
+              .declare(b, false)
+              .write(a, _Type('int'), h);
+          expect(s1.variableInfo, {
+            a: _matchVariableModel(assigned: true, unassigned: false),
+            b: _matchVariableModel(assigned: false, unassigned: true),
+          });
+
+          var s2 = s1.joinUnassigned(written: [a]);
+          expect(s2, same(s1));
+        });
+
+        test('changed', () {
+          var h = _Harness();
+
+          var a = _Var('a', _Type('int'));
+          var b = _Var('b', _Type('int'));
+          var c = _Var('c', _Type('int'));
+
+          var s1 = FlowModel<_Var, _Type>(true)
+              .declare(a, false)
+              .declare(b, false)
+              .declare(c, false)
+              .write(a, _Type('int'), h);
+          expect(s1.variableInfo, {
+            a: _matchVariableModel(assigned: true, unassigned: false),
+            b: _matchVariableModel(assigned: false, unassigned: true),
+            c: _matchVariableModel(assigned: false, unassigned: true),
+          });
+
+          var s2 = s1.joinUnassigned(written: [b]);
+          expect(s2.variableInfo, {
+            a: _matchVariableModel(assigned: true, unassigned: false),
+            b: _matchVariableModel(assigned: false, unassigned: false),
+            c: _matchVariableModel(assigned: false, unassigned: true),
+          });
         });
       });
     });
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 6b68d27..75045dd 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -5126,6 +5126,11 @@
           an analysis root, or the requested operation is not available
           for the file.
         </p>
+      </dd><dt class="value">FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED</dt><dd>
+        
+        <p>
+          A file was change while widget descriptions were being computed.
+        </p>
       </dd><dt class="value">FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET</dt><dd>
         
         <p>
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 4d8dc58..1300974 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -17642,6 +17642,7 @@
 ///   CONTENT_MODIFIED
 ///   DEBUG_PORT_COULD_NOT_BE_OPENED
 ///   FILE_NOT_ANALYZED
+///   FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED
 ///   FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET
 ///   FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION
 ///   FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID
@@ -17691,6 +17692,11 @@
   static const RequestErrorCode FILE_NOT_ANALYZED =
       RequestErrorCode._('FILE_NOT_ANALYZED');
 
+  /// A file was change while widget descriptions were being computed.
+  static const RequestErrorCode
+      FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED =
+      RequestErrorCode._('FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED');
+
   /// The given location does not have a supported widget.
   static const RequestErrorCode FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET =
       RequestErrorCode._('FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET');
@@ -17848,6 +17854,7 @@
     CONTENT_MODIFIED,
     DEBUG_PORT_COULD_NOT_BE_OPENED,
     FILE_NOT_ANALYZED,
+    FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED,
     FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET,
     FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION,
     FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID,
@@ -17893,6 +17900,8 @@
         return DEBUG_PORT_COULD_NOT_BE_OPENED;
       case 'FILE_NOT_ANALYZED':
         return FILE_NOT_ANALYZED;
+      case 'FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED':
+        return FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED;
       case 'FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET':
         return FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET;
       case 'FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION':
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
index 6c2468b..4a4e1da 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
@@ -514,27 +514,18 @@
     }).toList();
   }
 
-  TraceEntryInfo _computeTraceEntry(PropagationStepInfo step) {
-    var codeReference = step.codeReference;
-    var length = 1; // TODO(paulberry): figure out the correct value.
-    var description = step.toString(); // TODO(paulberry): improve this message.
-    return TraceEntryInfo(
-        description,
-        codeReference?.function,
-        codeReference == null
-            ? null
-            : NavigationTarget(codeReference.path, codeReference.column,
-                codeReference.line, length));
-  }
-
   TraceInfo _computeTraceInfo(NullabilityNodeInfo node) {
     List<TraceEntryInfo> entries = [];
     var step = node.whyNullable;
+    assert(identical(step.targetNode, node));
     while (step != null) {
-      entries.add(_computeTraceEntry(step));
+      entries.add(_nodeToTraceEntry(step.targetNode));
+      if (step.codeReference != null) {
+        entries.add(_stepToTraceEntry(step));
+      }
       step = step.principalCause;
     }
-    var description = node.toString(); // TODO(paulberry): improve this message.
+    var description = 'Nullability reason';
     return TraceInfo(description, entries);
   }
 
@@ -728,6 +719,23 @@
     return resourceProvider.pathContext.split(filePath).contains('test');
   }
 
+  TraceEntryInfo _makeTraceEntry(
+      String description, CodeReference codeReference) {
+    var length = 1; // TODO(paulberry): figure out the correct value.
+    return TraceEntryInfo(
+        description,
+        codeReference?.function,
+        codeReference == null
+            ? null
+            : NavigationTarget(codeReference.path, codeReference.column,
+                codeReference.line, length));
+  }
+
+  TraceEntryInfo _nodeToTraceEntry(NullabilityNodeInfo node) {
+    var description = node.toString(); // TODO(paulberry): improve this message
+    return _makeTraceEntry(description, node.codeReference);
+  }
+
   /// Return the navigation target corresponding to the given [node] in the file
   /// with the given [filePath].
   ///
@@ -764,6 +772,11 @@
     }
   }
 
+  TraceEntryInfo _stepToTraceEntry(PropagationStepInfo step) {
+    var description = step.toString(); // TODO(paulberry): improve this message.
+    return _makeTraceEntry(description, step.codeReference);
+  }
+
   /// Return the navigation target in the file with the given [filePath] at the
   /// given [offset] ans with the given [length].
   NavigationTarget _targetForNode(
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_domain.dart b/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
index bada9dd..7686e8f 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
@@ -7,6 +7,7 @@
 import 'package:analysis_server/src/domain_abstract.dart';
 import 'package:analysis_server/src/protocol/protocol_internal.dart';
 import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/dart/analysis/session.dart';
 
 /// A [RequestHandler] that handles requests in the `flutter` domain.
 class FlutterDomainHandler extends AbstractRequestHandler {
@@ -31,10 +32,24 @@
 
     var computer = server.flutterWidgetDescriptions;
 
-    var result = await computer.getDescription(
-      resolvedUnit,
-      offset,
-    );
+    FlutterGetWidgetDescriptionResult result;
+    try {
+      result = await computer.getDescription(
+        resolvedUnit,
+        offset,
+      );
+    } on InconsistentAnalysisException {
+      server.sendResponse(
+        Response(
+          request.id,
+          error: RequestError(
+            RequestErrorCode.FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED,
+            'Concurrent modification detected.',
+          ),
+        ),
+      );
+      return;
+    }
 
     if (result == null) {
       server.sendResponse(
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index 9613ccd..901d588 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -121,6 +121,13 @@
   double startsWithDollarFeature(String name) =>
       name.startsWith('\$') ? 0.0 : 1.0;
 
+  /// Return the value of the _super matches_ feature.
+  double superMatchesFeature(
+          String containingMethodName, String proposedMemberName) =>
+      containingMethodName == null
+          ? -1.0
+          : (proposedMemberName == containingMethodName ? 1.0 : 0.0);
+
   /// Return the inheritance distance between the [subclass] and the
   /// [superclass]. The set of [visited] elements is used to guard against
   /// cycles in the type graph.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index e4570fe..d08d787 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -524,6 +524,7 @@
       // See similar logic in `imported_reference_contributor`.
 
       _addSuggestion(Keyword.DYNAMIC);
+      _addSuggestion(Keyword.VOID);
     } else {
       super.visitMethodInvocation(node);
     }
@@ -666,6 +667,7 @@
   @override
   void visitTypeArgumentList(TypeArgumentList node) {
     _addSuggestion(Keyword.DYNAMIC);
+    _addSuggestion(Keyword.VOID);
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index 7eb0343..5325ebd 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -271,9 +271,10 @@
           if (request.useNewRelevance) {
             var contextType = featureComputer.contextTypeFeature(
                 request.target.containingNode, method.returnType);
-            var superMatches = method.name == containingMethodName ? 1.0 : 0.0;
             var startsWithDollar =
                 featureComputer.startsWithDollarFeature(method.name);
+            var superMatches = featureComputer.superMatchesFeature(
+                containingMethodName, method.name);
             relevance = _computeRelevance(
                 contextType: contextType,
                 inheritanceDistance: inheritanceDistance,
@@ -299,11 +300,13 @@
                     request.target.containingNode, variable.type);
                 var startsWithDollar = featureComputer
                     .startsWithDollarFeature(propertyAccessor.name);
+                var superMatches = featureComputer.superMatchesFeature(
+                    containingMethodName, propertyAccessor.name);
                 relevance = _computeRelevance(
                     contextType: contextType,
                     inheritanceDistance: inheritanceDistance,
                     startsWithDollar: startsWithDollar,
-                    superMatches: -1.0);
+                    superMatches: superMatches);
               }
               addSuggestion(variable, relevance: relevance);
             }
@@ -317,11 +320,13 @@
                   request.target.containingNode, type);
               var startsWithDollar = featureComputer
                   .startsWithDollarFeature(propertyAccessor.name);
+              var superMatches = featureComputer.superMatchesFeature(
+                  containingMethodName, propertyAccessor.name);
               relevance = _computeRelevance(
                   contextType: contextType,
                   inheritanceDistance: inheritanceDistance,
                   startsWithDollar: startsWithDollar,
-                  superMatches: -1.0);
+                  superMatches: superMatches);
             }
             addSuggestion(propertyAccessor, relevance: relevance);
           }
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 58cd025..785aec6 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -11,6 +11,7 @@
 import 'package:analysis_server/src/services/correction/assist.dart';
 import 'package:analysis_server/src/services/correction/base_processor.dart';
 import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/dart/add_return_type.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_list_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_map_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_null_aware.dart';
@@ -161,9 +162,6 @@
     )) {
       await _addProposal_addDiagnosticPropertyReference();
     }
-    if (!_containsErrorCode({LintNames.always_declare_return_types})) {
-      await _addProposal_addReturnType();
-    }
     if (experimentStatus.control_flow_collections) {
       if (!_containsErrorCode(
         {LintNames.prefer_if_elements_to_conditional_expressions},
@@ -269,6 +267,10 @@
     }
 
     await computeIfNotErrorCode(
+      AddReturnType(),
+      {LintNames.always_declare_return_types},
+    );
+    await computeIfNotErrorCode(
       ConvertToListLiteral(),
       {LintNames.prefer_collection_literals},
     );
@@ -349,11 +351,6 @@
     }
   }
 
-  Future<void> _addProposal_addReturnType() async {
-    final changeBuilder = await createBuilder_addReturnType();
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_RETURN_TYPE);
-  }
-
   Future<void> _addProposal_assignToLocalVariable() async {
     // prepare enclosing ExpressionStatement
     ExpressionStatement expressionStatement;
diff --git a/pkg/analysis_server/lib/src/services/correction/base_processor.dart b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
index 01d7a94..3bbc4f0 100644
--- a/pkg/analysis_server/lib/src/services/correction/base_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
@@ -12,7 +12,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/dart/element/type_system.dart';
 import 'package:analyzer/source/source_range.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/session_helper.dart';
@@ -235,45 +234,6 @@
     return null;
   }
 
-  Future<ChangeBuilder> createBuilder_addReturnType() async {
-    var node = this.node;
-    if (node is SimpleIdentifier) {
-      FunctionBody body;
-      var parent = node.parent;
-      if (parent is MethodDeclaration) {
-        if (parent.returnType != null) {
-          _coverageMarker();
-          return null;
-        }
-        body = parent.body;
-      } else if (parent is FunctionDeclaration) {
-        if (parent.returnType != null) {
-          _coverageMarker();
-          return null;
-        }
-        body = parent.functionExpression.body;
-      } else {
-        _coverageMarker();
-        return null;
-      }
-      var returnType = inferReturnType(body);
-      if (returnType == null) {
-        _coverageMarker();
-        return null;
-      }
-      var changeBuilder = _newDartChangeBuilder();
-      bool validChange = true;
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        builder.addInsertion(node.offset, (DartEditBuilder builder) {
-          validChange = builder.writeType(returnType);
-          builder.write(' ');
-        });
-      });
-      return validChange ? changeBuilder : null;
-    }
-    return null;
-  }
-
   Future<ChangeBuilder>
       createBuilder_addTypeAnnotation_DeclaredIdentifier() async {
     DeclaredIdentifier declaredIdentifier =
@@ -1388,47 +1348,6 @@
     return null;
   }
 
-  /// Return the type of value returned by the function [body], or `null` if a
-  /// type can't be inferred.
-  DartType inferReturnType(FunctionBody body) {
-    bool isAsynchronous;
-    bool isGenerator;
-    DartType baseType;
-    if (body is ExpressionFunctionBody) {
-      isAsynchronous = body.isAsynchronous;
-      isGenerator = body.isGenerator;
-      baseType = body.expression.staticType;
-    } else if (body is BlockFunctionBody) {
-      isAsynchronous = body.isAsynchronous;
-      isGenerator = body.isGenerator;
-      var computer = _ReturnTypeComputer(resolvedResult.typeSystem);
-      body.block.accept(computer);
-      baseType = computer.returnType;
-      if (baseType == null && computer.hasReturn) {
-        baseType = typeProvider.voidType;
-      }
-    }
-    if (baseType == null) {
-      return null;
-    }
-    if (isAsynchronous) {
-      if (isGenerator) {
-        return typeProvider.streamElement.instantiate(
-            typeArguments: [baseType],
-            nullabilitySuffix: baseType.nullabilitySuffix);
-      } else {
-        return typeProvider.futureElement.instantiate(
-            typeArguments: [baseType],
-            nullabilitySuffix: baseType.nullabilitySuffix);
-      }
-    } else if (isGenerator) {
-      return typeProvider.iterableElement.instantiate(
-          typeArguments: [baseType],
-          nullabilitySuffix: baseType.nullabilitySuffix);
-    }
-    return baseType;
-  }
-
   bool isEnum(DartType type) {
     final element = type.element;
     return element is ClassElement && element.isEnum;
@@ -1617,45 +1536,3 @@
     }
   }
 }
-
-/// Copied from lib/src/services/correction/base_processor.dart, but [hasReturn]
-/// was added.
-// TODO(brianwilkerson) Decide whether to unify the two classes.
-class _ReturnTypeComputer extends RecursiveAstVisitor<void> {
-  final TypeSystem typeSystem;
-
-  DartType returnType;
-
-  /// A flag indicating whether at least one return statement was found.
-  bool hasReturn = false;
-
-  _ReturnTypeComputer(this.typeSystem);
-
-  @override
-  void visitBlockFunctionBody(BlockFunctionBody node) {}
-
-  @override
-  void visitReturnStatement(ReturnStatement node) {
-    hasReturn = true;
-    // prepare expression
-    Expression expression = node.expression;
-    if (expression == null) {
-      return;
-    }
-    // prepare type
-    DartType type = expression.staticType;
-    if (type.isBottom) {
-      return;
-    }
-    // combine types
-    if (returnType == null) {
-      returnType = type;
-    } else {
-      if (returnType is InterfaceType && type is InterfaceType) {
-        returnType = InterfaceType.getSmartLeastUpperBound(returnType, type);
-      } else {
-        returnType = typeSystem.leastUpperBound(returnType, type);
-      }
-    }
-  }
-}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
index a39e416..9f7282e 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
@@ -43,6 +43,8 @@
   /// producer doesn't support fixes.
   FixKind get fixKind => null;
 
+  Flutter get flutter => _context.flutter;
+
   AstNode get node => _context.node;
 
   ResolvedUnitResult get resolvedResult => _context.resolvedResult;
@@ -68,6 +70,11 @@
     return utils.getRangeText(range);
   }
 
+  /// Return `true` the lint with the given [name] is enabled.
+  bool isLintEnabled(String name) {
+    return _context.isLintEnabled(name);
+  }
+
   /// Return `true` if the selection covers an operator of the given
   /// [binaryExpression].
   bool isOperatorSelected(BinaryExpression binaryExpression) {
@@ -126,6 +133,12 @@
 
   AstNode get node => _node;
 
+  /// Return `true` the lint with the given [name] is enabled.
+  bool isLintEnabled(String name) {
+    var analysisOptions = session.analysisContext.analysisOptions;
+    return analysisOptions.isLintEnabled(name);
+  }
+
   bool setupCompute() {
     final locator = NodeLocator(selectionOffset, selectionEnd);
     _node = locator.searchWithin(resolvedResult.unit);
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_field_formal_parameters.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_field_formal_parameters.dart
new file mode 100644
index 0000000..76a79c7
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_field_formal_parameters.dart
@@ -0,0 +1,76 @@
+// 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 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/generated/error_verifier.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+
+class AddFieldFormalParameters extends CorrectionProducer {
+  @override
+  FixKind get fixKind => DartFixKind.ADD_FIELD_FORMAL_PARAMETERS;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    if (node is! SimpleIdentifier || node.parent is! ConstructorDeclaration) {
+      return;
+    }
+    ConstructorDeclaration constructor = node.parent;
+    List<FormalParameter> parameters = constructor.parameters.parameters;
+
+    ClassDeclaration classNode = constructor.parent;
+    InterfaceType superType = classNode.declaredElement.supertype;
+
+    // Compute uninitialized final fields.
+    List<FieldElement> fields =
+        ErrorVerifier.computeNotInitializedFields(constructor);
+    fields.retainWhere((FieldElement field) => field.isFinal);
+
+    // Prepare new parameters code.
+    fields.sort((a, b) => a.nameOffset - b.nameOffset);
+    String fieldParametersCode =
+        fields.map((field) => 'this.${field.name}').join(', ');
+
+    // Specialize for Flutter widgets.
+    if (flutter.isExactlyStatelessWidgetType(superType) ||
+        flutter.isExactlyStatefulWidgetType(superType)) {
+      if (parameters.isNotEmpty && parameters.last.isNamed) {
+        await builder.addFileEdit(file, (builder) {
+          builder.addSimpleInsertion(
+            parameters.last.end,
+            ', $fieldParametersCode',
+          );
+        });
+        return;
+      }
+    }
+
+    // Prepare the last required parameter.
+    FormalParameter lastRequiredParameter;
+    for (FormalParameter parameter in parameters) {
+      if (parameter.isRequiredPositional) {
+        lastRequiredParameter = parameter;
+      }
+    }
+
+    await builder.addFileEdit(file, (builder) {
+      if (lastRequiredParameter != null) {
+        builder.addSimpleInsertion(
+          lastRequiredParameter.end,
+          ', $fieldParametersCode',
+        );
+      } else {
+        int offset = constructor.parameters.leftParenthesis.end;
+        if (parameters.isNotEmpty) {
+          fieldParametersCode += ', ';
+        }
+        builder.addSimpleInsertion(offset, fieldParametersCode);
+      }
+    });
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_return_type.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_return_type.dart
new file mode 100644
index 0000000..ede0d75
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_return_type.dart
@@ -0,0 +1,156 @@
+// 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 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_system.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+
+class AddReturnType extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.ADD_RETURN_TYPE;
+
+  @override
+  FixKind get fixKind => DartFixKind.ADD_RETURN_TYPE;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    SyntacticEntity insertBeforeEntity;
+    FunctionBody body;
+    if (node is SimpleIdentifier) {
+      var executable = node.parent;
+      if (executable is MethodDeclaration && executable.name == node) {
+        if (executable.returnType != null) {
+          return;
+        }
+        if (isLintEnabled(LintNames.avoid_return_types_on_setters) &&
+            executable.isSetter) {
+          return;
+        }
+        insertBeforeEntity = executable.propertyKeyword ?? executable.name;
+        body = executable.body;
+      } else if (executable is FunctionDeclaration && executable.name == node) {
+        if (executable.returnType != null) {
+          return;
+        }
+        if (isLintEnabled(LintNames.avoid_return_types_on_setters) &&
+            executable.isSetter) {
+          return;
+        }
+        insertBeforeEntity = executable.propertyKeyword ?? executable.name;
+        body = executable.functionExpression.body;
+      } else {
+        return;
+      }
+    }
+
+    var returnType = _inferReturnType(body);
+    if (returnType == null) {
+      return null;
+    }
+
+    await builder.addFileEdit(file, (builder) {
+      builder.addInsertion(insertBeforeEntity.offset, (builder) {
+        if (returnType.isDynamic) {
+          builder.write('dynamic');
+        } else {
+          builder.writeType(returnType);
+        }
+        builder.write(' ');
+      });
+    });
+  }
+
+  /// Return the type of value returned by the function [body], or `null` if a
+  /// type can't be inferred.
+  DartType _inferReturnType(FunctionBody body) {
+    DartType baseType;
+    if (body is ExpressionFunctionBody) {
+      baseType = body.expression.staticType;
+    } else if (body is BlockFunctionBody) {
+      var computer = _ReturnTypeComputer(resolvedResult.typeSystem);
+      body.block.accept(computer);
+      baseType = computer.returnType;
+      if (baseType == null && computer.hasReturn) {
+        baseType = typeProvider.voidType;
+      }
+    }
+
+    if (baseType == null) {
+      return null;
+    }
+
+    var isAsynchronous = body.isAsynchronous;
+    var isGenerator = body.isGenerator;
+    if (isAsynchronous) {
+      if (isGenerator) {
+        return typeProvider.streamElement.instantiate(
+          typeArguments: [baseType],
+          nullabilitySuffix: baseType.nullabilitySuffix,
+        );
+      } else {
+        return typeProvider.futureElement.instantiate(
+          typeArguments: [baseType],
+          nullabilitySuffix: baseType.nullabilitySuffix,
+        );
+      }
+    } else if (isGenerator) {
+      return typeProvider.iterableElement.instantiate(
+        typeArguments: [baseType],
+        nullabilitySuffix: baseType.nullabilitySuffix,
+      );
+    }
+    return baseType;
+  }
+}
+
+/// Copied from lib/src/services/refactoring/extract_method.dart", but
+/// [hasReturn] was added.
+// TODO(brianwilkerson) Decide whether to unify the two classes.
+class _ReturnTypeComputer extends RecursiveAstVisitor<void> {
+  final TypeSystem typeSystem;
+
+  DartType returnType;
+
+  /// A flag indicating whether at least one return statement was found.
+  bool hasReturn = false;
+
+  _ReturnTypeComputer(this.typeSystem);
+
+  @override
+  void visitBlockFunctionBody(BlockFunctionBody node) {}
+
+  @override
+  void visitReturnStatement(ReturnStatement node) {
+    hasReturn = true;
+    // prepare expression
+    Expression expression = node.expression;
+    if (expression == null) {
+      return;
+    }
+    // prepare type
+    DartType type = expression.staticType;
+    if (type.isBottom) {
+      return;
+    }
+    // combine types
+    if (returnType == null) {
+      returnType = type;
+    } else {
+      if (returnType is InterfaceType && type is InterfaceType) {
+        returnType = InterfaceType.getSmartLeastUpperBound(returnType, type);
+      } else {
+        returnType = typeSystem.leastUpperBound(returnType, type);
+      }
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_local_variable.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_local_variable.dart
index febeea4..366a7c1 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_local_variable.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_local_variable.dart
@@ -30,29 +30,26 @@
     final sourceRanges = <SourceRange>[];
 
     final functionBody = declaration.thisOrAncestorOfType<FunctionBody>();
+    if (functionBody == null) {
+      return;
+    }
+
     final references = findLocalElementReferences(functionBody, element);
     for (var reference in references) {
       final node = reference.thisOrAncestorMatching((node) =>
           node is VariableDeclaration || node is AssignmentExpression);
-      var sourceRange;
-      if (node is VariableDeclaration) {
-        VariableDeclarationList parent = node.parent;
-        if (parent.variables.length == 1) {
-          sourceRange = utils.getLinesRange(range.node(parent.parent));
-        } else {
-          sourceRange = range.nodeInList(parent.variables, node);
-        }
-      } else if (node is AssignmentExpression) {
-        // todo (pq): consider node.parent is! ExpressionStatement to handle
-        // assignments in parens, etc.
-        if (node.parent is ArgumentList) {
-          sourceRange = range.startStart(node, node.operator.next);
-        } else {
-          sourceRange = utils.getLinesRange(range.node(node.parent));
-        }
-      } else {
+
+      SourceRange sourceRange;
+      if (node is AssignmentExpression) {
+        sourceRange = _forAssignmentExpression(node);
+      } else if (node is VariableDeclaration) {
+        sourceRange = _forVariableDeclaration(node);
+      }
+
+      if (sourceRange == null) {
         return;
       }
+
       sourceRanges.add(sourceRange);
     }
 
@@ -62,4 +59,29 @@
       }
     });
   }
+
+  SourceRange _forAssignmentExpression(AssignmentExpression node) {
+    // todo (pq): consider node.parent is! ExpressionStatement to handle
+    // assignments in parens, etc.
+    if (node.parent is ArgumentList) {
+      return range.startStart(node, node.operator.next);
+    } else {
+      return utils.getLinesRange(range.node(node.parent));
+    }
+  }
+
+  SourceRange _forVariableDeclaration(VariableDeclaration node) {
+    var declarationList = node.parent as VariableDeclarationList;
+
+    var declarationListParent = declarationList.parent;
+    if (declarationListParent is VariableDeclarationStatement) {
+      if (declarationList.variables.length == 1) {
+        return utils.getLinesRange(range.node(declarationListParent));
+      } else {
+        return range.nodeInList(declarationList.variables, node);
+      }
+    } else {
+      return null;
+    }
+  }
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 65b4196..5e9f9df 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -12,6 +12,8 @@
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
 import 'package:analysis_server/src/services/correction/base_processor.dart';
 import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/dart/add_field_formal_parameters.dart';
+import 'package:analysis_server/src/services/correction/dart/add_return_type.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_contains.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_list_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_map_literal.dart';
@@ -52,7 +54,6 @@
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/error/inheritance_override.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error_verifier.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -453,12 +454,6 @@
     if (errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED) {
       await _addFix_createConstructor_forUninitializedFinalFields();
     }
-    if (errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 ||
-        errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 ||
-        errorCode ==
-            StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS) {
-      await _addFix_updateConstructor_forUninitializedFinalFields();
-    }
     if (errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER) {
       await _addFix_undefinedClassAccessor_useSimilar();
       await _addFix_createClass();
@@ -592,9 +587,6 @@
     // lints
     if (errorCode is LintCode) {
       String name = errorCode.name;
-      if (name == LintNames.always_declare_return_types) {
-        await _addFix_addReturnType();
-      }
       if (name == LintNames.always_specify_types ||
           name == LintNames.type_annotate_public_apis) {
         await _addFix_addTypeAnnotation();
@@ -1274,11 +1266,6 @@
     _addFixFromBuilder(changeBuilder, DartFixKind.ADD_REQUIRED);
   }
 
-  Future<void> _addFix_addReturnType() async {
-    var changeBuilder = await createBuilder_addReturnType();
-    _addFixFromBuilder(changeBuilder, DartFixKind.ADD_RETURN_TYPE);
-  }
-
   Future<void> _addFix_addStatic() async {
     FieldDeclaration declaration =
         node.thisOrAncestorOfType<FieldDeclaration>();
@@ -4349,68 +4336,6 @@
     }
   }
 
-  /// Here we handle cases when a constructors does not initialize all of the
-  /// final fields.
-  Future<void> _addFix_updateConstructor_forUninitializedFinalFields() async {
-    if (node is! SimpleIdentifier || node.parent is! ConstructorDeclaration) {
-      return;
-    }
-    ConstructorDeclaration constructor = node.parent;
-    List<FormalParameter> parameters = constructor.parameters.parameters;
-
-    ClassDeclaration classNode = constructor.parent;
-    InterfaceType superType = classNode.declaredElement.supertype;
-
-    // Compute uninitialized final fields.
-    List<FieldElement> fields =
-        ErrorVerifier.computeNotInitializedFields(constructor);
-    fields.retainWhere((FieldElement field) => field.isFinal);
-
-    // Prepare new parameters code.
-    fields.sort((a, b) => a.nameOffset - b.nameOffset);
-    String fieldParametersCode =
-        fields.map((field) => 'this.${field.name}').join(', ');
-
-    // Specialize for Flutter widgets.
-    if (flutter.isExactlyStatelessWidgetType(superType) ||
-        flutter.isExactlyStatefulWidgetType(superType)) {
-      if (parameters.isNotEmpty && parameters.last.isNamed) {
-        var changeBuilder = _newDartChangeBuilder();
-        await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-          builder.addSimpleInsertion(
-              parameters.last.end, ', $fieldParametersCode');
-        });
-        _addFixFromBuilder(
-            changeBuilder, DartFixKind.ADD_FIELD_FORMAL_PARAMETERS);
-        return;
-      }
-    }
-
-    // Prepare the last required parameter.
-    FormalParameter lastRequiredParameter;
-    for (FormalParameter parameter in parameters) {
-      if (parameter.isRequiredPositional) {
-        lastRequiredParameter = parameter;
-      }
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      // append new field formal initializers
-      if (lastRequiredParameter != null) {
-        builder.addSimpleInsertion(
-            lastRequiredParameter.end, ', $fieldParametersCode');
-      } else {
-        int offset = constructor.parameters.leftParenthesis.end;
-        if (parameters.isNotEmpty) {
-          fieldParametersCode += ', ';
-        }
-        builder.addSimpleInsertion(offset, fieldParametersCode);
-      }
-    });
-    _addFixFromBuilder(changeBuilder, DartFixKind.ADD_FIELD_FORMAL_PARAMETERS);
-  }
-
   Future<void> _addFix_updateSdkConstraints(String minimumVersion) async {
     Context context = resourceProvider.pathContext;
     File pubspecFile;
@@ -4562,9 +4487,17 @@
       await compute(RemoveUnusedLocalVariable());
     } else if (errorCode == StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION) {
       await compute(RemoveDeadIfNull());
+    } else if (errorCode ==
+            StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 ||
+        errorCode == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 ||
+        errorCode ==
+            StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS) {
+      await compute(AddFieldFormalParameters());
     } else if (errorCode is LintCode) {
       String name = errorCode.name;
-      if (name == LintNames.avoid_private_typedef_functions) {
+      if (name == LintNames.always_declare_return_types) {
+        await compute(AddReturnType());
+      } else if (name == LintNames.avoid_private_typedef_functions) {
         await compute(InlineTypedef());
       } else if (name == LintNames.avoid_returning_null_for_future) {
         await compute(WrapInFuture());
diff --git a/pkg/analysis_server/test/client/completion_driver_test.dart b/pkg/analysis_server/test/client/completion_driver_test.dart
index 0e41a7d..e318791 100644
--- a/pkg/analysis_server/test/client/completion_driver_test.dart
+++ b/pkg/analysis_server/test/client/completion_driver_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -28,6 +29,8 @@
 
   String get projectPath => '/$projectName';
 
+  AnalysisServerOptions get serverOptions => AnalysisServerOptions();
+
   bool get supportsAvailableSuggestions;
 
   String get testFilePath => '$projectPath/bin/test.dart';
@@ -131,10 +134,12 @@
   @mustCallSuper
   void setUp() {
     driver = CompletionDriver(
-        supportsAvailableSuggestions: supportsAvailableSuggestions,
-        projectPath: projectPath,
-        testFilePath: testFilePath,
-        resourceProvider: resourceProvider);
+      supportsAvailableSuggestions: supportsAvailableSuggestions,
+      projectPath: projectPath,
+      testFilePath: testFilePath,
+      resourceProvider: resourceProvider,
+      serverOptions: serverOptions,
+    );
     driver.createProject(packageRoots: packageRoots);
 
     newFile('$projectPath/pubspec.yaml', content: '');
diff --git a/pkg/analysis_server/test/client/impl/abstract_client.dart b/pkg/analysis_server/test/client/impl/abstract_client.dart
index b8f60a0..0c82e50 100644
--- a/pkg/analysis_server/test/client/impl/abstract_client.dart
+++ b/pkg/analysis_server/test/client/impl/abstract_client.dart
@@ -38,10 +38,13 @@
 
   MockSdk sdk;
 
+  final AnalysisServerOptions serverOptions;
+
   AbstractClient({
     @required this.projectPath,
     @required this.testFilePath,
     @required String sdkPath,
+    @required this.serverOptions,
   })  : serverChannel = MockServerChannel(),
         pluginManager = TestPluginManager() {
     server = createAnalysisServer(sdkPath);
@@ -54,11 +57,11 @@
   AnalysisDomainHandler get analysisHandler => server.handlers
       .singleWhere((handler) => handler is AnalysisDomainHandler);
 
+  AnalysisOptions get analysisOptions => testDriver.analysisOptions;
+
   CompletionDomainHandler get completionHandler =>
       server.handlers.whereType<CompletionDomainHandler>().single;
 
-  AnalysisOptions get analysisOptions => testDriver.analysisOptions;
-
   ResourceProvider get resourceProvider;
 
   AnalysisDriver get testDriver => server.getAnalysisDriver(testFilePath);
@@ -104,11 +107,10 @@
   /// Create an analysis server with the given [sdkPath].
   AnalysisServer createAnalysisServer(String sdkPath) {
     sdk = MockSdk(resourceProvider: resourceProvider);
-    var options = AnalysisServerOptions();
     return AnalysisServer(
         serverChannel,
         resourceProvider,
-        options,
+        serverOptions,
         DartSdkManager(sdkPath, true),
         CrashReportingAttachmentsBuilder.empty,
         InstrumentationService.NULL_SERVICE);
diff --git a/pkg/analysis_server/test/client/impl/completion_driver.dart b/pkg/analysis_server/test/client/impl/completion_driver.dart
index 2b80c19..b586253 100644
--- a/pkg/analysis_server/test/client/impl/completion_driver.dart
+++ b/pkg/analysis_server/test/client/impl/completion_driver.dart
@@ -9,6 +9,7 @@
 import 'package:analysis_server/protocol/protocol_constants.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart'
     hide AnalysisOptions;
+import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -77,11 +78,13 @@
 
   CompletionDriver({
     @required this.supportsAvailableSuggestions,
+    AnalysisServerOptions serverOptions,
     @required MemoryResourceProvider resourceProvider,
     @required String projectPath,
     @required String testFilePath,
   })  : _resourceProvider = resourceProvider,
         super(
+            serverOptions: serverOptions ?? AnalysisServerOptions(),
             projectPath: resourceProvider.convertPath(projectPath),
             testFilePath: resourceProvider.convertPath(testFilePath),
             sdkPath: resourceProvider.convertPath('/sdk'));
diff --git a/pkg/analysis_server/test/client/relevance/test_all.dart b/pkg/analysis_server/test/client/relevance/test_all.dart
new file mode 100644
index 0000000..26af7cd
--- /dev/null
+++ b/pkg/analysis_server/test/client/relevance/test_all.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 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'type_member_relevance_test.dart' as type_member_relevance_test;
+
+void main() {
+  defineReflectiveSuite(() {
+    type_member_relevance_test.main();
+  });
+}
diff --git a/pkg/analysis_server/test/client/relevance/type_member_relevance_test.dart b/pkg/analysis_server/test/client/relevance/type_member_relevance_test.dart
new file mode 100644
index 0000000..22a526f
--- /dev/null
+++ b/pkg/analysis_server/test/client/relevance/type_member_relevance_test.dart
@@ -0,0 +1,55 @@
+// 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 'package:analysis_server/src/analysis_server.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../completion_driver_test.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TypeMemberRelevanceTest);
+  });
+}
+
+@reflectiveTest
+class TypeMemberRelevanceTest extends AbstractCompletionDriverTest {
+  @override
+  AnalysisServerOptions get serverOptions =>
+      AnalysisServerOptions()..useNewRelevance = true;
+
+  @override
+  bool get supportsAvailableSuggestions => true;
+
+  Future<void> test_type_member_relevance() async {
+    await addTestFile('''
+class A {
+  void a() { }
+}
+
+class B extends A {
+  void b() { }
+}
+
+void main() {
+  var b = B();
+  b.^
+}
+''');
+
+    expect(
+        suggestionWith(
+                completion: 'b',
+                element: ElementKind.METHOD,
+                kind: CompletionSuggestionKind.INVOCATION)
+            .relevance,
+        greaterThan(suggestionWith(
+                completion: 'a',
+                element: ElementKind.METHOD,
+                kind: CompletionSuggestionKind.INVOCATION)
+            .relevance));
+  }
+}
diff --git a/pkg/analysis_server/test/client/test_all.dart b/pkg/analysis_server/test/client/test_all.dart
index 417c4d3..1d2a312 100644
--- a/pkg/analysis_server/test/client/test_all.dart
+++ b/pkg/analysis_server/test/client/test_all.dart
@@ -5,9 +5,11 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'completion_driver_test.dart' as completion_driver;
+import 'relevance/test_all.dart' as relevance_tests;
 
 void main() {
   defineReflectiveSuite(() {
     completion_driver.main();
+    relevance_tests.main();
   });
 }
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index eb1ad52..cf1d8fd 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -2422,6 +2422,10 @@
   /// If the location does not have a support widget, an error of type
   /// FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET will be generated.
   ///
+  /// If a change to a file happens while widget descriptions are computed, an
+  /// error of type FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED will be
+  /// generated.
+  ///
   /// Parameters
   ///
   /// file: FilePath
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 6cf2b8a..e1f3fcb 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -1350,6 +1350,7 @@
 ///   CONTENT_MODIFIED
 ///   DEBUG_PORT_COULD_NOT_BE_OPENED
 ///   FILE_NOT_ANALYZED
+///   FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED
 ///   FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET
 ///   FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION
 ///   FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID
@@ -1385,6 +1386,7 @@
   'CONTENT_MODIFIED',
   'DEBUG_PORT_COULD_NOT_BE_OPENED',
   'FILE_NOT_ANALYZED',
+  'FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED',
   'FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET',
   'FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION',
   'FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID',
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 15bf575..abff347 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -177,7 +177,6 @@
       'references': {'dynamicRegistration': true},
       'documentHighlight': {'dynamicRegistration': true},
       'documentSymbol': {'dynamicRegistration': true},
-      'synchronization': {'dynamicRegistration': true},
       'formatting': {'dynamicRegistration': true},
       'onTypeFormatting': {'dynamicRegistration': true},
       'declaration': {'dynamicRegistration': true},
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index cf1b4b7..14b27ab 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -2153,7 +2153,7 @@
   Future<void> test_variable_decl_type_args() async {
     addTestSource('void m() {List<^> list;}');
     await computeSuggestions();
-    assertSuggestKeywords([Keyword.DYNAMIC]);
+    assertSuggestKeywords([Keyword.DYNAMIC, Keyword.VOID]);
   }
 
   Future<void> test_while_break_continue() async {
@@ -2273,7 +2273,7 @@
 ''');
 
     await computeSuggestions();
-    assertSuggestKeywords([Keyword.DYNAMIC]);
+    assertSuggestKeywords([Keyword.DYNAMIC, Keyword.VOID]);
   }
 }
 
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
index c1c9e05..ca2f5f1 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
@@ -1761,15 +1761,27 @@
             regionInfo.offset == unit.content.indexOf('? i) {} // f'))
         .single;
     expect(region.traces, hasLength(1));
-    var entries = region.traces.single.entries;
-    expect(entries, hasLength(3));
-    // Entry 0 is the edge from g's argument to f's argument, due to g's call to
+    var trace = region.traces.single;
+    expect(trace.description, 'Nullability reason');
+    var entries = trace.entries;
+    expect(entries, hasLength(6));
+    // Entry 0 is the nullability of f's argument
+    assertTraceEntry(
+        unit, entries[0], 'f', unit.content.indexOf('int? i) {} // f'));
+    // Entry 1 is the edge from g's argument to f's argument, due to g's call to
     // f.
-    assertTraceEntry(unit, entries[0], 'g', unit.content.indexOf('i);'));
-    // Entry 1 is the edge from null to g's argument, due to h's call to g.
-    assertTraceEntry(unit, entries[1], 'h', unit.content.indexOf('null'));
-    // Entry 2 is the edge from always to null.
-    assertTraceEntry(unit, entries[2], 'h', unit.content.indexOf('null'));
+    assertTraceEntry(unit, entries[1], 'g', unit.content.indexOf('i);'));
+    // Entry 2 is the nullability of g's argument
+    assertTraceEntry(
+        unit, entries[2], 'g', unit.content.indexOf('int? i) { // g'));
+    // Entry 3 is the edge from null to g's argument, due to h's call to g.
+    assertTraceEntry(unit, entries[3], 'h', unit.content.indexOf('null'));
+    // Entry 4 is the nullability of the null literal.
+    assertTraceEntry(unit, entries[4], 'h', unit.content.indexOf('null'));
+    // Entry 5 is the edge from always to null.
+    // TODO(paulberry): this edge provides no additional useful information and
+    // shouldn't be included in the trace.
+    assertTraceEntry(unit, entries[5], 'h', unit.content.indexOf('null'));
   }
 
   Future<void> test_trace_nullCheck() async {
@@ -1780,10 +1792,16 @@
         .where((regionInfo) => regionInfo.offset == unit.content.indexOf('! +'))
         .single;
     expect(region.traces, hasLength(1));
-    var entries = region.traces.single.entries;
-    expect(entries, hasLength(1));
-    // Entry 0 is the edge from always to the type of i.
+    var trace = region.traces.single;
+    expect(trace.description, 'Nullability reason');
+    var entries = trace.entries;
+    expect(entries, hasLength(2));
+    // Entry 0 is the nullability of the type of i.
     assertTraceEntry(unit, entries[0], 'f', unit.content.indexOf('int?'));
+    // Entry 1 is the edge from always to the type of i.
+    // TODO(paulberry): this edge provides no additional useful information and
+    // shouldn't be included in the trace.
+    assertTraceEntry(unit, entries[1], 'f', unit.content.indexOf('int?'));
   }
 
   Future<void> test_uninitializedField() async {
diff --git a/pkg/analysis_server/test/src/services/correction/assist/add_return_type_test.dart b/pkg/analysis_server/test/src/services/correction/assist/add_return_type_test.dart
index 7f9bc17..748ec86 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/add_return_type_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/add_return_type_test.dart
@@ -11,12 +11,12 @@
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(AddTypeAnnotationTest);
+    defineReflectiveTests(AddReturnTypeTest);
   });
 }
 
 @reflectiveTest
-class AddTypeAnnotationTest extends AssistProcessorTest {
+class AddReturnTypeTest extends AssistProcessorTest {
   @override
   AssistKind get kind => DartAssistKind.ADD_RETURN_TYPE;
 
@@ -76,7 +76,13 @@
   }
 }
 ''');
-    await assertNoAssist();
+    await assertHasAssist('''
+class A {
+  dynamic m(p) {
+    return p;
+  }
+}
+''');
   }
 
   Future<void> test_method_block_returnNoValue() async {
@@ -126,6 +132,50 @@
 ''');
   }
 
+  Future<void> test_method_getter() async {
+    await resolveTestUnit('''
+class A {
+  get /*caret*/foo => 0;
+}
+''');
+    await assertHasAssist('''
+class A {
+  int get foo => 0;
+}
+''');
+  }
+
+  Future<void> test_method_setter() async {
+    await resolveTestUnit('''
+class A {
+  set /*caret*/foo(int a) {
+    if (a == 0) return;
+  }
+}
+''');
+    await assertHasAssist('''
+class A {
+  void set foo(int a) {
+    if (a == 0) return;
+  }
+}
+''');
+  }
+
+  Future<void> test_method_setter_lint_avoidReturnTypesOnSetters() async {
+    createAnalysisOptionsFile(lints: [
+      LintNames.avoid_return_types_on_setters,
+    ]);
+    await resolveTestUnit('''
+class A {
+  set /*caret*/foo(int a) {
+    if (a == 0) return;
+  }
+}
+''');
+    await assertNoAssist();
+  }
+
   Future<void> test_topLevelFunction_block() async {
     await resolveTestUnit('''
 /*caret*/f() {
@@ -156,4 +206,39 @@
 ''');
     await assertNoAssist();
   }
+
+  Future<void> test_topLevelFunction_getter() async {
+    await resolveTestUnit('''
+get /*caret*/foo => 0;
+''');
+    await assertHasAssist('''
+int get foo => 0;
+''');
+  }
+
+  Future<void> test_topLevelFunction_setter() async {
+    await resolveTestUnit('''
+set /*caret*/foo(int a) {
+  if (a == 0) return;
+}
+''');
+    await assertHasAssist('''
+void set foo(int a) {
+  if (a == 0) return;
+}
+''');
+  }
+
+  Future<void>
+      test_topLevelFunction_setter_lint_avoidReturnTypesOnSetters() async {
+    createAnalysisOptionsFile(lints: [
+      LintNames.avoid_return_types_on_setters,
+    ]);
+    await resolveTestUnit('''
+set /*caret*/foo(int a) {
+  if (a == 0) return;
+}
+''');
+    await assertNoAssist();
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_return_type_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_return_type_test.dart
index 614490f..b3a2423 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_return_type_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_return_type_test.dart
@@ -83,7 +83,13 @@
   }
 }
 ''');
-    await assertNoFix();
+    await assertHasFix('''
+class A {
+  dynamic m(p) {
+    return p;
+  }
+}
+''');
   }
 
   Future<void> test_method_block_returnNoValue() async {
@@ -133,6 +139,19 @@
 ''');
   }
 
+  Future<void> test_method_getter() async {
+    await resolveTestUnit('''
+class A {
+  get foo => 0;
+}
+''');
+    await assertHasFix('''
+class A {
+  int get foo => 0;
+}
+''');
+  }
+
   Future<void> test_topLevelFunction_block() async {
     await resolveTestUnit('''
 f() {
@@ -154,4 +173,13 @@
 String f() => '';
 ''');
   }
+
+  Future<void> test_topLevelFunction_getter() async {
+    await resolveTestUnit('''
+get foo => 0;
+''');
+    await assertHasFix('''
+int get foo => 0;
+''');
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_local_variable_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_local_variable_test.dart
index cf625ca..5d6b701 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_local_variable_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_local_variable_test.dart
@@ -97,6 +97,13 @@
 ''');
   }
 
+  Future<void> test_notInFunctionBody() async {
+    await resolveTestUnit(r'''
+var a = [for (var v = 0;;) 0];
+''');
+    await assertNoFix();
+  }
+
   Future<void> test_withReferences() async {
     await resolveTestUnit(r'''
 main() {
diff --git a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
index a1ab90c..75e5568 100644
--- a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
@@ -30,12 +30,17 @@
   ArgParser parser = createArgParser();
   ArgResults result = parser.parse(args);
 
-  if (validArguments(parser, result)) {
-    var code = await CompletionCoverageMetrics(result.rest[0])
-        .compute(corpus: result['corpus'], verbose: result['verbose']);
-    io.exit(code);
+  var stopwatch = Stopwatch()..start();
+  if (!validArguments(parser, result)) {
+    return io.exit(1);
   }
-  return io.exit(1);
+  var code = await CompletionMetricsComputer(result.rest[0])
+      .compute(corpus: result['corpus'], verbose: result['verbose']);
+  stopwatch.stop();
+
+  var duration = Duration(milliseconds: stopwatch.elapsedMilliseconds);
+  print('\nMetrics computed in $duration');
+  return io.exit(code);
 }
 
 /// Create a parser that can be used to parse the command-line arguments.
@@ -94,7 +99,7 @@
 /// This is the main metrics computer class for code completions. After the
 /// object is constructed, [computeCompletionMetrics] is executed to do analysis
 /// and print a summary of the metrics gathered from the completion tests.
-class CompletionCoverageMetrics {
+class CompletionMetricsComputer {
   final String _rootPath;
 
   String _currentFilePath;
@@ -106,20 +111,9 @@
   /// The int to be returned from the [compute] call.
   int resultCode;
 
-  var completionCounter = Counter('successful/ unsuccessful completions');
-  var completionMissedTokenCounter =
-      Counter('unsuccessful completion token counter');
-  var completionKindCounter = Counter('unsuccessful completion kind counter');
-  var completionElementKindCounter =
-      Counter('unsuccessful completion element kind counter');
-  var mRRComputer =
-      MeanReciprocalRankComputer('successful/ unsuccessful completions');
-  var typeMemberMRRComputer =
-      MeanReciprocalRankComputer('type member completions');
-  var nonTypeMemberMRRComputer =
-      MeanReciprocalRankComputer('non-type member completions');
+  CompletionMetrics metricsOldMode, metricsNewMode;
 
-  CompletionCoverageMetrics(this._rootPath);
+  CompletionMetricsComputer(this._rootPath);
 
   /// The path to the current file.
   String get currentFilePath => _currentFilePath;
@@ -130,6 +124,8 @@
   Future<int> compute({bool corpus = false, bool verbose = false}) async {
     _verbose = verbose;
     resultCode = 0;
+    metricsOldMode = CompletionMetrics('useNewRelevance = false');
+    metricsNewMode = CompletionMetrics('useNewRelevance = true');
 
     var roots = _computeRootPaths(_rootPath, corpus);
     for (var root in roots) {
@@ -173,10 +169,30 @@
               _resolvedUnitResult.unit.accept(visitor);
 
               for (var expectedCompletion in visitor.expectedCompletions) {
+                // As this point the completion suggestions are computed,
+                // and results are collected with varying settings for
+                // comparison:
+
+                // First we compute the completions useNewRelevance set to
+                // false:
+                var suggestions = await _computeCompletionSuggestions(
+                    _resolvedUnitResult,
+                    expectedCompletion.offset,
+                    declarationsTracker,
+                    false);
+
                 forEachExpectedCompletion(
-                    expectedCompletion,
-                    await _computeCompletionSuggestions(_resolvedUnitResult,
-                        expectedCompletion.offset, declarationsTracker));
+                    expectedCompletion, suggestions, metricsOldMode);
+
+                // And again here with useNewRelevance set to true:
+                suggestions = await _computeCompletionSuggestions(
+                    _resolvedUnitResult,
+                    expectedCompletion.offset,
+                    declarationsTracker,
+                    true);
+
+                forEachExpectedCompletion(
+                    expectedCompletion, suggestions, metricsNewMode);
               }
             } catch (e) {
               print('Exception caught analyzing: $filePath');
@@ -187,32 +203,33 @@
         }
       }
     }
-    printAndClearComputers();
+    printAndClearComputers(metricsOldMode);
+    printAndClearComputers(metricsNewMode);
     return resultCode;
   }
 
   void forEachExpectedCompletion(ExpectedCompletion expectedCompletion,
-      List<CompletionSuggestion> suggestions) {
+      List<CompletionSuggestion> suggestions, CompletionMetrics metrics) {
     assert(suggestions != null);
 
     var place = placementInSuggestionList(suggestions, expectedCompletion);
 
-    mRRComputer.addRank(place.rank);
+    metrics.mRRComputer.addRank(place.rank);
 
     if (place.denominator != 0) {
-      completionCounter.count('successful');
+      metrics.completionCounter.count('successful');
 
       if (isTypeMember(expectedCompletion.syntacticEntity)) {
-        typeMemberMRRComputer.addRank(place.rank);
+        metrics.typeMemberMRRComputer.addRank(place.rank);
       } else {
-        nonTypeMemberMRRComputer.addRank(place.rank);
+        metrics.nonTypeMemberMRRComputer.addRank(place.rank);
       }
     } else {
-      completionCounter.count('unsuccessful');
+      metrics.completionCounter.count('unsuccessful');
 
-      completionMissedTokenCounter.count(expectedCompletion.completion);
-      completionKindCounter.count(expectedCompletion.kind.toString());
-      completionElementKindCounter
+      metrics.completionMissedTokenCounter.count(expectedCompletion.completion);
+      metrics.completionKindCounter.count(expectedCompletion.kind.toString());
+      metrics.completionElementKindCounter
           .count(expectedCompletion.elementKind.toString());
 
       if (_verbose) {
@@ -227,45 +244,51 @@
     }
   }
 
-  void printAndClearComputers() {
-    print('');
-    completionMissedTokenCounter.printCounterValues();
+  void printAndClearComputers(CompletionMetrics metrics) {
+    print('\n\n');
+    print('====================');
+    print('Completion metrics for ${metrics.name}:');
+    if (_verbose) {
+      metrics.completionMissedTokenCounter.printCounterValues();
+      print('');
+
+      metrics.completionKindCounter.printCounterValues();
+      print('');
+
+      metrics.completionElementKindCounter.printCounterValues();
+      print('');
+    }
+
+    metrics.mRRComputer.printMean();
     print('');
 
-    completionKindCounter.printCounterValues();
+    metrics.typeMemberMRRComputer.printMean();
     print('');
 
-    completionElementKindCounter.printCounterValues();
-    print('');
-
-    mRRComputer.printMean();
-    print('');
-
-    typeMemberMRRComputer.printMean();
-    print('');
-
-    nonTypeMemberMRRComputer.printMean();
+    metrics.nonTypeMemberMRRComputer.printMean();
     print('');
 
     print('Summary for $_rootPath:');
-    completionCounter.printCounterValues();
+    metrics.completionCounter.printCounterValues();
+    print('====================');
 
-    completionMissedTokenCounter.clear();
-    completionKindCounter.clear();
-    completionElementKindCounter.clear();
-    completionCounter.clear();
-    mRRComputer.clear();
-    typeMemberMRRComputer.clear();
-    nonTypeMemberMRRComputer.clear();
+    metrics.completionMissedTokenCounter.clear();
+    metrics.completionKindCounter.clear();
+    metrics.completionElementKindCounter.clear();
+    metrics.completionCounter.clear();
+    metrics.mRRComputer.clear();
+    metrics.typeMemberMRRComputer.clear();
+    metrics.nonTypeMemberMRRComputer.clear();
   }
 
   Future<List<CompletionSuggestion>> _computeCompletionSuggestions(
       ResolvedUnitResult resolvedUnitResult, int offset,
-      [DeclarationsTracker declarationsTracker]) async {
+      [DeclarationsTracker declarationsTracker,
+      bool useNewRelevance = false]) async {
     var completionRequestImpl = CompletionRequestImpl(
       resolvedUnitResult,
       offset,
-      false,
+      useNewRelevance,
       CompletionPerformance(),
     );
 
@@ -338,3 +361,24 @@
     return roots;
   }
 }
+
+/// A wrapper for the collection of [Counter] and [MeanReciprocalRankComputer]
+/// objects for a run of [CompletionMetricsComputer].
+class CompletionMetrics {
+  final String name;
+
+  CompletionMetrics(this.name);
+
+  var completionCounter = Counter('successful/ unsuccessful completions');
+  var completionMissedTokenCounter =
+      Counter('unsuccessful completion token counter');
+  var completionKindCounter = Counter('unsuccessful completion kind counter');
+  var completionElementKindCounter =
+      Counter('unsuccessful completion element kind counter');
+  var mRRComputer =
+      MeanReciprocalRankComputer('successful/ unsuccessful completions');
+  var typeMemberMRRComputer =
+      MeanReciprocalRankComputer('type member completions');
+  var nonTypeMemberMRRComputer =
+      MeanReciprocalRankComputer('non-type member completions');
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index 7f9bbc7..53267ad 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -790,6 +790,9 @@
    * If the location does not have a support widget, an error of type
    * FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET will be generated.
    *
+   * If a change to a file happens while widget descriptions are computed, an error of type
+   * FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED will be generated.
+   *
    * @param file The file where the widget instance is created.
    * @param offset The offset in the file where the widget instance is created.
    */
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
index c968830..0129bac 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
@@ -33,6 +33,11 @@
   public static final String FILE_NOT_ANALYZED = "FILE_NOT_ANALYZED";
 
   /**
+   * A file was change while widget descriptions were being computed.
+   */
+  public static final String FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED = "FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED";
+
+  /**
    * The given location does not have a supported widget.
    */
   public static final String FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET = "FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET";
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index b422873..59f2af9 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -3191,6 +3191,11 @@
       If the location does not have a support widget, an error of type
       <tt>FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET</tt> will be generated.
     </p>
+    <p>
+      If a change to a file happens while widget descriptions are computed,
+      an error of type <tt>FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED</tt>
+      will be generated.
+    </p>
     <params>
       <field name="file">
         <ref>FilePath</ref>
@@ -4909,6 +4914,12 @@
         </p>
       </value>
       <value>
+        <code>FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED</code>
+        <p>
+          A file was change while widget descriptions were being computed.
+        </p>
+      </value>
+      <value>
         <code>FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET</code>
         <p>
           The given location does not have a supported widget.
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index 2aa0e9b..21a2c04 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -17642,6 +17642,7 @@
 ///   CONTENT_MODIFIED
 ///   DEBUG_PORT_COULD_NOT_BE_OPENED
 ///   FILE_NOT_ANALYZED
+///   FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED
 ///   FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET
 ///   FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION
 ///   FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID
@@ -17691,6 +17692,11 @@
   static const RequestErrorCode FILE_NOT_ANALYZED =
       RequestErrorCode._('FILE_NOT_ANALYZED');
 
+  /// A file was change while widget descriptions were being computed.
+  static const RequestErrorCode
+      FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED =
+      RequestErrorCode._('FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED');
+
   /// The given location does not have a supported widget.
   static const RequestErrorCode FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET =
       RequestErrorCode._('FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET');
@@ -17848,6 +17854,7 @@
     CONTENT_MODIFIED,
     DEBUG_PORT_COULD_NOT_BE_OPENED,
     FILE_NOT_ANALYZED,
+    FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED,
     FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET,
     FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION,
     FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID,
@@ -17893,6 +17900,8 @@
         return DEBUG_PORT_COULD_NOT_BE_OPENED;
       case 'FILE_NOT_ANALYZED':
         return FILE_NOT_ANALYZED;
+      case 'FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED':
+        return FLUTTER_GET_WIDGET_DESCRIPTION_CONTENT_MODIFIED;
       case 'FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET':
         return FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET;
       case 'FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION':
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index c85edce..bb65367 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -131,6 +131,7 @@
   CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR,
   CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER,
   CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION,
+  CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE,
   CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT,
   CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME,
   CompileTimeErrorCode.DUPLICATE_DEFINITION,
@@ -542,6 +543,7 @@
   ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
   ParserErrorCode.FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS,
   ParserErrorCode.FINAL_AND_COVARIANT,
+  ParserErrorCode.FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER,
   ParserErrorCode.FINAL_AND_VAR,
   ParserErrorCode.FINAL_CLASS,
   ParserErrorCode.FINAL_CONSTRUCTOR,
diff --git a/pkg/analyzer/lib/src/context/packages.dart b/pkg/analyzer/lib/src/context/packages.dart
index 9c8d40c..8d79d78 100644
--- a/pkg/analyzer/lib/src/context/packages.dart
+++ b/pkg/analyzer/lib/src/context/packages.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/src/context/package_config_json.dart';
 import 'package:analyzer/src/util/uri.dart';
 import 'package:meta/meta.dart';
+// ignore: deprecated_member_use
 import 'package:package_config/packages_file.dart' as dot_packages;
 import 'package:pub_semver/pub_semver.dart';
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index ada9a29..5d9e1e5 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -604,8 +604,20 @@
       useFasta: useFasta,
     );
     parser.enableOptionalNewAndConst = true;
-    CompilationUnit unit = parser.parseCompilationUnit(token);
-    unit.lineInfo = lineInfo;
+
+    // TODO(scheglov) https://github.com/dart-lang/sdk/issues/41023
+    CompilationUnit unit;
+    try {
+      unit = parser.parseCompilationUnit(token);
+      unit.lineInfo = lineInfo;
+    } catch (e) {
+      throw StateError('''
+Parser error.
+path: $path
+${'-' * 40}
+$content
+''');
+    }
 
     // StringToken uses a static instance of StringCanonicalizer, so we need
     // to clear it explicitly once we are done using it for this file.
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 3b812a2..ff2cdda 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -4254,7 +4254,7 @@
         reference: enclosingRef.getChild('@getter').getChild(name),
       );
 
-      if (!isConst && !isFinal) {
+      if (_hasSetter) {
         this.setter = PropertyAccessorElementImpl_ImplicitSetter(
           this,
           reference: enclosingRef.getChild('@setter').getChild(name),
@@ -6408,6 +6408,26 @@
     // We don't support type inference errors without linking.
     return null;
   }
+
+  bool get _hasInitializer {
+    return linkedNode != null && linkedContext.hasInitializer(linkedNode);
+  }
+
+  /// Return `true` if this variable needs the setter.
+  bool get _hasSetter {
+    if (isConst) {
+      return false;
+    }
+
+    if (isLate) {
+      if (isFinal) {
+        return !_hasInitializer;
+      }
+      return true;
+    }
+
+    return !isFinal;
+  }
 }
 
 /// A concrete implementation of a [ParameterElement].
@@ -7361,7 +7381,7 @@
         reference: enclosingRef.getChild('@getter').getChild(name),
       );
 
-      if (!isConst && !isFinal) {
+      if (_hasSetter) {
         this.setter = PropertyAccessorElementImpl_ImplicitSetter(
           this,
           reference: enclosingRef.getChild('@setter').getChild(name),
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 1f70c7b..eda8b3d 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -832,6 +832,14 @@
   @override
   bool get isInitializingFormal => declaration.isInitializingFormal;
 
+  @override
+  bool get isRequiredNamed {
+    if (isLegacy) {
+      return false;
+    }
+    return super.isRequiredNamed;
+  }
+
   @deprecated
   @override
   ParameterKind get parameterKind => declaration.parameterKind;
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index 56aa287..88fc991 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -352,6 +352,9 @@
 
   static const ParserErrorCode FINAL_AND_COVARIANT = _FINAL_AND_COVARIANT;
 
+  static const ParserErrorCode FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER =
+      _FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER;
+
   static const ParserErrorCode FINAL_AND_VAR = _FINAL_AND_VAR;
 
   static const ParserErrorCode FINAL_CLASS = ParserErrorCode(
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index a07b175..a6061ec 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -108,6 +108,7 @@
   _INVALID_USE_OF_COVARIANT_IN_EXTENSION,
   _TYPE_PARAMETER_ON_CONSTRUCTOR,
   _VOID_WITH_TYPE_ARGUMENTS,
+  _FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER,
 ];
 
 const ParserErrorCode _ABSTRACT_CLASS_MEMBER = ParserErrorCode(
@@ -328,6 +329,12 @@
     r"Members can't be declared to be both 'final' and 'covariant'.",
     correction: "Try removing either the 'final' or 'covariant' keyword.");
 
+const ParserErrorCode _FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER = ParserErrorCode(
+    'FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER',
+    r"Members marked 'late' with an initializer can't be declared to be both 'final' and 'covariant'.",
+    correction:
+        "Try removing either the 'final' or 'covariant' keyword, or removing the initializer.");
+
 const ParserErrorCode _FINAL_AND_VAR = ParserErrorCode(
     'FINAL_AND_VAR', r"Members can't be declared to be both 'final' and 'var'.",
     correction: "Try removing the keyword 'var'.");
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index fbccb1d..c74a46d 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -54,13 +54,6 @@
    */
   final Source source;
 
-  /*
-   * A function that returns the digest for a file as a String. The function
-   * returns a non null value, can return an empty string if file does
-   * not exist/has no contents.
-   */
-  final String Function(String path) getFileDigest;
-
   final List<FileState> importedFiles = [];
   final List<FileState> exportedFiles = [];
   final List<FileState> partedFiles = [];
@@ -73,8 +66,7 @@
   UnlinkedUnit2 unlinked2;
   LibraryCycle _libraryCycle;
 
-  FileState._(
-      this._fsState, this.path, this.uri, this.source, this.getFileDigest);
+  FileState._(this._fsState, this.path, this.uri, this.source);
 
   List<int> get apiSignature => _apiSignature;
 
@@ -132,7 +124,7 @@
   }
 
   void refresh() {
-    var digest = utf8.encode(getFileDigest(path));
+    var digest = utf8.encode(_fsState.getFileDigest(path));
     _exists = digest.isNotEmpty;
     String unlinkedKey = path;
 
@@ -163,6 +155,9 @@
           bytes = unlinkedBuilder.toBuffer();
           _fsState._byteStore.put(unlinkedKey, bytes);
         });
+
+        unlinked2 = CiderUnlinkedUnit.fromBuffer(bytes).unlinkedUnit;
+        _prefetchDirectReferences(unlinked2);
       }
     }
 
@@ -209,6 +204,41 @@
     return _fsState.getFileForUri(absoluteUri);
   }
 
+  void _prefetchDirectReferences(UnlinkedUnit2 unlinkedUnit2) {
+    if (_fsState.prefetchFiles == null) {
+      return;
+    }
+
+    var paths = <String>{};
+
+    void findPathForUri(String relativeUri) {
+      if (relativeUri.isEmpty) {
+        return;
+      }
+      Uri absoluteUri;
+      try {
+        absoluteUri = resolveRelativeUri(uri, Uri.parse(relativeUri));
+      } on FormatException {
+        return;
+      }
+      var p = _fsState.getPathForUri(absoluteUri);
+      if (p != null) {
+        paths.add(p);
+      }
+    }
+
+    for (var directive in unlinked2.imports) {
+      findPathForUri(directive.uri);
+    }
+    for (var directive in unlinked2.exports) {
+      findPathForUri(directive.uri);
+    }
+    for (var uri in unlinked2.parts) {
+      findPathForUri(uri);
+    }
+    _fsState.prefetchFiles(paths.toList());
+  }
+
   static CiderUnlinkedUnitBuilder serializeAstCiderUnlinked(
       List<int> digest, CompilationUnit unit) {
     var exports = <UnlinkedNamespaceDirectiveBuilder>[];
@@ -282,6 +312,12 @@
   final SourceFactory _sourceFactory;
   final AnalysisOptions _analysisOptions;
   final Uint32List _linkedSalt;
+
+  /**
+   * A function that returns the digest for a file as a String. The function
+   * returns a non null value, returns an empty string if file does
+   * not exist/has no contents.
+   */
   final String Function(String path) getFileDigest;
 
   final Map<String, FileState> _pathToFile = {};
@@ -290,6 +326,12 @@
   final FeatureSetProvider featureSetProvider;
 
   /**
+   * A function that fetches the given list of files. This function can be used
+   * to batch file reads in systems where file fetches are expensive.
+   */
+  final void Function(List<String> paths) prefetchFiles;
+
+  /**
    * The [FileState] instance that correspond to an unresolved URI.
    */
   FileState _unresolvedFile;
@@ -303,6 +345,7 @@
     this._linkedSalt,
     this.featureSetProvider,
     this.getFileDigest,
+    this.prefetchFiles,
   );
 
   /**
@@ -310,7 +353,7 @@
    */
   FileState get unresolvedFile {
     if (_unresolvedFile == null) {
-      _unresolvedFile = FileState._(this, null, null, null, null);
+      _unresolvedFile = FileState._(this, null, null, null);
       _unresolvedFile.refresh();
     }
     return _unresolvedFile;
@@ -325,7 +368,7 @@
       );
 
       var source = _sourceFactory.forUri2(uri);
-      file = FileState._(this, path, uri, source, getFileDigest);
+      file = FileState._(this, path, uri, source);
 
       _pathToFile[path] = file;
       _uriToFile[uri] = file;
@@ -344,7 +387,7 @@
       }
       var path = source.fullName;
 
-      file = FileState._(this, path, uri, source, getFileDigest);
+      file = FileState._(this, path, uri, source);
       _pathToFile[path] = file;
       _uriToFile[uri] = file;
 
@@ -352,6 +395,14 @@
     }
     return file;
   }
+
+  String getPathForUri(Uri uri) {
+    var source = _sourceFactory.forUri2(uri);
+    if (source == null) {
+      return null;
+    }
+    return source.fullName;
+  }
 }
 
 /// Information about libraries that reference each other, so form a cycle.
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 4930380..401bbe7 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -49,12 +49,18 @@
    */
   final String Function(String path) getFileDigest;
 
+  /**
+   * A function that fetches the given list of files. This function can be used
+   * to batch file reads in systems where file fetches are expensive.
+   */
+  final void Function(List<String> paths) prefetchFiles;
+
   Workspace workspace;
 
   MicroAnalysisContextImpl analysisContext;
 
   FileResolver(this.logger, this.resourceProvider, this.byteStore,
-      this.sourceFactory, this.getFileDigest,
+      this.sourceFactory, this.getFileDigest, this.prefetchFiles,
       {Workspace workspace})
       : this.workspace = workspace;
 
@@ -115,6 +121,7 @@
       Uint32List(0), // linkedSalt
       featureSetProvider,
       getFileDigest,
+      prefetchFiles,
     );
 
     FileState file;
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index 35941b2..81ce4ed 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -180,10 +180,6 @@
 
     var element = node.staticElement;
     if (element is LocalVariableElement) {
-      if (flow.isUnassigned(element)) {
-        dataForTesting?.definitelyUnassignedNodes?.add(node);
-      }
-
       var typeSystem = _typeOperations.typeSystem;
       if (typeSystem.isPotentiallyNonNullable(element.type)) {
         var isUnassigned = !flow.isAssigned(element);
@@ -204,6 +200,25 @@
     return false;
   }
 
+  bool isReadOfDefinitelyUnassignedLateLocal(SimpleIdentifier node) {
+    if (flow == null) return false;
+
+    if (node.inDeclarationContext()) return false;
+    if (!node.inGetterContext()) return false;
+
+    var element = node.staticElement;
+    if (element is LocalVariableElement) {
+      if (flow.isUnassigned(element)) {
+        dataForTesting?.definitelyUnassignedNodes?.add(node);
+        if (element.isLate) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
   void topLevelDeclaration_enter(
       Declaration node, FormalParameterList parameters, FunctionBody body) {
     assert(node != null);
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 4b9438d..6ec81e3 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -1430,6 +1430,21 @@
               "extensions.");
 
   /**
+   * It is a compile time error to read a local variable marked `late` when the
+   * variable is definitely unassigned. This includes all forms of reads,
+   * including implicit reads via the composite assignment operators as well
+   * as pre and post-fix operators.
+   *
+   * Parameters:
+   * 0: the name of the variable that is invalid
+   */
+  static const CompileTimeErrorCode DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE =
+      CompileTimeErrorCode('DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE',
+          "The late local variable '{0}' is definitely unassigned.",
+          correction:
+              "Ensure that it is assigned on necessary execution paths.");
+
+  /**
    * No parameters.
    */
   // #### Description
diff --git a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
index 4ada2b5..3ad3883 100644
--- a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
+++ b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
@@ -41,11 +41,7 @@
     _initFieldsMap(node.declaredElement);
   }
 
-  void enterMixin(MixinDeclaration node) {
-    _initFieldsMap(node.declaredElement);
-  }
-
-  void leaveClassOrMixin() {
+  void leaveClass() {
     _isInNativeClass = false;
     _initialFieldMap = null;
   }
@@ -60,6 +56,10 @@
       return;
     }
 
+    if (node.parent is! ClassDeclaration) {
+      return;
+    }
+
     if (_isInNativeClass) {
       return;
     }
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 41ff1ec..7eb47a4 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -1474,6 +1474,12 @@
       TypeAnnotation returnType = pop();
       List<Annotation> metadata = pop();
       Comment comment = _findComment(metadata, typedefKeyword);
+
+      // TODO(scheglov) https://github.com/dart-lang/sdk/issues/41023
+      if (parameters == null) {
+        throw StateError('FunctionTypeAlias without parameters.');
+      }
+
       declarations.add(ast.functionTypeAlias(comment, metadata, typedefKeyword,
           returnType, name, typeParameters, parameters, semicolon));
     } else {
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 82d2949..2d2182c 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -476,7 +476,7 @@
       super.visitClassDeclaration(node);
     } finally {
       _isInNativeClass = false;
-      _constructorFieldsVerifier.leaveClassOrMixin();
+      _constructorFieldsVerifier.leaveClass();
       _enclosingClass = outerClass;
     }
   }
@@ -1018,13 +1018,11 @@
         _checkMixinInheritance(node, onClause, implementsClause);
       }
 
-      _constructorFieldsVerifier.enterMixin(node);
       _checkForFinalNotInitializedInClass(members);
       _checkForWrongTypeParameterVarianceInSuperinterfaces();
       //      _checkForBadFunctionUse(node);
       super.visitMixinDeclaration(node);
     } finally {
-      _constructorFieldsVerifier.leaveClassOrMixin();
       _enclosingClass = outerClass;
     }
   }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index b6d3ae7..02015c3 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1118,7 +1118,7 @@
     var body = node.body;
 
     if (_flowAnalysis != null) {
-      if (!isFunctionDeclaration) {
+      if (_flowAnalysis.flow != null && !isFunctionDeclaration) {
         _flowAnalysis.executableDeclaration_enter(node, node.parameters, true);
       }
     } else {
@@ -1142,7 +1142,7 @@
     super.visitFunctionExpression(node);
 
     if (_flowAnalysis != null) {
-      if (!isFunctionDeclaration) {
+      if (_flowAnalysis.flow != null && !isFunctionDeclaration) {
         _checkForBodyMayCompleteNormally(
           returnType: returnType,
           body: body,
@@ -1511,14 +1511,22 @@
       return;
     }
 
-    if (_flowAnalysis != null &&
-        _flowAnalysis.isPotentiallyNonNullableLocalReadBeforeWrite(node)) {
-      errorReporter.reportErrorForNode(
-        CompileTimeErrorCode
-            .NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
-        node,
-        [node.name],
-      );
+    if (_flowAnalysis != null) {
+      if (_flowAnalysis.isPotentiallyNonNullableLocalReadBeforeWrite(node)) {
+        errorReporter.reportErrorForNode(
+          CompileTimeErrorCode
+              .NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
+          node,
+          [node.name],
+        );
+      }
+      if (_flowAnalysis.isReadOfDefinitelyUnassignedLateLocal(node)) {
+        errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE,
+          node,
+          [node.name],
+        );
+      }
     }
 
     super.visitSimpleIdentifier(node);
diff --git a/pkg/analyzer/lib/src/summary2/simply_bounded.dart b/pkg/analyzer/lib/src/summary2/simply_bounded.dart
index 3ae599f..bb5b05d 100644
--- a/pkg/analyzer/lib/src/summary2/simply_bounded.dart
+++ b/pkg/analyzer/lib/src/summary2/simply_bounded.dart
@@ -127,6 +127,32 @@
   /// parameter declarations and their bounds are not included.
   static List<TypeAnnotation> _collectTypedefRhsTypes(AstNode node) {
     if (node is FunctionTypeAlias) {
+      // TODO(scheglov) https://github.com/dart-lang/sdk/issues/41023
+      if (node.parameters == null) {
+        var buffer = StringBuffer();
+        buffer.writeln('Unexpected FunctionTypeAlias state.');
+        try {
+          buffer.writeln('unit: ');
+          buffer.writeln(node.parent.toSource());
+        } catch (_) {
+          try {
+            buffer.writeln('node: ');
+            buffer.writeln(node.toSource());
+          } catch (_) {
+            try {
+              buffer.writeln('node parts:');
+              buffer.writeln('  name: ${node.name}');
+              buffer.writeln('  typeParameters: ${node.typeParameters}');
+              buffer.writeln('  returnType: ${node.returnType}');
+              buffer.writeln('  parameters: ${node.parameters}');
+            } catch (_) {
+              buffer.writeln('nothing worked');
+            }
+          }
+        }
+        throw StateError(buffer.toString());
+      }
+
       var collector = _TypeCollector();
       collector.addType(node.returnType);
       collector.visitParameters(node.parameters);
diff --git a/pkg/analyzer/test/generated/invalid_code_test.dart b/pkg/analyzer/test/generated/invalid_code_test.dart
index 64f79ab..db7160f 100644
--- a/pkg/analyzer/test/generated/invalid_code_test.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -4,7 +4,9 @@
 
 import 'dart:async';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../src/dart/resolution/driver_resolution.dart';
@@ -12,6 +14,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(InvalidCodeTest);
+    defineReflectiveTests(InvalidCodeWithNullSafetyTest);
   });
 }
 
@@ -306,3 +309,30 @@
     assertHasTestErrors();
   }
 }
+
+@reflectiveTest
+class InvalidCodeWithNullSafetyTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  test_issue_40837() async {
+    await _assertCanBeAnalyzed('''
+class A {
+  const A(_);
+}
+
+@A(() => 0)
+class B {}
+''');
+  }
+
+  Future<void> _assertCanBeAnalyzed(String text) async {
+    await resolveTestCode(text);
+    assertHasTestErrors();
+  }
+}
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 11abdce..ed796bf 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -87,6 +87,18 @@
     expect(invocation.toSource(), 'new C().late()');
   }
 
+  void test_parseClassMember_finalAndCovariantLateWithInitializer() {
+    createParser(
+      'covariant late final int f = 0;',
+      featureSet: nonNullable,
+    );
+    parser.parseClassMember('C');
+    assertErrors(errors: [
+      expectedError(
+          ParserErrorCode.FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER, 0, 9)
+    ]);
+  }
+
   void test_parseClassMember_operator_gtgtgt() {
     CompilationUnitImpl unit = parseCompilationUnit(
         'class C { bool operator >>>(other) => false; }',
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 46e0226..7469fd0 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -9,6 +9,7 @@
     show ScannerResult, scanString;
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/language_version.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -111,7 +112,12 @@
    * For any analyzer test where the last token is not EOF, set this value.
    * It is ignored when not using the fasta parser.
    */
-  void createParser(String content, {int expectedEndOffset});
+  void createParser(
+    String content, {
+    int expectedEndOffset,
+    LanguageVersion languageVersion,
+    FeatureSet featureSet,
+  });
 
   ExpectedError expectedError(ErrorCode code, int offset, int length);
 
@@ -9467,7 +9473,12 @@
    * prepared to parse the tokens scanned from the given [content].
    */
   @override
-  void createParser(String content, {int expectedEndOffset}) {
+  void createParser(
+    String content, {
+    int expectedEndOffset,
+    LanguageVersion languageVersion,
+    FeatureSet featureSet,
+  }) {
     Source source = TestSource();
     listener = GatheringErrorListener();
 
@@ -9477,8 +9488,8 @@
     parser = Parser(
       source,
       listener,
-      languageVersion: null,
-      featureSet: FeatureSet.forTesting(),
+      languageVersion: languageVersion,
+      featureSet: featureSet,
     );
     parser.allowNativeClause = allowNativeClause;
     parser.parseFunctionBodies = parseFunctionBodies;
diff --git a/pkg/analyzer/test/id_tests/definite_assignment_test.dart b/pkg/analyzer/test/id_tests/definite_assignment_test.dart
index 929b8df..732c27a 100644
--- a/pkg/analyzer/test/id_tests/definite_assignment_test.dart
+++ b/pkg/analyzer/test/id_tests/definite_assignment_test.dart
@@ -9,8 +9,10 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
 
 import '../util/id_testing_helper.dart';
@@ -37,6 +39,18 @@
       const _DefiniteAssignmentDataInterpreter();
 
   @override
+  bool get supportsErrors => true;
+
+  @override
+  String computeErrorData(TestConfig config, TestingData testingData, Id id,
+      List<AnalysisError> errors) {
+    var errorCodes = errors.map((e) => e.errorCode).where((errorCode) =>
+        errorCode !=
+        CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE);
+    return errorCodes.isNotEmpty ? errorCodes.join(',') : null;
+  }
+
+  @override
   void computeUnitData(TestingData testingData, CompilationUnit unit,
       Map<Id, ActualData<String>> actualMap) {
     var flowResult =
diff --git a/pkg/analyzer/test/id_tests/definite_unassignment_test.dart b/pkg/analyzer/test/id_tests/definite_unassignment_test.dart
index 963815a..1e2b9c5 100644
--- a/pkg/analyzer/test/id_tests/definite_unassignment_test.dart
+++ b/pkg/analyzer/test/id_tests/definite_unassignment_test.dart
@@ -9,8 +9,10 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
 
 import '../util/id_testing_helper.dart';
@@ -37,6 +39,18 @@
       const _DefiniteUnassignmentDataInterpreter();
 
   @override
+  bool get supportsErrors => true;
+
+  @override
+  String computeErrorData(TestConfig config, TestingData testingData, Id id,
+      List<AnalysisError> errors) {
+    var errorCodes = errors.map((e) => e.errorCode).where((errorCode) =>
+        errorCode !=
+        CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE);
+    return errorCodes.isNotEmpty ? errorCodes.join(',') : null;
+  }
+
+  @override
   void computeUnitData(TestingData testingData, CompilationUnit unit,
       Map<Id, ActualData<String>> actualMap) {
     var flowResult =
diff --git a/pkg/analyzer/test/src/dart/micro/file_resolution.dart b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
index fb0cfd0..22f938e 100644
--- a/pkg/analyzer/test/src/dart/micro/file_resolution.dart
+++ b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
@@ -76,6 +76,7 @@
           PackageMapUriResolver(resourceProvider, packageMap),
           ResourceUriResolver(resourceProvider)
         ]),
-        (String path) => _getDigest(path));
+        (String path) => _getDigest(path),
+        null);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index dee6f43..f3bb225 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -308,38 +307,6 @@
 ''');
   }
 
-  test_error_finalNotInitializedConstructor() async {
-    await assertErrorsInCode(r'''
-mixin M {
-  final int f;
-  M();
-}
-''', [
-      error(ParserErrorCode.MIXIN_DECLARES_CONSTRUCTOR, 27, 1),
-      error(StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1, 27, 1),
-    ]);
-  }
-
-  test_error_finalNotInitializedConstructor_OK() async {
-    await assertErrorsInCode(r'''
-mixin M {
-  final int f;
-  M(this.f);
-}
-''', [
-      error(ParserErrorCode.MIXIN_DECLARES_CONSTRUCTOR, 27, 1),
-    ]);
-
-    var element = findElement.mixin('M');
-    var constructorElement = element.constructors.single;
-
-    var fpNode = findNode.fieldFormalParameter('f);');
-    assertElement(fpNode.identifier, constructorElement.parameters[0]);
-
-    FieldFormalParameterElement fpElement = fpNode.declaredElement;
-    expect(fpElement.field, same(findElement.field('f')));
-  }
-
   test_error_implementsClause_deferredClass() async {
     await assertErrorsInCode(r'''
 import 'dart:math' deferred as math;
@@ -820,37 +787,6 @@
     ]);
   }
 
-  test_error_mixinDeclaresConstructor() async {
-    await assertErrorsInCode(r'''
-mixin M {
-  M(int a) {
-    a; // read
-  }
-}
-''', [
-      error(ParserErrorCode.MIXIN_DECLARES_CONSTRUCTOR, 12, 1),
-    ]);
-
-    // Even though it is an error for a mixin to declare a constructor,
-    // we still build elements for constructors, and resolve them.
-
-    var element = findElement.mixin('M');
-    var constructors = element.constructors;
-    expect(constructors, hasLength(1));
-    var constructorElement = constructors[0];
-
-    var constructorNode = findNode.constructor('M(int a)');
-    assertElement(constructorNode, constructorElement);
-
-    var aElement = constructorElement.parameters[0];
-    var aNode = constructorNode.parameters.parameters[0];
-    assertElement(aNode, aElement);
-
-    var aRef = findNode.simple('a; // read');
-    assertElement(aRef, aElement);
-    assertType(aRef, 'int');
-  }
-
   test_error_mixinInstantiate_default() async {
     await assertErrorsInCode(r'''
 mixin M {}
diff --git a/pkg/analyzer/test/src/diagnostics/definitely_unassigned_late_local_variable_test.dart b/pkg/analyzer/test/src/diagnostics/definitely_unassigned_late_local_variable_test.dart
new file mode 100644
index 0000000..24bb1e0
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/definitely_unassigned_late_local_variable_test.dart
@@ -0,0 +1,161 @@
+// 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 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DefinitelyUnassignedLateLocalVariableTest);
+  });
+}
+
+@reflectiveTest
+class DefinitelyUnassignedLateLocalVariableTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.fromEnableFlags(
+      [EnableString.non_nullable],
+    );
+
+  CompileTimeErrorCode get _errorCode {
+    return CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE;
+  }
+
+  test_definitelyAssigned_after_compoundAssignment() async {
+    await assertErrorsInCode(r'''
+void f() {
+  late int v;
+  v += 1;
+  v;
+}
+''', [
+      error(_errorCode, 27, 1),
+    ]);
+  }
+
+  test_definitelyAssigned_after_postfixExpression_increment() async {
+    await assertErrorsInCode(r'''
+void f() {
+  late int v;
+  v++;
+  v;
+}
+''', [
+      error(_errorCode, 27, 1),
+    ]);
+  }
+
+  test_mightBeAssigned_if_else() async {
+    await assertNoErrorsInCode(r'''
+void f(bool c) {
+  late int v;
+  if (c) {
+    print(0);
+  } else {
+    v = 0;
+  }
+  v;
+}
+''');
+  }
+
+  test_mightBeAssigned_if_then() async {
+    await assertNoErrorsInCode(r'''
+void f(bool c) {
+  late int v;
+  if (c) {
+    v = 0;
+  }
+  v;
+}
+''');
+  }
+
+  test_mightBeAssigned_while() async {
+    await assertNoErrorsInCode(r'''
+void f(bool c) {
+  late int v;
+  while (c) {
+    v = 0;
+  }
+  v;
+}
+''');
+  }
+
+  test_neverAssigned_assignment_compound() async {
+    await assertErrorsInCode(r'''
+void f() {
+  late int v;
+  v += 1;
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 22, 1),
+      error(_errorCode, 27, 1),
+    ]);
+  }
+
+  test_neverAssigned_assignment_pure() async {
+    await assertErrorsInCode(r'''
+void f() {
+  late int v;
+  v = 0;
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 22, 1),
+    ]);
+  }
+
+  test_neverAssigned_nullable() async {
+    await assertErrorsInCode(r'''
+void f() {
+  late int? v;
+  v;
+}
+''', [
+      error(_errorCode, 28, 1),
+    ]);
+  }
+
+  test_neverAssigned_prefixExpression() async {
+    await assertErrorsInCode(r'''
+void f() {
+  late int v;
+  ++v;
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 22, 1),
+      error(_errorCode, 29, 1),
+    ]);
+  }
+
+  test_neverAssigned_read() async {
+    await assertErrorsInCode(r'''
+void f() {
+  late int v;
+  v;
+}
+''', [
+      error(_errorCode, 27, 1),
+    ]);
+  }
+
+  test_neverAssigned_suffixExpression() async {
+    await assertErrorsInCode(r'''
+void f() {
+  late int v;
+  v++;
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 22, 1),
+      error(_errorCode, 27, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart b/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
index 2157307..fb6002e 100644
--- a/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/final_not_initialized_test.dart
@@ -72,6 +72,16 @@
       error(StaticWarningCode.FINAL_NOT_INITIALIZED, 18, 1),
     ]);
   }
+
+  test_mixin() async {
+    await assertErrorsInCode('''
+mixin M {
+  final int x;
+}
+''', [
+      error(StaticWarningCode.FINAL_NOT_INITIALIZED, 22, 1),
+    ]);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart b/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
index ff8fa6a..8cc3c98 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
@@ -354,6 +354,22 @@
     ]);
   }
 
+  test_method_legacy() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  void foo({required int a}) {}
+}
+''');
+    await assertNoErrorsInCode(r'''
+// @dart = 2.7
+import "a.dart";
+
+f() {
+  A().foo();
+}
+''');
+  }
+
   test_typedef_function() async {
     await assertErrorsInCode(r'''
 String test(C c) => c.m()();
diff --git a/pkg/analyzer/test/src/diagnostics/mixin_declares_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/mixin_declares_constructor_test.dart
new file mode 100644
index 0000000..355a804
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/mixin_declares_constructor_test.dart
@@ -0,0 +1,67 @@
+// 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 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MixinDeclaresConstructorTest);
+  });
+}
+
+@reflectiveTest
+class MixinDeclaresConstructorTest extends DriverResolutionTest {
+  test_fieldFormalParameter() async {
+    await assertErrorsInCode(r'''
+mixin M {
+  final int f;
+  M(this.f);
+}
+''', [
+      error(ParserErrorCode.MIXIN_DECLARES_CONSTRUCTOR, 27, 1),
+    ]);
+
+    var element = findElement.mixin('M');
+    var constructorElement = element.constructors.single;
+
+    var fpNode = findNode.fieldFormalParameter('f);');
+    assertElement(fpNode.identifier, constructorElement.parameters[0]);
+
+    FieldFormalParameterElement fpElement = fpNode.declaredElement;
+    assertElement(fpElement.field, findElement.field('f'));
+  }
+
+  test_resolved() async {
+    await assertErrorsInCode(r'''
+mixin M {
+  M(int a) {
+    a; // read
+  }
+}
+''', [
+      error(ParserErrorCode.MIXIN_DECLARES_CONSTRUCTOR, 12, 1),
+    ]);
+
+    // Even though it is an error for a mixin to declare a constructor,
+    // we still build elements for constructors, and resolve them.
+
+    var element = findElement.mixin('M');
+    var constructorElement = element.constructors.single;
+
+    var constructorNode = findNode.constructor('M(int a)');
+    assertElement(constructorNode, constructorElement);
+
+    var aElement = constructorElement.parameters[0];
+    var aNode = constructorNode.parameters.parameters[0];
+    assertElement(aNode, aElement);
+
+    var aRef = findNode.simple('a; // read');
+    assertElement(aRef, aElement);
+    assertType(aRef, 'int');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart b/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
index 9a758ed..50e9132 100644
--- a/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
@@ -903,6 +903,12 @@
     await assertNoErrorsInCode('''
 f() {
   late int v;
+
+  void g() {
+    v = 0;
+  }
+
+  g();
   v;
 }
 ''');
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 9275a0a..1d56343 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -69,6 +69,8 @@
 import 'default_value_on_required_parameter_test.dart'
     as default_value_on_required_parameter;
 import 'deferred_import_of_extension_test.dart' as deferred_import_of_extension;
+import 'definitely_unassigned_late_local_variable_test.dart'
+    as definitely_unassigned_late_local_variable;
 import 'deprecated_extends_function_test.dart' as deprecated_extends_function;
 import 'deprecated_function_class_declaration_test.dart'
     as deprecated_function_class_declaration;
@@ -267,6 +269,7 @@
     as mixin_application_not_implemented_interface;
 import 'mixin_class_declares_constructor_test.dart'
     as mixin_class_declares_constructor;
+import 'mixin_declares_constructor_test.dart' as mixin_declares_constructor;
 import 'mixin_deferred_class_test.dart' as mixin_deferred_class;
 import 'mixin_inherits_from_not_object_test.dart'
     as mixin_inherits_from_not_object;
@@ -545,6 +548,7 @@
     default_value_in_redirecting_factory_constructor.main();
     default_value_on_required_parameter.main();
     deferred_import_of_extension.main();
+    definitely_unassigned_late_local_variable.main();
     deprecated_extends_function.main();
     deprecated_function_class_declaration.main();
     deprecated_member_use.main();
@@ -678,6 +682,7 @@
     missing_return.main();
     mixin_application_not_implemented_interface.main();
     mixin_class_declares_constructor.main();
+    mixin_declares_constructor.main();
     mixin_deferred_class.main();
     mixin_inherits_from_not_object.main();
     mixin_of_disallowed_class.main();
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index dee20b0..227d445 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -964,11 +964,8 @@
       expect(e.getter, isNotNull);
       _assertSyntheticAccessorEnclosing(e, e.getter);
 
-      if (e.isFinal || e.isConst) {
-        expect(e.setter, isNull);
-      } else {
-        expect(e.setter, isNotNull);
-        _assertSyntheticAccessorEnclosing(e, e.getter);
+      if (e.setter != null) {
+        _assertSyntheticAccessorEnclosing(e, e.setter);
       }
     }
 
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 1472711..e312162 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -960,13 +960,58 @@
 
   test_class_fields_late() async {
     featureSet = enableNnbd;
-    var library = await checkLibrary('class C { int i; late int j; }');
-    checkElementText(library, r'''
+    var library = await checkLibrary('''
 class C {
-  int i;
-  late int j;
+  late int foo;
 }
 ''');
+    checkElementText(
+        library,
+        r'''
+class C {
+  late int foo;
+  synthetic int get foo {}
+  synthetic void set foo(int _foo) {}
+}
+''',
+        withSyntheticAccessors: true);
+  }
+
+  test_class_fields_late_final() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('''
+class C {
+  late final int foo;
+}
+''');
+    checkElementText(
+        library,
+        r'''
+class C {
+  late final int foo;
+  synthetic int get foo {}
+  synthetic void set foo(int _foo) {}
+}
+''',
+        withSyntheticAccessors: true);
+  }
+
+  test_class_fields_late_final_initialized() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('''
+class C {
+  late final int foo = 0;
+}
+''');
+    checkElementText(
+        library,
+        r'''
+class C {
+  late final int foo;
+  synthetic int get foo {}
+}
+''',
+        withSyntheticAccessors: true);
   }
 
   test_class_getter_abstract() async {
@@ -11240,14 +11285,6 @@
 ''');
   }
 
-  test_variable_final_late() async {
-    featureSet = enableNnbd;
-    var library = await checkLibrary('late final int x = 0;');
-    checkElementText(library, r'''
-late final int x;
-''');
-  }
-
   test_variable_getterInLib_setterInPart() async {
     addSource('/a.dart', '''
 part of my.lib;
@@ -11373,9 +11410,39 @@
   test_variable_late() async {
     featureSet = enableNnbd;
     var library = await checkLibrary('late int x = 0;');
-    checkElementText(library, r'''
+    checkElementText(
+        library,
+        r'''
 late int x;
-''');
+synthetic int get x {}
+synthetic void set x(int _x) {}
+''',
+        withSyntheticAccessors: true);
+  }
+
+  test_variable_late_final() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('late final int x;');
+    checkElementText(
+        library,
+        r'''
+late final int x;
+synthetic int get x {}
+synthetic void set x(int _x) {}
+''',
+        withSyntheticAccessors: true);
+  }
+
+  test_variable_late_final_initialized() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary('late final int x = 0;');
+    checkElementText(
+        library,
+        r'''
+late final int x;
+synthetic int get x {}
+''',
+        withSyntheticAccessors: true);
   }
 
   test_variable_propagatedType_const_noDep() async {
diff --git a/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart b/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart
index 7e4c9f9..384f2dc 100644
--- a/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart
@@ -39,11 +39,13 @@
 }
 
 dynamic tempSkipped(File file) {
+  const String prefix = "front_end/parser_testcases";
   String uriString = file.uri.toString();
-  if (uriString.endsWith(
-          "front_end/parser_testcases/nnbd/issue_40267_case_02.dart") ||
-      uriString.endsWith(
-          "front_end/parser_testcases/nnbd/issue_40267_case_05.dart")) {
+  if (uriString.endsWith("$prefix/nnbd/issue_40267_case_02.dart") ||
+      uriString.endsWith("$prefix/nnbd/issue_40267_case_05.dart") ||
+      uriString.endsWith("$prefix/nnbd/issue_40267_lookup_plus_plus.dart") ||
+      uriString.endsWith("$prefix/nnbd/issue_40267_lookup_plus.dart") ||
+      uriString.endsWith("$prefix/nnbd/issue_40267_plus_plus_lookup.dart")) {
     return "Temporarily skipped because of "
         "https://dart-review.googlesource.com/c/sdk/+/135903";
   }
diff --git a/pkg/analyzer_fe_comparison/bin/compare_programs.dart b/pkg/analyzer_fe_comparison/bin/compare_programs.dart
deleted file mode 100644
index 0118aee..0000000
--- a/pkg/analyzer_fe_comparison/bin/compare_programs.dart
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:io';
-
-import 'package:analyzer/src/command_line/arguments.dart';
-import 'package:analyzer_fe_comparison/comparison.dart';
-import 'package:args/args.dart';
-import 'package:path/path.dart' as path;
-
-/// Compares the analyzer and front_end behavior when compiling a program.
-main(List<String> args) async {
-  ArgResults options = _parseArgs(args);
-  var sourcePaths = options.rest;
-  if (sourcePaths.length != 1) {
-    throw new StateError('Exactly one source file must be specified.');
-  }
-  var sourcePath = sourcePaths[0];
-  var scriptPath = Platform.script.toFilePath();
-  var sdkRepoPath =
-      path.normalize(path.join(path.dirname(scriptPath), '..', '..', '..'));
-  var buildPath = await _findBuildDir(sdkRepoPath, 'ReleaseX64');
-  var dillPath = path.join(buildPath, 'vm_platform_strong.dill');
-  var packagesFilePath = path.join(sdkRepoPath, '.packages');
-
-  await compareTestPrograms(sourcePath, dillPath, packagesFilePath);
-}
-
-Future<String> _findBuildDir(String sdkRepoPath, String targetName) async {
-  for (var subdirName in ['out', 'xcodebuild']) {
-    var candidatePath = path.join(sdkRepoPath, subdirName, targetName);
-    if (await new Directory(candidatePath).exists()) {
-      return candidatePath;
-    }
-  }
-  throw new StateError('Cannot find build directory');
-}
-
-ArgResults _parseArgs(List<String> args) {
-  var parser = new ArgParser(allowTrailingOptions: true);
-  parser.addOption('dart-sdk', help: 'The path to the Dart SDK.');
-  if (args.contains('--ignore-unrecognized-flags')) {
-    args = filterUnknownArguments(args, parser);
-  }
-  return parser.parse(args);
-}
diff --git a/pkg/analyzer_fe_comparison/bin/compare_sdk_tests b/pkg/analyzer_fe_comparison/bin/compare_sdk_tests
deleted file mode 100755
index b84851f..0000000
--- a/pkg/analyzer_fe_comparison/bin/compare_sdk_tests
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-# Run analyzer_fe_comparison on the Dart VM.  This script assumes the Dart
-# repo's directory structure.
-
-function follow_links() {
-  file="$1"
-  while [ -h "$file" ]; do
-    # On Mac OS, readlink -f doesn't work.
-    file="$(readlink "$file")"
-  done
-  echo "$file"
-}
-
-# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-
-# Find directories.
-PKG_BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-DART_ROOT="$(cd "${PKG_BIN_DIR}/../../.." ; pwd -P)"
-SDK_DIR="${DART_ROOT}/sdk"
-BIN_DIR="${SDK_DIR}/bin"
-
-SDK_ARG="--dart-sdk=$SDK_DIR"
-
-DART="$BIN_DIR/dart"
-
-unset EXTRA_VM_OPTIONS
-declare -a EXTRA_VM_OPTIONS
-
-# We allow extra vm options to be passed in through an environment variable.
-if [[ $DART_VM_OPTIONS ]]; then
-  read -a OPTIONS <<< "$DART_VM_OPTIONS"
-  EXTRA_VM_OPTIONS+=("${OPTIONS[@]}")
-fi
-
-COMPARE_PROGRAMS="$PKG_BIN_DIR/compare_programs.dart"
-
-exec "$DART" "--packages=$DART_ROOT/.packages" "${EXTRA_VM_OPTIONS[@]}" "$COMPARE_PROGRAMS" "$SDK_ARG" "$@"
diff --git a/pkg/analyzer_fe_comparison/lib/comparison.dart b/pkg/analyzer_fe_comparison/lib/comparison.dart
deleted file mode 100644
index a8dcf37..0000000
--- a/pkg/analyzer_fe_comparison/lib/comparison.dart
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer_fe_comparison/src/analyzer.dart' as analyzer;
-import 'package:analyzer_fe_comparison/src/comparison_node.dart';
-import 'package:analyzer_fe_comparison/src/kernel.dart' as kernel;
-import 'package:path/path.dart' as path;
-
-/// Compares the analyzer and kernel representations of a package, and prints
-/// the resulting diff.
-void comparePackages(
-    String platformPath, String projectLibPath, String packagesFilePath) async {
-  ComparisonNode analyzerNode = await analyzer.analyzePackage(projectLibPath);
-  var packagesFileUri = Uri.file(packagesFilePath);
-  var inputs = <Uri>[];
-  for (var library in analyzerNode.children) {
-    inputs.add(Uri.parse(library.text));
-  }
-  var platformUri = Uri.file(platformPath);
-  ComparisonNode kernelNode =
-      await kernel.analyzePackage(inputs, packagesFileUri, platformUri);
-  print(ComparisonNode.diff(kernelNode, analyzerNode, 'CFE', 'analyzer'));
-}
-
-/// Compares the analyzer and kernel representations of a test file, and prints
-/// the resulting diff.
-///
-/// Only libraries reached by a "file:" URI are compared.
-void compareTestPrograms(
-    String sourcePath, String platformPath, String packagesFilePath) async {
-  var packagesFileUri = Uri.file(packagesFilePath);
-  var platformUri = Uri.file(platformPath);
-  ComparisonNode kernelNode = await kernel.analyzeProgram(
-      path.toUri(sourcePath),
-      packagesFileUri,
-      platformUri,
-      (uri) => uri.scheme == 'file');
-  if (kernelNode.text == 'Error occurred') {
-    // TODO(paulberry): really we should verify that the analyzer detects an
-    // error as well.  But that's not easy to do right now because we use the
-    // front end to chase imports so that we know which files to pass to the
-    // analyzer, and we can't rely on the front end import chasing when an error
-    // occurred.
-    print('No differences found (skipped due to front end compilation error)');
-    return;
-  }
-  String startingPath;
-  var inputs = <String>[];
-  for (var library in kernelNode.children) {
-    var filePath = path.fromUri(Uri.parse(library.text));
-    if (startingPath == null) {
-      startingPath = path.dirname(filePath);
-    } else {
-      while (!path.isWithin(startingPath, filePath)) {
-        startingPath = path.dirname(startingPath);
-      }
-    }
-    inputs.add(filePath);
-  }
-  ComparisonNode analyzerNode =
-      await analyzer.analyzeFiles(startingPath, inputs);
-  if (kernelNode == analyzerNode) {
-    print('No differences found!');
-  } else {
-    print('Differences found:');
-    print(ComparisonNode.diff(kernelNode, analyzerNode, 'CFE', 'analyzer'));
-  }
-}
diff --git a/pkg/analyzer_fe_comparison/lib/src/analyzer.dart b/pkg/analyzer_fe_comparison/lib/src/analyzer.dart
deleted file mode 100644
index c1a9ad6..0000000
--- a/pkg/analyzer_fe_comparison/lib/src/analyzer.dart
+++ /dev/null
@@ -1,341 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
-import 'package:analyzer/dart/analysis/context_root.dart';
-import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/analysis/uri_converter.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart' show SourceKind;
-import 'package:analyzer_fe_comparison/src/comparison_node.dart';
-
-/// Analyzes the files in [filePaths] using the analyzer, and returns a
-/// [ComparisonNode] representing them.
-Future<ComparisonNode> analyzeFiles(
-    String startingPath, List<String> filePaths) async {
-  var driver = await _AnalyzerDriver.create(startingPath);
-  return driver.analyzeFiles(filePaths);
-}
-
-/// Analyzes the package located at [libPath] using the analyzer, and returns a
-/// [ComparisonNode] representing it.
-Future<ComparisonNode> analyzePackage(String libPath) async {
-  var driver = await _AnalyzerDriver.create(libPath);
-  return driver.analyzePackage();
-}
-
-class _AnalyzerDriver {
-  final AnalysisSession _session;
-
-  final TypeProvider _typeProvider;
-
-  final UriConverter _uriConverter;
-
-  final ContextRoot _contextRoot;
-
-  _AnalyzerDriver._(
-      this._session, this._typeProvider, this._uriConverter, this._contextRoot);
-
-  Future<ComparisonNode> analyzeFiles(Iterable<String> filePaths) async {
-    var libraryNodes = <ComparisonNode>[];
-    for (var filePath in filePaths) {
-      var kind = await _session.getSourceKind(filePath);
-      if (kind == SourceKind.LIBRARY) {
-        var importUri = _uriConverter.pathToUri(filePath);
-        var libraryElement =
-            await _session.getLibraryByUri(importUri.toString());
-        var childNodes = <ComparisonNode>[];
-        if (libraryElement.name.isNotEmpty) {
-          childNodes.add(ComparisonNode('name=${libraryElement.name}'));
-        }
-        for (var compilationUnit in libraryElement.units) {
-          var unitResult =
-              await _session.getResolvedAst(compilationUnit.source.fullName);
-          _AnalyzerVisitor(_typeProvider, childNodes)
-              ._visitList(unitResult.unit.declarations);
-        }
-        libraryNodes
-            .add(ComparisonNode.sorted(importUri.toString(), childNodes));
-      }
-    }
-    return ComparisonNode.sorted('Component', libraryNodes);
-  }
-
-  Future<ComparisonNode> analyzePackage() async {
-    return analyzeFiles(_contextRoot.analyzedFiles());
-  }
-
-  static Future<_AnalyzerDriver> create(String startingPath) async {
-    var contextCollection =
-        AnalysisContextCollection(includedPaths: [startingPath]);
-    var contexts = contextCollection.contexts;
-    if (contexts.length != 1) {
-      throw new StateError('Expected exactly one context');
-    }
-    var context = contexts[0];
-    var session = context.currentSession;
-    var typeProvider = await session.typeProvider;
-    var uriConverter = session.uriConverter;
-    var contextRoot = context.contextRoot;
-    return _AnalyzerDriver._(session, typeProvider, uriConverter, contextRoot);
-  }
-}
-
-/// Visitor for serializing the contents of an analyzer AST into
-/// ComparisonNodes.
-///
-/// Results are accumulated into [_resultNodes].
-class _AnalyzerVisitor extends UnifyingAstVisitor<void> {
-  final TypeProvider _typeProvider;
-
-  final List<ComparisonNode> _resultNodes;
-
-  _AnalyzerVisitor(this._typeProvider, this._resultNodes);
-
-  @override
-  void visitClassDeclaration(ClassDeclaration node) {
-    var children = <ComparisonNode>[];
-    var visitor = _AnalyzerVisitor(_typeProvider, children);
-    visitor._handleClassOrClassTypeAlias(node.declaredElement);
-    visitor._visitList(node.members);
-    _resultNodes
-        .add(ComparisonNode.sorted('Class ${node.name.name}', children));
-  }
-
-  @override
-  void visitClassTypeAlias(ClassTypeAlias node) {
-    var children = <ComparisonNode>[];
-    var visitor = _AnalyzerVisitor(_typeProvider, children);
-    visitor._handleClassOrClassTypeAlias(node.declaredElement);
-    _resultNodes.add(
-        ComparisonNode.sorted('MixinApplication ${node.name.name}', children));
-  }
-
-  @override
-  void visitConstructorDeclaration(ConstructorDeclaration node) {
-    var children = <ComparisonNode>[];
-    var visitor = _AnalyzerVisitor(_typeProvider, children);
-    visitor._visitParameters(node.parameters);
-    _resultNodes.add(ComparisonNode.sorted(
-        'Constructor ${node.name?.name ?? '(unnamed)'}', children));
-  }
-
-  @override
-  void visitEnumDeclaration(EnumDeclaration node) {
-    var children = <ComparisonNode>[];
-    for (var enumValue in node.constants) {
-      children.add(ComparisonNode('EnumValue ${enumValue.name.name}'));
-    }
-    _resultNodes.add(ComparisonNode.sorted('Enum ${node.name.name}', children));
-  }
-
-  @override
-  void visitFieldDeclaration(FieldDeclaration node) {
-    node.fields.accept(this);
-  }
-
-  @override
-  void visitFunctionDeclaration(FunctionDeclaration node) {
-    String kind;
-    if (node.isGetter) {
-      kind = 'Getter';
-    } else if (node.isSetter) {
-      kind = 'Setter';
-    } else {
-      // Kernel calls top level functions "methods".
-      kind = 'Method';
-    }
-    var children = <ComparisonNode>[];
-    var visitor = _AnalyzerVisitor(_typeProvider, children);
-    visitor._visitTypeParameters(node.declaredElement.typeParameters);
-    visitor._visitParameters(node.functionExpression.parameters);
-    children
-        .add(_translateType('Return type: ', node.declaredElement.returnType));
-    _resultNodes
-        .add(ComparisonNode.sorted('$kind ${node.name.name}', children));
-  }
-
-  @override
-  void visitFunctionTypeAlias(FunctionTypeAlias node) {
-    _visitTypedef(node);
-  }
-
-  @override
-  void visitGenericTypeAlias(GenericTypeAlias node) {
-    _visitTypedef(node);
-  }
-
-  @override
-  void visitMethodDeclaration(MethodDeclaration node) {
-    var name = node.name.name;
-    String kind;
-    if (node.isGetter) {
-      kind = 'Getter';
-    } else if (node.isSetter) {
-      kind = 'Setter';
-    } else if (node.isOperator) {
-      kind = 'Operator';
-      if (name == '-' && node.declaredElement.parameters.isEmpty) {
-        name = 'unary-';
-      }
-    } else {
-      kind = 'Method';
-    }
-    var children = <ComparisonNode>[];
-    var visitor = _AnalyzerVisitor(_typeProvider, children);
-    visitor._visitTypeParameters(node.declaredElement.typeParameters);
-    visitor._visitParameters(node.parameters);
-    children
-        .add(_translateType('Return type: ', node.declaredElement.returnType));
-    _resultNodes.add(ComparisonNode.sorted('$kind $name', children));
-  }
-
-  @override
-  void visitMixinDeclaration(MixinDeclaration node) {
-    // At present, kernel doesn't distinguish between mixin and class
-    // declarations.  So treat the mixin as a class.
-    var children = <ComparisonNode>[];
-    var visitor = _AnalyzerVisitor(_typeProvider, children);
-    visitor._handleClassOrClassTypeAlias(node.declaredElement);
-    visitor._visitList(node.members);
-    _resultNodes
-        .add(ComparisonNode.sorted('Mixin ${node.name.name}', children));
-  }
-
-  @override
-  Null visitNode(AstNode node) {
-    throw new UnimplementedError('AnalyzerVisitor: ${node.runtimeType}');
-  }
-
-  @override
-  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    node.variables.accept(this);
-  }
-
-  @override
-  void visitVariableDeclarationList(VariableDeclarationList node) {
-    for (var variableDeclaration in node.variables) {
-      var children = <ComparisonNode>[];
-      children.add(
-          _translateType('Type: ', variableDeclaration.declaredElement.type));
-      // Kernel calls both fields and top level variable declarations "fields".
-      _resultNodes.add(ComparisonNode.sorted(
-          'Field ${variableDeclaration.name.name}', children));
-    }
-  }
-
-  void _handleClassOrClassTypeAlias(ClassElement element) {
-    _visitTypeParameters(element.typeParameters);
-    if (element.isMixin) {
-      for (int i = 0; i < element.superclassConstraints.length; i++) {
-        _resultNodes
-            .add(_translateType('On $i: ', element.superclassConstraints[i]));
-      }
-    } else {
-      if (element.supertype != null) {
-        _resultNodes.add(_translateType('Extends: ', element.supertype));
-      }
-      for (int i = 0; i < element.mixins.length; i++) {
-        _resultNodes.add(_translateType('Mixin $i: ', element.mixins[i]));
-      }
-    }
-    for (int i = 0; i < element.interfaces.length; i++) {
-      _resultNodes
-          .add(_translateType('Implements $i: ', element.interfaces[i]));
-    }
-  }
-
-  /// Converts the analyzer representation of a type into a ComparisonNode.
-  ComparisonNode _translateType(String prefix, DartType type) {
-    if (type is InterfaceType) {
-      var children = <ComparisonNode>[];
-      children
-          .add(ComparisonNode('Library: ${type.element.librarySource.uri}'));
-      for (int i = 0; i < type.typeArguments.length; i++) {
-        children.add(_translateType('Type arg $i: ', type.typeArguments[i]));
-      }
-      return ComparisonNode('${prefix}InterfaceType ${type.name}', children);
-    }
-    if (type is TypeParameterType) {
-      // TODO(paulberry): disambiguate if needed.
-      return ComparisonNode('${prefix}TypeParameterType: ${type.name}');
-    }
-    if (type.isDynamic) {
-      return ComparisonNode('${prefix}Dynamic');
-    }
-    if (type.isVoid) {
-      return ComparisonNode('${prefix}Void');
-    }
-    if (type is FunctionType) {
-      var children = <ComparisonNode>[];
-      var visitor = _AnalyzerVisitor(_typeProvider, children);
-      visitor._visitTypeParameters(type.typeFormals);
-      children.add(_translateType('Return type: ', type.returnType));
-      int positionalParameterIndex = 0;
-      for (var parameterElement in type.parameters) {
-        var kind = parameterElement.isNotOptional
-            ? 'Required'
-            : parameterElement.isOptionalPositional ? 'Optional' : 'Named';
-        var name = parameterElement.isNamed
-            ? parameterElement.name
-            : '${positionalParameterIndex++}';
-        children.add(
-            _translateType('$kind parameter $name: ', parameterElement.type));
-      }
-      return ComparisonNode.sorted('${prefix}FunctionType', children);
-    }
-    throw new UnimplementedError('_translateType: ${type.runtimeType}');
-  }
-
-  /// Visits all the nodes in [nodes].
-  void _visitList(List<AstNode> nodes) {
-    for (var astNode in nodes) {
-      astNode.accept(this);
-    }
-  }
-
-  void _visitParameters(FormalParameterList parameters) {
-    var children = <ComparisonNode>[];
-    // Note: parameters == null for getters
-    if (parameters != null) {
-      for (var parameter in parameters.parameters) {
-        var element = parameter.declaredElement;
-        var kind = element.isNotOptional
-            ? 'Required'
-            : element.isOptionalPositional ? 'Optional' : 'Named';
-        var parameterChildren = <ComparisonNode>[];
-        parameterChildren.add(_translateType('Type: ', element.type));
-        children.add(
-            ComparisonNode.sorted('$kind: ${element.name}', parameterChildren));
-      }
-    }
-    _resultNodes.add(ComparisonNode('Parameters', children));
-  }
-
-  void _visitTypedef(TypeAlias node) {
-    var children = <ComparisonNode>[];
-    var visitor = _AnalyzerVisitor(_typeProvider, children);
-    GenericTypeAliasElement element = node.declaredElement;
-    visitor._visitTypeParameters(element.typeParameters);
-    children.add(_translateType('Type: ', element.function.type));
-    _resultNodes
-        .add(ComparisonNode.sorted('Typedef ${node.name.name}', children));
-  }
-
-  void _visitTypeParameters(List<TypeParameterElement> typeParameters) {
-    for (int i = 0; i < typeParameters.length; i++) {
-      _resultNodes.add(ComparisonNode(
-          'Type parameter $i: ${typeParameters[i].name}', [
-        _translateType(
-            'Bound: ', typeParameters[i].bound ?? _typeProvider.objectType)
-      ]));
-    }
-  }
-}
diff --git a/pkg/analyzer_fe_comparison/lib/src/comparison_node.dart b/pkg/analyzer_fe_comparison/lib/src/comparison_node.dart
deleted file mode 100644
index 44ea835..0000000
--- a/pkg/analyzer_fe_comparison/lib/src/comparison_node.dart
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:math';
-
-/// [ComparisonNode] defines a simple tree structure that can be used to compare
-/// two representations of Dart code.
-///
-/// Each node contains a textual string and a list of child nodes.
-class ComparisonNode {
-  final String text;
-  final List<ComparisonNode> children;
-
-  ComparisonNode(this.text, [List<ComparisonNode> children])
-      : children = children ?? <ComparisonNode>[];
-
-  factory ComparisonNode.sorted(
-          String text, Iterable<ComparisonNode> children) =>
-      ComparisonNode(text, sortList(children));
-
-  @override
-  bool operator ==(Object other) {
-    if (other is ComparisonNode) {
-      if (text != other.text) return false;
-      if (children.length != other.children.length) return false;
-      for (int i = 0; i < children.length; i++) {
-        if (children[i] != other.children[i]) return false;
-      }
-      return true;
-    }
-    return false;
-  }
-
-  String toString({String newline: '\n'}) {
-    var lines = ['$text'];
-    var indentedNewline = '$newline  ';
-    for (var child in children) {
-      lines.add(child.toString(newline: indentedNewline));
-    }
-    return lines.join(indentedNewline);
-  }
-
-  static ComparisonNode diff(
-      ComparisonNode a, ComparisonNode b, String aName, String bName) {
-    if (a.text == b.text) {
-      return ComparisonNode(
-          a.text, diffLists(a.children, b.children, aName, bName));
-    } else {
-      return ComparisonNode('Root nodes differ',
-          [_prefix('In $aName: ', a), _prefix('In $bName: ', b)]);
-    }
-  }
-
-  static List<ComparisonNode> diffLists(List<ComparisonNode> a,
-      List<ComparisonNode> b, String aName, String bName) {
-    // Note: this is an O(n) "poor man's" diff algorithm; it produces optimal
-    // results if the incoming results are sorted by text or if there is just
-    // one contiguous hunk of differences.  Otherwise it may not find the
-    // shortest diff.  This should be sufficient for our purposes, since we are
-    // not expecting many diffs.
-
-    // We'll exclude common nodes at the beginning of both lists
-    var shorterLength = min(a.length, b.length);
-    var commonInitialNodes = 0;
-    while (commonInitialNodes < shorterLength &&
-        a[commonInitialNodes] == b[commonInitialNodes]) {
-      commonInitialNodes++;
-    }
-
-    // Fast exit if a == b
-    if (commonInitialNodes == a.length && a.length == b.length) {
-      return [];
-    }
-
-    // We'll exclude common nodes at the end of both lists (note: we don't want
-    // to overcount by re-testing the common nodes identified above)
-    var commonFinalNodes = 0;
-    while (commonInitialNodes + commonFinalNodes < shorterLength &&
-        a[a.length - commonFinalNodes - 1] ==
-            b[b.length - commonFinalNodes - 1]) {
-      commonFinalNodes++;
-    }
-
-    // Walk the remaining nodes starting at the first node that's different,
-    // matching up nodes by their text.
-    var aIndex = commonInitialNodes;
-    var bIndex = commonInitialNodes;
-    var aEnd = a.length - commonFinalNodes;
-    var bEnd = b.length - commonFinalNodes;
-    var result = <ComparisonNode>[];
-    while (aIndex < aEnd && bIndex < bEnd) {
-      var comparisonResult = a[aIndex].text.compareTo(b[bIndex].text);
-      if (comparisonResult < 0) {
-        // a[aIndex].text sorts before b[bIndex].text.  Assume that this means
-        // a[aIndex] was removed.
-        result.add(_prefix('Only in $aName: ', a[aIndex++]));
-      } else if (comparisonResult > 0) {
-        // b[bIndex].text sorts before a[aIndex].text.  Assume that this means
-        // b[bIndex] was added.
-        result.add(_prefix('Only in $bName: ', b[bIndex++]));
-      } else {
-        // a[aIndex].text matches b[bIndex].text, so diff the nodes if
-        // necessary.
-        var aNode = a[aIndex++];
-        var bNode = b[bIndex++];
-        if (aNode != bNode) {
-          result.add(diff(aNode, bNode, aName, bName));
-        }
-      }
-    }
-
-    // Deal with any nodes left over.
-    while (aIndex < aEnd) {
-      result.add(_prefix('Only in $aName: ', a[aIndex++]));
-    }
-    while (bIndex < bEnd) {
-      result.add(_prefix('Only in $bName: ', b[bIndex++]));
-    }
-
-    // If we get here and we haven't added any nodes, something has gone wrong.
-    if (result.isEmpty) {
-      throw StateError('Diff produced empty diff for non-matching lists');
-    }
-
-    return result;
-  }
-
-  static List<ComparisonNode> sortList(Iterable<ComparisonNode> nodes) {
-    var result = nodes.toList();
-    result.sort((a, b) => a.text.compareTo(b.text));
-    return result;
-  }
-
-  static ComparisonNode _prefix(String prefixString, ComparisonNode node) {
-    return ComparisonNode(prefixString + node.text, node.children);
-  }
-}
diff --git a/pkg/analyzer_fe_comparison/lib/src/kernel.dart b/pkg/analyzer_fe_comparison/lib/src/kernel.dart
deleted file mode 100644
index be9f0ad..0000000
--- a/pkg/analyzer_fe_comparison/lib/src/kernel.dart
+++ /dev/null
@@ -1,360 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
-    show DiagnosticMessage, DiagnosticMessageHandler, getMessageHeaderText;
-import 'package:analyzer_fe_comparison/src/comparison_node.dart';
-import 'package:front_end/src/api_prototype/compiler_options.dart'
-    show CompilerOptions;
-import 'package:front_end/src/api_prototype/kernel_generator.dart';
-import 'package:front_end/src/api_prototype/standard_file_system.dart';
-import 'package:kernel/ast.dart';
-import 'package:kernel/target/targets.dart';
-
-/// Compiles the given [inputs] to kernel using the front_end, and returns a
-/// [ComparisonNode] representing them.
-Future<ComparisonNode> analyzePackage(
-    List<Uri> inputs, Uri packagesFileUri, Uri platformUri) async {
-  var messages = <DiagnosticMessage>[];
-  var component = (await kernelForModule(inputs,
-          _makeCompilerOptions(packagesFileUri, platformUri, messages.add)))
-      .component;
-  if (messages.isNotEmpty) {
-    return ComparisonNode(
-        'Error occurred', messages.map(_diagnosticMessageToNode).toList());
-  }
-  var libraryNodes = <ComparisonNode>[];
-  var visitor = _KernelVisitor(libraryNodes);
-  for (var library in component.libraries) {
-    if (inputs.contains(library.importUri)) {
-      library.accept(visitor);
-    }
-  }
-  return ComparisonNode.sorted('Component', libraryNodes);
-}
-
-/// Compiles the given [input] to kernel using the front_end, and returns a
-/// [ComparisonNode] representing it.
-///
-/// Only libraries whose URI passes the [uriFilter] are included in the results.
-Future<ComparisonNode> analyzeProgram(Uri input, Uri packagesFileUri,
-    Uri platformUri, bool uriFilter(Uri uri)) async {
-  var messages = <DiagnosticMessage>[];
-  var component = (await kernelForProgram(input,
-          _makeCompilerOptions(packagesFileUri, platformUri, messages.add)))
-      .component;
-  if (messages.isNotEmpty) {
-    return ComparisonNode(
-        'Error occurred', messages.map(_diagnosticMessageToNode).toList());
-  }
-  var libraryNodes = <ComparisonNode>[];
-  var visitor = _KernelVisitor(libraryNodes);
-  for (var library in component.libraries) {
-    if (uriFilter(library.importUri)) {
-      library.accept(visitor);
-    }
-  }
-  return ComparisonNode.sorted('Component', libraryNodes);
-}
-
-ComparisonNode _diagnosticMessageToNode(DiagnosticMessage message) {
-  return ComparisonNode(getMessageHeaderText(message));
-}
-
-CompilerOptions _makeCompilerOptions(Uri packagesFileUri, Uri platformUri,
-    DiagnosticMessageHandler onDiagnostic) {
-  var targetFlags = TargetFlags();
-  var target = NoneTarget(targetFlags);
-  var fileSystem = StandardFileSystem.instance;
-
-  return CompilerOptions()
-    ..fileSystem = fileSystem
-    ..packagesFileUri = packagesFileUri
-    ..sdkSummary = platformUri
-    ..target = target
-    ..throwOnErrorsForDebugging = false
-    ..embedSourceText = false
-    ..onDiagnostic = onDiagnostic;
-}
-
-/// Visitor for serializing a kernel representation of a program into
-/// ComparisonNodes.
-///
-/// Results are accumulated into [_resultNodes].
-class _KernelVisitor extends TreeVisitor<void> {
-  final List<ComparisonNode> _resultNodes;
-
-  _KernelVisitor(this._resultNodes);
-
-  @override
-  void defaultTreeNode(TreeNode node) {
-    throw new UnimplementedError('KernelVisitor: ${node.runtimeType}');
-  }
-
-  @override
-  void visitClass(Class class_) {
-    if (class_.isAnonymousMixin) return null;
-    var kind = class_.isEnum
-        ? 'Enum'
-        : class_.isMixinApplication
-            ? 'MixinApplication'
-            : class_.isMixinDeclaration ? 'Mixin' : 'Class';
-    var children = <ComparisonNode>[];
-    var visitor = _KernelVisitor(children);
-    if (class_.isEnum) {
-      for (var field in class_.fields) {
-        if (!field.isStatic) continue;
-        if (field.name.name == 'values') continue;
-        // TODO(paulberry): handle index
-        children.add(ComparisonNode('EnumValue ${field.name.name}'));
-      }
-    } else {
-      visitor._visitTypeParameters(class_.typeParameters);
-      if (class_.supertype != null) {
-        var declaredSupertype = class_.supertype.asInterfaceType;
-        if (class_.isMixinDeclaration) {
-          var constraints = <DartType>[];
-          // Kernel represents a mixin declaration such as:
-          //   mixin M on S0, S1, S2 {...}
-          // By desugaring it to:
-          //   abstract class _M&S0&S1 implements S0, S1 {}
-          //   abstract class _M&S0&S1&S2 implements _M&S0&S1 {}
-          //   abstract class M extends M&S0&S1&S2 {...}
-          // (See dartbug.com/34783)
-          while (declaredSupertype.classNode.isAnonymousMixin) {
-            // Since we're walking up the class hierarchy, we encounter the
-            // mixins in the reverse order that they were declared, so we have
-            // to use [List.insert] to add them to [constraints].
-            constraints.insert(
-                0,
-                declaredSupertype
-                    .classNode.implementedTypes[1].asInterfaceType);
-            declaredSupertype =
-                declaredSupertype.classNode.implementedTypes[0].asInterfaceType;
-          }
-          constraints.insert(0, declaredSupertype);
-          for (int i = 0; i < constraints.length; i++) {
-            children.add(_TypeVisitor.translate('On $i: ', constraints[i]));
-          }
-        } else {
-          var mixedInTypes = <DartType>[];
-          if (class_.isMixinApplication) {
-            mixedInTypes.add(class_.mixedInType.asInterfaceType);
-          }
-          while (declaredSupertype.classNode.isAnonymousMixin) {
-            // Since we're walking from the class to its declared supertype, we
-            // encounter the mixins in the reverse order that they were declared,
-            // so we have to use [List.insert] to add them to [mixedInTypes].
-            mixedInTypes.insert(
-                0, declaredSupertype.classNode.mixedInType.asInterfaceType);
-            declaredSupertype =
-                declaredSupertype.classNode.supertype.asInterfaceType;
-          }
-          children.add(_TypeVisitor.translate('Extends: ', declaredSupertype));
-          for (int i = 0; i < mixedInTypes.length; i++) {
-            children.add(_TypeVisitor.translate('Mixin $i: ', mixedInTypes[i]));
-          }
-        }
-      }
-      for (int i = 0; i < class_.implementedTypes.length; i++) {
-        children.add(_TypeVisitor.translate(
-            'Implements $i: ', class_.implementedTypes[i].asInterfaceType));
-      }
-      visitor._visitList(class_.fields);
-      visitor._visitList(class_.constructors);
-      visitor._visitList(class_.procedures);
-    }
-    // TODO(paulberry): handle more fields from Class
-    _resultNodes.add(ComparisonNode.sorted('$kind ${class_.name}', children));
-  }
-
-  @override
-  void visitConstructor(Constructor constructor) {
-    if (constructor.isSynthetic) return null;
-    var name = constructor.name.name;
-    if (name.isEmpty) {
-      name = '(unnamed)';
-    }
-    var children = <ComparisonNode>[];
-    var visitor = _KernelVisitor(children);
-    constructor.function.accept(visitor);
-    // TODO(paulberry): handle more fields from Constructor
-    _resultNodes.add(ComparisonNode.sorted('Constructor $name', children));
-  }
-
-  @override
-  void visitField(Field field) {
-    if (field.name.name == '_redirecting#') return null;
-    if (field.name.name == '_exports#') return null;
-    var children = <ComparisonNode>[];
-    children.add(_TypeVisitor.translate('Type: ', field.type));
-    // TODO(paulberry): handle more fields from Field
-    _resultNodes
-        .add(ComparisonNode.sorted('Field ${field.name.name}', children));
-  }
-
-  @override
-  void visitFunctionNode(FunctionNode node) {
-    var parent = node.parent;
-    if (!(parent is Constructor || parent is Procedure && parent.isFactory)) {
-      _visitTypeParameters(node.typeParameters);
-      _resultNodes
-          .add(_TypeVisitor.translate('Return type: ', node.returnType));
-    }
-    var parameterChildren = <ComparisonNode>[];
-    var parameterVisitor = _KernelVisitor(parameterChildren);
-    for (int i = 0; i < node.positionalParameters.length; i++) {
-      parameterVisitor._visitParameter(node.positionalParameters[i],
-          i < node.requiredParameterCount ? 'Required' : 'Optional');
-    }
-    for (int i = 0; i < node.namedParameters.length; i++) {
-      parameterVisitor._visitParameter(node.namedParameters[i], 'Named');
-    }
-    _resultNodes.add(ComparisonNode('Parameters', parameterChildren));
-    // TODO(paulberry): handle more fields from FunctionNode
-  }
-
-  @override
-  void visitLibrary(Library library) {
-    var children = <ComparisonNode>[];
-    if (library.name != null) {
-      children.add(ComparisonNode('name=${library.name}'));
-    }
-    var visitor = _KernelVisitor(children);
-    visitor._visitList(library.typedefs);
-    visitor._visitList(library.classes);
-    visitor._visitList(library.procedures);
-    visitor._visitList(library.fields);
-    // TODO(paulberry): handle more fields from Library
-    _resultNodes
-        .add(ComparisonNode.sorted(library.importUri.toString(), children));
-  }
-
-  @override
-  void visitProcedure(Procedure procedure) {
-    if (procedure.isSyntheticForwarder) {
-      return null;
-    }
-    if (procedure.name.name.startsWith('_#loadLibrary_')) {
-      // Sometimes the front end generates procedures with this name that don't
-      // correspond to anything in the source file.  Ignore them.
-      return null;
-    }
-    // TODO(paulberry): add an annotation to the ComparisonNode when the
-    // procedure is a factory.
-    var kind = procedure.isFactory
-        ? 'Constructor'
-        : procedure.kind.toString().replaceAll('ProcedureKind.', '');
-    var name = procedure.name.name;
-    if (name.isEmpty) {
-      name = '(unnamed)';
-    }
-    var children = <ComparisonNode>[];
-    var visitor = _KernelVisitor(children);
-    procedure.function.accept(visitor);
-    // TODO(paulberry): handle more fields from Procedure
-    _resultNodes.add(ComparisonNode.sorted('$kind $name', children));
-  }
-
-  @override
-  void visitTypedef(Typedef typedef) {
-    var children = <ComparisonNode>[];
-    var visitor = _KernelVisitor(children);
-    visitor._visitTypeParameters(typedef.typeParameters);
-    children.add(_TypeVisitor.translate('Type: ', typedef.type));
-    // TODO(paulberry): handle more fields from Typedef
-    _resultNodes
-        .add(ComparisonNode.sorted('Typedef ${typedef.name}', children));
-  }
-
-  /// Visits all the nodes in [nodes].
-  void _visitList(List<TreeNode> nodes) {
-    for (var node in nodes) {
-      node.accept(this);
-    }
-  }
-
-  void _visitParameter(VariableDeclaration parameter, String kind) {
-    var children = <ComparisonNode>[];
-    children.add(_TypeVisitor.translate('Type: ', parameter.type));
-    // TODO(paulberry): handle more fields from VariableDeclaration
-    _resultNodes
-        .add(ComparisonNode.sorted('$kind: ${parameter.name}', children));
-  }
-
-  void _visitTypeParameters(List<TypeParameter> typeParameters) {
-    for (int i = 0; i < typeParameters.length; i++) {
-      _resultNodes.add(ComparisonNode(
-          'Type parameter $i: ${typeParameters[i].name}',
-          [_TypeVisitor.translate('Bound: ', typeParameters[i].bound)]));
-    }
-  }
-}
-
-/// Visitor for serializing a kernel representation of a type into
-/// ComparisonNodes.
-class _TypeVisitor extends DartTypeVisitor<ComparisonNode> {
-  /// Text to prepend to the node text.
-  String _prefix;
-
-  _TypeVisitor(this._prefix);
-
-  @override
-  ComparisonNode defaultDartType(DartType node) {
-    throw new UnimplementedError('_TypeVisitor: ${node.runtimeType}');
-  }
-
-  @override
-  ComparisonNode visitDynamicType(DynamicType node) {
-    return ComparisonNode('${_prefix}Dynamic');
-  }
-
-  @override
-  ComparisonNode visitFunctionType(FunctionType node) {
-    var children = <ComparisonNode>[];
-    var visitor = _KernelVisitor(children);
-    visitor._visitTypeParameters(node.typeParameters);
-    children.add(translate('Return type: ', node.returnType));
-    for (int i = 0; i < node.positionalParameters.length; i++) {
-      var kind = i < node.requiredParameterCount ? 'Required' : 'Optional';
-      children
-          .add(translate('$kind parameter $i: ', node.positionalParameters[i]));
-    }
-    for (var namedType in node.namedParameters) {
-      children.add(
-          translate('Named parameter ${namedType.name}: ', namedType.type));
-    }
-    return ComparisonNode.sorted('${_prefix}FunctionType', children);
-  }
-
-  @override
-  ComparisonNode visitInterfaceType(InterfaceType node) {
-    var children = <ComparisonNode>[];
-    children.add(ComparisonNode(
-        'Library: ${node.classNode.enclosingLibrary.importUri}'));
-    for (int i = 0; i < node.typeArguments.length; i++) {
-      children.add(translate('Type arg $i: ', node.typeArguments[i]));
-    }
-    return ComparisonNode(
-        '${_prefix}InterfaceType ${node.classNode.name}', children);
-  }
-
-  @override
-  ComparisonNode visitTypeParameterType(TypeParameterType node) {
-    // TODO(paulberry): disambiguate if needed.
-    return ComparisonNode(
-        '${_prefix}TypeParameterType: ${node.parameter.name}');
-  }
-
-  @override
-  ComparisonNode visitVoidType(VoidType node) {
-    return ComparisonNode('${_prefix}Void');
-  }
-
-  static ComparisonNode translate(String prefix, DartType type) {
-    return type.accept(new _TypeVisitor(prefix));
-  }
-}
diff --git a/pkg/analyzer_fe_comparison/pubspec.yaml b/pkg/analyzer_fe_comparison/pubspec.yaml
deleted file mode 100644
index fb579c8..0000000
--- a/pkg/analyzer_fe_comparison/pubspec.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-name: analyzer_fe_comparison
-publish_to: none
-author: Dart Team <misc@dartlang.org>
-description: Tool for comparing the behavior of the analyzer and the front end.
-homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_fe_comparison
-environment:
-  sdk: '>=2.0.0-dev-48.0 <3.0.0'
-dependencies:
-  kernel: ^0.3.4
diff --git a/pkg/analyzer_fe_comparison/tool/compare_packages.dart b/pkg/analyzer_fe_comparison/tool/compare_packages.dart
deleted file mode 100644
index e1a7b71..0000000
--- a/pkg/analyzer_fe_comparison/tool/compare_packages.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:io';
-
-import 'package:analyzer_fe_comparison/comparison.dart';
-import 'package:path/path.dart' as path;
-
-/// Compares the analyzer and front_end behavior when compiling a package.
-///
-/// Currently hardcoded to use the package "analyzer".
-main() async {
-  var scriptPath = Platform.script.toFilePath();
-  var sdkRepoPath =
-      path.normalize(path.join(path.dirname(scriptPath), '..', '..', '..'));
-  var buildPath = await _findBuildDir(sdkRepoPath, 'ReleaseX64');
-  var dillPath = path.join(buildPath, 'vm_platform_strong.dill');
-  var analyzerLibPath = path.join(sdkRepoPath, 'pkg', 'analyzer', 'lib');
-  var packagesFilePath = path.join(sdkRepoPath, '.packages');
-  comparePackages(dillPath, analyzerLibPath, packagesFilePath);
-}
-
-Future<String> _findBuildDir(String sdkRepoPath, String targetName) async {
-  for (var subdirName in ['out', 'xcodebuild']) {
-    var candidatePath = path.join(sdkRepoPath, subdirName, targetName);
-    if (await new Directory(candidatePath).exists()) {
-      return candidatePath;
-    }
-  }
-  throw new StateError('Cannot find build directory');
-}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index bb3a129..61368d5 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -74,15 +74,6 @@
   /// method.
   bool inStaticMethodBody = false;
 
-  /// Indicates whether the completion location is in the body of a method.
-  bool inMethodBody = false;
-
-  /// Indicates whether the completion location is in the body of a function.
-  bool inFunctionBody = false;
-
-  /// Indicates whether the completion location is in the body of a constructor.
-  bool inConstructorBody = false;
-
   /// Indicates whether the completion target is prefixed.
   bool isPrefixed = false;
 
@@ -112,16 +103,7 @@
     if (functionBody != null) {
       var parent = functionBody.parent;
 
-      if (parent is ConstructorDeclaration) {
-        optype.inConstructorBody = true;
-      }
-
-      if (parent is FunctionExpression) {
-        optype.inFunctionBody = true;
-      }
-
       if (parent is MethodDeclaration) {
-        optype.inMethodBody = true;
         optype.inStaticMethodBody = parent.isStatic;
       }
     }
@@ -164,13 +146,6 @@
       !includeReturnValueSuggestions &&
       !includeVoidReturnSuggestions;
 
-  /// Indicate whether only type names should be suggested
-  bool get includeOnlyTypeNameSuggestions =>
-      includeTypeNameSuggestions &&
-      !includeNamedArgumentSuggestions &&
-      !includeReturnValueSuggestions &&
-      !includeVoidReturnSuggestions;
-
   /// Try to determine the required context type, and configure filters.
   void _computeRequiredTypeAndFilters(CompletionTarget target) {
     Object entity = target.entity;
@@ -849,13 +824,7 @@
       // Check for named parameters in constructor calls.
       AstNode grandparent = node.parent.parent;
       if (grandparent is ConstructorReferenceNode) {
-        ConstructorElement element =
-            // TODO(paulberry): remove the unnecessary cast when we are ready to
-            // depend on a version of the analyzer that includes
-            // https://dart-review.googlesource.com/c/sdk/+/89923
-            (grandparent // ignore: unnecessary_cast
-                    as ConstructorReferenceNode)
-                .staticElement;
+        ConstructorElement element = grandparent.staticElement;
         if (element != null) {
           List<ParameterElement> parameters = element.parameters;
           ParameterElement parameterElement = parameters.firstWhere((e) {
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
index b975c97..581775c 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
@@ -23,24 +23,16 @@
 }
 
 @reflectiveTest
-// TODO: determine if tests here need to be fixed for Dart2.
 class OpTypeDart1OnlyTest extends OpTypeTestCommon {
   @failingTest
   Future<void> test_Annotation() async {
     // SimpleIdentifier  Annotation  MethodDeclaration  ClassDeclaration
     addTestSource('class C { @A^ }');
     await assertOpType(constructors: true, returnValue: true, typeNames: true);
-    // TODO(danrubel): This test fails when fasta parser is enabled
-    // because the @A is dropped from the Analyzer AST.
+    // TODO(danrubel): This test fails because the @A is dropped from the AST.
     // Ideally we generate a synthetic field and associate the annotation
     // with that field, but doing so breaks test_constructorAndMethodNameCollision.
     // See https://dart-review.googlesource.com/c/sdk/+/65760/3/pkg/analyzer/lib/src/fasta/ast_builder.dart#2395
-
-    // The old Analyzer parser passes this test, but will be turned off soon.
-    // It is preferable to throw only if the old analyzer is being used,
-    // but there does not seem to be a reliable way to determine that here.
-    // TODO(danrubel): remove this once fasta parser is enabled by default.
-    throw 'Remove this exception once fasta parser is the default';
   }
 
   Future<void> test_ArgumentList() async {
@@ -52,40 +44,27 @@
         constructors: true,
         namedArgs: true,
         returnValue: true,
-        typeNames: true,
-        functionBody: true);
+        typeNames: true);
   }
 
   Future<void> test_ArgumentList_namedParam() async {
     // SimpleIdentifier  NamedExpression  ArgumentList  MethodInvocation
     // ExpressionStatement
     addTestSource('void main() {expect(foo: ^)}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ArgumentList_prefixedIdentifier() async {
     // SimpleIdentifier  PrefixedIdentifier  ArgumentList
     addTestSource('void main() {expect(aa.^)}');
     await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        prefixed: true,
-        functionBody: true);
+        constructors: true, returnValue: true, typeNames: true, prefixed: true);
   }
 
   Future<void> test_ArgumentList_resolved() async {
     // ArgumentList  MethodInvocation  ExpressionStatement  Block
     addTestSource('void main() {int.parse(^)}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_AsIdentifier() async {
@@ -94,17 +73,12 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        methodBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Assert() async {
     addTestSource('main() {assert(^)}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_AssertInitializer() async {
@@ -116,11 +90,7 @@
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('class A {} main() {int a; int b = ^}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_AssignmentExpression_type() async {
@@ -139,8 +109,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_AssignmentExpression_type_newline() async {
@@ -158,8 +127,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_AssignmentExpression_type_partial() async {
@@ -178,8 +146,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_AssignmentExpression_type_partial_newline() async {
@@ -197,104 +164,63 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_AwaitExpression() async {
     // SimpleIdentifier  AwaitExpression  ExpressionStatement
     addTestSource('main() async {A a; await ^}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_AwaitExpression2() async {
     addTestSource('main() async {A a; await c^ await}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_AwaitExpression3() async {
     addTestSource('main() async {A a; await ^ await foo;}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_AwaitExpression4() async {
     addTestSource('main() async {A a; await ^ await bar();}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_AwaitExpression_assignment() async {
     addTestSource('main() async {A a; int x = await ^}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_AwaitExpression_assignment2() async {
     addTestSource('main() async {A a; int x = await ^ await foo;}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_AwaitExpression_assignment3() async {
     addTestSource('main() async {A a; int x = await v^ int y = await foo;}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_BinaryExpression_LHS() async {
     // SimpleIdentifier  BinaryExpression  VariableDeclaration
     // VariableDeclarationList  VariableDeclarationStatement
     addTestSource('main() {int a = 1, b = ^ + 2;}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_BinaryExpression_RHS() async {
     // SimpleIdentifier  BinaryExpression  VariableDeclaration
     // VariableDeclarationList  VariableDeclarationStatement
     addTestSource('main() {int a = 1, b = 2 + ^;}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_BinaryExpression_RHS2() async {
     // SimpleIdentifier  BinaryExpression
     addTestSource('main() {if (c < ^)}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_Block() async {
@@ -312,8 +238,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        methodBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_catch_2a() async {
@@ -323,8 +248,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_catch_2b() async {
@@ -334,8 +258,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_catch_2c() async {
@@ -345,8 +268,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_catch_2d() async {
@@ -356,8 +278,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_catch_3a() async {
@@ -367,8 +288,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_catch_3b() async {
@@ -378,8 +298,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_catch_3c() async {
@@ -389,8 +308,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_catch_3d() async {
@@ -400,8 +318,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_empty() async {
@@ -411,8 +328,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        methodBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_identifier_partial() async {
@@ -421,8 +337,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        methodBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_in_constructor() async {
@@ -431,7 +346,6 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        constructorBody: true,
         voidReturn: true);
   }
 
@@ -441,7 +355,6 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        functionBody: true,
         voidReturn: true);
   }
 
@@ -451,7 +364,6 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        methodBody: true,
         voidReturn: true);
   }
 
@@ -462,8 +374,7 @@
         prefixed: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_Block_static() async {
@@ -473,7 +384,6 @@
         returnValue: true,
         typeNames: true,
         staticMethodBody: true,
-        methodBody: true,
         voidReturn: true);
   }
 
@@ -488,8 +398,7 @@
         returnValue: true,
         typeNames: true,
         voidReturn: true,
-        prefixed: true,
-        functionBody: true);
+        prefixed: true);
   }
 
   Future<void> test_CascadeExpression_selector2() async {
@@ -499,8 +408,7 @@
         constructors: true,
         returnValue: true,
         voidReturn: true,
-        prefixed: true,
-        functionBody: true);
+        prefixed: true);
   }
 
   Future<void> test_CascadeExpression_selector2_withTrailingReturn() async {
@@ -510,8 +418,7 @@
         constructors: true,
         returnValue: true,
         voidReturn: true,
-        prefixed: true,
-        functionBody: true);
+        prefixed: true);
   }
 
   Future<void> test_CascadeExpression_target() async {
@@ -521,8 +428,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_CatchClause_typed() async {
@@ -532,8 +438,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        methodBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_CatchClause_untyped() async {
@@ -543,8 +448,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        methodBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_CommentReference() async {
@@ -561,51 +465,31 @@
   Future<void> test_ConditionalExpression_elseExpression() async {
     // SimpleIdentifier  ConditionalExpression  ReturnStatement
     addTestSource('class C {foo(){var f; {var x;} return a ? T1 : T^}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        methodBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ConditionalExpression_elseExpression_empty() async {
     // SimpleIdentifier  ConditionalExpression  ReturnStatement
     addTestSource('class C {foo(){var f; {var x;} return a ? T1 : ^}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        methodBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ConditionalExpression_partial_thenExpression() async {
     // SimpleIdentifier  ConditionalExpression  ReturnStatement
     addTestSource('class C {foo(){var f; {var x;} return a ? T^}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        methodBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ConditionalExpression_partial_thenExpression_empty() async {
     // SimpleIdentifier  ConditionalExpression  ReturnStatement
     addTestSource('class C {foo(){var f; {var x;} return a ? ^}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        methodBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ConditionalExpression_thenExpression() async {
     // SimpleIdentifier  ConditionalExpression  ReturnStatement
     addTestSource('class C {foo(){var f; {var x;} return a ? T^ : c}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        methodBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ConstructorFieldInitializer_name() async {
@@ -647,21 +531,13 @@
   Future<void> test_DoStatement() async {
     // SimpleIdentifier  DoStatement  Block
     addTestSource('main() {do{} while(^x);}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ExpressionFunctionBody() async {
     // SimpleIdentifier  ExpressionFunctionBody  FunctionExpression
     addTestSource('m(){[1].forEach((x)=>^x);}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ExpressionStatement() async {
@@ -671,18 +547,13 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_ForEachStatement() async {
     // SimpleIdentifier  ForEachStatement  Block
     addTestSource('main() {for(z in ^zs) {}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ForEachStatement_body_typed() async {
@@ -692,8 +563,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_ForEachStatement_body_untyped() async {
@@ -703,41 +573,28 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_ForEachStatement_iterable() async {
     // SimpleIdentifier  ForEachStatement  Block
     addTestSource('main(args) {for (int foo in ^) {}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ForElement_body() async {
     addTestSource('main(args) {[for (var foo in [0]) ^];}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ForElement_forEachParts_iterable() async {
     addTestSource('main(args) {[for (var foo in ^) foo];}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ForElement_forEachParts_type() async {
     addTestSource('main(args) {[for (i^ foo in [0]) foo];}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_FormalParameter_partialType() async {
@@ -776,11 +633,7 @@
   Future<void> test_ForStatement_condition() async {
     // SimpleIdentifier  ForStatement
     addTestSource('main() {for (int index = 0; i^)}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ForStatement_updaters() async {
@@ -791,18 +644,13 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_ForStatement_updaters_prefix_expression() async {
     // SimpleIdentifier  PrefixExpression  ForStatement
     addTestSource('main() {for (int index = 0; index < 10; ++i^)}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_IfElement_condition() async {
@@ -811,11 +659,7 @@
   [if (^)];
 }
 ''');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_IfElement_else() async {
@@ -828,7 +672,6 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        functionBody: true,
         voidReturn: true);
   }
 
@@ -842,7 +685,6 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        functionBody: true,
         voidReturn: true);
   }
 
@@ -853,57 +695,36 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_IfStatement_condition() async {
     // SimpleIdentifier  IfStatement  Block  BlockFunctionBody
     addTestSource('main(){var a; if (^)}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_IfStatement_empty() async {
     // SimpleIdentifier  PrefixIdentifier  IfStatement
     addTestSource('class A {foo() {A a; if (^) something}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        methodBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_IfStatement_invocation() async {
     // SimpleIdentifier  PrefixIdentifier  IfStatement
     addTestSource('main() {var a; if (a.^) something}');
     await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        prefixed: true,
-        functionBody: true);
+        constructors: true, returnValue: true, typeNames: true, prefixed: true);
   }
 
   Future<void> test_IndexExpression() async {
     addTestSource('class C {foo(){var f; {var x;} f[^]}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        methodBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_IndexExpression2() async {
     addTestSource('class C {foo(){var f; {var x;} f[T^]}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        methodBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_InstanceCreationExpression_keyword() async {
@@ -913,8 +734,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        methodBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_InstanceCreationExpression_keyword2() async {
@@ -924,76 +744,50 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        methodBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_InterpolationExpression() async {
     // SimpleIdentifier  InterpolationExpression  StringInterpolation
     addTestSource('main() {String name; print("hello \$^");}');
-    await assertOpType(
-        constructors: true, returnValue: true, functionBody: true);
+    await assertOpType(constructors: true, returnValue: true);
   }
 
   Future<void> test_InterpolationExpression_block() async {
     // SimpleIdentifier  InterpolationExpression  StringInterpolation
     addTestSource('main() {String name; print("hello \${n^}");}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_InterpolationExpression_prefix_selector() async {
     // SimpleIdentifier  PrefixedIdentifier  InterpolationExpression
     addTestSource('main() {String name; print("hello \${name.^}");}');
     await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        prefixed: true,
-        functionBody: true);
+        constructors: true, returnValue: true, typeNames: true, prefixed: true);
   }
 
   Future<void> test_InterpolationExpression_prefix_target() async {
     // SimpleIdentifier  PrefixedIdentifier  InterpolationExpression
     addTestSource('main() {String name; print("hello \${nam^e.length}");}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_IsExpression_target() async {
     // IfStatement  Block  BlockFunctionBody
     addTestSource('main(){var a; if (^ is A)}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_Literal_list() async {
     // ']'  ListLiteral  ArgumentList  MethodInvocation
     addTestSource('main() {var Some; print([^]);}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_Literal_list2() async {
     // SimpleIdentifier ListLiteral  ArgumentList  MethodInvocation
     addTestSource('main() {var Some; print([S^]);}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_MapLiteralEntry() async {
@@ -1026,18 +820,13 @@
         returnValue: true,
         typeNames: true,
         voidReturn: true,
-        prefixed: true,
-        methodBody: true);
+        prefixed: true);
   }
 
   Future<void> test_PostfixExpression() async {
     // SimpleIdentifier  PostfixExpression  ForStatement
     addTestSource('int x = 0; main() {ax+^+;}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_PrefixedIdentifier_class_const() async {
@@ -1048,8 +837,7 @@
         returnValue: true,
         typeNames: true,
         voidReturn: true,
-        prefixed: true,
-        functionBody: true);
+        prefixed: true);
   }
 
   Future<void> test_PrefixedIdentifier_class_imported() async {
@@ -1060,8 +848,7 @@
         returnValue: true,
         typeNames: true,
         voidReturn: true,
-        prefixed: true,
-        functionBody: true);
+        prefixed: true);
   }
 
   Future<void> test_PrefixedIdentifier_prefix() async {
@@ -1071,8 +858,7 @@
         constructors: true,
         typeNames: true,
         returnValue: true,
-        voidReturn: true,
-        methodBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_PropertyAccess_expression() async {
@@ -1083,8 +869,7 @@
         returnValue: true,
         typeNames: true,
         voidReturn: true,
-        prefixed: true,
-        methodBody: true);
+        prefixed: true);
   }
 
   Future<void> test_PropertyAccess_selector() async {
@@ -1095,18 +880,13 @@
         returnValue: true,
         typeNames: true,
         voidReturn: true,
-        prefixed: true,
-        methodBody: true);
+        prefixed: true);
   }
 
   Future<void> test_ReturnStatement() async {
     // ReturnStatement  Block
     addTestSource('f() { var vvv = 42; return ^ }');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_SpreadElement() async {
@@ -1115,11 +895,7 @@
   [...^];
 }
 ''');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_SwitchCase_between() async {
@@ -1129,28 +905,19 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_SwitchCase_expression1() async {
     // SimpleIdentifier  SwitchCase  SwitchStatement
     addTestSource('''m() {switch (x) {case ^D: return;}}''');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_SwitchCase_expression2() async {
     // SimpleIdentifier  SwitchCase  SwitchStatement
     addTestSource('''m() {switch (x) {case ^}}''');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_SwitchDefault_between() async {
@@ -1160,8 +927,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_SwitchStatement_body_end() async {
@@ -1171,8 +937,7 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_SwitchStatement_body_end2() async {
@@ -1181,39 +946,26 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        functionBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_SwitchStatement_expression1() async {
     // SimpleIdentifier  SwitchStatement  Block
     addTestSource('main() {switch(^k) {case 1:{}}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_SwitchStatement_expression2() async {
     // SimpleIdentifier  SwitchStatement  Block
     addTestSource('main() {switch(k^) {case 1:{}}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
 //
   Future<void> test_SwitchStatement_expression_empty() async {
     // SimpleIdentifier  SwitchStatement  Block
     addTestSource('main() {switch(^) {case 1:{}}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_ThisExpression_block() async {
@@ -1228,8 +980,7 @@
         constructors: true,
         returnValue: true,
         voidReturn: true,
-        prefixed: true,
-        methodBody: true);
+        prefixed: true);
   }
 
   Future<void> test_ThisExpression_constructor() async {
@@ -1242,18 +993,13 @@
         constructors: true,
         returnValue: true,
         voidReturn: true,
-        prefixed: true,
-        constructorBody: true);
+        prefixed: true);
   }
 
   Future<void> test_ThrowExpression() async {
     // SimpleIdentifier  ThrowExpression  ExpressionStatement
     addTestSource('main() {throw ^;}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_VariableDeclarationStatement_afterSemicolon() async {
@@ -1263,40 +1009,27 @@
         constructors: true,
         returnValue: true,
         typeNames: true,
-        voidReturn: true,
-        methodBody: true);
+        voidReturn: true);
   }
 
   Future<void> test_VariableDeclarationStatement_RHS() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement
     addTestSource('class C {bar(){var f; {var x;} var e = ^}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        methodBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_VariableDeclarationStatement_RHS_missing_semicolon() async {
     // VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement
     addTestSource('class C {bar(){var f; {var x;} var e = ^ var g}}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        methodBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   Future<void> test_WhileStatement() async {
     // SimpleIdentifier  WhileStatement  Block
     addTestSource('mth() { while (b^) {} }}');
-    await assertOpType(
-        constructors: true,
-        returnValue: true,
-        typeNames: true,
-        functionBody: true);
+    await assertOpType(constructors: true, returnValue: true, typeNames: true);
   }
 
   @failingTest
@@ -1315,7 +1048,7 @@
       'main() { new A.b(^); }'
       'class A{ A.b({one, two}) {} }',
     );
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_ArgumentList_constructor_named_resolved_1_1() async {
@@ -1324,7 +1057,7 @@
       'main() { new A.b(o^); }'
       'class A { A.b({one, two}) {} }',
     );
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_ArgumentList_constructor_resolved_1_0() async {
@@ -1333,7 +1066,7 @@
       'main() { new A(^); }'
       'class A{ A({one, two}) {} }',
     );
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_ArgumentList_constructor_resolved_1_1() async {
@@ -1342,7 +1075,7 @@
       'main() { new A(o^); }'
       'class A { A({one, two}) {} }',
     );
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_ArgumentList_factory_named_resolved_1_0() async {
@@ -1351,7 +1084,7 @@
       'main() { new A.b(^); }'
       'class A{ factory A.b({one, two}) {} }',
     );
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_ArgumentList_factory_named_resolved_1_1() async {
@@ -1360,7 +1093,7 @@
       'main() { new A.b(o^); }'
       'class A { factory A.b({one, two}) {} }',
     );
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_ArgumentList_factory_resolved_1_0() async {
@@ -1369,7 +1102,7 @@
       'main() { new A(^); }'
       'class A{ factory A({one, two}) {} }',
     );
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_ArgumentList_factory_resolved_1_1() async {
@@ -1378,163 +1111,163 @@
       'main() { new A(o^); }'
       'class A { factory A({one, two}) {} }',
     );
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_ArgumentList_method_resolved_1_0() async {
     // ArgumentList  MethodInvocation  ExpressionStatement  Block
     addTestSource('main() { foo(^);} foo({one, two}) {}');
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_ArgumentList_method_resolved_1_1() async {
     // ArgumentList  MethodInvocation  ExpressionStatement  Block
     addTestSource('main() { foo(o^);} foo({one, two}) {}');
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_ArgumentList_resolved_2_0() async {
     // ArgumentList  MethodInvocation  ExpressionStatement  Block
     addTestSource('void main() {int.parse("16", ^)}');
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_AsExpression() async {
     // SimpleIdentifier  TypeName  AsExpression
     addTestSource('class A {var b; X _c; foo() {var a; (a as ^).foo();}');
-    await assertOpType(typeNames: true, methodBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_AsIdentifier2() async {
     addTestSource('class A {var asdf; foo() {A as^}');
-    await assertOpType(methodBody: true);
+    await assertOpType();
   }
 
   Future<void> test_AssignmentExpression_name() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('class A {} main() {int a; int ^b = 1;}');
-    await assertOpType(varNames: true, functionBody: true);
+    await assertOpType(varNames: true);
   }
 
   Future<void> test_Block_catch_1a() async {
     // '}'  Block  BlockFunctionBody  FunctionExpression
     addTestSource('main() {try {} ^}');
     // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_Block_catch_1b() async {
     // [ExpressionStatement 'c']  Block  BlockFunctionBody
     addTestSource('main() {try {} c^}');
     // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_Block_catch_1c() async {
     // [EmptyStatement]  Block  BlockFunctionBody  FunctionExpression
     addTestSource('main() {try {} ^;}');
     // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_Block_catch_1d() async {
     // [VariableDeclarationStatement 'Foo foo']  Block  BlockFunctionBody
     addTestSource('main() {try {} ^ Foo foo;}');
     // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_Block_final() async {
     addTestSource('main() {final ^}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_Block_final2() async {
     addTestSource('main() {final S^ v;}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_Block_final3() async {
     addTestSource('main() {final ^ v;}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_Block_final_final() async {
     addTestSource('main() {final ^ final S x;}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_Block_final_final2() async {
     addTestSource('main() {final S^ final S x;}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_Break_after_label() async {
     addTestSource('main() { foo: while (true) { break foo ^ ; } }');
-    await assertOpType(/* No valid completions */ functionBody: true);
+    await assertOpType(/* No valid completions */);
   }
 
   Future<void> test_Break_before_label() async {
     addTestSource('main() { foo: while (true) { break ^ foo; } }');
-    await assertOpType(statementLabel: true, functionBody: true);
+    await assertOpType(statementLabel: true);
   }
 
   Future<void> test_Break_no_label() async {
     addTestSource('main() { foo: while (true) { break ^; } }');
-    await assertOpType(statementLabel: true, functionBody: true);
+    await assertOpType(statementLabel: true);
   }
 
   Future<void> test_catch_4a1() async {
     addTestSource('main() {try {} ^ on SomeException {}}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_catch_4a2() async {
     addTestSource('main() {try {} c^ on SomeException {}}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_catch_4b1() async {
     addTestSource('main() {try {} ^ catch (e) {}}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_catch_4b2() async {
     addTestSource('main() {try {} c^ catch (e) {}}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_catch_4c1() async {
     addTestSource('main() {try {} ^ finally {}}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_catch_4c2() async {
     addTestSource('main() {try {} c^ finally {}}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_catch_5a() async {
     addTestSource('main() {try {} on ^ finally {}}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_catch_5b() async {
     addTestSource('main() {try {} on E^ finally {}}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_CatchClause_onType() async {
     // TypeName  CatchClause  TryStatement
     addTestSource('class A {a() {try{var x;} on ^ {}}}');
-    await assertOpType(typeNames: true, methodBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_CatchClause_onType_noBrackets() async {
     // TypeName  CatchClause  TryStatement
     addTestSource('class A {a() {try{var x;} on ^}}');
-    await assertOpType(typeNames: true, methodBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_ClassDeclaration_body() async {
@@ -1570,14 +1303,14 @@
     // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
     // InstanceCreationExpression
     addTestSource('main() {new X.^}');
-    await assertOpType(constructors: true, prefixed: true, functionBody: true);
+    await assertOpType(constructors: true, prefixed: true);
   }
 
   Future<void> test_ConstructorName_name_resolved() async {
     // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
     // InstanceCreationExpression
     addTestSource('main() {new Str^ing.fromCharCodes([]);}');
-    await assertOpType(constructors: true, functionBody: true);
+    await assertOpType(constructors: true);
   }
 
   Future<void> test_ConstructorName_nameAndPrefix_resolved() async {
@@ -1587,68 +1320,65 @@
 import 'dart:core' as core;
 main() {new core.String.from^CharCodes([]);}
 ''');
-    await assertOpType(constructors: true, prefixed: true, functionBody: true);
+    await assertOpType(constructors: true, prefixed: true);
   }
 
   Future<void> test_ConstructorName_resolved() async {
     // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
     // InstanceCreationExpression
     addTestSource('main() {new String.fr^omCharCodes([]);}');
-    await assertOpType(constructors: true, prefixed: true, functionBody: true);
+    await assertOpType(constructors: true, prefixed: true);
   }
 
   Future<void> test_ConstructorName_unresolved() async {
     // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
     // InstanceCreationExpression
     addTestSource('main() {new String.fr^omCharCodes([]);}');
-    await assertOpType(constructors: true, prefixed: true, functionBody: true);
+    await assertOpType(constructors: true, prefixed: true);
   }
 
   Future<void> test_Continue_after_label() async {
     addTestSource('main() { foo: while (true) { continue foo ^ ; } }');
-    await assertOpType(/* No valid completions */ functionBody: true);
+    await assertOpType(/* No valid completions */);
   }
 
   Future<void> test_Continue_before_label() async {
     addTestSource('main() { foo: while (true) { continue ^ foo; } }');
-    await assertOpType(
-        statementLabel: true, caseLabel: true, functionBody: true);
+    await assertOpType(statementLabel: true, caseLabel: true);
   }
 
   Future<void> test_Continue_no_label() async {
     addTestSource('main() { foo: while (true) { continue ^; } }');
-    await assertOpType(
-        statementLabel: true, caseLabel: true, functionBody: true);
+    await assertOpType(statementLabel: true, caseLabel: true);
   }
 
   Future<void> test_DoubleLiteral() async {
     addTestSource('main() { print(1.2^); }');
-    // TODO expected functionBody: true
-    await assertOpType(functionBody: false);
+    await assertOpType();
   }
 
   Future<void> test_ExpressionStatement_name() async {
     // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
     addTestSource('class C {a() {C ^}}');
-    await assertOpType(varNames: true, methodBody: true);
+    await assertOpType(varNames: true);
   }
 
   Future<void> test_ExpressionStatement_name_semicolon() async {
     // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
     addTestSource('class C {a() {C ^;}}');
-    await assertOpType(varNames: true, methodBody: true);
+    await assertOpType(varNames: true);
   }
 
   Future<void> test_ExpressionStatement_prefixed_name() async {
     // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
     addTestSource('class C {a() {x.Y ^}}');
-    await assertOpType(varNames: true, methodBody: true);
+    await assertOpType(varNames: true);
   }
 
   Future<void> test_ExpressionStatement_prefixed_name_semicolon() async {
     // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
     addTestSource('class C {a() {x.Y ^;}}');
-    await assertOpType(varNames: true, methodBody: true);
+    await assertOpType(varNames: true);
   }
 
   Future<void> test_ExtendsClause() async {
@@ -1674,31 +1404,31 @@
   Future<void> test_ForEachStatement_loopVariable() async {
     // SimpleIdentifier  ForEachStatement  Block
     addTestSource('main(args) {for (^ in args) {}}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_ForEachStatement_loopVariable_name() async {
     // DeclaredIdentifier  ForEachStatement  Block
     addTestSource('main(args) {for (String ^ in args) {}}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_ForEachStatement_loopVariable_name2() async {
     // DeclaredIdentifier  ForEachStatement  Block
     addTestSource('main(args) {for (String f^ in args) {}}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_ForEachStatement_loopVariable_type() async {
     // SimpleIdentifier  ForEachStatement  Block
     addTestSource('main(args) {for (^ foo in args) {}}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_ForEachStatement_loopVariable_type2() async {
     // DeclaredIdentifier  ForEachStatement  Block
     addTestSource('main(args) {for (S^ foo in args) {}}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_FormalParameterList() async {
@@ -1710,24 +1440,24 @@
   Future<void> test_ForStatement_initializer() async {
     // SimpleIdentifier  ForStatement
     addTestSource('main() {List a; for (^)}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_ForStatement_initializer_inKeyword() async {
     addTestSource('main() { for (var v i^) }');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_ForStatement_initializer_type() async {
     // SimpleIdentifier  ForStatement
     addTestSource('main() {List a; for (i^ v = 0;)}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void>
       test_ForStatement_initializer_variableNameEmpty_afterType() async {
     addTestSource('main() { for (String ^) }');
-    await assertOpType(varNames: true, functionBody: true);
+    await assertOpType(varNames: true);
   }
 
   Future<void> test_FunctionDeclaration1() async {
@@ -1890,7 +1620,7 @@
   Future<void> test_FunctionExpressionInvocation() async {
     // ArgumentList  FunctionExpressionInvocation  ExpressionStatement
     addTestSource('main() { ((x) => x + 7)^(2) }');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_FunctionTypeAlias() async {
@@ -1916,43 +1646,41 @@
   Future<void> test_InstanceCreationExpression() async {
     // SimpleIdentifier  TypeName  ConstructorName  InstanceCreationExpression
     addTestSource('class C {foo(){var f; {var x;} new ^}}');
-    await assertOpType(constructors: true, methodBody: true);
+    await assertOpType(constructors: true);
   }
 
   Future<void> test_InstanceCreationExpression_trailingStmt() async {
     // SimpleIdentifier  TypeName  ConstructorName  InstanceCreationExpression
     addTestSource('class C {foo(){var f; {var x;} new ^ int x = 7;}}');
-    await assertOpType(constructors: true, methodBody: true);
+    await assertOpType(constructors: true);
   }
 
   Future<void> test_IntegerLiteral_inArgumentList() async {
-    // TODO expected functionBody: true
     addTestSource('main() { print(1^); }');
-    await assertOpType(functionBody: false);
+    await assertOpType();
   }
 
   Future<void> test_IntegerLiteral_inListLiteral() async {
-    // TODO expected functionBody: true
     addTestSource('main() { var items = [1^]; }');
-    await assertOpType(functionBody: false);
+    await assertOpType();
   }
 
   Future<void> test_IsExpression() async {
     // SimpleIdentifier  TypeName  IsExpression  IfStatement
     addTestSource('main() {var x; if (x is ^) { }}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_IsExpression_type_partial() async {
     // SimpleIdentifier  TypeName  IsExpression  IfStatement
     addTestSource('main(){var a; if (a is Obj^)}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_Literal_string() async {
     // SimpleStringLiteral  ExpressionStatement  Block
     addTestSource('class A {a() {"hel^lo"}}');
-    await assertOpType(methodBody: true);
+    await assertOpType();
   }
 
   Future<void> test_MethodDeclaration_inClass1() async {
@@ -2147,7 +1875,7 @@
 main() { f(3, ^); }
 void f(int a, {int b}) {}
 ''');
-    await assertOpType(namedArgs: true, functionBody: true);
+    await assertOpType(namedArgs: true);
   }
 
   Future<void> test_OnClause() async {
@@ -2159,25 +1887,25 @@
   Future<void> test_PropertyAccess_noTarget() async {
     // SimpleIdentifier  PropertyAccess  ExpressionStatement
     addTestSource('main() {.^}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_PropertyAccess_noTarget2() async {
     // SimpleIdentifier  PropertyAccess  CascadeExpressions
     addTestSource('main() {.^.}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_PropertyAccess_noTarget3() async {
     // SimpleIdentifier  PropertyAccess  CascadeExpressions
     addTestSource('main() {..^}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_SimpleFormalParameter_closure() async {
     // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
     addTestSource('mth() { PNGS.sort((String a, Str^) => a.compareTo(b)); }');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_SimpleFormalParameter_name_typed() async {
@@ -2249,19 +1977,19 @@
   Future<void> test_SwitchCase_before() async {
     // SwitchCase  SwitchStatement  Block
     addTestSource('main() {switch(k) {^case 1:}}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_SwitchDefault_before() async {
     // SwitchDefault  SwitchStatement  Block
     addTestSource('main() {switch(k) { ^ default: return;}}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_SwitchStatement_body_empty() async {
     // Token('}')  SwitchStatement  Block
     addTestSource('main() {switch(k) {^}}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_ThisExpression_constructor_param() async {
@@ -2328,13 +2056,13 @@
   Future<void> test_TypeArgumentList() async {
     // SimpleIdentifier  BinaryExpression  ExpressionStatement
     addTestSource('main() { C<^> c; }');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_TypeArgumentList2() async {
     // TypeName  TypeArgumentList  TypeName
     addTestSource('main() { C<C^> c; }');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 
   Future<void> test_TypeParameter() async {
@@ -2353,27 +2081,27 @@
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('main() {var ^}');
-    await assertOpType(functionBody: true);
+    await assertOpType();
   }
 
   Future<void> test_VariableDeclaration_name_hasSome_parameterizedType() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('main() {List<int> m^}');
-    await assertOpType(varNames: true, functionBody: true);
+    await assertOpType(varNames: true);
   }
 
   Future<void> test_VariableDeclaration_name_hasSome_simpleType() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
     addTestSource('main() {String m^}');
-    await assertOpType(varNames: true, functionBody: true);
+    await assertOpType(varNames: true);
   }
 
   Future<void> test_VariableDeclarationList_final() async {
     // VariableDeclarationList  VariableDeclarationStatement  Block
     addTestSource('main() {final ^}');
-    await assertOpType(typeNames: true, functionBody: true);
+    await assertOpType(typeNames: true);
   }
 }
 
@@ -2401,9 +2129,6 @@
       bool returnValue = false,
       bool statementLabel = false,
       bool staticMethodBody = false,
-      bool methodBody = false,
-      bool functionBody = false,
-      bool constructorBody = false,
       bool typeNames = false,
       bool varNames = false,
       bool voidReturn = false,
@@ -2430,10 +2155,6 @@
         reason: 'voidReturn');
     expect(visitor.inStaticMethodBody, staticMethodBody,
         reason: 'staticMethodBody');
-    expect(visitor.inMethodBody, methodBody, reason: 'methodBody');
-    expect(visitor.inFunctionBody, functionBody, reason: 'functionBody');
-    expect(visitor.inConstructorBody, constructorBody,
-        reason: 'constructorBody');
     expect(visitor.isPrefixed, prefixed, reason: 'prefixed');
     expect(visitor.suggestKind, kind, reason: 'suggestion kind');
   }
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 2a882d5..4f3613f 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -1165,9 +1165,29 @@
       subscription.pause();
       exitCode = 0;
       if (line == null) exit(0);
-      List<String> args = <String>[];
-      args.addAll(batchArguments);
-      args.addAll(splitLine(line, windows: Platform.isWindows));
+      List<String> testArgs = splitLine(line, windows: Platform.isWindows);
+
+      // Merge experiment flags from the batch and the test arguments.
+      //
+      // Batch arguments are provided when the batch compiler is created, and
+      // contain flags that are generally enabled for all tests. Tests
+      // may have more specific flags that could conflict with the batch flags.
+      // For example, the compiler might be setup to run the non-nullable
+      // experiment, but the test may enable more experiments.
+      //
+      // At this time we are only aware of these kind of conflicts with
+      // experiment flags, so we handle those directly. We know that if the
+      // batch compiler has an experiment flag, the test itself will
+      // have it too (either identical or more accurate when the test requires
+      // additional experiments).
+      bool hasExperiment(List<String> list) =>
+          list.any((a) => a.startsWith('--enable-experiment'));
+      assert(!hasExperiment(batchArguments) || hasExperiment(testArgs));
+      List<String> args = [
+        for (var arg in batchArguments)
+          if (!arg.startsWith('--enable-experiment')) arg,
+        ...testArgs,
+      ];
       return internalMain(args,
           kernelInitializedCompilerState: kernelInitializedCompilerState);
     }).catchError((exception, trace) {
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 7083e91..3c49a8c 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -314,10 +314,10 @@
           DartType type = typeUse.type;
           switch (typeUse.kind) {
             case TypeUseKind.TYPE_LITERAL:
-              if (type is InterfaceType) {
-                InterfaceType interface = type;
+              var typeWithoutNullability = type.withoutNullability;
+              if (typeWithoutNullability is InterfaceType) {
                 dependencies.addClass(
-                    interface.element, typeUse.deferredImport);
+                    typeWithoutNullability.element, typeUse.deferredImport);
               }
               break;
             case TypeUseKind.CONST_INSTANTIATION:
@@ -395,6 +395,7 @@
       }
       if (constant is InstantiationConstantValue) {
         for (DartType type in constant.typeArguments) {
+          type = type.withoutNullability;
           if (type is InterfaceType) {
             _updateClassRecursive(
                 closedWorld, type.element, oldSet, newSet, queue);
@@ -549,7 +550,7 @@
       LibraryEntity library, Spannable context) {
     if (info.isDeferred || compiler.options.newDeferredSplit) return;
     if (constant is TypeConstantValue) {
-      var type = constant.representedType;
+      var type = constant.representedType.withoutNullability;
       if (type is InterfaceType) {
         var imports = classImportsTo(type.element, library);
         _fixDependencyInfo(
@@ -1465,7 +1466,10 @@
   /// Returns the [OutputUnit] where [constant] belongs.
   OutputUnit outputUnitForConstant(ConstantValue constant) {
     if (!isProgramSplit) return mainOutputUnit;
-    return _constantToUnit[constant];
+    OutputUnit unit = _constantToUnit[constant];
+    // TODO(sigmund): enforce unit is not null: it is sometimes null on some
+    // corner cases on internal apps.
+    return unit ?? mainOutputUnit;
   }
 
   OutputUnit outputUnitForConstantForTesting(ConstantValue constant) =>
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 94e3f0a..669f45e 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -388,7 +388,8 @@
 
     void addProcedure(ir.Procedure member,
         {bool includeStatic, bool includeNoSuchMethodForwarders}) {
-      if (member.isForwardingStub && member.isAbstract) {
+      if ((member.isMemberSignature || member.isForwardingStub) &&
+          member.isAbstract) {
         // Skip abstract forwarding stubs. These are never emitted but they
         // might shadow the inclusion of a mixed in method in code like:
         //
@@ -403,7 +404,8 @@
         // `Mixin.method` is inherited by `Class`.
         return;
       }
-      if (member.isForwardingStub && cls.isAnonymousMixin) {
+      if ((member.isMemberSignature || member.isForwardingStub) &&
+          cls.isAnonymousMixin) {
         return;
       }
       if (!includeStatic && member.isStatic) return;
diff --git a/pkg/dart2native/pubspec.yaml b/pkg/dart2native/pubspec.yaml
index 99e6f94..feca449 100644
--- a/pkg/dart2native/pubspec.yaml
+++ b/pkg/dart2native/pubspec.yaml
@@ -1,8 +1,5 @@
 name: dart2native
-version: 0.0.1
-author: Dart Team <misc@dartlang.org>
-homepage: https://github.com/dart-lang/sdk/tree/master/pkg/aot
-
+publish_to: none
 
 # Add the bin/dart2native.dart script to the scripts pub installs.
 executables:
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index e36af94..7317c59 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -2577,7 +2577,14 @@
     if (typeArgument is InterfaceType &&
         typeArgument.classNode == _coreTypes.objectClass) {
       // Normalize FutureOr of Object, Object?, Object*.
-      normalizedType = typeArgument;
+      var nullable = futureOr.nullability == Nullability.nullable ||
+          typeArgument.nullability == Nullability.nullable;
+      var legacy = futureOr.nullability == Nullability.legacy ||
+          typeArgument.nullability == Nullability.legacy;
+      var nullability = nullable
+          ? Nullability.nullable
+          : legacy ? Nullability.legacy : Nullability.nonNullable;
+      normalizedType = typeArgument.withNullability(nullability);
     } else if (typeArgument is NeverType) {
       // FutureOr<Never> --> Future<Never>
       normalizedType = InterfaceType(
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index 3a3084c..cb9e036 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -594,10 +594,6 @@
     Expect.throws(f, (error) => error is AssertionError, reason);
   }
 
-  static void throwsCastError(void f(), [String reason = "CastError"]) {
-    Expect.throws(f, (error) => error is CastError, reason);
-  }
-
   static void throwsFormatException(void f(),
       [String reason = "FormatException"]) {
     Expect.throws(f, (error) => error is FormatException, reason);
@@ -707,10 +703,10 @@
   final String name;
 
   ExpectException(this.message)
-      : name = (_getTestName == null) ? null : _getTestName();
+      : name = (_getTestName == null) ? "" : _getTestName();
 
   String toString() {
-    if (name != null) return 'In test "$name" $message';
+    if (name != "") return 'In test "$name" $message';
     return message;
   }
 }
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index b0cacef..a65e500 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -512,7 +512,7 @@
   /// If the file does exist but is invalid an error is always reported and an
   /// empty package config is returned.
   Future<PackageConfig> _createPackagesFromFile(
-      Uri requestedUri, bool forceCreation) async {
+      Uri requestedUri, bool forceCreation, bool requireJson) async {
     Uint8List contents = await _readFile(requestedUri, forceCreation);
     if (contents == null) {
       if (forceCreation) {
@@ -524,14 +524,7 @@
 
     _packagesUri = requestedUri;
     try {
-      return await loadPackageConfigUri(requestedUri, preferNewest: false,
-          loader: (uri) {
-        if (uri != requestedUri) {
-          throw new StateError(
-              "Unexpected request from package config package");
-        }
-        return new Future.value(contents);
-      }, onError: (Object error) {
+      void Function(Object error) onError = (Object error) {
         if (error is FormatException) {
           report(
               templatePackagesFileFormat
@@ -543,7 +536,19 @@
               templateCantReadFile.withArguments(requestedUri, "$error"),
               Severity.error);
         }
-      });
+      };
+      if (requireJson) {
+        return PackageConfig.parseBytes(contents, requestedUri,
+            onError: onError);
+      }
+      return await loadPackageConfigUri(requestedUri, preferNewest: false,
+          loader: (uri) {
+        if (uri != requestedUri) {
+          throw new StateError(
+              "Unexpected request from package config package");
+        }
+        return new Future.value(contents);
+      }, onError: onError);
     } on FormatException catch (e) {
       report(
           templatePackagesFileFormat
@@ -566,16 +571,17 @@
   /// (relative to the .packages file) `package_config.json` file exists, the
   /// `package_config.json` file will be used instead.
   Future<PackageConfig> createPackagesFromFile(Uri file) async {
-    if (file.path.endsWith("/.dart_tool/package_config.json")) {
-      // Already a package config json file.
-      return _createPackagesFromFile(file, true);
-    } else {
+    // If the input is a ".packages" file we assume the standard layout, and
+    // if a ".dart_tool/package_config.json" exists, we'll use that (and require
+    // it to be a json file).
+    if (file.path.endsWith("/.packages")) {
       // .packages -> try the package_config first.
       Uri tryFirst = file.resolve(".dart_tool/package_config.json");
-      PackageConfig result = await _createPackagesFromFile(tryFirst, false);
+      PackageConfig result =
+          await _createPackagesFromFile(tryFirst, false, true);
       if (result != null) return result;
-      return await _createPackagesFromFile(file, true);
     }
+    return _createPackagesFromFile(file, true, false);
   }
 
   /// Finds a package resolution strategy using a [FileSystem].
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 df4c39b..02883c3 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -8,6 +8,7 @@
 
 import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/core_types.dart';
+import 'package:kernel/src/future_or.dart';
 import 'package:kernel/src/legacy_erasure.dart';
 
 import '../constant_context.dart' show ConstantContext;
@@ -774,7 +775,7 @@
       if (_lateSetter != null) {
         _lateSetter.function.positionalParameters.single.type = value;
       }
-      if (!_type.isPotentiallyNullable && !_forceIncludeIsSetField) {
+      if (!isPotentiallyNullable(_type, null) && !_forceIncludeIsSetField) {
         // We only need the is-set field if the field is potentially nullable.
         //  Otherwise we use `null` to signal that the field is uninitialized.
         _lateIsSetField = null;
@@ -934,7 +935,8 @@
   Statement _createSetterBody(
       CoreTypes coreTypes, String name, VariableDeclaration parameter) {
     assert(_type != null, "Type has not been computed for field $name.");
-    return late_lowering.createSetterBody(fileOffset, name, parameter, _type,
+    return late_lowering.createSetterBody(
+        coreTypes, fileOffset, name, parameter, _type,
         shouldReturnValue: false,
         createVariableWrite: (Expression value) =>
             _createFieldSet(_field, value),
@@ -989,7 +991,7 @@
       CoreTypes coreTypes, String name, Expression initializer) {
     assert(_type != null, "Type has not been computed for field $name.");
     return late_lowering.createGetterWithInitializer(
-        fileOffset, name, _type, initializer,
+        coreTypes, fileOffset, name, _type, initializer,
         createVariableRead: _createFieldRead,
         createVariableWrite: (Expression value) =>
             _createFieldSet(_field, value),
diff --git a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
index 521e537..027d8c3 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
@@ -74,13 +74,15 @@
   FunctionType build(LibraryBuilder library,
       [TypedefType origin, bool notInstanceContext]) {
     DartType builtReturnType =
-        returnType?.build(library) ?? const DynamicType();
+        returnType?.build(library, null, notInstanceContext) ??
+            const DynamicType();
     List<DartType> positionalParameters = <DartType>[];
     List<NamedType> namedParameters;
     int requiredParameterCount = 0;
     if (formals != null) {
       for (FormalParameterBuilder formal in formals) {
-        DartType type = formal.type?.build(library) ?? const DynamicType();
+        DartType type = formal.type?.build(library, null, notInstanceContext) ??
+            const DynamicType();
         if (formal.isPositional) {
           positionalParameters.add(type);
           if (formal.isRequired) requiredParameterCount++;
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 7cadadf..b3f2461 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -5764,8 +5764,10 @@
       if (!isDeclarationInstanceContext &&
           (typeParameter.parent is Class ||
               typeParameter.parent is Extension)) {
-        message = fasta.messageTypeVariableInStaticContext
-            .withLocation(fileUri, charOffset, typeParameter.name.length);
+        message = fasta.messageTypeVariableInStaticContext.withLocation(
+            builder.fileUri ?? fileUri,
+            builder.charOffset ?? charOffset,
+            typeParameter.name.length);
       } else if (constantContext == ConstantContext.inferred) {
         message = fasta.messageTypeVariableInConstantContext
             .withLocation(fileUri, charOffset, typeParameter.name.length);
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index be297da..a5d05ad 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -2943,7 +2943,7 @@
       }
     }
     return new NamedTypeBuilder(
-        targetName, nullabilityBuilder, argumentBuilders)
+        targetName, nullabilityBuilder, argumentBuilders, _uri, fileOffset)
       ..bind(declaration);
   }
 
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 60fa08e..9cf058f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -2347,7 +2347,8 @@
     if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
       if (receiverType is! DynamicType &&
           receiverType is! InvalidType &&
-          receiverType.isPotentiallyNullable) {
+          isPotentiallyNullable(
+              receiverType, inferrer.coreTypes.futureOrClass)) {
         if (inferrer.nnbdMode == NnbdMode.Weak) {
           inferrer.helper.addProblem(
               templateNullableExpressionCallWarning.withArguments(
@@ -3587,7 +3588,8 @@
       }
     }
     if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
-      if (leftType is! DynamicType && leftType.isPotentiallyNullable) {
+      if (leftType is! DynamicType &&
+          isPotentiallyNullable(leftType, inferrer.coreTypes.futureOrClass)) {
         if (inferrer.nnbdMode == NnbdMode.Weak) {
           inferrer.helper.addProblem(
               templateNullableOperatorCallWarning.withArguments(
@@ -3675,7 +3677,8 @@
     }
     if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
       if (expressionType is! DynamicType &&
-          expressionType.isPotentiallyNullable) {
+          isPotentiallyNullable(
+              expressionType, inferrer.coreTypes.futureOrClass)) {
         // TODO(johnniwinther): Special case 'unary-' in messages. It should
         // probably be referred to as "Unary operator '-' ...".
         if (inferrer.nnbdMode == NnbdMode.Weak) {
@@ -3755,7 +3758,8 @@
     if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
       if (receiverType is! DynamicType &&
           receiverType is! InvalidType &&
-          receiverType.isPotentiallyNullable) {
+          isPotentiallyNullable(
+              receiverType, inferrer.coreTypes.futureOrClass)) {
         if (inferrer.nnbdMode == NnbdMode.Weak) {
           inferrer.helper.addProblem(
               templateNullableOperatorCallWarning.withArguments(
@@ -3815,7 +3819,9 @@
         ..fileOffset = fileOffset;
     }
     if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
-      if (receiverType is! DynamicType && receiverType.isPotentiallyNullable) {
+      if (receiverType is! DynamicType &&
+          isPotentiallyNullable(
+              receiverType, inferrer.coreTypes.futureOrClass)) {
         if (inferrer.nnbdMode == NnbdMode.Weak) {
           inferrer.helper.addProblem(
               templateNullableOperatorCallWarning.withArguments(
@@ -3937,7 +3943,8 @@
     if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
       if (receiverType is! DynamicType &&
           receiverType is! InvalidType &&
-          receiverType.isPotentiallyNullable &&
+          isPotentiallyNullable(
+              receiverType, inferrer.coreTypes.futureOrClass) &&
           !inferrer.matchesObjectMemberCall(
               propertyName, const [], const [], const [])) {
         if (inferrer.nnbdMode == NnbdMode.Weak) {
@@ -4020,7 +4027,9 @@
         ..fileOffset = fileOffset;
     }
     if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
-      if (receiverType is! DynamicType && receiverType.isPotentiallyNullable) {
+      if (receiverType is! DynamicType &&
+          isPotentiallyNullable(
+              receiverType, inferrer.coreTypes.futureOrClass)) {
         if (inferrer.nnbdMode == NnbdMode.Weak) {
           inferrer.helper.addProblem(
               templateNullablePropertyAccessWarning.withArguments(
@@ -5409,7 +5418,7 @@
       result.add(node);
 
       VariableDeclaration isSetVariable;
-      if (node.type.isPotentiallyNullable) {
+      if (isPotentiallyNullable(node.type, inferrer.coreTypes.futureOrClass)) {
         isSetVariable = new VariableDeclaration('#${node.name}#isSet',
             initializer: new BoolLiteral(false)..fileOffset = fileOffset,
             type: inferrer.coreTypes.boolRawType(inferrer.library.nonNullable))
@@ -5446,7 +5455,11 @@
                       createVariableRead: createVariableRead,
                       createIsSetRead: createIsSetRead)
                   : late_lowering.createGetterWithInitializer(
-                      fileOffset, node.name, node.type, node.initializer,
+                      inferrer.coreTypes,
+                      fileOffset,
+                      node.name,
+                      node.type,
+                      node.initializer,
                       createVariableRead: createVariableRead,
                       createVariableWrite: createVariableWrite,
                       createIsSetRead: createIsSetRead,
@@ -5481,7 +5494,7 @@
                             createVariableWrite: createVariableWrite,
                             createIsSetRead: createIsSetRead,
                             createIsSetWrite: createIsSetWrite)
-                        : late_lowering.createSetterBody(
+                        : late_lowering.createSetterBody(inferrer.coreTypes,
                             fileOffset, node.name, setterParameter, node.type,
                             shouldReturnValue: true,
                             createVariableWrite: createVariableWrite,
@@ -5776,7 +5789,9 @@
   void reportNonNullableInNullAwareWarningIfNeeded(
       DartType operandType, String operationName, int offset) {
     if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
-      if (operandType is! InvalidType && !operandType.isPotentiallyNullable) {
+      if (operandType is! InvalidType &&
+          !isPotentiallyNullable(
+              operandType, inferrer.coreTypes.futureOrClass)) {
         inferrer.library.addProblem(
             templateNonNullableInNullAware.withArguments(
                 operationName, operandType, inferrer.isNonNullableByDefault),
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 171e1fd..51904ae 100644
--- a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
@@ -4,6 +4,7 @@
 
 import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/core_types.dart';
+import 'package:kernel/src/future_or.dart';
 
 import '../names.dart';
 
@@ -15,13 +16,13 @@
 /// uses [createGetterWithInitializerWithRecheck] instead. Late final locals
 /// cannot have writes during initialization since they are not in scope in
 /// their own initializer.
-Statement createGetterWithInitializer(
-    int fileOffset, String name, DartType type, Expression initializer,
+Statement createGetterWithInitializer(CoreTypes coreTypes, int fileOffset,
+    String name, DartType type, Expression initializer,
     {Expression createVariableRead({bool needsPromotion}),
     Expression createVariableWrite(Expression value),
     Expression createIsSetRead(),
     Expression createIsSetWrite(Expression value)}) {
-  if (type.isPotentiallyNullable) {
+  if (isPotentiallyNullable(type, coreTypes.futureOrClass)) {
     // Generate:
     //
     //    if (!_#isSet#field) {
@@ -48,7 +49,9 @@
           // If [type] is a type variable with undetermined nullability we need
           // to create a read of the field that is promoted to the type variable
           // type.
-          createVariableRead(needsPromotion: type.isPotentiallyNonNullable))
+          createVariableRead(
+              needsPromotion:
+                  isPotentiallyNonNullable(type, coreTypes.futureOrClass)))
         ..fileOffset = fileOffset
     ])
       ..fileOffset = fileOffset;
@@ -113,7 +116,7 @@
   VariableDeclaration temp =
       new VariableDeclaration.forValue(initializer, type: type)
         ..fileOffset = fileOffset;
-  if (type.isPotentiallyNullable) {
+  if (isPotentiallyNullable(type, coreTypes.futureOrClass)) {
     // Generate:
     //
     //    if (!_#isSet#field) {
@@ -150,7 +153,9 @@
           // If [type] is a type variable with undetermined nullability we need
           // to create a read of the field that is promoted to the type variable
           // type.
-          createVariableRead(needsPromotion: type.isPotentiallyNonNullable))
+          createVariableRead(
+              needsPromotion:
+                  isPotentiallyNonNullable(type, coreTypes.futureOrClass)))
         ..fileOffset = fileOffset
     ])
       ..fileOffset = fileOffset;
@@ -218,14 +223,16 @@
         ..fileOffset = fileOffset)
     ..fileOffset = fileOffset)
     ..fileOffset = fileOffset;
-  if (type.isPotentiallyNullable) {
+  if (isPotentiallyNullable(type, coreTypes.futureOrClass)) {
     // Generate:
     //
     //    return _#isSet#field ? _#field : throw '...';
     return new ReturnStatement(
         new ConditionalExpression(
             createIsSetRead()..fileOffset = fileOffset,
-            createVariableRead(needsPromotion: type.isPotentiallyNonNullable)
+            createVariableRead(
+                needsPromotion:
+                    isPotentiallyNonNullable(type, coreTypes.futureOrClass))
               ..fileOffset = fileOffset,
             exception,
             type)
@@ -262,8 +269,8 @@
 
 /// Creates the body for the synthesized setter used to encode the lowering
 /// of a non-final late field or local.
-Statement createSetterBody(
-    int fileOffset, String name, VariableDeclaration parameter, DartType type,
+Statement createSetterBody(CoreTypes coreTypes, int fileOffset, String name,
+    VariableDeclaration parameter, DartType type,
     {bool shouldReturnValue,
     Expression createVariableWrite(Expression value),
     Expression createIsSetWrite(Expression value)}) {
@@ -279,7 +286,7 @@
       createVariableWrite(new VariableGet(parameter)..fileOffset = fileOffset)
         ..fileOffset = fileOffset);
 
-  if (type.isPotentiallyNullable) {
+  if (isPotentiallyNullable(type, coreTypes.futureOrClass)) {
     // Generate:
     //
     //    _#isSet#field = true;
@@ -335,7 +342,7 @@
     }
   }
 
-  if (type.isPotentiallyNullable) {
+  if (isPotentiallyNullable(type, coreTypes.futureOrClass)) {
     // Generate:
     //
     //    if (_#isSet#field) {
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index c823d27..b3b0a5f 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -1073,6 +1073,7 @@
         }
       }
     });
+    ticker.logMs("Build outline expressions");
   }
 
   void buildClassHierarchy(
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart b/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart
index d2dbbc0..c9e3fe2 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart
@@ -55,45 +55,64 @@
 }
 
 /// Returns [type] in which all promoted type variables have been replace with
-/// their unpromoted equivalents, and, if [library] is non-nullable by default,
-/// replaces all legacy types with their non-nullable equivalents.
+/// their unpromoted equivalents, and where all nullabilities have been
+/// normalized to the default nullability of [library].
+///
+/// If [library] is non-nullable by default all legacy types have been replaced
+/// with non-nullable types. Otherwise all non-legacy types have been replaced
+/// with legacy types.
 DartType demoteTypeInLibrary(DartType type, Library library) {
   if (library.isNonNullableByDefault) {
-    return type.accept(const _DemotionNonNullification()) ?? type;
+    return type.accept(const _DemotionNullabilityNormalization(
+            demoteTypeVariables: true, forNonNullableByDefault: true)) ??
+        type;
   } else {
-    return type
-            .accept(const _DemotionNonNullification(nonNullifyTypes: false)) ??
+    return type.accept(const _DemotionNullabilityNormalization(
+            demoteTypeVariables: true, forNonNullableByDefault: false)) ??
         type;
   }
 }
 
-/// Returns [type] in which all legacy types have been replaced with
-/// non-nullable types.
-DartType nonNullifyInLibrary(DartType type, Library library) {
+/// Returns [type] normalized to the default nullability of [library].
+///
+/// If [library] is non-nullable by default all legacy types have been replaced
+/// with non-nullable types. Otherwise all non-legacy types have been replaced
+/// with legacy types.
+DartType normalizeNullabilityInLibrary(DartType type, Library library) {
   if (library.isNonNullableByDefault) {
-    return type.accept(
-            const _DemotionNonNullification(demoteTypeVariables: false)) ??
+    return type.accept(const _DemotionNullabilityNormalization(
+            demoteTypeVariables: false, forNonNullableByDefault: true)) ??
+        type;
+  } else {
+    return type.accept(const _DemotionNullabilityNormalization(
+            demoteTypeVariables: false, forNonNullableByDefault: false)) ??
         type;
   }
-  return type;
 }
 
 /// Visitor that replaces all promoted type variables the type variable itself
-/// and/or replaces all legacy types with non-nullable types.
+/// and normalizes the type nullabilities.
 ///
 /// The visitor returns `null` if the type wasn't changed.
-class _DemotionNonNullification extends ReplacementVisitor {
+class _DemotionNullabilityNormalization extends ReplacementVisitor {
   final bool demoteTypeVariables;
-  final bool nonNullifyTypes;
+  final bool forNonNullableByDefault;
 
-  const _DemotionNonNullification(
-      {this.demoteTypeVariables: true, this.nonNullifyTypes: true})
-      : assert(demoteTypeVariables || nonNullifyTypes);
+  const _DemotionNullabilityNormalization(
+      {this.demoteTypeVariables, this.forNonNullableByDefault})
+      : assert(demoteTypeVariables != null),
+        assert(forNonNullableByDefault != null);
 
   @override
   Nullability visitNullability(DartType node) {
-    if (nonNullifyTypes && node.nullability == Nullability.legacy) {
-      return Nullability.nonNullable;
+    if (forNonNullableByDefault) {
+      if (node.nullability == Nullability.legacy) {
+        return Nullability.nonNullable;
+      }
+    } else {
+      if (node.nullability != Nullability.legacy) {
+        return Nullability.legacy;
+      }
     }
     return null;
   }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 3a83aa2..cdb7703 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -945,7 +945,8 @@
       if (callMember is Procedure && callMember.kind == ProcedureKind.Method) {
         if (_shouldTearOffCall(contextType, expressionType)) {
           needsTearoff = true;
-          if (isStrongNullabilityMode && expressionType.isPotentiallyNullable) {
+          if (isStrongNullabilityMode &&
+              isPotentiallyNullable(expressionType, coreTypes.futureOrClass)) {
             return AssignabilityKind.unassignableCantTearoff;
           }
           expressionType =
@@ -1898,7 +1899,7 @@
       return const DynamicType();
     }
     if (forSyntheticVariable) {
-      return nonNullifyInLibrary(initializerType, library.library);
+      return normalizeNullabilityInLibrary(initializerType, library.library);
     } else {
       return demoteTypeInLibrary(initializerType, library.library);
     }
@@ -2424,7 +2425,7 @@
     if (isNonNullableByDefault && performNnbdChecks) {
       if (receiverType != null &&
           receiverType is! DynamicType &&
-          receiverType.isPotentiallyNullable &&
+          isPotentiallyNullable(receiverType, coreTypes.futureOrClass) &&
           !matchesObjectMemberCall(targetName, inferredTypes,
               positionalArgumentTypes, namedArgumentTypes)) {
         // Use length 1 for .call -- in most cases its name is skipped.
diff --git a/pkg/front_end/lib/src/testing/compiler_common.dart b/pkg/front_end/lib/src/testing/compiler_common.dart
index e47eb41..0f698a84 100644
--- a/pkg/front_end/lib/src/testing/compiler_common.dart
+++ b/pkg/front_end/lib/src/testing/compiler_common.dart
@@ -105,8 +105,10 @@
   options
     ..verify = true
     ..fileSystem = new HybridFileSystem(fs)
-    ..additionalDills = additionalDills.map(toTestUri).toList()
-    ..packagesFileUri = toTestUri('.packages');
+    ..additionalDills = additionalDills.map(toTestUri).toList();
+  if (options.packagesFileUri == null) {
+    options.packagesFileUri = toTestUri('.packages');
+  }
 
   if (options.sdkSummary == null) {
     options.sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
diff --git a/pkg/front_end/lib/src/testing/id_testing_helper.dart b/pkg/front_end/lib/src/testing/id_testing_helper.dart
index 17be137..b106164 100644
--- a/pkg/front_end/lib/src/testing/id_testing_helper.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_helper.dart
@@ -51,7 +51,7 @@
       this.librariesSpecificationUri,
       this.compileSdk: false});
 
-  void customizeCompilerOptions(CompilerOptions options) {}
+  void customizeCompilerOptions(CompilerOptions options, TestData testData) {}
 }
 
 // TODO(johnniwinther): Support annotations for compile-time errors.
@@ -293,7 +293,7 @@
       options.compileSdk = config.compileSdk;
     }
   }
-  config.customizeCompilerOptions(options);
+  config.customizeCompilerOptions(options, testData);
   InternalCompilerResult compilerResult = await compileScript(
       testData.memorySourceFiles,
       options: options,
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 8b833caa..edbf467 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -814,9 +814,10 @@
     - "class C { final covariant f = 5; }"
 
 FinalAndCovariantLateWithInitializer:
+  index: 101
   template: "Members marked 'late' with an initializer can't be declared to be both 'final' and 'covariant'."
   tip: "Try removing either the 'final' or 'covariant' keyword, or removing the initializer."
-  analyzerCode: ParserErrorCode.FINAL_AND_COVARIANT
+  analyzerCode: ParserErrorCode.FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER
   # Weak and strong doesn't matter in this instance.
   configuration: nnbd-strong
   script:
diff --git a/pkg/front_end/parser_testcases/error_recovery/await_not_in_async.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/await_not_in_async.dart.intertwined.expect
index 44432d6..afe1750 100644
--- a/pkg/front_end/parser_testcases/error_recovery/await_not_in_async.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/await_not_in_async.dart.intertwined.expect
@@ -89,12 +89,14 @@
             parseStatementX({)
               inPlainSync()
               looksLikeAwaitExpression({)
+                looksLikeExpression(await)
               parseExpressionStatement({)
                 parseExpression({)
                   parsePrecedenceExpression({, 1, true)
                     parseUnaryExpression({, true)
                       inPlainSync()
                       looksLikeAwaitExpression({)
+                        looksLikeExpression(await)
                       parseAwaitExpression({, true)
                         listener: beginAwaitExpression(await)
                         parsePrecedenceExpression(await, 16, true)
diff --git a/pkg/front_end/parser_testcases/error_recovery/yield_not_in_generator.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/yield_not_in_generator.dart.intertwined.expect
index 25d0a2e..ccafa7e 100644
--- a/pkg/front_end/parser_testcases/error_recovery/yield_not_in_generator.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/yield_not_in_generator.dart.intertwined.expect
@@ -100,6 +100,8 @@
           notEofOrValue(}, yield)
           parseStatement({)
             parseStatementX({)
+              looksLikeYieldStatement({)
+                looksLikeExpression(yield)
               parseYieldStatement({)
                 listener: beginYieldStatement(yield)
                 parseExpression(yield)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_case_01.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_case_01.dart.intertwined.expect
index 9f44e64..11cef0c 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_case_01.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_case_01.dart.intertwined.expect
@@ -64,65 +64,64 @@
                               parseArgumentsOpt(b)
                                 listener: handleNoArguments(?)
                               listener: handleSend(b, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(b, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(c)
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                      parseArgumentsOpt(d)
-                        parseConditionalExpressionRest(b)
-                          listener: beginConditionalExpression(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  listener: handleNoTypeArguments([)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                  listener: handleIdentifier(c, expression)
-                                                listener: handleNoTypeArguments(])
-                                                parseArgumentsOpt(c)
-                                                  listener: handleNoArguments(])
-                                                listener: handleSend(c, ])
-                                    listener: handleLiteralList(1, [, null, ])
-                          ensureColon(])
-                          listener: handleConditionalExpressionColon()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                        listener: handleIdentifier(d, expression)
-                                      listener: handleNoTypeArguments(:)
-                                      parseArgumentsOpt(d)
-                                        listener: handleNoArguments(:)
-                                      listener: handleSend(d, :)
-                          listener: endConditionalExpression(?, :)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(c)
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                    parseArgumentsOpt(d)
+                      parseConditionalExpressionRest(b)
+                        listener: beginConditionalExpression(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                listener: handleNoTypeArguments([)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                                listener: handleIdentifier(c, expression)
+                                              listener: handleNoTypeArguments(])
+                                              parseArgumentsOpt(c)
+                                                listener: handleNoArguments(])
+                                              listener: handleSend(c, ])
+                                  listener: handleLiteralList(1, [, null, ])
+                        ensureColon(])
+                        listener: handleConditionalExpressionColon()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(d, expression)
+                                    listener: handleNoTypeArguments(:)
+                                    parseArgumentsOpt(d)
+                                      listener: handleNoArguments(:)
+                                    listener: handleSend(d, :)
+                        listener: endConditionalExpression(?, :)
                   ensureColon(d)
                   listener: endCaseExpression(:)
                   listener: handleCaseMatch(case, :)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_case_02.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_case_02.dart.intertwined.expect
index bad7824..193d377 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_case_02.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_case_02.dart.intertwined.expect
@@ -64,56 +64,55 @@
                               parseArgumentsOpt(b)
                                 listener: handleNoArguments(?)
                               listener: handleSend(b, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(b, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(c)
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseLiteralSetOrMapSuffix(:, null)
-                                    parseExpression({)
-                                      parsePrecedenceExpression({, 1, true)
-                                        parseUnaryExpression({, true)
-                                          parsePrimary({, expression)
-                                            parseLiteralSetOrMapSuffix({, null)
-                                              parseExpression({)
-                                                parsePrecedenceExpression({, 1, true)
-                                                  parseUnaryExpression({, true)
-                                                    parsePrimary({, expression)
-                                                      inPlainSync()
-                                                      parseSend({, expression)
-                                                        ensureIdentifier({, expression)
-                                                          reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-                                                          rewriter()
-                                                        parseArgumentsOpt()
-                                              reportRecoverableError(break, Message[ExpectedButGot, Expected '}' before this., null, {string: }}])
-                        parseArgumentOrIndexStar(b, Instance of 'NoTypeParamOrArg', true)
-                          parseExpression([)
-                            parsePrecedenceExpression([, 1, true)
-                              parseUnaryExpression([, true)
-                                parsePrimary([, expression)
-                                  parseSendOrFunctionLiteral([, expression)
-                                    parseSend([, expression)
-                                      ensureIdentifier([, expression)
-                                        listener: handleIdentifier(c, expression)
-                                      listener: handleNoTypeArguments(])
-                                      parseArgumentsOpt(c)
-                                        listener: handleNoArguments(])
-                                      listener: handleSend(c, ])
-                          listener: handleIndexedExpression(?, [, ])
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(c)
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseLiteralSetOrMapSuffix(:, null)
+                                  parseExpression({)
+                                    parsePrecedenceExpression({, 1, true)
+                                      parseUnaryExpression({, true)
+                                        parsePrimary({, expression)
+                                          parseLiteralSetOrMapSuffix({, null)
+                                            parseExpression({)
+                                              parsePrecedenceExpression({, 1, true)
+                                                parseUnaryExpression({, true)
+                                                  parsePrimary({, expression)
+                                                    inPlainSync()
+                                                    parseSend({, expression)
+                                                      ensureIdentifier({, expression)
+                                                        reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
+                                                        rewriter()
+                                                      parseArgumentsOpt()
+                                            reportRecoverableError(break, Message[ExpectedButGot, Expected '}' before this., null, {string: }}])
+                      parseArgumentOrIndexStar(b, Instance of 'NoTypeParamOrArg', true)
+                        parseExpression([)
+                          parsePrecedenceExpression([, 1, true)
+                            parseUnaryExpression([, true)
+                              parsePrimary([, expression)
+                                parseSendOrFunctionLiteral([, expression)
+                                  parseSend([, expression)
+                                    ensureIdentifier([, expression)
+                                      listener: handleIdentifier(c, expression)
+                                    listener: handleNoTypeArguments(])
+                                    parseArgumentsOpt(c)
+                                      listener: handleNoArguments(])
+                                    listener: handleSend(c, ])
+                        listener: handleIndexedExpression(?, [, ])
                   ensureColon(])
                   listener: endCaseExpression(:)
                   listener: handleCaseMatch(case, :)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_case_03.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_case_03.dart.intertwined.expect
index cb93b62..dd08234 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_case_03.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_case_03.dart.intertwined.expect
@@ -64,56 +64,55 @@
                               parseArgumentsOpt(x)
                                 listener: handleNoArguments(?)
                               listener: handleSend(x, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(x, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseLiteralInt([)
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                      parseArgumentsOpt(baz)
-                        parseConditionalExpressionRest(x)
-                          listener: beginConditionalExpression(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  listener: handleNoTypeArguments([)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseLiteralInt([)
-                                              listener: handleLiteralInt(4)
-                                    listener: handleLiteralList(1, [, null, ])
-                          ensureColon(])
-                          listener: handleConditionalExpressionColon()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                        listener: handleIdentifier(baz, expression)
-                                      listener: handleNoTypeArguments(:)
-                                      parseArgumentsOpt(baz)
-                                        listener: handleNoArguments(:)
-                                      listener: handleSend(baz, :)
-                          listener: endConditionalExpression(?, :)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseLiteralInt([)
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                    parseArgumentsOpt(baz)
+                      parseConditionalExpressionRest(x)
+                        listener: beginConditionalExpression(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                listener: handleNoTypeArguments([)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseLiteralInt([)
+                                            listener: handleLiteralInt(4)
+                                  listener: handleLiteralList(1, [, null, ])
+                        ensureColon(])
+                        listener: handleConditionalExpressionColon()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(baz, expression)
+                                    listener: handleNoTypeArguments(:)
+                                    parseArgumentsOpt(baz)
+                                      listener: handleNoArguments(:)
+                                    listener: handleSend(baz, :)
+                        listener: endConditionalExpression(?, :)
                   ensureColon(baz)
                   listener: endCaseExpression(:)
                   listener: handleCaseMatch(case, :)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_case_04.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_case_04.dart.intertwined.expect
index b402784..9e05db0 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_case_04.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_case_04.dart.intertwined.expect
@@ -64,83 +64,82 @@
                               parseArgumentsOpt(x)
                                 listener: handleNoArguments(?)
                               listener: handleSend(x, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(x, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseLiteralInt([)
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseLiteralSetOrMapSuffix(:, null)
-                                    parseExpression({)
-                                      parsePrecedenceExpression({, 1, true)
-                                        parseUnaryExpression({, true)
-                                          parsePrimary({, expression)
-                                            parseLiteralSetOrMapSuffix({, null)
-                                              parseExpression({)
-                                                parsePrecedenceExpression({, 1, true)
-                                                  parseUnaryExpression({, true)
-                                                    parsePrimary({, expression)
-                                                      parseLiteralSetOrMapSuffix({, null)
-                                                        parseExpression({)
-                                                          parsePrecedenceExpression({, 1, true)
-                                                            parseUnaryExpression({, true)
-                                                              parsePrimary({, expression)
-                                                                parseLiteralInt({)
-                        parseConditionalExpressionRest(x)
-                          listener: beginConditionalExpression(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  listener: handleNoTypeArguments([)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseLiteralInt([)
-                                              listener: handleLiteralInt(4)
-                                    listener: handleLiteralList(1, [, null, ])
-                          ensureColon(])
-                          listener: handleConditionalExpressionColon()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  listener: handleNoTypeArguments({)
-                                  parseLiteralSetOrMapSuffix(:, null)
-                                    parseExpression({)
-                                      parsePrecedenceExpression({, 1, true)
-                                        parseUnaryExpression({, true)
-                                          parsePrimary({, expression)
-                                            listener: handleNoTypeArguments({)
-                                            parseLiteralSetOrMapSuffix({, null)
-                                              parseExpression({)
-                                                parsePrecedenceExpression({, 1, true)
-                                                  parseUnaryExpression({, true)
-                                                    parsePrimary({, expression)
-                                                      listener: handleNoTypeArguments({)
-                                                      parseLiteralSetOrMapSuffix({, null)
-                                                        parseExpression({)
-                                                          parsePrecedenceExpression({, 1, true)
-                                                            parseUnaryExpression({, true)
-                                                              parsePrimary({, expression)
-                                                                parseLiteralInt({)
-                                                                  listener: handleLiteralInt(2)
-                                                        listener: handleLiteralSetOrMap(1, {, null, }, true)
-                                              listener: handleLiteralSetOrMap(1, {, null, }, true)
-                                    listener: handleLiteralSetOrMap(1, {, null, }, true)
-                          listener: endConditionalExpression(?, :)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseLiteralInt([)
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseLiteralSetOrMapSuffix(:, null)
+                                  parseExpression({)
+                                    parsePrecedenceExpression({, 1, true)
+                                      parseUnaryExpression({, true)
+                                        parsePrimary({, expression)
+                                          parseLiteralSetOrMapSuffix({, null)
+                                            parseExpression({)
+                                              parsePrecedenceExpression({, 1, true)
+                                                parseUnaryExpression({, true)
+                                                  parsePrimary({, expression)
+                                                    parseLiteralSetOrMapSuffix({, null)
+                                                      parseExpression({)
+                                                        parsePrecedenceExpression({, 1, true)
+                                                          parseUnaryExpression({, true)
+                                                            parsePrimary({, expression)
+                                                              parseLiteralInt({)
+                      parseConditionalExpressionRest(x)
+                        listener: beginConditionalExpression(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                listener: handleNoTypeArguments([)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseLiteralInt([)
+                                            listener: handleLiteralInt(4)
+                                  listener: handleLiteralList(1, [, null, ])
+                        ensureColon(])
+                        listener: handleConditionalExpressionColon()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                listener: handleNoTypeArguments({)
+                                parseLiteralSetOrMapSuffix(:, null)
+                                  parseExpression({)
+                                    parsePrecedenceExpression({, 1, true)
+                                      parseUnaryExpression({, true)
+                                        parsePrimary({, expression)
+                                          listener: handleNoTypeArguments({)
+                                          parseLiteralSetOrMapSuffix({, null)
+                                            parseExpression({)
+                                              parsePrecedenceExpression({, 1, true)
+                                                parseUnaryExpression({, true)
+                                                  parsePrimary({, expression)
+                                                    listener: handleNoTypeArguments({)
+                                                    parseLiteralSetOrMapSuffix({, null)
+                                                      parseExpression({)
+                                                        parsePrecedenceExpression({, 1, true)
+                                                          parseUnaryExpression({, true)
+                                                            parsePrimary({, expression)
+                                                              parseLiteralInt({)
+                                                                listener: handleLiteralInt(2)
+                                                      listener: handleLiteralSetOrMap(1, {, null, }, true)
+                                            listener: handleLiteralSetOrMap(1, {, null, }, true)
+                                  listener: handleLiteralSetOrMap(1, {, null, }, true)
+                        listener: endConditionalExpression(?, :)
                   ensureColon(})
                     rewriteAndRecover(}, Message[ExpectedButGot, Expected ':' before this., null, {string: :}], :)
                       reportRecoverableError(;, Message[ExpectedButGot, Expected ':' before this., null, {string: :}])
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_case_05.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_case_05.dart.intertwined.expect
index d64328e..ac93388 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_case_05.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_case_05.dart.intertwined.expect
@@ -64,47 +64,46 @@
                               parseArgumentsOpt(x)
                                 listener: handleNoArguments(?)
                               listener: handleSend(x, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(x, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseLiteralInt([)
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseLiteralSetOrMapSuffix(:, null)
-                                    parseExpression({)
-                                      parsePrecedenceExpression({, 1, true)
-                                        parseUnaryExpression({, true)
-                                          parsePrimary({, expression)
-                                            parseLiteralSetOrMapSuffix({, null)
-                                              parseExpression({)
-                                                parsePrecedenceExpression({, 1, true)
-                                                  parseUnaryExpression({, true)
-                                                    parsePrimary({, expression)
-                                                      parseLiteralSetOrMapSuffix({, null)
-                                                        parseExpression({)
-                                                          parsePrecedenceExpression({, 1, true)
-                                                            parseUnaryExpression({, true)
-                                                              parsePrimary({, expression)
-                                                                parseLiteralInt({)
-                                                        reportRecoverableError(;, Message[ExpectedButGot, Expected '}' before this., null, {string: }}])
-                        parseArgumentOrIndexStar(x, Instance of 'NoTypeParamOrArg', true)
-                          parseExpression([)
-                            parsePrecedenceExpression([, 1, true)
-                              parseUnaryExpression([, true)
-                                parsePrimary([, expression)
-                                  parseLiteralInt([)
-                                    listener: handleLiteralInt(4)
-                          listener: handleIndexedExpression(?, [, ])
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseLiteralInt([)
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseLiteralSetOrMapSuffix(:, null)
+                                  parseExpression({)
+                                    parsePrecedenceExpression({, 1, true)
+                                      parseUnaryExpression({, true)
+                                        parsePrimary({, expression)
+                                          parseLiteralSetOrMapSuffix({, null)
+                                            parseExpression({)
+                                              parsePrecedenceExpression({, 1, true)
+                                                parseUnaryExpression({, true)
+                                                  parsePrimary({, expression)
+                                                    parseLiteralSetOrMapSuffix({, null)
+                                                      parseExpression({)
+                                                        parsePrecedenceExpression({, 1, true)
+                                                          parseUnaryExpression({, true)
+                                                            parsePrimary({, expression)
+                                                              parseLiteralInt({)
+                                                      reportRecoverableError(;, Message[ExpectedButGot, Expected '}' before this., null, {string: }}])
+                      parseArgumentOrIndexStar(x, Instance of 'NoTypeParamOrArg', true)
+                        parseExpression([)
+                          parsePrecedenceExpression([, 1, true)
+                            parseUnaryExpression([, true)
+                              parsePrimary([, expression)
+                                parseLiteralInt([)
+                                  listener: handleLiteralInt(4)
+                        listener: handleIndexedExpression(?, [, ])
                   ensureColon(])
                   listener: endCaseExpression(:)
                   listener: handleCaseMatch(case, :)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_conditional.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_conditional.dart.intertwined.expect
index b9e60d7..7d4e907 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_conditional.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_conditional.dart.intertwined.expect
@@ -76,65 +76,64 @@
                               parseArgumentsOpt(a)
                                 listener: handleNoArguments(?)
                               listener: handleSend(a, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(b)
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                      parseArgumentsOpt(c)
-                        parseConditionalExpressionRest(a)
-                          listener: beginConditionalExpression(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  listener: handleNoTypeArguments([)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                  listener: handleIdentifier(b, expression)
-                                                listener: handleNoTypeArguments(])
-                                                parseArgumentsOpt(b)
-                                                  listener: handleNoArguments(])
-                                                listener: handleSend(b, ])
-                                    listener: handleLiteralList(1, [, null, ])
-                          ensureColon(])
-                          listener: handleConditionalExpressionColon()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                        listener: handleIdentifier(c, expression)
-                                      listener: handleNoTypeArguments(;)
-                                      parseArgumentsOpt(c)
-                                        listener: handleNoArguments(;)
-                                      listener: handleSend(c, ;)
-                          listener: endConditionalExpression(?, :)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(b)
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                    parseArgumentsOpt(c)
+                      parseConditionalExpressionRest(a)
+                        listener: beginConditionalExpression(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                listener: handleNoTypeArguments([)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                                listener: handleIdentifier(b, expression)
+                                              listener: handleNoTypeArguments(])
+                                              parseArgumentsOpt(b)
+                                                listener: handleNoArguments(])
+                                              listener: handleSend(b, ])
+                                  listener: handleLiteralList(1, [, null, ])
+                        ensureColon(])
+                        listener: handleConditionalExpressionColon()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(c, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(c)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(c, ;)
+                        listener: endConditionalExpression(?, :)
                   ensureSemicolon(c)
                   listener: handleExpressionStatement(;)
           notEofOrValue(}, a)
@@ -155,65 +154,64 @@
                               parseArgumentsOpt(a)
                                 listener: handleNoArguments(?)
                               listener: handleSend(a, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(b)
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                      parseArgumentsOpt(c)
-                        parseConditionalExpressionRest(a)
-                          listener: beginConditionalExpression(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  listener: handleNoTypeArguments([)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                  listener: handleIdentifier(b, expression)
-                                                listener: handleNoTypeArguments(])
-                                                parseArgumentsOpt(b)
-                                                  listener: handleNoArguments(])
-                                                listener: handleSend(b, ])
-                                    listener: handleLiteralList(1, [, null, ])
-                          ensureColon(])
-                          listener: handleConditionalExpressionColon()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                        listener: handleIdentifier(c, expression)
-                                      listener: handleNoTypeArguments(;)
-                                      parseArgumentsOpt(c)
-                                        listener: handleNoArguments(;)
-                                      listener: handleSend(c, ;)
-                          listener: endConditionalExpression(?, :)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(b)
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                    parseArgumentsOpt(c)
+                      parseConditionalExpressionRest(a)
+                        listener: beginConditionalExpression(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                listener: handleNoTypeArguments([)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                                listener: handleIdentifier(b, expression)
+                                              listener: handleNoTypeArguments(])
+                                              parseArgumentsOpt(b)
+                                                listener: handleNoArguments(])
+                                              listener: handleSend(b, ])
+                                  listener: handleLiteralList(1, [, null, ])
+                        ensureColon(])
+                        listener: handleConditionalExpressionColon()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(c, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(c)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(c, ;)
+                        listener: endConditionalExpression(?, :)
                   ensureSemicolon(c)
                   listener: handleExpressionStatement(;)
           notEofOrValue(}, a)
@@ -234,87 +232,86 @@
                               parseArgumentsOpt(a)
                                 listener: handleNoArguments(?)
                               listener: handleSend(a, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(b)
-                              parsePrimary(., expressionContinuation)
-                                parseSendOrFunctionLiteral(., expressionContinuation)
-                                  looksLikeFunctionBody(:)
-                                  parseSend(., expressionContinuation)
-                                    ensureIdentifier(., expressionContinuation)
-                                    parseArgumentsOpt(toString)
-                                      parseArguments(toString)
-                                        parseArgumentsRest(()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                      parseArgumentsOpt(c)
-                        parseConditionalExpressionRest(a)
-                          listener: beginConditionalExpression(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  listener: handleNoTypeArguments([)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                  listener: handleIdentifier(b, expression)
-                                                listener: handleNoTypeArguments(])
-                                                parseArgumentsOpt(b)
-                                                  listener: handleNoArguments(])
-                                                listener: handleSend(b, ])
-                                    listener: handleLiteralList(1, [, null, ])
-                              parsePrimary(., expressionContinuation)
-                                parseSendOrFunctionLiteral(., expressionContinuation)
-                                  looksLikeFunctionBody(:)
-                                  parseSend(., expressionContinuation)
-                                    ensureIdentifier(., expressionContinuation)
-                                      listener: handleIdentifier(toString, expressionContinuation)
-                                    listener: handleNoTypeArguments(()
-                                    parseArgumentsOpt(toString)
-                                      parseArguments(toString)
-                                        parseArgumentsRest(()
-                                          listener: beginArguments(()
-                                          listener: endArguments(0, (, ))
-                                    listener: handleSend(toString, :)
-                              listener: endBinaryExpression(.)
-                          ensureColon())
-                          listener: handleConditionalExpressionColon()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                        listener: handleIdentifier(c, expression)
-                                      listener: handleNoTypeArguments(;)
-                                      parseArgumentsOpt(c)
-                                        listener: handleNoArguments(;)
-                                      listener: handleSend(c, ;)
-                          listener: endConditionalExpression(?, :)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(b)
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                looksLikeFunctionBody(:)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                  parseArgumentsOpt(toString)
+                                    parseArguments(toString)
+                                      parseArgumentsRest(()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                    parseArgumentsOpt(c)
+                      parseConditionalExpressionRest(a)
+                        listener: beginConditionalExpression(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                listener: handleNoTypeArguments([)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                                listener: handleIdentifier(b, expression)
+                                              listener: handleNoTypeArguments(])
+                                              parseArgumentsOpt(b)
+                                                listener: handleNoArguments(])
+                                              listener: handleSend(b, ])
+                                  listener: handleLiteralList(1, [, null, ])
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                looksLikeFunctionBody(:)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                    listener: handleIdentifier(toString, expressionContinuation)
+                                  listener: handleNoTypeArguments(()
+                                  parseArgumentsOpt(toString)
+                                    parseArguments(toString)
+                                      parseArgumentsRest(()
+                                        listener: beginArguments(()
+                                        listener: endArguments(0, (, ))
+                                  listener: handleSend(toString, :)
+                            listener: endBinaryExpression(.)
+                        ensureColon())
+                        listener: handleConditionalExpressionColon()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(c, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(c)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(c, ;)
+                        listener: endConditionalExpression(?, :)
                   ensureSemicolon(c)
                   listener: handleExpressionStatement(;)
           notEofOrValue(}, a)
@@ -335,87 +332,86 @@
                               parseArgumentsOpt(a)
                                 listener: handleNoArguments(?)
                               listener: handleSend(a, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(b)
-                              parsePrimary(., expressionContinuation)
-                                parseSendOrFunctionLiteral(., expressionContinuation)
-                                  looksLikeFunctionBody(:)
-                                  parseSend(., expressionContinuation)
-                                    ensureIdentifier(., expressionContinuation)
-                                    parseArgumentsOpt(toString)
-                                      parseArguments(toString)
-                                        parseArgumentsRest(()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                      parseArgumentsOpt(c)
-                        parseConditionalExpressionRest(a)
-                          listener: beginConditionalExpression(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  listener: handleNoTypeArguments([)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                  listener: handleIdentifier(b, expression)
-                                                listener: handleNoTypeArguments(])
-                                                parseArgumentsOpt(b)
-                                                  listener: handleNoArguments(])
-                                                listener: handleSend(b, ])
-                                    listener: handleLiteralList(1, [, null, ])
-                              parsePrimary(., expressionContinuation)
-                                parseSendOrFunctionLiteral(., expressionContinuation)
-                                  looksLikeFunctionBody(:)
-                                  parseSend(., expressionContinuation)
-                                    ensureIdentifier(., expressionContinuation)
-                                      listener: handleIdentifier(toString, expressionContinuation)
-                                    listener: handleNoTypeArguments(()
-                                    parseArgumentsOpt(toString)
-                                      parseArguments(toString)
-                                        parseArgumentsRest(()
-                                          listener: beginArguments(()
-                                          listener: endArguments(0, (, ))
-                                    listener: handleSend(toString, :)
-                              listener: endBinaryExpression(.)
-                          ensureColon())
-                          listener: handleConditionalExpressionColon()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                        listener: handleIdentifier(c, expression)
-                                      listener: handleNoTypeArguments(;)
-                                      parseArgumentsOpt(c)
-                                        listener: handleNoArguments(;)
-                                      listener: handleSend(c, ;)
-                          listener: endConditionalExpression(?, :)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(b)
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                looksLikeFunctionBody(:)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                  parseArgumentsOpt(toString)
+                                    parseArguments(toString)
+                                      parseArgumentsRest(()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                    parseArgumentsOpt(c)
+                      parseConditionalExpressionRest(a)
+                        listener: beginConditionalExpression(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                listener: handleNoTypeArguments([)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                                listener: handleIdentifier(b, expression)
+                                              listener: handleNoTypeArguments(])
+                                              parseArgumentsOpt(b)
+                                                listener: handleNoArguments(])
+                                              listener: handleSend(b, ])
+                                  listener: handleLiteralList(1, [, null, ])
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                looksLikeFunctionBody(:)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                    listener: handleIdentifier(toString, expressionContinuation)
+                                  listener: handleNoTypeArguments(()
+                                  parseArgumentsOpt(toString)
+                                    parseArguments(toString)
+                                      parseArgumentsRest(()
+                                        listener: beginArguments(()
+                                        listener: endArguments(0, (, ))
+                                  listener: handleSend(toString, :)
+                            listener: endBinaryExpression(.)
+                        ensureColon())
+                        listener: handleConditionalExpressionColon()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(c, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(c)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(c, ;)
+                        listener: endConditionalExpression(?, :)
                   ensureSemicolon(c)
                   listener: handleExpressionStatement(;)
           notEofOrValue(}, a)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_conditional_2.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_conditional_2.dart.intertwined.expect
index d636a7e..3af70bd 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_conditional_2.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_conditional_2.dart.intertwined.expect
@@ -68,81 +68,80 @@
                             parseArgumentsOpt(a)
                               listener: handleNoArguments(?)
                             listener: handleSend(a, ?)
-                    parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                      canParseAsConditional(?)
-                        parseExpressionWithoutCascade(?)
-                          parsePrecedenceExpression(?, 1, false)
-                            parseUnaryExpression(?, false)
-                              parsePrimary(?, expression)
-                                parseLiteralListSuffix(?, null)
-                                  parseExpression([)
-                                    parsePrecedenceExpression([, 1, true)
-                                      parseUnaryExpression([, true)
-                                        parsePrimary([, expression)
-                                          parseSendOrFunctionLiteral([, expression)
-                                            looksLikeFunctionBody(])
-                                            parseSend([, expression)
-                                              ensureIdentifier([, expression)
-                                              parseArgumentsOpt(b)
-                                                parseArguments(b)
-                                                  parseArgumentsRest(()
-                                                    parseExpression(()
-                                                      parsePrecedenceExpression((, 1, true)
-                                                        parseUnaryExpression((, true)
-                                                          parsePrimary((, expression)
-                                                            parseLiteralListSuffix((, null)
-                                                              rewriteSquareBrackets(()
-                                                                link([, ])
-                                                                rewriter()
-                        parseExpressionWithoutCascade(:)
-                          parsePrecedenceExpression(:, 1, false)
-                            parseUnaryExpression(:, false)
-                              parsePrimary(:, expression)
-                                parseLiteralNull(:)
-                      parseConditionalExpressionRest(a)
-                        listener: beginConditionalExpression(?)
-                        parseExpressionWithoutCascade(?)
-                          parsePrecedenceExpression(?, 1, false)
-                            parseUnaryExpression(?, false)
-                              parsePrimary(?, expression)
-                                listener: handleNoTypeArguments([)
-                                parseLiteralListSuffix(?, null)
-                                  parseExpression([)
-                                    parsePrecedenceExpression([, 1, true)
-                                      parseUnaryExpression([, true)
-                                        parsePrimary([, expression)
-                                          parseSendOrFunctionLiteral([, expression)
-                                            looksLikeFunctionBody(])
-                                            parseSend([, expression)
-                                              ensureIdentifier([, expression)
-                                                listener: handleIdentifier(b, expression)
-                                              listener: handleNoTypeArguments(()
-                                              parseArgumentsOpt(b)
-                                                parseArguments(b)
-                                                  parseArgumentsRest(()
-                                                    listener: beginArguments(()
-                                                    parseExpression(()
-                                                      parsePrecedenceExpression((, 1, true)
-                                                        parseUnaryExpression((, true)
-                                                          parsePrimary((, expression)
-                                                            listener: handleNoTypeArguments([])
-                                                            parseLiteralListSuffix((, null)
-                                                              rewriteSquareBrackets(()
-                                                                link([, ])
-                                                                rewriter()
-                                                              listener: handleLiteralList(0, [, null, ])
-                                                    listener: endArguments(1, (, ))
-                                              listener: handleSend(b, ])
-                                  listener: handleLiteralList(1, [, null, ])
-                        ensureColon(])
-                        listener: handleConditionalExpressionColon()
-                        parseExpressionWithoutCascade(:)
-                          parsePrecedenceExpression(:, 1, false)
-                            parseUnaryExpression(:, false)
-                              parsePrimary(:, expression)
-                                parseLiteralNull(:)
-                                  listener: handleLiteralNull(null)
-                        listener: endConditionalExpression(?, :)
+                    canParseAsConditional(?)
+                      parseExpressionWithoutCascade(?)
+                        parsePrecedenceExpression(?, 1, false)
+                          parseUnaryExpression(?, false)
+                            parsePrimary(?, expression)
+                              parseLiteralListSuffix(?, null)
+                                parseExpression([)
+                                  parsePrecedenceExpression([, 1, true)
+                                    parseUnaryExpression([, true)
+                                      parsePrimary([, expression)
+                                        parseSendOrFunctionLiteral([, expression)
+                                          looksLikeFunctionBody(])
+                                          parseSend([, expression)
+                                            ensureIdentifier([, expression)
+                                            parseArgumentsOpt(b)
+                                              parseArguments(b)
+                                                parseArgumentsRest(()
+                                                  parseExpression(()
+                                                    parsePrecedenceExpression((, 1, true)
+                                                      parseUnaryExpression((, true)
+                                                        parsePrimary((, expression)
+                                                          parseLiteralListSuffix((, null)
+                                                            rewriteSquareBrackets(()
+                                                              link([, ])
+                                                              rewriter()
+                      parseExpressionWithoutCascade(:)
+                        parsePrecedenceExpression(:, 1, false)
+                          parseUnaryExpression(:, false)
+                            parsePrimary(:, expression)
+                              parseLiteralNull(:)
+                    parseConditionalExpressionRest(a)
+                      listener: beginConditionalExpression(?)
+                      parseExpressionWithoutCascade(?)
+                        parsePrecedenceExpression(?, 1, false)
+                          parseUnaryExpression(?, false)
+                            parsePrimary(?, expression)
+                              listener: handleNoTypeArguments([)
+                              parseLiteralListSuffix(?, null)
+                                parseExpression([)
+                                  parsePrecedenceExpression([, 1, true)
+                                    parseUnaryExpression([, true)
+                                      parsePrimary([, expression)
+                                        parseSendOrFunctionLiteral([, expression)
+                                          looksLikeFunctionBody(])
+                                          parseSend([, expression)
+                                            ensureIdentifier([, expression)
+                                              listener: handleIdentifier(b, expression)
+                                            listener: handleNoTypeArguments(()
+                                            parseArgumentsOpt(b)
+                                              parseArguments(b)
+                                                parseArgumentsRest(()
+                                                  listener: beginArguments(()
+                                                  parseExpression(()
+                                                    parsePrecedenceExpression((, 1, true)
+                                                      parseUnaryExpression((, true)
+                                                        parsePrimary((, expression)
+                                                          listener: handleNoTypeArguments([])
+                                                          parseLiteralListSuffix((, null)
+                                                            rewriteSquareBrackets(()
+                                                              link([, ])
+                                                              rewriter()
+                                                            listener: handleLiteralList(0, [, null, ])
+                                                  listener: endArguments(1, (, ))
+                                            listener: handleSend(b, ])
+                                listener: handleLiteralList(1, [, null, ])
+                      ensureColon(])
+                      listener: handleConditionalExpressionColon()
+                      parseExpressionWithoutCascade(:)
+                        parsePrecedenceExpression(:, 1, false)
+                          parseUnaryExpression(:, false)
+                            parsePrimary(:, expression)
+                              parseLiteralNull(:)
+                                listener: handleLiteralNull(null)
+                      listener: endConditionalExpression(?, :)
                 ensureSemicolon(null)
                 listener: endReturnStatement(true, return, ;)
                 inGenerator()
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_index_access.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_index_access.dart.intertwined.expect
index 243c2ea..4674f50 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_index_access.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_index_access.dart.intertwined.expect
@@ -103,35 +103,34 @@
                               parseArgumentsOpt(a)
                                 listener: handleNoArguments(?)
                               listener: handleSend(a, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(b)
-                        parseArgumentOrIndexStar(a, Instance of 'NoTypeParamOrArg', true)
-                          parseExpression([)
-                            parsePrecedenceExpression([, 1, true)
-                              parseUnaryExpression([, true)
-                                parsePrimary([, expression)
-                                  parseSendOrFunctionLiteral([, expression)
-                                    parseSend([, expression)
-                                      ensureIdentifier([, expression)
-                                        listener: handleIdentifier(b, expression)
-                                      listener: handleNoTypeArguments(])
-                                      parseArgumentsOpt(b)
-                                        listener: handleNoArguments(])
-                                      listener: handleSend(b, ])
-                          listener: handleIndexedExpression(?, [, ])
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(b)
+                      parseArgumentOrIndexStar(a, Instance of 'NoTypeParamOrArg', true)
+                        parseExpression([)
+                          parsePrecedenceExpression([, 1, true)
+                            parseUnaryExpression([, true)
+                              parsePrimary([, expression)
+                                parseSendOrFunctionLiteral([, expression)
+                                  parseSend([, expression)
+                                    ensureIdentifier([, expression)
+                                      listener: handleIdentifier(b, expression)
+                                    listener: handleNoTypeArguments(])
+                                    parseArgumentsOpt(b)
+                                      listener: handleNoArguments(])
+                                    listener: handleSend(b, ])
+                        listener: handleIndexedExpression(?, [, ])
                   ensureSemicolon(])
                   listener: handleExpressionStatement(;)
           notEofOrValue(}, })
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_index_set.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_index_set.dart.intertwined.expect
index 7fd92a2..ecd4668 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_index_set.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_index_set.dart.intertwined.expect
@@ -122,42 +122,41 @@
                               parseArgumentsOpt(a)
                                 listener: handleNoArguments(?)
                               listener: handleSend(a, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(b)
-                              parsePrecedenceExpression(=, 1, false)
-                                parseUnaryExpression(=, false)
-                                  parsePrimary(=, expression)
-                                    parseSendOrFunctionLiteral(=, expression)
-                                      parseSend(=, expression)
-                                        ensureIdentifier(=, expression)
-                                        parseArgumentsOpt(c)
-                        parseArgumentOrIndexStar(a, Instance of 'NoTypeParamOrArg', true)
-                          parseExpression([)
-                            parsePrecedenceExpression([, 1, true)
-                              parseUnaryExpression([, true)
-                                parsePrimary([, expression)
-                                  parseSendOrFunctionLiteral([, expression)
-                                    parseSend([, expression)
-                                      ensureIdentifier([, expression)
-                                        listener: handleIdentifier(b, expression)
-                                      listener: handleNoTypeArguments(])
-                                      parseArgumentsOpt(b)
-                                        listener: handleNoArguments(])
-                                      listener: handleSend(b, ])
-                          listener: handleIndexedExpression(?, [, ])
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(b)
+                            parsePrecedenceExpression(=, 1, false)
+                              parseUnaryExpression(=, false)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                      parseArgumentsOpt(c)
+                      parseArgumentOrIndexStar(a, Instance of 'NoTypeParamOrArg', true)
+                        parseExpression([)
+                          parsePrecedenceExpression([, 1, true)
+                            parseUnaryExpression([, true)
+                              parsePrimary([, expression)
+                                parseSendOrFunctionLiteral([, expression)
+                                  parseSend([, expression)
+                                    ensureIdentifier([, expression)
+                                      listener: handleIdentifier(b, expression)
+                                    listener: handleNoTypeArguments(])
+                                    parseArgumentsOpt(b)
+                                      listener: handleNoArguments(])
+                                    listener: handleSend(b, ])
+                        listener: handleIndexedExpression(?, [, ])
                       parsePrecedenceExpression(=, 1, true)
                         parseUnaryExpression(=, true)
                           parsePrimary(=, expression)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart
new file mode 100644
index 0000000..af2c6b2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart
@@ -0,0 +1,3 @@
+f(dynamic a) {
+  a?[0] + 1;
+}
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.expect
new file mode 100644
index 0000000..29249f9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.expect
@@ -0,0 +1,35 @@
+beginCompilationUnit(f)
+  beginMetadataStar(f)
+  endMetadataStar(0)
+  beginTopLevelMember(f)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(dynamic)
+        endMetadataStar(0)
+        beginFormalParameter(dynamic, MemberKind.TopLevelMethod, null, null, null)
+          handleIdentifier(dynamic, typeReference)
+          handleNoTypeArguments(a)
+          handleType(dynamic, null)
+          handleIdentifier(a, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, a, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(a, expression)
+        handleNoTypeArguments(?)
+        handleNoArguments(?)
+        handleSend(a, ?)
+        handleLiteralInt(0)
+        handleIndexedExpression(?, [, ])
+        beginBinaryExpression(+)
+        handleLiteralInt(1)
+        endBinaryExpression(+)
+        handleExpressionStatement(;)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(f, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.intertwined.expect
new file mode 100644
index 0000000..2475c14
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.intertwined.expect
@@ -0,0 +1,95 @@
+parseUnit(f)
+  skipErrorTokens(f)
+  listener: beginCompilationUnit(f)
+  syntheticPreviousToken(f)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(f)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(f)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, f)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(dynamic)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(dynamic, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleIdentifier(dynamic, typeReference)
+                listener: handleNoTypeArguments(a)
+                listener: handleType(dynamic, null)
+                ensureIdentifier(dynamic, formalParameterDeclaration)
+                  listener: handleIdentifier(a, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, a, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, a)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(a)
+                parseExpressionStatement({)
+                  parseExpression({)
+                    parsePrecedenceExpression({, 1, true)
+                      parseUnaryExpression({, true)
+                        parsePrimary({, expression)
+                          parseSendOrFunctionLiteral({, expression)
+                            parseSend({, expression)
+                              ensureIdentifier({, expression)
+                                listener: handleIdentifier(a, expression)
+                              listener: handleNoTypeArguments(?)
+                              parseArgumentsOpt(a)
+                                listener: handleNoArguments(?)
+                              listener: handleSend(a, ?)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseLiteralInt([)
+                            parsePrecedenceExpression(+, 14, false)
+                              parseUnaryExpression(+, false)
+                                parsePrimary(+, expression)
+                                  parseLiteralInt(+)
+                      parseArgumentOrIndexStar(a, Instance of 'NoTypeParamOrArg', true)
+                        parseExpression([)
+                          parsePrecedenceExpression([, 1, true)
+                            parseUnaryExpression([, true)
+                              parsePrimary([, expression)
+                                parseLiteralInt([)
+                                  listener: handleLiteralInt(0)
+                        listener: handleIndexedExpression(?, [, ])
+                      listener: beginBinaryExpression(+)
+                      parsePrecedenceExpression(+, 14, true)
+                        parseUnaryExpression(+, true)
+                          parsePrimary(+, expression)
+                            parseLiteralInt(+)
+                              listener: handleLiteralInt(1)
+                      listener: endBinaryExpression(+)
+                  ensureSemicolon(1)
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(f, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(f)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.parser.expect
new file mode 100644
index 0000000..b216698
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.parser.expect
@@ -0,0 +1,7 @@
+f(dynamic a) {
+a?[0] + 1;
+}
+
+f[StringToken]([BeginToken]dynamic[KeywordToken] a[StringToken])[SimpleToken] {[BeginToken]
+a[StringToken]?[SimpleToken][[BeginToken]0[StringToken]][SimpleToken] +[SimpleToken] 1[StringToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.scanner.expect
new file mode 100644
index 0000000..b216698
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus.dart.scanner.expect
@@ -0,0 +1,7 @@
+f(dynamic a) {
+a?[0] + 1;
+}
+
+f[StringToken]([BeginToken]dynamic[KeywordToken] a[StringToken])[SimpleToken] {[BeginToken]
+a[StringToken]?[SimpleToken][[BeginToken]0[StringToken]][SimpleToken] +[SimpleToken] 1[StringToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart
new file mode 100644
index 0000000..8b33d56
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart
@@ -0,0 +1,3 @@
+f(dynamic x, dynamic i) {
+  x?[i]++;
+}
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.expect
new file mode 100644
index 0000000..90d68a0
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.expect
@@ -0,0 +1,45 @@
+beginCompilationUnit(f)
+  beginMetadataStar(f)
+  endMetadataStar(0)
+  beginTopLevelMember(f)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(dynamic)
+        endMetadataStar(0)
+        beginFormalParameter(dynamic, MemberKind.TopLevelMethod, null, null, null)
+          handleIdentifier(dynamic, typeReference)
+          handleNoTypeArguments(x)
+          handleType(dynamic, null)
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue(,)
+        endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+        beginMetadataStar(dynamic)
+        endMetadataStar(0)
+        beginFormalParameter(dynamic, MemberKind.TopLevelMethod, null, null, null)
+          handleIdentifier(dynamic, typeReference)
+          handleNoTypeArguments(i)
+          handleType(dynamic, null)
+          handleIdentifier(i, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, i, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+      endFormalParameters(2, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(x, expression)
+        handleNoTypeArguments(?)
+        handleNoArguments(?)
+        handleSend(x, ?)
+        handleIdentifier(i, expression)
+        handleNoTypeArguments(])
+        handleNoArguments(])
+        handleSend(i, ])
+        handleIndexedExpression(?, [, ])
+        handleUnaryPostfixAssignmentExpression(++)
+        handleExpressionStatement(;)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(f, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.intertwined.expect
new file mode 100644
index 0000000..244201e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.intertwined.expect
@@ -0,0 +1,106 @@
+parseUnit(f)
+  skipErrorTokens(f)
+  listener: beginCompilationUnit(f)
+  syntheticPreviousToken(f)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(f)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(f)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, f)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(dynamic)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(dynamic, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleIdentifier(dynamic, typeReference)
+                listener: handleNoTypeArguments(x)
+                listener: handleType(dynamic, null)
+                ensureIdentifier(dynamic, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue(,)
+                listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+              parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+                parseMetadataStar(,)
+                  listener: beginMetadataStar(dynamic)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(dynamic, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleIdentifier(dynamic, typeReference)
+                listener: handleNoTypeArguments(i)
+                listener: handleType(dynamic, null)
+                ensureIdentifier(dynamic, formalParameterDeclaration)
+                  listener: handleIdentifier(i, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, i, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(2, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, x)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(x)
+                parseExpressionStatement({)
+                  parseExpression({)
+                    parsePrecedenceExpression({, 1, true)
+                      parseUnaryExpression({, true)
+                        parsePrimary({, expression)
+                          parseSendOrFunctionLiteral({, expression)
+                            parseSend({, expression)
+                              ensureIdentifier({, expression)
+                                listener: handleIdentifier(x, expression)
+                              listener: handleNoTypeArguments(?)
+                              parseArgumentsOpt(x)
+                                listener: handleNoArguments(?)
+                              listener: handleSend(x, ?)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(i)
+                      parseArgumentOrIndexStar(x, Instance of 'NoTypeParamOrArg', true)
+                        parseExpression([)
+                          parsePrecedenceExpression([, 1, true)
+                            parseUnaryExpression([, true)
+                              parsePrimary([, expression)
+                                parseSendOrFunctionLiteral([, expression)
+                                  parseSend([, expression)
+                                    ensureIdentifier([, expression)
+                                      listener: handleIdentifier(i, expression)
+                                    listener: handleNoTypeArguments(])
+                                    parseArgumentsOpt(i)
+                                      listener: handleNoArguments(])
+                                    listener: handleSend(i, ])
+                        listener: handleIndexedExpression(?, [, ])
+                      listener: handleUnaryPostfixAssignmentExpression(++)
+                  ensureSemicolon(++)
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(f, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(f)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.parser.expect
new file mode 100644
index 0000000..98a6966
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.parser.expect
@@ -0,0 +1,7 @@
+f(dynamic x, dynamic i) {
+x?[i]++;
+}
+
+f[StringToken]([BeginToken]dynamic[KeywordToken] x[StringToken],[SimpleToken] dynamic[KeywordToken] i[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken]?[SimpleToken][[BeginToken]i[StringToken]][SimpleToken]++[SimpleToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.scanner.expect
new file mode 100644
index 0000000..98a6966
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_lookup_plus_plus.dart.scanner.expect
@@ -0,0 +1,7 @@
+f(dynamic x, dynamic i) {
+x?[i]++;
+}
+
+f[StringToken]([BeginToken]dynamic[KeywordToken] x[StringToken],[SimpleToken] dynamic[KeywordToken] i[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken]?[SimpleToken][[BeginToken]i[StringToken]][SimpleToken]++[SimpleToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart b/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart
new file mode 100644
index 0000000..23d8492
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart
@@ -0,0 +1,3 @@
+f(dynamic x, dynamic i) {
+  ++x?[i];
+}
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.expect
new file mode 100644
index 0000000..6d91dd6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.expect
@@ -0,0 +1,45 @@
+beginCompilationUnit(f)
+  beginMetadataStar(f)
+  endMetadataStar(0)
+  beginTopLevelMember(f)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(dynamic)
+        endMetadataStar(0)
+        beginFormalParameter(dynamic, MemberKind.TopLevelMethod, null, null, null)
+          handleIdentifier(dynamic, typeReference)
+          handleNoTypeArguments(x)
+          handleType(dynamic, null)
+          handleIdentifier(x, formalParameterDeclaration)
+          handleFormalParameterWithoutValue(,)
+        endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+        beginMetadataStar(dynamic)
+        endMetadataStar(0)
+        beginFormalParameter(dynamic, MemberKind.TopLevelMethod, null, null, null)
+          handleIdentifier(dynamic, typeReference)
+          handleNoTypeArguments(i)
+          handleType(dynamic, null)
+          handleIdentifier(i, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, i, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+      endFormalParameters(2, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(x, expression)
+        handleNoTypeArguments(?)
+        handleNoArguments(?)
+        handleSend(x, ?)
+        handleIdentifier(i, expression)
+        handleNoTypeArguments(])
+        handleNoArguments(])
+        handleSend(i, ])
+        handleIndexedExpression(?, [, ])
+        handleUnaryPrefixAssignmentExpression(++)
+        handleExpressionStatement(;)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(f, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.intertwined.expect
new file mode 100644
index 0000000..2b47b0f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.intertwined.expect
@@ -0,0 +1,109 @@
+parseUnit(f)
+  skipErrorTokens(f)
+  listener: beginCompilationUnit(f)
+  syntheticPreviousToken(f)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(f)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(f)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, f)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(dynamic)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(dynamic, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleIdentifier(dynamic, typeReference)
+                listener: handleNoTypeArguments(x)
+                listener: handleType(dynamic, null)
+                ensureIdentifier(dynamic, formalParameterDeclaration)
+                  listener: handleIdentifier(x, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue(,)
+                listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+              parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+                parseMetadataStar(,)
+                  listener: beginMetadataStar(dynamic)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(dynamic, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleIdentifier(dynamic, typeReference)
+                listener: handleNoTypeArguments(i)
+                listener: handleType(dynamic, null)
+                ensureIdentifier(dynamic, formalParameterDeclaration)
+                  listener: handleIdentifier(i, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, i, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(2, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, ++)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclaration({, false)
+                parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                  looksLikeLocalFunction(++)
+                  parseExpressionStatement({)
+                    parseExpression({)
+                      parsePrecedenceExpression({, 1, true)
+                        parseUnaryExpression({, true)
+                          parsePrecedenceExpression(++, 16, true)
+                            parseUnaryExpression(++, true)
+                              parsePrimary(++, expression)
+                                parseSendOrFunctionLiteral(++, expression)
+                                  parseSend(++, expression)
+                                    ensureIdentifier(++, expression)
+                                      listener: handleIdentifier(x, expression)
+                                    listener: handleNoTypeArguments(?)
+                                    parseArgumentsOpt(x)
+                                      listener: handleNoArguments(?)
+                                    listener: handleSend(x, ?)
+                            canParseAsConditional(?)
+                              parseExpressionWithoutCascade(?)
+                                parsePrecedenceExpression(?, 1, false)
+                                  parseUnaryExpression(?, false)
+                                    parsePrimary(?, expression)
+                                      parseLiteralListSuffix(?, null)
+                                        parseExpression([)
+                                          parsePrecedenceExpression([, 1, true)
+                                            parseUnaryExpression([, true)
+                                              parsePrimary([, expression)
+                                                parseSendOrFunctionLiteral([, expression)
+                                                  parseSend([, expression)
+                                                    ensureIdentifier([, expression)
+                                                    parseArgumentsOpt(i)
+                            parseArgumentOrIndexStar(x, Instance of 'NoTypeParamOrArg', true)
+                              parseExpression([)
+                                parsePrecedenceExpression([, 1, true)
+                                  parseUnaryExpression([, true)
+                                    parsePrimary([, expression)
+                                      parseSendOrFunctionLiteral([, expression)
+                                        parseSend([, expression)
+                                          ensureIdentifier([, expression)
+                                            listener: handleIdentifier(i, expression)
+                                          listener: handleNoTypeArguments(])
+                                          parseArgumentsOpt(i)
+                                            listener: handleNoArguments(])
+                                          listener: handleSend(i, ])
+                              listener: handleIndexedExpression(?, [, ])
+                          listener: handleUnaryPrefixAssignmentExpression(++)
+                    ensureSemicolon(])
+                    listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(f, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(f)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.parser.expect
new file mode 100644
index 0000000..999ca84
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.parser.expect
@@ -0,0 +1,7 @@
+f(dynamic x, dynamic i) {
+++x?[i];
+}
+
+f[StringToken]([BeginToken]dynamic[KeywordToken] x[StringToken],[SimpleToken] dynamic[KeywordToken] i[StringToken])[SimpleToken] {[BeginToken]
+++[SimpleToken]x[StringToken]?[SimpleToken][[BeginToken]i[StringToken]][SimpleToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.scanner.expect
new file mode 100644
index 0000000..999ca84
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_plus_plus_lookup.dart.scanner.expect
@@ -0,0 +1,7 @@
+f(dynamic x, dynamic i) {
+++x?[i];
+}
+
+f[StringToken]([BeginToken]dynamic[KeywordToken] x[StringToken],[SimpleToken] dynamic[KeywordToken] i[StringToken])[SimpleToken] {[BeginToken]
+++[SimpleToken]x[StringToken]?[SimpleToken][[BeginToken]i[StringToken]][SimpleToken];[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional.dart.intertwined.expect b/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional.dart.intertwined.expect
index b9e60d7..7d4e907 100644
--- a/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional.dart.intertwined.expect
@@ -76,65 +76,64 @@
                               parseArgumentsOpt(a)
                                 listener: handleNoArguments(?)
                               listener: handleSend(a, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(b)
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                      parseArgumentsOpt(c)
-                        parseConditionalExpressionRest(a)
-                          listener: beginConditionalExpression(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  listener: handleNoTypeArguments([)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                  listener: handleIdentifier(b, expression)
-                                                listener: handleNoTypeArguments(])
-                                                parseArgumentsOpt(b)
-                                                  listener: handleNoArguments(])
-                                                listener: handleSend(b, ])
-                                    listener: handleLiteralList(1, [, null, ])
-                          ensureColon(])
-                          listener: handleConditionalExpressionColon()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                        listener: handleIdentifier(c, expression)
-                                      listener: handleNoTypeArguments(;)
-                                      parseArgumentsOpt(c)
-                                        listener: handleNoArguments(;)
-                                      listener: handleSend(c, ;)
-                          listener: endConditionalExpression(?, :)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(b)
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                    parseArgumentsOpt(c)
+                      parseConditionalExpressionRest(a)
+                        listener: beginConditionalExpression(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                listener: handleNoTypeArguments([)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                                listener: handleIdentifier(b, expression)
+                                              listener: handleNoTypeArguments(])
+                                              parseArgumentsOpt(b)
+                                                listener: handleNoArguments(])
+                                              listener: handleSend(b, ])
+                                  listener: handleLiteralList(1, [, null, ])
+                        ensureColon(])
+                        listener: handleConditionalExpressionColon()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(c, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(c)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(c, ;)
+                        listener: endConditionalExpression(?, :)
                   ensureSemicolon(c)
                   listener: handleExpressionStatement(;)
           notEofOrValue(}, a)
@@ -155,65 +154,64 @@
                               parseArgumentsOpt(a)
                                 listener: handleNoArguments(?)
                               listener: handleSend(a, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(b)
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                      parseArgumentsOpt(c)
-                        parseConditionalExpressionRest(a)
-                          listener: beginConditionalExpression(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  listener: handleNoTypeArguments([)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                  listener: handleIdentifier(b, expression)
-                                                listener: handleNoTypeArguments(])
-                                                parseArgumentsOpt(b)
-                                                  listener: handleNoArguments(])
-                                                listener: handleSend(b, ])
-                                    listener: handleLiteralList(1, [, null, ])
-                          ensureColon(])
-                          listener: handleConditionalExpressionColon()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                        listener: handleIdentifier(c, expression)
-                                      listener: handleNoTypeArguments(;)
-                                      parseArgumentsOpt(c)
-                                        listener: handleNoArguments(;)
-                                      listener: handleSend(c, ;)
-                          listener: endConditionalExpression(?, :)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(b)
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                    parseArgumentsOpt(c)
+                      parseConditionalExpressionRest(a)
+                        listener: beginConditionalExpression(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                listener: handleNoTypeArguments([)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                                listener: handleIdentifier(b, expression)
+                                              listener: handleNoTypeArguments(])
+                                              parseArgumentsOpt(b)
+                                                listener: handleNoArguments(])
+                                              listener: handleSend(b, ])
+                                  listener: handleLiteralList(1, [, null, ])
+                        ensureColon(])
+                        listener: handleConditionalExpressionColon()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(c, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(c)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(c, ;)
+                        listener: endConditionalExpression(?, :)
                   ensureSemicolon(c)
                   listener: handleExpressionStatement(;)
           notEofOrValue(}, a)
@@ -234,87 +232,86 @@
                               parseArgumentsOpt(a)
                                 listener: handleNoArguments(?)
                               listener: handleSend(a, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(b)
-                              parsePrimary(., expressionContinuation)
-                                parseSendOrFunctionLiteral(., expressionContinuation)
-                                  looksLikeFunctionBody(:)
-                                  parseSend(., expressionContinuation)
-                                    ensureIdentifier(., expressionContinuation)
-                                    parseArgumentsOpt(toString)
-                                      parseArguments(toString)
-                                        parseArgumentsRest(()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                      parseArgumentsOpt(c)
-                        parseConditionalExpressionRest(a)
-                          listener: beginConditionalExpression(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  listener: handleNoTypeArguments([)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                  listener: handleIdentifier(b, expression)
-                                                listener: handleNoTypeArguments(])
-                                                parseArgumentsOpt(b)
-                                                  listener: handleNoArguments(])
-                                                listener: handleSend(b, ])
-                                    listener: handleLiteralList(1, [, null, ])
-                              parsePrimary(., expressionContinuation)
-                                parseSendOrFunctionLiteral(., expressionContinuation)
-                                  looksLikeFunctionBody(:)
-                                  parseSend(., expressionContinuation)
-                                    ensureIdentifier(., expressionContinuation)
-                                      listener: handleIdentifier(toString, expressionContinuation)
-                                    listener: handleNoTypeArguments(()
-                                    parseArgumentsOpt(toString)
-                                      parseArguments(toString)
-                                        parseArgumentsRest(()
-                                          listener: beginArguments(()
-                                          listener: endArguments(0, (, ))
-                                    listener: handleSend(toString, :)
-                              listener: endBinaryExpression(.)
-                          ensureColon())
-                          listener: handleConditionalExpressionColon()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                        listener: handleIdentifier(c, expression)
-                                      listener: handleNoTypeArguments(;)
-                                      parseArgumentsOpt(c)
-                                        listener: handleNoArguments(;)
-                                      listener: handleSend(c, ;)
-                          listener: endConditionalExpression(?, :)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(b)
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                looksLikeFunctionBody(:)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                  parseArgumentsOpt(toString)
+                                    parseArguments(toString)
+                                      parseArgumentsRest(()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                    parseArgumentsOpt(c)
+                      parseConditionalExpressionRest(a)
+                        listener: beginConditionalExpression(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                listener: handleNoTypeArguments([)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                                listener: handleIdentifier(b, expression)
+                                              listener: handleNoTypeArguments(])
+                                              parseArgumentsOpt(b)
+                                                listener: handleNoArguments(])
+                                              listener: handleSend(b, ])
+                                  listener: handleLiteralList(1, [, null, ])
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                looksLikeFunctionBody(:)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                    listener: handleIdentifier(toString, expressionContinuation)
+                                  listener: handleNoTypeArguments(()
+                                  parseArgumentsOpt(toString)
+                                    parseArguments(toString)
+                                      parseArgumentsRest(()
+                                        listener: beginArguments(()
+                                        listener: endArguments(0, (, ))
+                                  listener: handleSend(toString, :)
+                            listener: endBinaryExpression(.)
+                        ensureColon())
+                        listener: handleConditionalExpressionColon()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(c, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(c)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(c, ;)
+                        listener: endConditionalExpression(?, :)
                   ensureSemicolon(c)
                   listener: handleExpressionStatement(;)
           notEofOrValue(}, a)
@@ -335,87 +332,86 @@
                               parseArgumentsOpt(a)
                                 listener: handleNoArguments(?)
                               listener: handleSend(a, ?)
-                      parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                        canParseAsConditional(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                parseArgumentsOpt(b)
-                              parsePrimary(., expressionContinuation)
-                                parseSendOrFunctionLiteral(., expressionContinuation)
-                                  looksLikeFunctionBody(:)
-                                  parseSend(., expressionContinuation)
-                                    ensureIdentifier(., expressionContinuation)
-                                    parseArgumentsOpt(toString)
-                                      parseArguments(toString)
-                                        parseArgumentsRest(()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                      parseArgumentsOpt(c)
-                        parseConditionalExpressionRest(a)
-                          listener: beginConditionalExpression(?)
-                          parseExpressionWithoutCascade(?)
-                            parsePrecedenceExpression(?, 1, false)
-                              parseUnaryExpression(?, false)
-                                parsePrimary(?, expression)
-                                  listener: handleNoTypeArguments([)
-                                  parseLiteralListSuffix(?, null)
-                                    parseExpression([)
-                                      parsePrecedenceExpression([, 1, true)
-                                        parseUnaryExpression([, true)
-                                          parsePrimary([, expression)
-                                            parseSendOrFunctionLiteral([, expression)
-                                              parseSend([, expression)
-                                                ensureIdentifier([, expression)
-                                                  listener: handleIdentifier(b, expression)
-                                                listener: handleNoTypeArguments(])
-                                                parseArgumentsOpt(b)
-                                                  listener: handleNoArguments(])
-                                                listener: handleSend(b, ])
-                                    listener: handleLiteralList(1, [, null, ])
-                              parsePrimary(., expressionContinuation)
-                                parseSendOrFunctionLiteral(., expressionContinuation)
-                                  looksLikeFunctionBody(:)
-                                  parseSend(., expressionContinuation)
-                                    ensureIdentifier(., expressionContinuation)
-                                      listener: handleIdentifier(toString, expressionContinuation)
-                                    listener: handleNoTypeArguments(()
-                                    parseArgumentsOpt(toString)
-                                      parseArguments(toString)
-                                        parseArgumentsRest(()
-                                          listener: beginArguments(()
-                                          listener: endArguments(0, (, ))
-                                    listener: handleSend(toString, :)
-                              listener: endBinaryExpression(.)
-                          ensureColon())
-                          listener: handleConditionalExpressionColon()
-                          parseExpressionWithoutCascade(:)
-                            parsePrecedenceExpression(:, 1, false)
-                              parseUnaryExpression(:, false)
-                                parsePrimary(:, expression)
-                                  parseSendOrFunctionLiteral(:, expression)
-                                    parseSend(:, expression)
-                                      ensureIdentifier(:, expression)
-                                        listener: handleIdentifier(c, expression)
-                                      listener: handleNoTypeArguments(;)
-                                      parseArgumentsOpt(c)
-                                        listener: handleNoArguments(;)
-                                      listener: handleSend(c, ;)
-                          listener: endConditionalExpression(?, :)
+                      canParseAsConditional(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                              parseArgumentsOpt(b)
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                looksLikeFunctionBody(:)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                  parseArgumentsOpt(toString)
+                                    parseArguments(toString)
+                                      parseArgumentsRest(()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                    parseArgumentsOpt(c)
+                      parseConditionalExpressionRest(a)
+                        listener: beginConditionalExpression(?)
+                        parseExpressionWithoutCascade(?)
+                          parsePrecedenceExpression(?, 1, false)
+                            parseUnaryExpression(?, false)
+                              parsePrimary(?, expression)
+                                listener: handleNoTypeArguments([)
+                                parseLiteralListSuffix(?, null)
+                                  parseExpression([)
+                                    parsePrecedenceExpression([, 1, true)
+                                      parseUnaryExpression([, true)
+                                        parsePrimary([, expression)
+                                          parseSendOrFunctionLiteral([, expression)
+                                            parseSend([, expression)
+                                              ensureIdentifier([, expression)
+                                                listener: handleIdentifier(b, expression)
+                                              listener: handleNoTypeArguments(])
+                                              parseArgumentsOpt(b)
+                                                listener: handleNoArguments(])
+                                              listener: handleSend(b, ])
+                                  listener: handleLiteralList(1, [, null, ])
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                looksLikeFunctionBody(:)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                    listener: handleIdentifier(toString, expressionContinuation)
+                                  listener: handleNoTypeArguments(()
+                                  parseArgumentsOpt(toString)
+                                    parseArguments(toString)
+                                      parseArgumentsRest(()
+                                        listener: beginArguments(()
+                                        listener: endArguments(0, (, ))
+                                  listener: handleSend(toString, :)
+                            listener: endBinaryExpression(.)
+                        ensureColon())
+                        listener: handleConditionalExpressionColon()
+                        parseExpressionWithoutCascade(:)
+                          parsePrecedenceExpression(:, 1, false)
+                            parseUnaryExpression(:, false)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(c, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(c)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(c, ;)
+                        listener: endConditionalExpression(?, :)
                   ensureSemicolon(c)
                   listener: handleExpressionStatement(;)
           notEofOrValue(}, a)
diff --git a/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_2.dart.intertwined.expect b/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_2.dart.intertwined.expect
index d636a7e..3af70bd 100644
--- a/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_2.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_2.dart.intertwined.expect
@@ -68,81 +68,80 @@
                             parseArgumentsOpt(a)
                               listener: handleNoArguments(?)
                             listener: handleSend(a, ?)
-                    parseNullAwareBracketOrConditionalExpressionRest(a, Instance of 'NoTypeParamOrArg')
-                      canParseAsConditional(?)
-                        parseExpressionWithoutCascade(?)
-                          parsePrecedenceExpression(?, 1, false)
-                            parseUnaryExpression(?, false)
-                              parsePrimary(?, expression)
-                                parseLiteralListSuffix(?, null)
-                                  parseExpression([)
-                                    parsePrecedenceExpression([, 1, true)
-                                      parseUnaryExpression([, true)
-                                        parsePrimary([, expression)
-                                          parseSendOrFunctionLiteral([, expression)
-                                            looksLikeFunctionBody(])
-                                            parseSend([, expression)
-                                              ensureIdentifier([, expression)
-                                              parseArgumentsOpt(b)
-                                                parseArguments(b)
-                                                  parseArgumentsRest(()
-                                                    parseExpression(()
-                                                      parsePrecedenceExpression((, 1, true)
-                                                        parseUnaryExpression((, true)
-                                                          parsePrimary((, expression)
-                                                            parseLiteralListSuffix((, null)
-                                                              rewriteSquareBrackets(()
-                                                                link([, ])
-                                                                rewriter()
-                        parseExpressionWithoutCascade(:)
-                          parsePrecedenceExpression(:, 1, false)
-                            parseUnaryExpression(:, false)
-                              parsePrimary(:, expression)
-                                parseLiteralNull(:)
-                      parseConditionalExpressionRest(a)
-                        listener: beginConditionalExpression(?)
-                        parseExpressionWithoutCascade(?)
-                          parsePrecedenceExpression(?, 1, false)
-                            parseUnaryExpression(?, false)
-                              parsePrimary(?, expression)
-                                listener: handleNoTypeArguments([)
-                                parseLiteralListSuffix(?, null)
-                                  parseExpression([)
-                                    parsePrecedenceExpression([, 1, true)
-                                      parseUnaryExpression([, true)
-                                        parsePrimary([, expression)
-                                          parseSendOrFunctionLiteral([, expression)
-                                            looksLikeFunctionBody(])
-                                            parseSend([, expression)
-                                              ensureIdentifier([, expression)
-                                                listener: handleIdentifier(b, expression)
-                                              listener: handleNoTypeArguments(()
-                                              parseArgumentsOpt(b)
-                                                parseArguments(b)
-                                                  parseArgumentsRest(()
-                                                    listener: beginArguments(()
-                                                    parseExpression(()
-                                                      parsePrecedenceExpression((, 1, true)
-                                                        parseUnaryExpression((, true)
-                                                          parsePrimary((, expression)
-                                                            listener: handleNoTypeArguments([])
-                                                            parseLiteralListSuffix((, null)
-                                                              rewriteSquareBrackets(()
-                                                                link([, ])
-                                                                rewriter()
-                                                              listener: handleLiteralList(0, [, null, ])
-                                                    listener: endArguments(1, (, ))
-                                              listener: handleSend(b, ])
-                                  listener: handleLiteralList(1, [, null, ])
-                        ensureColon(])
-                        listener: handleConditionalExpressionColon()
-                        parseExpressionWithoutCascade(:)
-                          parsePrecedenceExpression(:, 1, false)
-                            parseUnaryExpression(:, false)
-                              parsePrimary(:, expression)
-                                parseLiteralNull(:)
-                                  listener: handleLiteralNull(null)
-                        listener: endConditionalExpression(?, :)
+                    canParseAsConditional(?)
+                      parseExpressionWithoutCascade(?)
+                        parsePrecedenceExpression(?, 1, false)
+                          parseUnaryExpression(?, false)
+                            parsePrimary(?, expression)
+                              parseLiteralListSuffix(?, null)
+                                parseExpression([)
+                                  parsePrecedenceExpression([, 1, true)
+                                    parseUnaryExpression([, true)
+                                      parsePrimary([, expression)
+                                        parseSendOrFunctionLiteral([, expression)
+                                          looksLikeFunctionBody(])
+                                          parseSend([, expression)
+                                            ensureIdentifier([, expression)
+                                            parseArgumentsOpt(b)
+                                              parseArguments(b)
+                                                parseArgumentsRest(()
+                                                  parseExpression(()
+                                                    parsePrecedenceExpression((, 1, true)
+                                                      parseUnaryExpression((, true)
+                                                        parsePrimary((, expression)
+                                                          parseLiteralListSuffix((, null)
+                                                            rewriteSquareBrackets(()
+                                                              link([, ])
+                                                              rewriter()
+                      parseExpressionWithoutCascade(:)
+                        parsePrecedenceExpression(:, 1, false)
+                          parseUnaryExpression(:, false)
+                            parsePrimary(:, expression)
+                              parseLiteralNull(:)
+                    parseConditionalExpressionRest(a)
+                      listener: beginConditionalExpression(?)
+                      parseExpressionWithoutCascade(?)
+                        parsePrecedenceExpression(?, 1, false)
+                          parseUnaryExpression(?, false)
+                            parsePrimary(?, expression)
+                              listener: handleNoTypeArguments([)
+                              parseLiteralListSuffix(?, null)
+                                parseExpression([)
+                                  parsePrecedenceExpression([, 1, true)
+                                    parseUnaryExpression([, true)
+                                      parsePrimary([, expression)
+                                        parseSendOrFunctionLiteral([, expression)
+                                          looksLikeFunctionBody(])
+                                          parseSend([, expression)
+                                            ensureIdentifier([, expression)
+                                              listener: handleIdentifier(b, expression)
+                                            listener: handleNoTypeArguments(()
+                                            parseArgumentsOpt(b)
+                                              parseArguments(b)
+                                                parseArgumentsRest(()
+                                                  listener: beginArguments(()
+                                                  parseExpression(()
+                                                    parsePrecedenceExpression((, 1, true)
+                                                      parseUnaryExpression((, true)
+                                                        parsePrimary((, expression)
+                                                          listener: handleNoTypeArguments([])
+                                                          parseLiteralListSuffix((, null)
+                                                            rewriteSquareBrackets(()
+                                                              link([, ])
+                                                              rewriter()
+                                                            listener: handleLiteralList(0, [, null, ])
+                                                  listener: endArguments(1, (, ))
+                                            listener: handleSend(b, ])
+                                listener: handleLiteralList(1, [, null, ])
+                      ensureColon(])
+                      listener: handleConditionalExpressionColon()
+                      parseExpressionWithoutCascade(:)
+                        parsePrecedenceExpression(:, 1, false)
+                          parseUnaryExpression(:, false)
+                            parsePrimary(:, expression)
+                              parseLiteralNull(:)
+                                listener: handleLiteralNull(null)
+                      listener: endConditionalExpression(?, :)
                 ensureSemicolon(null)
                 listener: endReturnStatement(true, return, ;)
                 inGenerator()
diff --git a/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_3.dart.intertwined.expect b/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_3.dart.intertwined.expect
index f19df50..0df432d 100644
--- a/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_3.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_3.dart.intertwined.expect
@@ -67,8 +67,6 @@
                         parsePrimary(!=, expression)
                           parseLiteralNull(!=)
                             listener: handleLiteralNull(null)
-                    listener: endBinaryExpression(!=)
-                    parseNullAwareBracketOrConditionalExpressionRest(null, Instance of 'NoTypeParamOrArg')
                       canParseAsConditional(?)
                         parseExpressionWithoutCascade(?)
                           parsePrecedenceExpression(?, 1, false)
@@ -92,43 +90,67 @@
                                     rewriteSquareBrackets(const)
                                       link([, ])
                                       rewriter()
-                      parseConditionalExpressionRest(null)
-                        listener: beginConditionalExpression(?)
-                        parseExpressionWithoutCascade(?)
-                          parsePrecedenceExpression(?, 1, false)
-                            parseUnaryExpression(?, false)
-                              parsePrimary(?, expression)
-                                listener: handleNoTypeArguments([)
-                                parseLiteralListSuffix(?, null)
-                                  parseExpression([)
-                                    parsePrecedenceExpression([, 1, true)
-                                      parseUnaryExpression([, true)
-                                        parsePrimary([, expression)
-                                          parseSendOrFunctionLiteral([, expression)
-                                            parseSend([, expression)
-                                              ensureIdentifier([, expression)
-                                                listener: handleIdentifier(a, expression)
-                                              listener: handleNoTypeArguments(])
-                                              parseArgumentsOpt(a)
-                                                listener: handleNoArguments(])
-                                              listener: handleSend(a, ])
-                                  listener: handleLiteralList(1, [, null, ])
-                        ensureColon(])
-                        listener: handleConditionalExpressionColon()
-                        parseExpressionWithoutCascade(:)
-                          parsePrecedenceExpression(:, 1, false)
-                            parseUnaryExpression(:, false)
-                              parsePrimary(:, expression)
-                                parseConstExpression(:)
-                                  listener: beginConstLiteral([])
-                                  listener: handleNoTypeArguments([])
-                                  parseLiteralListSuffix(const, const)
-                                    rewriteSquareBrackets(const)
-                                      link([, ])
-                                      rewriter()
-                                    listener: handleLiteralList(0, [, const, ])
-                                  listener: endConstLiteral(;)
-                        listener: endConditionalExpression(?, :)
+                    listener: endBinaryExpression(!=)
+                    canParseAsConditional(?)
+                      parseExpressionWithoutCascade(?)
+                        parsePrecedenceExpression(?, 1, false)
+                          parseUnaryExpression(?, false)
+                            parsePrimary(?, expression)
+                              parseLiteralListSuffix(?, null)
+                                parseExpression([)
+                                  parsePrecedenceExpression([, 1, true)
+                                    parseUnaryExpression([, true)
+                                      parsePrimary([, expression)
+                                        parseSendOrFunctionLiteral([, expression)
+                                          parseSend([, expression)
+                                            ensureIdentifier([, expression)
+                                            parseArgumentsOpt(a)
+                      parseExpressionWithoutCascade(:)
+                        parsePrecedenceExpression(:, 1, false)
+                          parseUnaryExpression(:, false)
+                            parsePrimary(:, expression)
+                              parseConstExpression(:)
+                                parseLiteralListSuffix(const, const)
+                                  rewriteSquareBrackets(const)
+                                    link([, ])
+                                    rewriter()
+                    parseConditionalExpressionRest(null)
+                      listener: beginConditionalExpression(?)
+                      parseExpressionWithoutCascade(?)
+                        parsePrecedenceExpression(?, 1, false)
+                          parseUnaryExpression(?, false)
+                            parsePrimary(?, expression)
+                              listener: handleNoTypeArguments([)
+                              parseLiteralListSuffix(?, null)
+                                parseExpression([)
+                                  parsePrecedenceExpression([, 1, true)
+                                    parseUnaryExpression([, true)
+                                      parsePrimary([, expression)
+                                        parseSendOrFunctionLiteral([, expression)
+                                          parseSend([, expression)
+                                            ensureIdentifier([, expression)
+                                              listener: handleIdentifier(a, expression)
+                                            listener: handleNoTypeArguments(])
+                                            parseArgumentsOpt(a)
+                                              listener: handleNoArguments(])
+                                            listener: handleSend(a, ])
+                                listener: handleLiteralList(1, [, null, ])
+                      ensureColon(])
+                      listener: handleConditionalExpressionColon()
+                      parseExpressionWithoutCascade(:)
+                        parsePrecedenceExpression(:, 1, false)
+                          parseUnaryExpression(:, false)
+                            parsePrimary(:, expression)
+                              parseConstExpression(:)
+                                listener: beginConstLiteral([])
+                                listener: handleNoTypeArguments([])
+                                parseLiteralListSuffix(const, const)
+                                  rewriteSquareBrackets(const)
+                                    link([, ])
+                                    rewriter()
+                                  listener: handleLiteralList(0, [, const, ])
+                                listener: endConstLiteral(;)
+                      listener: endConditionalExpression(?, :)
                 ensureSemicolon(])
                 listener: endReturnStatement(true, return, ;)
                 inGenerator()
diff --git a/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_4.dart.intertwined.expect b/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_4.dart.intertwined.expect
index efef438..1f6b298 100644
--- a/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_4.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/non-nnbd/issue_40267_conditional_4.dart.intertwined.expect
@@ -163,8 +163,6 @@
                                                         parseSend([, expression)
                                                           ensureIdentifier([, expression)
                                                           parseArgumentsOpt(a)
-                              listener: endBinaryExpression(&&)
-                              parseNullAwareBracketOrConditionalExpressionRest(], Instance of 'NoTypeParamOrArg')
                                 canParseAsConditional(?)
                                   parseExpressionWithoutCascade(?)
                                     parsePrecedenceExpression(?, 1, false)
@@ -211,77 +209,124 @@
                                                       parseSend([, expression)
                                                         ensureIdentifier([, expression)
                                                         parseArgumentsOpt(a)
-                                parseConditionalExpressionRest(])
-                                  listener: beginConditionalExpression(?)
-                                  parseExpressionWithoutCascade(?)
-                                    parsePrecedenceExpression(?, 1, false)
-                                      parseUnaryExpression(?, false)
-                                        parsePrimary(?, expression)
-                                          listener: handleNoTypeArguments([)
-                                          parseLiteralListSuffix(?, null)
-                                            parseExpression([)
-                                              parsePrecedenceExpression([, 1, true)
-                                                parseUnaryExpression([, true)
-                                                  parsePrimary([, expression)
-                                                    parseSendOrFunctionLiteral([, expression)
-                                                      parseSend([, expression)
-                                                        ensureIdentifier([, expression)
-                                                          listener: handleIdentifier(a, expression)
-                                                        listener: handleNoTypeArguments(,)
-                                                        parseArgumentsOpt(a)
-                                                          listener: handleNoArguments(,)
-                                                        listener: handleSend(a, ,)
-                                            parseExpression(,)
-                                              parsePrecedenceExpression(,, 1, true)
-                                                parseUnaryExpression(,, true)
-                                                  parsePrimary(,, expression)
-                                                    parseSendOrFunctionLiteral(,, expression)
-                                                      looksLikeFunctionBody(])
-                                                      parseSend(,, expression)
-                                                        ensureIdentifier(,, expression)
-                                                          listener: handleIdentifier(e, expression)
-                                                        listener: handleNoTypeArguments(()
-                                                        parseArgumentsOpt(e)
-                                                          parseArguments(e)
-                                                            parseArgumentsRest(()
-                                                              listener: beginArguments(()
-                                                              parseExpression(()
-                                                                parsePrecedenceExpression((, 1, true)
-                                                                  parseUnaryExpression((, true)
-                                                                    parsePrimary((, expression)
-                                                                      parseSendOrFunctionLiteral((, expression)
-                                                                        parseSend((, expression)
-                                                                          ensureIdentifier((, expression)
-                                                                            listener: handleIdentifier(f, expression)
-                                                                          listener: handleNoTypeArguments())
-                                                                          parseArgumentsOpt(f)
-                                                                            listener: handleNoArguments())
-                                                                          listener: handleSend(f, ))
-                                                              listener: endArguments(1, (, ))
-                                                        listener: handleSend(e, ])
-                                            listener: handleLiteralList(2, [, null, ])
-                                  ensureColon(])
-                                  listener: handleConditionalExpressionColon()
-                                  parseExpressionWithoutCascade(:)
-                                    parsePrecedenceExpression(:, 1, false)
-                                      parseUnaryExpression(:, false)
-                                        parsePrimary(:, expression)
-                                          listener: handleNoTypeArguments([)
-                                          parseLiteralListSuffix(:, null)
-                                            parseExpression([)
-                                              parsePrecedenceExpression([, 1, true)
-                                                parseUnaryExpression([, true)
-                                                  parsePrimary([, expression)
-                                                    parseSendOrFunctionLiteral([, expression)
-                                                      parseSend([, expression)
-                                                        ensureIdentifier([, expression)
-                                                          listener: handleIdentifier(a, expression)
-                                                        listener: handleNoTypeArguments(])
-                                                        parseArgumentsOpt(a)
-                                                          listener: handleNoArguments(])
-                                                        listener: handleSend(a, ])
-                                            listener: handleLiteralList(1, [, null, ])
-                                  listener: endConditionalExpression(?, :)
+                              listener: endBinaryExpression(&&)
+                              canParseAsConditional(?)
+                                parseExpressionWithoutCascade(?)
+                                  parsePrecedenceExpression(?, 1, false)
+                                    parseUnaryExpression(?, false)
+                                      parsePrimary(?, expression)
+                                        parseLiteralListSuffix(?, null)
+                                          parseExpression([)
+                                            parsePrecedenceExpression([, 1, true)
+                                              parseUnaryExpression([, true)
+                                                parsePrimary([, expression)
+                                                  parseSendOrFunctionLiteral([, expression)
+                                                    parseSend([, expression)
+                                                      ensureIdentifier([, expression)
+                                                      parseArgumentsOpt(a)
+                                          parseExpression(,)
+                                            parsePrecedenceExpression(,, 1, true)
+                                              parseUnaryExpression(,, true)
+                                                parsePrimary(,, expression)
+                                                  parseSendOrFunctionLiteral(,, expression)
+                                                    looksLikeFunctionBody(])
+                                                    parseSend(,, expression)
+                                                      ensureIdentifier(,, expression)
+                                                      parseArgumentsOpt(e)
+                                                        parseArguments(e)
+                                                          parseArgumentsRest(()
+                                                            parseExpression(()
+                                                              parsePrecedenceExpression((, 1, true)
+                                                                parseUnaryExpression((, true)
+                                                                  parsePrimary((, expression)
+                                                                    parseSendOrFunctionLiteral((, expression)
+                                                                      parseSend((, expression)
+                                                                        ensureIdentifier((, expression)
+                                                                        parseArgumentsOpt(f)
+                                parseExpressionWithoutCascade(:)
+                                  parsePrecedenceExpression(:, 1, false)
+                                    parseUnaryExpression(:, false)
+                                      parsePrimary(:, expression)
+                                        parseLiteralListSuffix(:, null)
+                                          parseExpression([)
+                                            parsePrecedenceExpression([, 1, true)
+                                              parseUnaryExpression([, true)
+                                                parsePrimary([, expression)
+                                                  parseSendOrFunctionLiteral([, expression)
+                                                    parseSend([, expression)
+                                                      ensureIdentifier([, expression)
+                                                      parseArgumentsOpt(a)
+                              parseConditionalExpressionRest(])
+                                listener: beginConditionalExpression(?)
+                                parseExpressionWithoutCascade(?)
+                                  parsePrecedenceExpression(?, 1, false)
+                                    parseUnaryExpression(?, false)
+                                      parsePrimary(?, expression)
+                                        listener: handleNoTypeArguments([)
+                                        parseLiteralListSuffix(?, null)
+                                          parseExpression([)
+                                            parsePrecedenceExpression([, 1, true)
+                                              parseUnaryExpression([, true)
+                                                parsePrimary([, expression)
+                                                  parseSendOrFunctionLiteral([, expression)
+                                                    parseSend([, expression)
+                                                      ensureIdentifier([, expression)
+                                                        listener: handleIdentifier(a, expression)
+                                                      listener: handleNoTypeArguments(,)
+                                                      parseArgumentsOpt(a)
+                                                        listener: handleNoArguments(,)
+                                                      listener: handleSend(a, ,)
+                                          parseExpression(,)
+                                            parsePrecedenceExpression(,, 1, true)
+                                              parseUnaryExpression(,, true)
+                                                parsePrimary(,, expression)
+                                                  parseSendOrFunctionLiteral(,, expression)
+                                                    looksLikeFunctionBody(])
+                                                    parseSend(,, expression)
+                                                      ensureIdentifier(,, expression)
+                                                        listener: handleIdentifier(e, expression)
+                                                      listener: handleNoTypeArguments(()
+                                                      parseArgumentsOpt(e)
+                                                        parseArguments(e)
+                                                          parseArgumentsRest(()
+                                                            listener: beginArguments(()
+                                                            parseExpression(()
+                                                              parsePrecedenceExpression((, 1, true)
+                                                                parseUnaryExpression((, true)
+                                                                  parsePrimary((, expression)
+                                                                    parseSendOrFunctionLiteral((, expression)
+                                                                      parseSend((, expression)
+                                                                        ensureIdentifier((, expression)
+                                                                          listener: handleIdentifier(f, expression)
+                                                                        listener: handleNoTypeArguments())
+                                                                        parseArgumentsOpt(f)
+                                                                          listener: handleNoArguments())
+                                                                        listener: handleSend(f, ))
+                                                            listener: endArguments(1, (, ))
+                                                      listener: handleSend(e, ])
+                                          listener: handleLiteralList(2, [, null, ])
+                                ensureColon(])
+                                listener: handleConditionalExpressionColon()
+                                parseExpressionWithoutCascade(:)
+                                  parsePrecedenceExpression(:, 1, false)
+                                    parseUnaryExpression(:, false)
+                                      parsePrimary(:, expression)
+                                        listener: handleNoTypeArguments([)
+                                        parseLiteralListSuffix(:, null)
+                                          parseExpression([)
+                                            parsePrecedenceExpression([, 1, true)
+                                              parseUnaryExpression([, true)
+                                                parsePrimary([, expression)
+                                                  parseSendOrFunctionLiteral([, expression)
+                                                    parseSend([, expression)
+                                                      ensureIdentifier([, expression)
+                                                        listener: handleIdentifier(a, expression)
+                                                      listener: handleNoTypeArguments(])
+                                                      parseArgumentsOpt(a)
+                                                        listener: handleNoArguments(])
+                                                      listener: handleSend(a, ])
+                                          listener: handleLiteralList(1, [, null, ])
+                                listener: endConditionalExpression(?, :)
                           listener: endArguments(1, (, ))
                     listener: handleSend(addAll, ;)
                   listener: endBinaryExpression(..)
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_01/.dart_tool/package_config.json b/pkg/front_end/test/language_versioning/data/specified_packages_01/.dart_tool/package_config.json
new file mode 100644
index 0000000..9280e5a
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_01/.dart_tool/package_config.json
@@ -0,0 +1,9 @@
+{
+    "configVersion": 2,
+    "packages": [
+        {
+            "name": "foo",
+            "rootUri": "../foo2/"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_01/.packages b/pkg/front_end/test/language_versioning/data/specified_packages_01/.packages
new file mode 100644
index 0000000..a0a43fc
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_01/.packages
@@ -0,0 +1 @@
+foo:foo1/
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_01/foo1/foo.dart b/pkg/front_end/test/language_versioning/data/specified_packages_01/foo1/foo.dart
new file mode 100644
index 0000000..4d80ea2
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_01/foo1/foo.dart
@@ -0,0 +1,5 @@
+// No language version --- this file shouldn't even be compiled.
+
+int notNamedFoo() {
+  return 42;
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_01/foo2/foo.dart b/pkg/front_end/test/language_versioning/data/specified_packages_01/foo2/foo.dart
new file mode 100644
index 0000000..0f5e6ce
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_01/foo2/foo.dart
@@ -0,0 +1,5 @@
+/*library: languageVersion=2.8*/
+
+String foo() {
+  return "42";
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_01/main.dart b/pkg/front_end/test/language_versioning/data/specified_packages_01/main.dart
new file mode 100644
index 0000000..f5a4c34
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_01/main.dart
@@ -0,0 +1,17 @@
+// 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.
+
+// Set version of this file (not technically in package) explicitly to test as
+// much as possibly separately.
+
+// @dart = 2.4
+
+import 'package:foo/foo.dart';
+
+/*library: languageVersion=2.4*/
+
+main() {
+  var result = foo();
+  print(result);
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_01/pubspec.yaml b/pkg/front_end/test/language_versioning/data/specified_packages_01/pubspec.yaml
new file mode 100644
index 0000000..ff98642
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_01/pubspec.yaml
@@ -0,0 +1,5 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Analyzer workaround, see https://github.com/dart-lang/sdk/issues/37513
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_01/test.options b/pkg/front_end/test/language_versioning/data/specified_packages_01/test.options
new file mode 100644
index 0000000..9044751
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_01/test.options
@@ -0,0 +1,2 @@
+# Point to .packages => Standard layout; redirect to .dart_tool/package_config.json
+--packages=.packages
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/.dart_tool/package_config.json b/pkg/front_end/test/language_versioning/data/specified_packages_02/.dart_tool/package_config.json
new file mode 100644
index 0000000..9280e5a
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/.dart_tool/package_config.json
@@ -0,0 +1,9 @@
+{
+    "configVersion": 2,
+    "packages": [
+        {
+            "name": "foo",
+            "rootUri": "../foo2/"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/.packagesX b/pkg/front_end/test/language_versioning/data/specified_packages_02/.packagesX
new file mode 100644
index 0000000..a0a43fc
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/.packagesX
@@ -0,0 +1 @@
+foo:foo1/
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/foo1/foo.dart b/pkg/front_end/test/language_versioning/data/specified_packages_02/foo1/foo.dart
new file mode 100644
index 0000000..bb0fb7c
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/foo1/foo.dart
@@ -0,0 +1,5 @@
+/*library: languageVersion=2.8*/
+
+int notNamedFoo() {
+  return 42;
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/foo2/foo.dart b/pkg/front_end/test/language_versioning/data/specified_packages_02/foo2/foo.dart
new file mode 100644
index 0000000..449c3f0
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/foo2/foo.dart
@@ -0,0 +1,5 @@
+// No language version --- this file shouldn't even be compiled.
+
+String foo() {
+  return "42";
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/main.dart b/pkg/front_end/test/language_versioning/data/specified_packages_02/main.dart
new file mode 100644
index 0000000..3dc5e95
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/main.dart
@@ -0,0 +1,17 @@
+// 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.
+
+// Set version of this file (not technically in package) explicitly to test as
+// much as possibly separately.
+
+// @dart = 2.4
+
+import 'package:foo/foo.dart';
+
+/*library: languageVersion=2.4*/
+
+main() {
+  var result = notNamedFoo();
+  print(result);
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/pubspec.yaml b/pkg/front_end/test/language_versioning/data/specified_packages_02/pubspec.yaml
new file mode 100644
index 0000000..ff98642
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/pubspec.yaml
@@ -0,0 +1,5 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Analyzer workaround, see https://github.com/dart-lang/sdk/issues/37513
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_02/test.options b/pkg/front_end/test/language_versioning/data/specified_packages_02/test.options
new file mode 100644
index 0000000..d3ccc47
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_02/test.options
@@ -0,0 +1,2 @@
+# Point to .packagesX => non-standard layout; use it directly
+--packages=.packagesX
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_03/.packages b/pkg/front_end/test/language_versioning/data/specified_packages_03/.packages
new file mode 100644
index 0000000..a0a43fc
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_03/.packages
@@ -0,0 +1 @@
+foo:foo1/
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_03/foo1/foo.dart b/pkg/front_end/test/language_versioning/data/specified_packages_03/foo1/foo.dart
new file mode 100644
index 0000000..4d80ea2
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_03/foo1/foo.dart
@@ -0,0 +1,5 @@
+// No language version --- this file shouldn't even be compiled.
+
+int notNamedFoo() {
+  return 42;
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_03/foo2/foo.dart b/pkg/front_end/test/language_versioning/data/specified_packages_03/foo2/foo.dart
new file mode 100644
index 0000000..0f5e6ce
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_03/foo2/foo.dart
@@ -0,0 +1,5 @@
+/*library: languageVersion=2.8*/
+
+String foo() {
+  return "42";
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_03/main.dart b/pkg/front_end/test/language_versioning/data/specified_packages_03/main.dart
new file mode 100644
index 0000000..f5a4c34
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_03/main.dart
@@ -0,0 +1,17 @@
+// 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.
+
+// Set version of this file (not technically in package) explicitly to test as
+// much as possibly separately.
+
+// @dart = 2.4
+
+import 'package:foo/foo.dart';
+
+/*library: languageVersion=2.4*/
+
+main() {
+  var result = foo();
+  print(result);
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_03/package_config.json b/pkg/front_end/test/language_versioning/data/specified_packages_03/package_config.json
new file mode 100644
index 0000000..d67acb0
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_03/package_config.json
@@ -0,0 +1,9 @@
+{
+    "configVersion": 2,
+    "packages": [
+        {
+            "name": "foo",
+            "rootUri": "foo2/"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_03/pubspec.yaml b/pkg/front_end/test/language_versioning/data/specified_packages_03/pubspec.yaml
new file mode 100644
index 0000000..ff98642
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_03/pubspec.yaml
@@ -0,0 +1,5 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Analyzer workaround, see https://github.com/dart-lang/sdk/issues/37513
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_03/test.options b/pkg/front_end/test/language_versioning/data/specified_packages_03/test.options
new file mode 100644
index 0000000..c01a27e
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_03/test.options
@@ -0,0 +1,2 @@
+# Point to package_config.json => non-standard layout; use it directly
+--packages=package_config.json
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_04/.dart_tool/package_config.json b/pkg/front_end/test/language_versioning/data/specified_packages_04/.dart_tool/package_config.json
new file mode 100644
index 0000000..c4b490f
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_04/.dart_tool/package_config.json
@@ -0,0 +1 @@
+/*error: PackagesFileFormat*/foo:foo2/
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_04/.packages b/pkg/front_end/test/language_versioning/data/specified_packages_04/.packages
new file mode 100644
index 0000000..a0a43fc
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_04/.packages
@@ -0,0 +1 @@
+foo:foo1/
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_04/foo1/foo.dart b/pkg/front_end/test/language_versioning/data/specified_packages_04/foo1/foo.dart
new file mode 100644
index 0000000..4d80ea2
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_04/foo1/foo.dart
@@ -0,0 +1,5 @@
+// No language version --- this file shouldn't even be compiled.
+
+int notNamedFoo() {
+  return 42;
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_04/foo2/foo.dart b/pkg/front_end/test/language_versioning/data/specified_packages_04/foo2/foo.dart
new file mode 100644
index 0000000..449c3f0
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_04/foo2/foo.dart
@@ -0,0 +1,5 @@
+// No language version --- this file shouldn't even be compiled.
+
+String foo() {
+  return "42";
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_04/main.dart b/pkg/front_end/test/language_versioning/data/specified_packages_04/main.dart
new file mode 100644
index 0000000..e625dcd
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_04/main.dart
@@ -0,0 +1,17 @@
+// 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.
+
+// Set version of this file (not technically in package) explicitly to test as
+// much as possibly separately.
+
+// @dart = 2.4
+
+import /*error: UntranslatableUri*/ 'package:foo/foo.dart';
+
+/*library: languageVersion=2.4*/
+
+main() {
+  var result = /*error: MethodNotFound*/ notNamedFoo();
+  print(result);
+}
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_04/null b/pkg/front_end/test/language_versioning/data/specified_packages_04/null
new file mode 100644
index 0000000..508fd9c
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_04/null
@@ -0,0 +1 @@
+/*error: PackageNotFound*/
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_04/pubspec.yaml b/pkg/front_end/test/language_versioning/data/specified_packages_04/pubspec.yaml
new file mode 100644
index 0000000..ff98642
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_04/pubspec.yaml
@@ -0,0 +1,5 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Analyzer workaround, see https://github.com/dart-lang/sdk/issues/37513
\ No newline at end of file
diff --git a/pkg/front_end/test/language_versioning/data/specified_packages_04/test.options b/pkg/front_end/test/language_versioning/data/specified_packages_04/test.options
new file mode 100644
index 0000000..5c8ed21
--- /dev/null
+++ b/pkg/front_end/test/language_versioning/data/specified_packages_04/test.options
@@ -0,0 +1,2 @@
+# Point to .packages => Standard layout; redirect to .dart_tool/package_config.json which in this case isn't a json file. That's an error!
+--packages=.packages
diff --git a/pkg/front_end/test/language_versioning/language_versioning_test.dart b/pkg/front_end/test/language_versioning/language_versioning_test.dart
index 8b4b12b..66b3e37 100644
--- a/pkg/front_end/test/language_versioning/language_versioning_test.dart
+++ b/pkg/front_end/test/language_versioning/language_versioning_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:io' show Directory, Platform;
+import 'dart:io' show Directory, File, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, StringDataInterpreter, runTests;
@@ -43,8 +43,24 @@
       : super(marker, name);
 
   @override
-  void customizeCompilerOptions(CompilerOptions options) {
+  void customizeCompilerOptions(CompilerOptions options, TestData testData) {
     options.currentSdkVersion = "2.8";
+
+    File f = new File.fromUri(testData.testFileUri.resolve("test.options"));
+    if (f.existsSync()) {
+      List<String> lines = f.readAsStringSync().split("\n");
+      for (String line in lines) {
+        const String packages = "--packages=";
+        if (line == "" || line.startsWith("#")) continue;
+        if (line.startsWith(packages)) {
+          String value = line.substring(packages.length);
+          options.packagesFileUri = testData.entryPoint.resolve(value);
+          print("Setting package file uri to ${options.packagesFileUri}");
+        } else {
+          throw "Unsupported: $line";
+        }
+      }
+    }
   }
 }
 
diff --git a/pkg/front_end/test/parser_test_parser.dart b/pkg/front_end/test/parser_test_parser.dart
index d8a9095..e916571 100644
--- a/pkg/front_end/test/parser_test_parser.dart
+++ b/pkg/front_end/test/parser_test_parser.dart
@@ -1218,18 +1218,6 @@
     return result;
   }
 
-  Token parseNullAwareBracketOrConditionalExpressionRest(
-      Token token, TypeParamOrArgInfo typeArg) {
-    doPrint('parseNullAwareBracketOrConditionalExpressionRest('
-        '$token, '
-        '$typeArg)');
-    indent++;
-    var result =
-        super.parseNullAwareBracketOrConditionalExpressionRest(token, typeArg);
-    indent--;
-    return result;
-  }
-
   Token parseConditionalExpressionRest(Token token) {
     doPrint('parseConditionalExpressionRest(' '$token)');
     indent++;
@@ -1755,6 +1743,14 @@
     return result;
   }
 
+  bool looksLikeExpression(Token token) {
+    doPrint('looksLikeExpression(' '$token)');
+    indent++;
+    var result = super.looksLikeExpression(token);
+    indent--;
+    return result;
+  }
+
   bool looksLikeAwaitExpression(Token token) {
     doPrint('looksLikeAwaitExpression(' '$token)');
     indent++;
@@ -1763,6 +1759,14 @@
     return result;
   }
 
+  bool looksLikeYieldStatement(Token token) {
+    doPrint('looksLikeYieldStatement(' '$token)');
+    indent++;
+    var result = super.looksLikeYieldStatement(token);
+    indent--;
+    return result;
+  }
+
   Token parseAwaitExpression(Token token, bool allowCascades) {
     doPrint('parseAwaitExpression(' '$token, ' '$allowCascades)');
     indent++;
diff --git a/pkg/front_end/test/patching/patching_test.dart b/pkg/front_end/test/patching/patching_test.dart
index 753ef203..389a779 100644
--- a/pkg/front_end/test/patching/patching_test.dart
+++ b/pkg/front_end/test/patching/patching_test.dart
@@ -53,7 +53,7 @@
             experimentalFlags: experimentalFlags);
 
   @override
-  void customizeCompilerOptions(CompilerOptions options) {
+  void customizeCompilerOptions(CompilerOptions options, TestData testData) {
     options.currentSdkVersion = "2.9999";
   }
 }
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 1552922..f38f1d0 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -538,6 +538,7 @@
 largest
 lattice
 layer
+layout
 leafp
 len
 lets
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index c043412..0d1bb73 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -102,6 +102,7 @@
 confirm
 consecutive
 considering
+consolidated
 constrains
 consts
 contract
diff --git a/pkg/front_end/testcases/extensions/extension_methods.dart.hierarchy.expect b/pkg/front_end/testcases/extensions/extension_methods.dart.hierarchy.expect
index 70bc80b..468454b 100644
--- a/pkg/front_end/testcases/extensions/extension_methods.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/extensions/extension_methods.dart.hierarchy.expect
@@ -42,7 +42,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general/function_type_is_check.dart.hierarchy.expect b/pkg/front_end/testcases/general/function_type_is_check.dart.hierarchy.expect
index 257f1e9..4f5c506 100644
--- a/pkg/front_end/testcases/general/function_type_is_check.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general/function_type_is_check.dart.hierarchy.expect
@@ -24,7 +24,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general/implicit_scope_test.dart.hierarchy.expect b/pkg/front_end/testcases/general/implicit_scope_test.dart.hierarchy.expect
index ad35f25..e04e5f9 100644
--- a/pkg/front_end/testcases/general/implicit_scope_test.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general/implicit_scope_test.dart.hierarchy.expect
@@ -43,7 +43,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.hierarchy.expect b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.hierarchy.expect
index 56e565b..3d588b6 100644
--- a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.hierarchy.expect
@@ -198,7 +198,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.hierarchy.expect b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.hierarchy.expect
index 4b4ba3b..1eaa41a 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.hierarchy.expect
@@ -82,7 +82,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.hierarchy.expect b/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.hierarchy.expect
index 4b4ba3b..1eaa41a 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.hierarchy.expect
@@ -82,7 +82,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general/redirection_type_arguments.dart.hierarchy.expect b/pkg/front_end/testcases/general/redirection_type_arguments.dart.hierarchy.expect
index 41b4b7f..8fd8c13 100644
--- a/pkg/front_end/testcases/general/redirection_type_arguments.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general/redirection_type_arguments.dart.hierarchy.expect
@@ -61,7 +61,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart
index 9a01ce1..d39e9de 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart
@@ -20,6 +20,7 @@
   // old syntax: variable named "b" of type "U" of a function called 'Function'.
   static void foo13(void Function(U b)) { return null; }
   static U foo14 = null;
+  static U Function(U) foo15 = null;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect
index 5db43ea..725cfb7 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect
@@ -34,11 +34,20 @@
 //   static U foo14 = null;
 //          ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:10: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:21: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//                     ^
+//
 import self as self;
 import "dart:core" as core;
 
 class Foo<U extends core::Object* = dynamic> extends core::Object {
   static field invalid-type foo14;
+  static field (invalid-type) →* invalid-type foo15;
   synthetic constructor •() → self::Foo<self::Foo::U*>*
     ;
   static method foo1() → dynamic
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect
index 966ed95..dfd67aa 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect
@@ -34,6 +34,14 @@
 //   static U foo14 = null;
 //          ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:10: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:21: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//                     ^
+//
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
 //                    ^
@@ -58,31 +66,24 @@
 //     void Function (U y) foo7 = (U y) => y;
 //                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:12:19: Error: Type variables can't be used in static members.
-//     void Function (U y) foo7 = (U y) => y;
-//                   ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:16:31: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:16:21: Error: Type variables can't be used in static members.
 //   static void foo10(U Function()) { return null; }
-//                               ^
+//                     ^
 //
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:19:35: Error: Type variables can't be used in static members.
 //   static void foo12(void Function(U) b) { return null; }
 //                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:19:34: Error: Type variables can't be used in static members.
-//   static void foo12(void Function(U) b) { return null; }
-//                                  ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:34: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:35: Error: Type variables can't be used in static members.
 //   static void foo13(void Function(U b)) { return null; }
-//                                  ^
+//                                   ^
 //
 import self as self;
 import "dart:core" as core;
 
 class Foo<U extends core::Object* = dynamic> extends core::Object {
   static field invalid-type foo14 = null;
+  static field (invalid-type) →* invalid-type foo15 = null;
   synthetic constructor •() → self::Foo<self::Foo::U*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect
index 966ed95..dfd67aa 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect
@@ -34,6 +34,14 @@
 //   static U foo14 = null;
 //          ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:10: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:21: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//                     ^
+//
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
 //                    ^
@@ -58,31 +66,24 @@
 //     void Function (U y) foo7 = (U y) => y;
 //                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:12:19: Error: Type variables can't be used in static members.
-//     void Function (U y) foo7 = (U y) => y;
-//                   ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:16:31: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:16:21: Error: Type variables can't be used in static members.
 //   static void foo10(U Function()) { return null; }
-//                               ^
+//                     ^
 //
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:19:35: Error: Type variables can't be used in static members.
 //   static void foo12(void Function(U) b) { return null; }
 //                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:19:34: Error: Type variables can't be used in static members.
-//   static void foo12(void Function(U) b) { return null; }
-//                                  ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:34: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:35: Error: Type variables can't be used in static members.
 //   static void foo13(void Function(U b)) { return null; }
-//                                  ^
+//                                   ^
 //
 import self as self;
 import "dart:core" as core;
 
 class Foo<U extends core::Object* = dynamic> extends core::Object {
   static field invalid-type foo14 = null;
+  static field (invalid-type) →* invalid-type foo15 = null;
   synthetic constructor •() → self::Foo<self::Foo::U*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart
index 7c56bec..78b773e 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart
@@ -20,6 +20,7 @@
   // old syntax: variable named "b" of type "U" of a function called 'Function'.
   static void foo13(void Function(U b)) { return null; }
   static U foo14 = null;
+  static U Function(U) foo15 = null;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect
index ef530f4..d6da116 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect
@@ -34,6 +34,14 @@
 //   static U foo14 = null;
 //          ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:10: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:21: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//                     ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -48,8 +56,10 @@
   static method foo12 = self::Foo|foo12;
   static method foo13 = self::Foo|foo13;
   static field foo14 = self::Foo|foo14;
+  static field foo15 = self::Foo|foo15;
 }
 static field invalid-type Foo|foo14;
+static field (invalid-type) →* invalid-type Foo|foo15;
 static method Foo|foo1() → dynamic
   ;
 static method Foo|foo2(dynamic x) → void
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect
index e6a1aa9..c1f1018 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect
@@ -34,6 +34,14 @@
 //   static U foo14 = null;
 //          ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:10: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:21: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//                     ^
+//
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
 //                    ^
@@ -58,25 +66,17 @@
 //     void Function (U y) foo7 = (U y) => y;
 //                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:12:19: Error: Type variables can't be used in static members.
-//     void Function (U y) foo7 = (U y) => y;
-//                   ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:16:31: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:16:21: Error: Type variables can't be used in static members.
 //   static void foo10(U Function()) { return null; }
-//                               ^
+//                     ^
 //
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:19:35: Error: Type variables can't be used in static members.
 //   static void foo12(void Function(U) b) { return null; }
 //                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:19:34: Error: Type variables can't be used in static members.
-//   static void foo12(void Function(U) b) { return null; }
-//                                  ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:34: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:35: Error: Type variables can't be used in static members.
 //   static void foo13(void Function(U b)) { return null; }
-//                                  ^
+//                                   ^
 //
 import self as self;
 import "dart:core" as core;
@@ -92,8 +92,10 @@
   static method foo12 = self::Foo|foo12;
   static method foo13 = self::Foo|foo13;
   static field foo14 = self::Foo|foo14;
+  static field foo15 = self::Foo|foo15;
 }
 static field invalid-type Foo|foo14 = null;
+static field (invalid-type) →* invalid-type Foo|foo15 = null;
 static method Foo|foo1() → dynamic {
   return null;
 }
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect
index e6a1aa9..c1f1018 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect
@@ -34,6 +34,14 @@
 //   static U foo14 = null;
 //          ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:10: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:21: Error: Type variables can't be used in static members.
+//   static U Function(U) foo15 = null;
+//                     ^
+//
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
 //                    ^
@@ -58,25 +66,17 @@
 //     void Function (U y) foo7 = (U y) => y;
 //                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:12:19: Error: Type variables can't be used in static members.
-//     void Function (U y) foo7 = (U y) => y;
-//                   ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:16:31: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:16:21: Error: Type variables can't be used in static members.
 //   static void foo10(U Function()) { return null; }
-//                               ^
+//                     ^
 //
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:19:35: Error: Type variables can't be used in static members.
 //   static void foo12(void Function(U) b) { return null; }
 //                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:19:34: Error: Type variables can't be used in static members.
-//   static void foo12(void Function(U) b) { return null; }
-//                                  ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:34: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:35: Error: Type variables can't be used in static members.
 //   static void foo13(void Function(U b)) { return null; }
-//                                  ^
+//                                   ^
 //
 import self as self;
 import "dart:core" as core;
@@ -92,8 +92,10 @@
   static method foo12 = self::Foo|foo12;
   static method foo13 = self::Foo|foo13;
   static field foo14 = self::Foo|foo14;
+  static field foo15 = self::Foo|foo15;
 }
 static field invalid-type Foo|foo14 = null;
+static field (invalid-type) →* invalid-type Foo|foo15 = null;
 static method Foo|foo1() → dynamic {
   return null;
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/function_type_is_check.dart.hierarchy.expect b/pkg/front_end/testcases/general_nnbd_opt_out/function_type_is_check.dart.hierarchy.expect
index 257f1e9..4f5c506 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/function_type_is_check.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/function_type_is_check.dart.hierarchy.expect
@@ -24,7 +24,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_scope_test.dart.hierarchy.expect b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_scope_test.dart.hierarchy.expect
index ad35f25..e04e5f9 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_scope_test.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_scope_test.dart.hierarchy.expect
@@ -43,7 +43,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.hierarchy.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.hierarchy.expect
index 56e565b..3d588b6 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.hierarchy.expect
@@ -198,7 +198,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.hierarchy.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.hierarchy.expect
index 4b4ba3b..1eaa41a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.hierarchy.expect
@@ -82,7 +82,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.hierarchy.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.hierarchy.expect
index 4b4ba3b..1eaa41a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.hierarchy.expect
@@ -82,7 +82,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.hierarchy.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.hierarchy.expect
index 41b4b7f..8fd8c13 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.hierarchy.expect
@@ -61,7 +61,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.hierarchy.expect b/pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.hierarchy.expect
index f3acb23..a7e1277 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/supertypes.dart.hierarchy.expect
@@ -76,7 +76,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart b/pkg/front_end/testcases/late_lowering/late_future_or.dart
new file mode 100644
index 0000000..c211da1
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart
@@ -0,0 +1,40 @@
+// 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';
+
+FutureOr method1() => null;
+FutureOr? method2() => null;
+FutureOr<dynamic> method3() => null;
+FutureOr<int> method4() => 0;
+FutureOr<int?> method5() => null;
+FutureOr<int?>? method6() => null;
+
+late var field1 = method1();
+late var field2 = method2();
+late var field3 = method3();
+late var field4 = method4();
+late var field5 = method5();
+late var field6 = method6();
+
+class C<T> {
+  late FutureOr field1;
+  late FutureOr? field2;
+  late FutureOr<T> field3;
+  late FutureOr<T?> field4;
+  late FutureOr<T?>? field5;
+
+  method() {
+    late FutureOr local1;
+    late FutureOr? local2;
+    late FutureOr<T> local3;
+    late FutureOr<T?> local4;
+    late FutureOr<T?>? local5;
+  }
+}
+
+// TODO(johnniwinther): Add test for override inference when the consolidated
+// model is implemented.
+
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.outline.expect
new file mode 100644
index 0000000..0cc888e
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.outline.expect
@@ -0,0 +1,71 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  field asy::FutureOr<dynamic>? _#C#field1;
+  field core::bool _#C#field1#isSet;
+  field asy::FutureOr<dynamic>? _#C#field2;
+  field core::bool _#C#field2#isSet;
+  generic-covariant-impl field asy::FutureOr<self::C::T%>? _#C#field3;
+  field core::bool _#C#field3#isSet;
+  generic-covariant-impl field asy::FutureOr<self::C::T?>? _#C#field4;
+  field core::bool _#C#field4#isSet;
+  generic-covariant-impl field asy::FutureOr<self::C::T?>? _#C#field5;
+  field core::bool _#C#field5#isSet;
+  synthetic constructor •() → self::C<self::C::T%>
+    ;
+  get field1() → asy::FutureOr<dynamic>;
+  set field1(asy::FutureOr<dynamic> #t1) → void;
+  get field2() → asy::FutureOr<dynamic>?;
+  set field2(asy::FutureOr<dynamic>? #t2) → void;
+  get field3() → asy::FutureOr<self::C::T%>;
+  set field3(asy::FutureOr<self::C::T%> #t3) → void;
+  get field4() → asy::FutureOr<self::C::T?>;
+  set field4(asy::FutureOr<self::C::T?> #t4) → void;
+  get field5() → asy::FutureOr<self::C::T?>?;
+  set field5(asy::FutureOr<self::C::T?>? #t5) → void;
+  method method() → dynamic
+    ;
+}
+static field asy::FutureOr<dynamic>? _#field1;
+static field core::bool _#field1#isSet;
+static field asy::FutureOr<dynamic>? _#field2;
+static field core::bool _#field2#isSet;
+static field asy::FutureOr<dynamic>? _#field3;
+static field core::bool _#field3#isSet;
+static field asy::FutureOr<core::int>? _#field4;
+static field core::bool _#field4#isSet;
+static field asy::FutureOr<core::int?>? _#field5;
+static field core::bool _#field5#isSet;
+static field asy::FutureOr<core::int?>? _#field6;
+static field core::bool _#field6#isSet;
+static method method1() → asy::FutureOr<dynamic>
+  ;
+static method method2() → asy::FutureOr<dynamic>?
+  ;
+static method method3() → asy::FutureOr<dynamic>
+  ;
+static method method4() → asy::FutureOr<core::int>
+  ;
+static method method5() → asy::FutureOr<core::int?>
+  ;
+static method method6() → asy::FutureOr<core::int?>?
+  ;
+static get field1() → asy::FutureOr<dynamic>;
+static set field1(asy::FutureOr<dynamic> #t6) → void;
+static get field2() → asy::FutureOr<dynamic>?;
+static set field2(asy::FutureOr<dynamic>? #t7) → void;
+static get field3() → asy::FutureOr<dynamic>;
+static set field3(asy::FutureOr<dynamic> #t8) → void;
+static get field4() → asy::FutureOr<core::int>;
+static set field4(asy::FutureOr<core::int> #t9) → void;
+static get field5() → asy::FutureOr<core::int?>;
+static set field5(asy::FutureOr<core::int?> #t10) → void;
+static get field6() → asy::FutureOr<core::int?>?;
+static set field6(asy::FutureOr<core::int?>? #t11) → void;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.expect
new file mode 100644
index 0000000..3ad795c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.expect
@@ -0,0 +1,179 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  field asy::FutureOr<dynamic>? _#C#field1 = null;
+  field core::bool _#C#field1#isSet = false;
+  field asy::FutureOr<dynamic>? _#C#field2 = null;
+  field core::bool _#C#field2#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T%>? _#C#field3 = null;
+  field core::bool _#C#field3#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T?>? _#C#field4 = null;
+  field core::bool _#C#field4#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T?>? _#C#field5 = null;
+  field core::bool _#C#field5#isSet = false;
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  get field1() → asy::FutureOr<dynamic>
+    return this.{self::C::_#C#field1#isSet} ?{asy::FutureOr<dynamic>} this.{self::C::_#C#field1} : throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.");
+  set field1(asy::FutureOr<dynamic> #t1) → void {
+    this.{self::C::_#C#field1#isSet} = true;
+    this.{self::C::_#C#field1} = #t1;
+  }
+  get field2() → asy::FutureOr<dynamic>?
+    return this.{self::C::_#C#field2#isSet} ?{asy::FutureOr<dynamic>?} this.{self::C::_#C#field2} : throw new _in::LateInitializationErrorImpl::•("Field 'field2' has not been initialized.");
+  set field2(asy::FutureOr<dynamic>? #t2) → void {
+    this.{self::C::_#C#field2#isSet} = true;
+    this.{self::C::_#C#field2} = #t2;
+  }
+  get field3() → asy::FutureOr<self::C::T%>
+    return this.{self::C::_#C#field3#isSet} ?{asy::FutureOr<self::C::T%>} let final asy::FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3} in #t3{asy::FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
+  set field3(asy::FutureOr<self::C::T%> #t4) → void {
+    this.{self::C::_#C#field3#isSet} = true;
+    this.{self::C::_#C#field3} = #t4;
+  }
+  get field4() → asy::FutureOr<self::C::T?>
+    return this.{self::C::_#C#field4#isSet} ?{asy::FutureOr<self::C::T?>} this.{self::C::_#C#field4} : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.");
+  set field4(asy::FutureOr<self::C::T?> #t5) → void {
+    this.{self::C::_#C#field4#isSet} = true;
+    this.{self::C::_#C#field4} = #t5;
+  }
+  get field5() → asy::FutureOr<self::C::T?>?
+    return this.{self::C::_#C#field5#isSet} ?{asy::FutureOr<self::C::T?>?} this.{self::C::_#C#field5} : throw new _in::LateInitializationErrorImpl::•("Field 'field5' has not been initialized.");
+  set field5(asy::FutureOr<self::C::T?>? #t6) → void {
+    this.{self::C::_#C#field5#isSet} = true;
+    this.{self::C::_#C#field5} = #t6;
+  }
+  method method() → dynamic {
+    asy::FutureOr<dynamic>? local1;
+    core::bool #local1#isSet = false;
+    function #local1#get() → asy::FutureOr<dynamic>
+      return #local1#isSet ?{asy::FutureOr<dynamic>} local1 : throw new _in::LateInitializationErrorImpl::•("Local 'local1' has not been initialized.");
+    function #local1#set(asy::FutureOr<dynamic> #t7) → dynamic {
+      #local1#isSet = true;
+      return local1 = #t7;
+    }
+    asy::FutureOr<dynamic>? local2;
+    core::bool #local2#isSet = false;
+    function #local2#get() → asy::FutureOr<dynamic>?
+      return #local2#isSet ?{asy::FutureOr<dynamic>?} local2 : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
+    function #local2#set(asy::FutureOr<dynamic>? #t8) → dynamic {
+      #local2#isSet = true;
+      return local2 = #t8;
+    }
+    asy::FutureOr<self::C::T%>? local3;
+    core::bool #local3#isSet = false;
+    function #local3#get() → asy::FutureOr<self::C::T%>
+      return #local3#isSet ?{asy::FutureOr<self::C::T%>} local3{asy::FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Local 'local3' has not been initialized.");
+    function #local3#set(asy::FutureOr<self::C::T%> #t9) → dynamic {
+      #local3#isSet = true;
+      return local3 = #t9;
+    }
+    asy::FutureOr<self::C::T?>? local4;
+    core::bool #local4#isSet = false;
+    function #local4#get() → asy::FutureOr<self::C::T?>
+      return #local4#isSet ?{asy::FutureOr<self::C::T?>} local4 : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+    function #local4#set(asy::FutureOr<self::C::T?> #t10) → dynamic {
+      #local4#isSet = true;
+      return local4 = #t10;
+    }
+    asy::FutureOr<self::C::T?>? local5;
+    core::bool #local5#isSet = false;
+    function #local5#get() → asy::FutureOr<self::C::T?>?
+      return #local5#isSet ?{asy::FutureOr<self::C::T?>?} local5 : throw new _in::LateInitializationErrorImpl::•("Local 'local5' has not been initialized.");
+    function #local5#set(asy::FutureOr<self::C::T?>? #t11) → dynamic {
+      #local5#isSet = true;
+      return local5 = #t11;
+    }
+  }
+}
+static field asy::FutureOr<dynamic>? _#field1 = null;
+static field core::bool _#field1#isSet = false;
+static field asy::FutureOr<dynamic>? _#field2 = null;
+static field core::bool _#field2#isSet = false;
+static field asy::FutureOr<dynamic>? _#field3 = null;
+static field core::bool _#field3#isSet = false;
+static field asy::FutureOr<core::int>? _#field4 = null;
+static field core::bool _#field4#isSet = false;
+static field asy::FutureOr<core::int?>? _#field5 = null;
+static field core::bool _#field5#isSet = false;
+static field asy::FutureOr<core::int?>? _#field6 = null;
+static field core::bool _#field6#isSet = false;
+static method method1() → asy::FutureOr<dynamic>
+  return null;
+static method method2() → asy::FutureOr<dynamic>?
+  return null;
+static method method3() → asy::FutureOr<dynamic>
+  return null;
+static method method4() → asy::FutureOr<core::int>
+  return 0;
+static method method5() → asy::FutureOr<core::int?>
+  return null;
+static method method6() → asy::FutureOr<core::int?>?
+  return null;
+static get field1() → asy::FutureOr<dynamic> {
+  if(!self::_#field1#isSet) {
+    self::_#field1#isSet = true;
+    self::_#field1 = self::method1();
+  }
+  return self::_#field1;
+}
+static set field1(asy::FutureOr<dynamic> #t12) → void {
+  self::_#field1#isSet = true;
+  self::_#field1 = #t12;
+}
+static get field2() → asy::FutureOr<dynamic>? {
+  if(!self::_#field2#isSet) {
+    self::_#field2#isSet = true;
+    self::_#field2 = self::method2();
+  }
+  return self::_#field2;
+}
+static set field2(asy::FutureOr<dynamic>? #t13) → void {
+  self::_#field2#isSet = true;
+  self::_#field2 = #t13;
+}
+static get field3() → asy::FutureOr<dynamic> {
+  if(!self::_#field3#isSet) {
+    self::_#field3#isSet = true;
+    self::_#field3 = self::method3();
+  }
+  return self::_#field3;
+}
+static set field3(asy::FutureOr<dynamic> #t14) → void {
+  self::_#field3#isSet = true;
+  self::_#field3 = #t14;
+}
+static get field4() → asy::FutureOr<core::int>
+  return let final asy::FutureOr<core::int>? #t15 = self::_#field4 in #t15.==(null) ?{asy::FutureOr<core::int>} self::_#field4 = self::method4() : #t15{asy::FutureOr<core::int>};
+static set field4(asy::FutureOr<core::int> #t16) → void
+  self::_#field4 = #t16;
+static get field5() → asy::FutureOr<core::int?> {
+  if(!self::_#field5#isSet) {
+    self::_#field5#isSet = true;
+    self::_#field5 = self::method5();
+  }
+  return self::_#field5;
+}
+static set field5(asy::FutureOr<core::int?> #t17) → void {
+  self::_#field5#isSet = true;
+  self::_#field5 = #t17;
+}
+static get field6() → asy::FutureOr<core::int?>? {
+  if(!self::_#field6#isSet) {
+    self::_#field6#isSet = true;
+    self::_#field6 = self::method6();
+  }
+  return self::_#field6;
+}
+static set field6(asy::FutureOr<core::int?>? #t18) → void {
+  self::_#field6#isSet = true;
+  self::_#field6 = #t18;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.transformed.expect
new file mode 100644
index 0000000..3ad795c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.transformed.expect
@@ -0,0 +1,179 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  field asy::FutureOr<dynamic>? _#C#field1 = null;
+  field core::bool _#C#field1#isSet = false;
+  field asy::FutureOr<dynamic>? _#C#field2 = null;
+  field core::bool _#C#field2#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T%>? _#C#field3 = null;
+  field core::bool _#C#field3#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T?>? _#C#field4 = null;
+  field core::bool _#C#field4#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T?>? _#C#field5 = null;
+  field core::bool _#C#field5#isSet = false;
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  get field1() → asy::FutureOr<dynamic>
+    return this.{self::C::_#C#field1#isSet} ?{asy::FutureOr<dynamic>} this.{self::C::_#C#field1} : throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.");
+  set field1(asy::FutureOr<dynamic> #t1) → void {
+    this.{self::C::_#C#field1#isSet} = true;
+    this.{self::C::_#C#field1} = #t1;
+  }
+  get field2() → asy::FutureOr<dynamic>?
+    return this.{self::C::_#C#field2#isSet} ?{asy::FutureOr<dynamic>?} this.{self::C::_#C#field2} : throw new _in::LateInitializationErrorImpl::•("Field 'field2' has not been initialized.");
+  set field2(asy::FutureOr<dynamic>? #t2) → void {
+    this.{self::C::_#C#field2#isSet} = true;
+    this.{self::C::_#C#field2} = #t2;
+  }
+  get field3() → asy::FutureOr<self::C::T%>
+    return this.{self::C::_#C#field3#isSet} ?{asy::FutureOr<self::C::T%>} let final asy::FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3} in #t3{asy::FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
+  set field3(asy::FutureOr<self::C::T%> #t4) → void {
+    this.{self::C::_#C#field3#isSet} = true;
+    this.{self::C::_#C#field3} = #t4;
+  }
+  get field4() → asy::FutureOr<self::C::T?>
+    return this.{self::C::_#C#field4#isSet} ?{asy::FutureOr<self::C::T?>} this.{self::C::_#C#field4} : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.");
+  set field4(asy::FutureOr<self::C::T?> #t5) → void {
+    this.{self::C::_#C#field4#isSet} = true;
+    this.{self::C::_#C#field4} = #t5;
+  }
+  get field5() → asy::FutureOr<self::C::T?>?
+    return this.{self::C::_#C#field5#isSet} ?{asy::FutureOr<self::C::T?>?} this.{self::C::_#C#field5} : throw new _in::LateInitializationErrorImpl::•("Field 'field5' has not been initialized.");
+  set field5(asy::FutureOr<self::C::T?>? #t6) → void {
+    this.{self::C::_#C#field5#isSet} = true;
+    this.{self::C::_#C#field5} = #t6;
+  }
+  method method() → dynamic {
+    asy::FutureOr<dynamic>? local1;
+    core::bool #local1#isSet = false;
+    function #local1#get() → asy::FutureOr<dynamic>
+      return #local1#isSet ?{asy::FutureOr<dynamic>} local1 : throw new _in::LateInitializationErrorImpl::•("Local 'local1' has not been initialized.");
+    function #local1#set(asy::FutureOr<dynamic> #t7) → dynamic {
+      #local1#isSet = true;
+      return local1 = #t7;
+    }
+    asy::FutureOr<dynamic>? local2;
+    core::bool #local2#isSet = false;
+    function #local2#get() → asy::FutureOr<dynamic>?
+      return #local2#isSet ?{asy::FutureOr<dynamic>?} local2 : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
+    function #local2#set(asy::FutureOr<dynamic>? #t8) → dynamic {
+      #local2#isSet = true;
+      return local2 = #t8;
+    }
+    asy::FutureOr<self::C::T%>? local3;
+    core::bool #local3#isSet = false;
+    function #local3#get() → asy::FutureOr<self::C::T%>
+      return #local3#isSet ?{asy::FutureOr<self::C::T%>} local3{asy::FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Local 'local3' has not been initialized.");
+    function #local3#set(asy::FutureOr<self::C::T%> #t9) → dynamic {
+      #local3#isSet = true;
+      return local3 = #t9;
+    }
+    asy::FutureOr<self::C::T?>? local4;
+    core::bool #local4#isSet = false;
+    function #local4#get() → asy::FutureOr<self::C::T?>
+      return #local4#isSet ?{asy::FutureOr<self::C::T?>} local4 : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+    function #local4#set(asy::FutureOr<self::C::T?> #t10) → dynamic {
+      #local4#isSet = true;
+      return local4 = #t10;
+    }
+    asy::FutureOr<self::C::T?>? local5;
+    core::bool #local5#isSet = false;
+    function #local5#get() → asy::FutureOr<self::C::T?>?
+      return #local5#isSet ?{asy::FutureOr<self::C::T?>?} local5 : throw new _in::LateInitializationErrorImpl::•("Local 'local5' has not been initialized.");
+    function #local5#set(asy::FutureOr<self::C::T?>? #t11) → dynamic {
+      #local5#isSet = true;
+      return local5 = #t11;
+    }
+  }
+}
+static field asy::FutureOr<dynamic>? _#field1 = null;
+static field core::bool _#field1#isSet = false;
+static field asy::FutureOr<dynamic>? _#field2 = null;
+static field core::bool _#field2#isSet = false;
+static field asy::FutureOr<dynamic>? _#field3 = null;
+static field core::bool _#field3#isSet = false;
+static field asy::FutureOr<core::int>? _#field4 = null;
+static field core::bool _#field4#isSet = false;
+static field asy::FutureOr<core::int?>? _#field5 = null;
+static field core::bool _#field5#isSet = false;
+static field asy::FutureOr<core::int?>? _#field6 = null;
+static field core::bool _#field6#isSet = false;
+static method method1() → asy::FutureOr<dynamic>
+  return null;
+static method method2() → asy::FutureOr<dynamic>?
+  return null;
+static method method3() → asy::FutureOr<dynamic>
+  return null;
+static method method4() → asy::FutureOr<core::int>
+  return 0;
+static method method5() → asy::FutureOr<core::int?>
+  return null;
+static method method6() → asy::FutureOr<core::int?>?
+  return null;
+static get field1() → asy::FutureOr<dynamic> {
+  if(!self::_#field1#isSet) {
+    self::_#field1#isSet = true;
+    self::_#field1 = self::method1();
+  }
+  return self::_#field1;
+}
+static set field1(asy::FutureOr<dynamic> #t12) → void {
+  self::_#field1#isSet = true;
+  self::_#field1 = #t12;
+}
+static get field2() → asy::FutureOr<dynamic>? {
+  if(!self::_#field2#isSet) {
+    self::_#field2#isSet = true;
+    self::_#field2 = self::method2();
+  }
+  return self::_#field2;
+}
+static set field2(asy::FutureOr<dynamic>? #t13) → void {
+  self::_#field2#isSet = true;
+  self::_#field2 = #t13;
+}
+static get field3() → asy::FutureOr<dynamic> {
+  if(!self::_#field3#isSet) {
+    self::_#field3#isSet = true;
+    self::_#field3 = self::method3();
+  }
+  return self::_#field3;
+}
+static set field3(asy::FutureOr<dynamic> #t14) → void {
+  self::_#field3#isSet = true;
+  self::_#field3 = #t14;
+}
+static get field4() → asy::FutureOr<core::int>
+  return let final asy::FutureOr<core::int>? #t15 = self::_#field4 in #t15.==(null) ?{asy::FutureOr<core::int>} self::_#field4 = self::method4() : #t15{asy::FutureOr<core::int>};
+static set field4(asy::FutureOr<core::int> #t16) → void
+  self::_#field4 = #t16;
+static get field5() → asy::FutureOr<core::int?> {
+  if(!self::_#field5#isSet) {
+    self::_#field5#isSet = true;
+    self::_#field5 = self::method5();
+  }
+  return self::_#field5;
+}
+static set field5(asy::FutureOr<core::int?> #t17) → void {
+  self::_#field5#isSet = true;
+  self::_#field5 = #t17;
+}
+static get field6() → asy::FutureOr<core::int?>? {
+  if(!self::_#field6#isSet) {
+    self::_#field6#isSet = true;
+    self::_#field6 = self::method6();
+  }
+  return self::_#field6;
+}
+static set field6(asy::FutureOr<core::int?>? #t18) → void {
+  self::_#field6#isSet = true;
+  self::_#field6 = #t18;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect
new file mode 100644
index 0000000..3ad795c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect
@@ -0,0 +1,179 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  field asy::FutureOr<dynamic>? _#C#field1 = null;
+  field core::bool _#C#field1#isSet = false;
+  field asy::FutureOr<dynamic>? _#C#field2 = null;
+  field core::bool _#C#field2#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T%>? _#C#field3 = null;
+  field core::bool _#C#field3#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T?>? _#C#field4 = null;
+  field core::bool _#C#field4#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T?>? _#C#field5 = null;
+  field core::bool _#C#field5#isSet = false;
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  get field1() → asy::FutureOr<dynamic>
+    return this.{self::C::_#C#field1#isSet} ?{asy::FutureOr<dynamic>} this.{self::C::_#C#field1} : throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.");
+  set field1(asy::FutureOr<dynamic> #t1) → void {
+    this.{self::C::_#C#field1#isSet} = true;
+    this.{self::C::_#C#field1} = #t1;
+  }
+  get field2() → asy::FutureOr<dynamic>?
+    return this.{self::C::_#C#field2#isSet} ?{asy::FutureOr<dynamic>?} this.{self::C::_#C#field2} : throw new _in::LateInitializationErrorImpl::•("Field 'field2' has not been initialized.");
+  set field2(asy::FutureOr<dynamic>? #t2) → void {
+    this.{self::C::_#C#field2#isSet} = true;
+    this.{self::C::_#C#field2} = #t2;
+  }
+  get field3() → asy::FutureOr<self::C::T%>
+    return this.{self::C::_#C#field3#isSet} ?{asy::FutureOr<self::C::T%>} let final asy::FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3} in #t3{asy::FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
+  set field3(asy::FutureOr<self::C::T%> #t4) → void {
+    this.{self::C::_#C#field3#isSet} = true;
+    this.{self::C::_#C#field3} = #t4;
+  }
+  get field4() → asy::FutureOr<self::C::T?>
+    return this.{self::C::_#C#field4#isSet} ?{asy::FutureOr<self::C::T?>} this.{self::C::_#C#field4} : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.");
+  set field4(asy::FutureOr<self::C::T?> #t5) → void {
+    this.{self::C::_#C#field4#isSet} = true;
+    this.{self::C::_#C#field4} = #t5;
+  }
+  get field5() → asy::FutureOr<self::C::T?>?
+    return this.{self::C::_#C#field5#isSet} ?{asy::FutureOr<self::C::T?>?} this.{self::C::_#C#field5} : throw new _in::LateInitializationErrorImpl::•("Field 'field5' has not been initialized.");
+  set field5(asy::FutureOr<self::C::T?>? #t6) → void {
+    this.{self::C::_#C#field5#isSet} = true;
+    this.{self::C::_#C#field5} = #t6;
+  }
+  method method() → dynamic {
+    asy::FutureOr<dynamic>? local1;
+    core::bool #local1#isSet = false;
+    function #local1#get() → asy::FutureOr<dynamic>
+      return #local1#isSet ?{asy::FutureOr<dynamic>} local1 : throw new _in::LateInitializationErrorImpl::•("Local 'local1' has not been initialized.");
+    function #local1#set(asy::FutureOr<dynamic> #t7) → dynamic {
+      #local1#isSet = true;
+      return local1 = #t7;
+    }
+    asy::FutureOr<dynamic>? local2;
+    core::bool #local2#isSet = false;
+    function #local2#get() → asy::FutureOr<dynamic>?
+      return #local2#isSet ?{asy::FutureOr<dynamic>?} local2 : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
+    function #local2#set(asy::FutureOr<dynamic>? #t8) → dynamic {
+      #local2#isSet = true;
+      return local2 = #t8;
+    }
+    asy::FutureOr<self::C::T%>? local3;
+    core::bool #local3#isSet = false;
+    function #local3#get() → asy::FutureOr<self::C::T%>
+      return #local3#isSet ?{asy::FutureOr<self::C::T%>} local3{asy::FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Local 'local3' has not been initialized.");
+    function #local3#set(asy::FutureOr<self::C::T%> #t9) → dynamic {
+      #local3#isSet = true;
+      return local3 = #t9;
+    }
+    asy::FutureOr<self::C::T?>? local4;
+    core::bool #local4#isSet = false;
+    function #local4#get() → asy::FutureOr<self::C::T?>
+      return #local4#isSet ?{asy::FutureOr<self::C::T?>} local4 : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+    function #local4#set(asy::FutureOr<self::C::T?> #t10) → dynamic {
+      #local4#isSet = true;
+      return local4 = #t10;
+    }
+    asy::FutureOr<self::C::T?>? local5;
+    core::bool #local5#isSet = false;
+    function #local5#get() → asy::FutureOr<self::C::T?>?
+      return #local5#isSet ?{asy::FutureOr<self::C::T?>?} local5 : throw new _in::LateInitializationErrorImpl::•("Local 'local5' has not been initialized.");
+    function #local5#set(asy::FutureOr<self::C::T?>? #t11) → dynamic {
+      #local5#isSet = true;
+      return local5 = #t11;
+    }
+  }
+}
+static field asy::FutureOr<dynamic>? _#field1 = null;
+static field core::bool _#field1#isSet = false;
+static field asy::FutureOr<dynamic>? _#field2 = null;
+static field core::bool _#field2#isSet = false;
+static field asy::FutureOr<dynamic>? _#field3 = null;
+static field core::bool _#field3#isSet = false;
+static field asy::FutureOr<core::int>? _#field4 = null;
+static field core::bool _#field4#isSet = false;
+static field asy::FutureOr<core::int?>? _#field5 = null;
+static field core::bool _#field5#isSet = false;
+static field asy::FutureOr<core::int?>? _#field6 = null;
+static field core::bool _#field6#isSet = false;
+static method method1() → asy::FutureOr<dynamic>
+  return null;
+static method method2() → asy::FutureOr<dynamic>?
+  return null;
+static method method3() → asy::FutureOr<dynamic>
+  return null;
+static method method4() → asy::FutureOr<core::int>
+  return 0;
+static method method5() → asy::FutureOr<core::int?>
+  return null;
+static method method6() → asy::FutureOr<core::int?>?
+  return null;
+static get field1() → asy::FutureOr<dynamic> {
+  if(!self::_#field1#isSet) {
+    self::_#field1#isSet = true;
+    self::_#field1 = self::method1();
+  }
+  return self::_#field1;
+}
+static set field1(asy::FutureOr<dynamic> #t12) → void {
+  self::_#field1#isSet = true;
+  self::_#field1 = #t12;
+}
+static get field2() → asy::FutureOr<dynamic>? {
+  if(!self::_#field2#isSet) {
+    self::_#field2#isSet = true;
+    self::_#field2 = self::method2();
+  }
+  return self::_#field2;
+}
+static set field2(asy::FutureOr<dynamic>? #t13) → void {
+  self::_#field2#isSet = true;
+  self::_#field2 = #t13;
+}
+static get field3() → asy::FutureOr<dynamic> {
+  if(!self::_#field3#isSet) {
+    self::_#field3#isSet = true;
+    self::_#field3 = self::method3();
+  }
+  return self::_#field3;
+}
+static set field3(asy::FutureOr<dynamic> #t14) → void {
+  self::_#field3#isSet = true;
+  self::_#field3 = #t14;
+}
+static get field4() → asy::FutureOr<core::int>
+  return let final asy::FutureOr<core::int>? #t15 = self::_#field4 in #t15.==(null) ?{asy::FutureOr<core::int>} self::_#field4 = self::method4() : #t15{asy::FutureOr<core::int>};
+static set field4(asy::FutureOr<core::int> #t16) → void
+  self::_#field4 = #t16;
+static get field5() → asy::FutureOr<core::int?> {
+  if(!self::_#field5#isSet) {
+    self::_#field5#isSet = true;
+    self::_#field5 = self::method5();
+  }
+  return self::_#field5;
+}
+static set field5(asy::FutureOr<core::int?> #t17) → void {
+  self::_#field5#isSet = true;
+  self::_#field5 = #t17;
+}
+static get field6() → asy::FutureOr<core::int?>? {
+  if(!self::_#field6#isSet) {
+    self::_#field6#isSet = true;
+    self::_#field6 = self::method6();
+  }
+  return self::_#field6;
+}
+static set field6(asy::FutureOr<core::int?>? #t18) → void {
+  self::_#field6#isSet = true;
+  self::_#field6 = #t18;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect
new file mode 100644
index 0000000..3ad795c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect
@@ -0,0 +1,179 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  field asy::FutureOr<dynamic>? _#C#field1 = null;
+  field core::bool _#C#field1#isSet = false;
+  field asy::FutureOr<dynamic>? _#C#field2 = null;
+  field core::bool _#C#field2#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T%>? _#C#field3 = null;
+  field core::bool _#C#field3#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T?>? _#C#field4 = null;
+  field core::bool _#C#field4#isSet = false;
+  generic-covariant-impl field asy::FutureOr<self::C::T?>? _#C#field5 = null;
+  field core::bool _#C#field5#isSet = false;
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  get field1() → asy::FutureOr<dynamic>
+    return this.{self::C::_#C#field1#isSet} ?{asy::FutureOr<dynamic>} this.{self::C::_#C#field1} : throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.");
+  set field1(asy::FutureOr<dynamic> #t1) → void {
+    this.{self::C::_#C#field1#isSet} = true;
+    this.{self::C::_#C#field1} = #t1;
+  }
+  get field2() → asy::FutureOr<dynamic>?
+    return this.{self::C::_#C#field2#isSet} ?{asy::FutureOr<dynamic>?} this.{self::C::_#C#field2} : throw new _in::LateInitializationErrorImpl::•("Field 'field2' has not been initialized.");
+  set field2(asy::FutureOr<dynamic>? #t2) → void {
+    this.{self::C::_#C#field2#isSet} = true;
+    this.{self::C::_#C#field2} = #t2;
+  }
+  get field3() → asy::FutureOr<self::C::T%>
+    return this.{self::C::_#C#field3#isSet} ?{asy::FutureOr<self::C::T%>} let final asy::FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3} in #t3{asy::FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
+  set field3(asy::FutureOr<self::C::T%> #t4) → void {
+    this.{self::C::_#C#field3#isSet} = true;
+    this.{self::C::_#C#field3} = #t4;
+  }
+  get field4() → asy::FutureOr<self::C::T?>
+    return this.{self::C::_#C#field4#isSet} ?{asy::FutureOr<self::C::T?>} this.{self::C::_#C#field4} : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.");
+  set field4(asy::FutureOr<self::C::T?> #t5) → void {
+    this.{self::C::_#C#field4#isSet} = true;
+    this.{self::C::_#C#field4} = #t5;
+  }
+  get field5() → asy::FutureOr<self::C::T?>?
+    return this.{self::C::_#C#field5#isSet} ?{asy::FutureOr<self::C::T?>?} this.{self::C::_#C#field5} : throw new _in::LateInitializationErrorImpl::•("Field 'field5' has not been initialized.");
+  set field5(asy::FutureOr<self::C::T?>? #t6) → void {
+    this.{self::C::_#C#field5#isSet} = true;
+    this.{self::C::_#C#field5} = #t6;
+  }
+  method method() → dynamic {
+    asy::FutureOr<dynamic>? local1;
+    core::bool #local1#isSet = false;
+    function #local1#get() → asy::FutureOr<dynamic>
+      return #local1#isSet ?{asy::FutureOr<dynamic>} local1 : throw new _in::LateInitializationErrorImpl::•("Local 'local1' has not been initialized.");
+    function #local1#set(asy::FutureOr<dynamic> #t7) → dynamic {
+      #local1#isSet = true;
+      return local1 = #t7;
+    }
+    asy::FutureOr<dynamic>? local2;
+    core::bool #local2#isSet = false;
+    function #local2#get() → asy::FutureOr<dynamic>?
+      return #local2#isSet ?{asy::FutureOr<dynamic>?} local2 : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
+    function #local2#set(asy::FutureOr<dynamic>? #t8) → dynamic {
+      #local2#isSet = true;
+      return local2 = #t8;
+    }
+    asy::FutureOr<self::C::T%>? local3;
+    core::bool #local3#isSet = false;
+    function #local3#get() → asy::FutureOr<self::C::T%>
+      return #local3#isSet ?{asy::FutureOr<self::C::T%>} local3{asy::FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Local 'local3' has not been initialized.");
+    function #local3#set(asy::FutureOr<self::C::T%> #t9) → dynamic {
+      #local3#isSet = true;
+      return local3 = #t9;
+    }
+    asy::FutureOr<self::C::T?>? local4;
+    core::bool #local4#isSet = false;
+    function #local4#get() → asy::FutureOr<self::C::T?>
+      return #local4#isSet ?{asy::FutureOr<self::C::T?>} local4 : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+    function #local4#set(asy::FutureOr<self::C::T?> #t10) → dynamic {
+      #local4#isSet = true;
+      return local4 = #t10;
+    }
+    asy::FutureOr<self::C::T?>? local5;
+    core::bool #local5#isSet = false;
+    function #local5#get() → asy::FutureOr<self::C::T?>?
+      return #local5#isSet ?{asy::FutureOr<self::C::T?>?} local5 : throw new _in::LateInitializationErrorImpl::•("Local 'local5' has not been initialized.");
+    function #local5#set(asy::FutureOr<self::C::T?>? #t11) → dynamic {
+      #local5#isSet = true;
+      return local5 = #t11;
+    }
+  }
+}
+static field asy::FutureOr<dynamic>? _#field1 = null;
+static field core::bool _#field1#isSet = false;
+static field asy::FutureOr<dynamic>? _#field2 = null;
+static field core::bool _#field2#isSet = false;
+static field asy::FutureOr<dynamic>? _#field3 = null;
+static field core::bool _#field3#isSet = false;
+static field asy::FutureOr<core::int>? _#field4 = null;
+static field core::bool _#field4#isSet = false;
+static field asy::FutureOr<core::int?>? _#field5 = null;
+static field core::bool _#field5#isSet = false;
+static field asy::FutureOr<core::int?>? _#field6 = null;
+static field core::bool _#field6#isSet = false;
+static method method1() → asy::FutureOr<dynamic>
+  return null;
+static method method2() → asy::FutureOr<dynamic>?
+  return null;
+static method method3() → asy::FutureOr<dynamic>
+  return null;
+static method method4() → asy::FutureOr<core::int>
+  return 0;
+static method method5() → asy::FutureOr<core::int?>
+  return null;
+static method method6() → asy::FutureOr<core::int?>?
+  return null;
+static get field1() → asy::FutureOr<dynamic> {
+  if(!self::_#field1#isSet) {
+    self::_#field1#isSet = true;
+    self::_#field1 = self::method1();
+  }
+  return self::_#field1;
+}
+static set field1(asy::FutureOr<dynamic> #t12) → void {
+  self::_#field1#isSet = true;
+  self::_#field1 = #t12;
+}
+static get field2() → asy::FutureOr<dynamic>? {
+  if(!self::_#field2#isSet) {
+    self::_#field2#isSet = true;
+    self::_#field2 = self::method2();
+  }
+  return self::_#field2;
+}
+static set field2(asy::FutureOr<dynamic>? #t13) → void {
+  self::_#field2#isSet = true;
+  self::_#field2 = #t13;
+}
+static get field3() → asy::FutureOr<dynamic> {
+  if(!self::_#field3#isSet) {
+    self::_#field3#isSet = true;
+    self::_#field3 = self::method3();
+  }
+  return self::_#field3;
+}
+static set field3(asy::FutureOr<dynamic> #t14) → void {
+  self::_#field3#isSet = true;
+  self::_#field3 = #t14;
+}
+static get field4() → asy::FutureOr<core::int>
+  return let final asy::FutureOr<core::int>? #t15 = self::_#field4 in #t15.==(null) ?{asy::FutureOr<core::int>} self::_#field4 = self::method4() : #t15{asy::FutureOr<core::int>};
+static set field4(asy::FutureOr<core::int> #t16) → void
+  self::_#field4 = #t16;
+static get field5() → asy::FutureOr<core::int?> {
+  if(!self::_#field5#isSet) {
+    self::_#field5#isSet = true;
+    self::_#field5 = self::method5();
+  }
+  return self::_#field5;
+}
+static set field5(asy::FutureOr<core::int?> #t17) → void {
+  self::_#field5#isSet = true;
+  self::_#field5 = #t17;
+}
+static get field6() → asy::FutureOr<core::int?>? {
+  if(!self::_#field6#isSet) {
+    self::_#field6#isSet = true;
+    self::_#field6 = self::method6();
+  }
+  return self::_#field6;
+}
+static set field6(asy::FutureOr<core::int?>? #t18) → void {
+  self::_#field6#isSet = true;
+  self::_#field6 = #t18;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart
new file mode 100644
index 0000000..6eec70e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart
@@ -0,0 +1,15 @@
+// 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.5
+
+import 'literal_from_opt_in_lib.dart';
+
+main() {
+  var l1 = const [a];
+  var l2 = const [b];
+  var l3 = const [c];
+  var l4 = const [d];
+  var l5 = const [e];
+}
diff --git a/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.outline.expect
new file mode 100644
index 0000000..7086aea
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.outline.expect
@@ -0,0 +1,23 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///literal_from_opt_in_lib.dart";
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:core" as core;
+
+class Const<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field self2::Const::T% field;
+  const constructor •(self2::Const::T% field) → self2::Const<self2::Const::T%>
+    : self2::Const::field = field, super core::Object::•()
+    ;
+}
+static const field self2::Const<core::int> a = const self2::Const::•<core::int>(0);
+static const field self2::Const<core::int?> b = const self2::Const::•<core::int?>(0);
+static const field self2::Const<core::int?> c = const self2::Const::•<core::int?>(null);
+static const field self2::Const<core::int>? d = const self2::Const::•<core::int>(0);
+static const field self2::Const<core::int>? e = null;
diff --git a/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.strong.expect
new file mode 100644
index 0000000..e5e0414
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.strong.expect
@@ -0,0 +1,42 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "literal_from_opt_in_lib.dart" as lit;
+
+import "org-dartlang-testcase:///literal_from_opt_in_lib.dart";
+
+static method main() → dynamic {
+  core::List<lit::Const<core::int*>*>* l1 = #C3;
+  core::List<lit::Const<core::int*>*>* l2 = #C5;
+  core::List<lit::Const<core::int*>*>* l3 = #C8;
+  core::List<lit::Const<core::int*>*>* l4 = #C3;
+  core::List<lit::Const<core::int*>*>* l5 = #C9;
+}
+
+library /*isNonNullableByDefault*/;
+import self as lit;
+import "dart:core" as core;
+
+class Const<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field lit::Const::T% field;
+  const constructor •(lit::Const::T% field) → lit::Const<lit::Const::T%>
+    : lit::Const::field = field, super core::Object::•()
+    ;
+}
+static const field lit::Const<core::int> a = #C2;
+static const field lit::Const<core::int?> b = #C4;
+static const field lit::Const<core::int?> c = #C7;
+static const field lit::Const<core::int>? d = #C2;
+static const field lit::Const<core::int>? e = #C6;
+
+constants  {
+  #C1 = 0
+  #C2 = lit::Const<core::int> {field:#C1}
+  #C3 = <lit::Const<core::int*>*>[#C2]
+  #C4 = lit::Const<core::int?> {field:#C1}
+  #C5 = <lit::Const<core::int*>*>[#C4]
+  #C6 = null
+  #C7 = lit::Const<core::int?> {field:#C6}
+  #C8 = <lit::Const<core::int*>*>[#C7]
+  #C9 = <lit::Const<core::int*>*>[#C6]
+}
diff --git a/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.strong.transformed.expect
new file mode 100644
index 0000000..e5e0414
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.strong.transformed.expect
@@ -0,0 +1,42 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "literal_from_opt_in_lib.dart" as lit;
+
+import "org-dartlang-testcase:///literal_from_opt_in_lib.dart";
+
+static method main() → dynamic {
+  core::List<lit::Const<core::int*>*>* l1 = #C3;
+  core::List<lit::Const<core::int*>*>* l2 = #C5;
+  core::List<lit::Const<core::int*>*>* l3 = #C8;
+  core::List<lit::Const<core::int*>*>* l4 = #C3;
+  core::List<lit::Const<core::int*>*>* l5 = #C9;
+}
+
+library /*isNonNullableByDefault*/;
+import self as lit;
+import "dart:core" as core;
+
+class Const<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field lit::Const::T% field;
+  const constructor •(lit::Const::T% field) → lit::Const<lit::Const::T%>
+    : lit::Const::field = field, super core::Object::•()
+    ;
+}
+static const field lit::Const<core::int> a = #C2;
+static const field lit::Const<core::int?> b = #C4;
+static const field lit::Const<core::int?> c = #C7;
+static const field lit::Const<core::int>? d = #C2;
+static const field lit::Const<core::int>? e = #C6;
+
+constants  {
+  #C1 = 0
+  #C2 = lit::Const<core::int> {field:#C1}
+  #C3 = <lit::Const<core::int*>*>[#C2]
+  #C4 = lit::Const<core::int?> {field:#C1}
+  #C5 = <lit::Const<core::int*>*>[#C4]
+  #C6 = null
+  #C7 = lit::Const<core::int?> {field:#C6}
+  #C8 = <lit::Const<core::int*>*>[#C7]
+  #C9 = <lit::Const<core::int*>*>[#C6]
+}
diff --git a/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.weak.expect
new file mode 100644
index 0000000..f236f21
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.weak.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "literal_from_opt_in_lib.dart" as lit;
+
+import "org-dartlang-testcase:///literal_from_opt_in_lib.dart";
+
+static method main() → dynamic {
+  core::List<lit::Const<core::int*>*>* l1 = #C3;
+  core::List<lit::Const<core::int*>*>* l2 = #C3;
+  core::List<lit::Const<core::int*>*>* l3 = #C6;
+  core::List<lit::Const<core::int*>*>* l4 = #C3;
+  core::List<lit::Const<core::int*>*>* l5 = #C7;
+}
+
+library /*isNonNullableByDefault*/;
+import self as lit;
+import "dart:core" as core;
+
+class Const<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field lit::Const::T% field;
+  const constructor •(lit::Const::T% field) → lit::Const<lit::Const::T%>
+    : lit::Const::field = field, super core::Object::•()
+    ;
+}
+static const field lit::Const<core::int> a = #C2;
+static const field lit::Const<core::int?> b = #C2;
+static const field lit::Const<core::int?> c = #C5;
+static const field lit::Const<core::int>? d = #C2;
+static const field lit::Const<core::int>? e = #C4;
+
+constants  {
+  #C1 = 0
+  #C2 = lit::Const<core::int*> {field:#C1}
+  #C3 = <lit::Const<core::int*>*>[#C2]
+  #C4 = null
+  #C5 = lit::Const<core::int*> {field:#C4}
+  #C6 = <lit::Const<core::int*>*>[#C5]
+  #C7 = <lit::Const<core::int*>*>[#C4]
+}
diff --git a/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.weak.transformed.expect
new file mode 100644
index 0000000..f236f21
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/literal_from_opt_in.dart.weak.transformed.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "literal_from_opt_in_lib.dart" as lit;
+
+import "org-dartlang-testcase:///literal_from_opt_in_lib.dart";
+
+static method main() → dynamic {
+  core::List<lit::Const<core::int*>*>* l1 = #C3;
+  core::List<lit::Const<core::int*>*>* l2 = #C3;
+  core::List<lit::Const<core::int*>*>* l3 = #C6;
+  core::List<lit::Const<core::int*>*>* l4 = #C3;
+  core::List<lit::Const<core::int*>*>* l5 = #C7;
+}
+
+library /*isNonNullableByDefault*/;
+import self as lit;
+import "dart:core" as core;
+
+class Const<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field lit::Const::T% field;
+  const constructor •(lit::Const::T% field) → lit::Const<lit::Const::T%>
+    : lit::Const::field = field, super core::Object::•()
+    ;
+}
+static const field lit::Const<core::int> a = #C2;
+static const field lit::Const<core::int?> b = #C2;
+static const field lit::Const<core::int?> c = #C5;
+static const field lit::Const<core::int>? d = #C2;
+static const field lit::Const<core::int>? e = #C4;
+
+constants  {
+  #C1 = 0
+  #C2 = lit::Const<core::int*> {field:#C1}
+  #C3 = <lit::Const<core::int*>*>[#C2]
+  #C4 = null
+  #C5 = lit::Const<core::int*> {field:#C4}
+  #C6 = <lit::Const<core::int*>*>[#C5]
+  #C7 = <lit::Const<core::int*>*>[#C4]
+}
diff --git a/pkg/front_end/testcases/nnbd/literal_from_opt_in_lib.dart b/pkg/front_end/testcases/nnbd/literal_from_opt_in_lib.dart
new file mode 100644
index 0000000..86c3129
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/literal_from_opt_in_lib.dart
@@ -0,0 +1,15 @@
+// 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.
+
+class Const<T> {
+  final T field;
+
+  const Const(this.field);
+}
+
+const Const<int> a = const Const<int>(0);
+const Const<int?> b = const Const<int?>(0);
+const Const<int?> c = const Const<int?>(null);
+const Const<int>? d = const Const<int>(0);
+const Const<int>? e = null;
diff --git a/pkg/front_end/testcases/nnbd/never_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/never_opt_out.dart.strong.expect
index 0fb13f2..83a210a 100644
--- a/pkg/front_end/testcases/nnbd/never_opt_out.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/never_opt_out.dart.strong.expect
@@ -44,7 +44,7 @@
 static method main() → dynamic {
   Never* localNever = null;
   core::Null? localNull = null;
-  Never inferredLocalNever = nev::optInNever;
+  Never* inferredLocalNever = nev::optInNever;
   localNever = localNever;
   self::optOutNever = localNever;
   nev::optInNever = localNever;
@@ -68,25 +68,25 @@
   nev::optInNever = localNull as{TypeError} Never;
   localNull = localNull;
   self::inferredOptOutNever = localNull;
-  inferredLocalNever = localNull as{TypeError} Never;
+  inferredLocalNever = localNull;
   localNever = self::inferredOptOutNever;
   self::optOutNever = self::inferredOptOutNever;
   nev::optInNever = self::inferredOptOutNever as{TypeError} Never;
   localNull = self::inferredOptOutNever;
   self::inferredOptOutNever = self::inferredOptOutNever;
-  inferredLocalNever = self::inferredOptOutNever as{TypeError} Never;
+  inferredLocalNever = self::inferredOptOutNever;
   localNever = inferredLocalNever;
   self::optOutNever = inferredLocalNever;
   nev::optInNever = inferredLocalNever;
   localNull = inferredLocalNever;
   self::inferredOptOutNever = inferredLocalNever;
   inferredLocalNever = inferredLocalNever;
-  self::throws(() → Never => self::optOutNever = nev::throwing());
-  self::throws(() → Never => localNever = nev::throwing());
-  self::throws(() → Never => self::optOutNever = nev::throwing());
-  self::throws(() → Never => nev::optInNever = nev::throwing());
-  self::throws(() → Never => self::inferredOptOutNever = nev::throwing());
-  self::throws(() → Never => inferredLocalNever = nev::throwing());
+  self::throws(() → Never* => self::optOutNever = nev::throwing());
+  self::throws(() → Never* => localNever = nev::throwing());
+  self::throws(() → Never* => self::optOutNever = nev::throwing());
+  self::throws(() → Never* => nev::optInNever = nev::throwing());
+  self::throws(() → Never* => self::inferredOptOutNever = nev::throwing());
+  self::throws(() → Never* => inferredLocalNever = nev::throwing());
 }
 static method throws(() →* void f) → dynamic {
   try {
diff --git a/pkg/front_end/testcases/nnbd/never_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/never_opt_out.dart.weak.expect
index e4651a2..ecb173e 100644
--- a/pkg/front_end/testcases/nnbd/never_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/never_opt_out.dart.weak.expect
@@ -44,7 +44,7 @@
 static method main() → dynamic {
   Never* localNever = null;
   core::Null? localNull = null;
-  Never inferredLocalNever = nev::optInNever;
+  Never* inferredLocalNever = nev::optInNever;
   localNever = localNever;
   self::optOutNever = localNever;
   nev::optInNever = localNever;
@@ -68,25 +68,25 @@
   nev::optInNever = localNull as{TypeError} Never;
   localNull = localNull;
   self::inferredOptOutNever = localNull;
-  inferredLocalNever = localNull as{TypeError} Never;
+  inferredLocalNever = localNull;
   localNever = self::inferredOptOutNever;
   self::optOutNever = self::inferredOptOutNever;
   nev::optInNever = self::inferredOptOutNever as{TypeError} Never;
   localNull = self::inferredOptOutNever;
   self::inferredOptOutNever = self::inferredOptOutNever;
-  inferredLocalNever = self::inferredOptOutNever as{TypeError} Never;
+  inferredLocalNever = self::inferredOptOutNever;
   localNever = inferredLocalNever;
   self::optOutNever = inferredLocalNever;
   nev::optInNever = inferredLocalNever;
   localNull = inferredLocalNever;
   self::inferredOptOutNever = inferredLocalNever;
   inferredLocalNever = inferredLocalNever;
-  self::throws(() → Never => self::optOutNever = nev::throwing());
-  self::throws(() → Never => localNever = nev::throwing());
-  self::throws(() → Never => self::optOutNever = nev::throwing());
-  self::throws(() → Never => nev::optInNever = nev::throwing());
-  self::throws(() → Never => self::inferredOptOutNever = nev::throwing());
-  self::throws(() → Never => inferredLocalNever = nev::throwing());
+  self::throws(() → Never* => self::optOutNever = nev::throwing());
+  self::throws(() → Never* => localNever = nev::throwing());
+  self::throws(() → Never* => self::optOutNever = nev::throwing());
+  self::throws(() → Never* => nev::optInNever = nev::throwing());
+  self::throws(() → Never* => self::inferredOptOutNever = nev::throwing());
+  self::throws(() → Never* => inferredLocalNever = nev::throwing());
 }
 static method throws(() →* void f) → dynamic {
   try {
diff --git a/pkg/front_end/testcases/rasta/issue_000002.dart.hierarchy.expect b/pkg/front_end/testcases/rasta/issue_000002.dart.hierarchy.expect
index 355be78..3c0c735 100644
--- a/pkg/front_end/testcases/rasta/issue_000002.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/rasta/issue_000002.dart.hierarchy.expect
@@ -42,7 +42,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/rasta/issue_000004.dart.hierarchy.expect b/pkg/front_end/testcases/rasta/issue_000004.dart.hierarchy.expect
index 257f1e9..4f5c506 100644
--- a/pkg/front_end/testcases/rasta/issue_000004.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/rasta/issue_000004.dart.hierarchy.expect
@@ -24,7 +24,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/rasta/issue_000067.dart.hierarchy.expect b/pkg/front_end/testcases/rasta/issue_000067.dart.hierarchy.expect
index 7f642c2..b93d5f7 100644
--- a/pkg/front_end/testcases/rasta/issue_000067.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/rasta/issue_000067.dart.hierarchy.expect
@@ -85,7 +85,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/rasta/issue_000068.dart.hierarchy.expect b/pkg/front_end/testcases/rasta/issue_000068.dart.hierarchy.expect
index 4f43eef..6c40be8 100644
--- a/pkg/front_end/testcases/rasta/issue_000068.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/rasta/issue_000068.dart.hierarchy.expect
@@ -95,7 +95,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.hierarchy.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.hierarchy.expect
index 2c66573..1b8b8b9 100644
--- a/pkg/front_end/testcases/rasta/issue_000070.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.hierarchy.expect
@@ -79,7 +79,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/rasta/parser_error.dart.hierarchy.expect b/pkg/front_end/testcases/rasta/parser_error.dart.hierarchy.expect
index 257f1e9..4f5c506 100644
--- a/pkg/front_end/testcases/rasta/parser_error.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/rasta/parser_error.dart.hierarchy.expect
@@ -24,7 +24,7 @@
   interfaces:
   classMembers:
     Expect.identical
-    Expect.throwsCastError
+    Expect.throwsTypeError
     Expect._fail
     Expect.notIdentical
     Expect.isNotNull
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 78eabf1..72977f5 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -1224,6 +1224,7 @@
 late_lowering/late_final_nullable_field_without_initializer: TextSerializationFailure
 late_lowering/late_final_nullable_local_with_initializer: TextSerializationFailure
 late_lowering/late_final_nullable_local_without_initializer: TextSerializationFailure
+late_lowering/late_future_or: TextSerializationFailure
 late_lowering/late_local_with_initializer: TextSerializationFailure
 late_lowering/late_local_without_initializer: TextSerializationFailure
 late_lowering/late_nullable_field_with_initializer: TextSerializationFailure
@@ -1271,6 +1272,7 @@
 nnbd/later: TextSerializationFailure
 nnbd/lhs_of_if_null: TextSerializationFailure
 nnbd/list_constructor: TextSerializationFailure
+nnbd/literal_from_opt_in: TextSerializationFailure
 nnbd/member_inheritance_from_opt_in: TextSerializationFailure
 nnbd/member_inheritance_from_opt_out: TextSerializationFailure
 nnbd/messages_with_types_opt_in: TypeCheckError
diff --git a/pkg/kernel/lib/src/future_or.dart b/pkg/kernel/lib/src/future_or.dart
index f655959..5555a0b 100644
--- a/pkg/kernel/lib/src/future_or.dart
+++ b/pkg/kernel/lib/src/future_or.dart
@@ -35,7 +35,7 @@
 
 Nullability computeNullabilityOfFutureOr(
     InterfaceType futureOr, Class futureOrClass) {
-  assert(futureOr.classNode == futureOrClass);
+  assert(_isFutureOr(futureOr, futureOrClass));
 
   // Performance note: the algorithm is linear.
   DartType argument = futureOr.typeArguments.single;
@@ -46,8 +46,7 @@
   }
   if (argument is TypeParameterType && argument.promotedBound != null) {
     DartType promotedBound = argument.promotedBound;
-    if (promotedBound is InterfaceType &&
-        promotedBound.className == futureOrClass) {
+    if (_isFutureOr(promotedBound, futureOrClass)) {
       return uniteNullabilities(
           intersectNullabilities(argument.typeParameterTypeNullability,
               computeNullabilityOfFutureOr(promotedBound, futureOrClass)),
@@ -59,8 +58,21 @@
   return uniteNullabilities(argumentNullability, futureOr.nullability);
 }
 
+bool _isFutureOr(DartType type, Class futureOrClass) {
+  if (type is InterfaceType) {
+    if (futureOrClass != null) {
+      return type.classNode == futureOrClass;
+    } else {
+      return type.classNode.name == 'FutureOr' &&
+          type.classNode.enclosingLibrary.importUri.scheme == 'dart' &&
+          type.classNode.enclosingLibrary.importUri.path == 'async';
+    }
+  }
+  return false;
+}
+
 Nullability computeNullability(DartType type, Class futureOrClass) {
-  if (type is InterfaceType && type.classNode == futureOrClass) {
+  if (_isFutureOr(type, futureOrClass)) {
     return computeNullabilityOfFutureOr(type, futureOrClass);
   }
   return type.nullability;
diff --git a/pkg/kernel/lib/src/replacement_visitor.dart b/pkg/kernel/lib/src/replacement_visitor.dart
index dcd6fd6..c0a7c0d 100644
--- a/pkg/kernel/lib/src/replacement_visitor.dart
+++ b/pkg/kernel/lib/src/replacement_visitor.dart
@@ -146,6 +146,11 @@
       // No nullability or type arguments needed to be substituted.
       return null;
     } else {
+      if (node.classNode.name == 'Null' &&
+          node.classNode.enclosingLibrary.importUri.scheme == 'dart' &&
+          node.classNode.enclosingLibrary.importUri.path == 'core') {
+        return null;
+      }
       return new InterfaceType(
           node.classNode,
           newNullability ?? node.nullability,
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index b80d616..5320c4a 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -286,7 +286,8 @@
       return const IsSubtypeOf.onlyIfIgnoringNullabilities();
     }
 
-    if (subtype.isPotentiallyNullable && supertype.isPotentiallyNonNullable) {
+    if (isPotentiallyNullable(subtype, futureOrClass) &&
+        isPotentiallyNonNullable(supertype, futureOrClass)) {
       // It's a special case to test X% <: X%, FutureOr<X%> <: FutureOr<X%>,
       // FutureOr<FutureOr<X%>> <: FutureOr<FutureOr<X%>>, etc, where X is a
       // type parameter.  In that case, the nullabilities of the subtype and the
diff --git a/pkg/nnbd_migration/lib/instrumentation.dart b/pkg/nnbd_migration/lib/instrumentation.dart
index 51c2c0a..93f3a9d 100644
--- a/pkg/nnbd_migration/lib/instrumentation.dart
+++ b/pkg/nnbd_migration/lib/instrumentation.dart
@@ -22,12 +22,31 @@
 
   CodeReference(this.path, this.line, this.column, this.function);
 
+  /// Creates a [CodeReference] pointing to the given [node].
+  factory CodeReference.fromAstNode(AstNode node) {
+    var compilationUnit = node.thisOrAncestorOfType<CompilationUnit>();
+    var source = compilationUnit.declaredElement.source;
+    var location = compilationUnit.lineInfo.getLocation(node.offset);
+    return CodeReference(source.fullName, location.lineNumber,
+        location.columnNumber, _computeEnclosingName(node));
+  }
+
   CodeReference.fromJson(dynamic json)
       : path = json['path'] as String,
         line = json['line'] as int,
         column = json['col'] as int,
         function = json['function'] as String;
 
+  /// Gets a short description of this code reference (using the last component
+  /// of the path rather than the full path)
+  String get shortName => '$shortPath:$line:$column';
+
+  /// Gets the last component of the path part of this code reference.
+  String get shortPath {
+    var pathAsUri = Uri.file(path);
+    return pathAsUri.pathSegments.last;
+  }
+
   Map<String, Object> toJson() {
     return {
       'path': path,
@@ -42,6 +61,27 @@
     var pathAsUri = Uri.file(path);
     return '${function ?? 'unknown'} ($pathAsUri:$line:$column)';
   }
+
+  static String _computeEnclosingName(AstNode node) {
+    List<String> parts = [];
+    while (node != null) {
+      var nodeName = _computeNodeDeclarationName(node);
+      if (nodeName != null) {
+        parts.add(nodeName);
+      }
+      node = node.parent;
+    }
+    if (parts.isEmpty) return null;
+    return parts.reversed.join('.');
+  }
+
+  static String _computeNodeDeclarationName(AstNode node) {
+    if (node is Declaration) {
+      return node.declaredElement?.name;
+    } else {
+      return null;
+    }
+  }
 }
 
 /// Information exposed to the migration client about the set of nullability
@@ -72,6 +112,20 @@
   DecoratedTypeInfo typeArgument(int i);
 }
 
+/// Information about a propagation stup that occurred during downstream
+/// propagation.
+abstract class DownstreamPropagationStepInfo implements PropagationStepInfo {
+  DownstreamPropagationStepInfo get principalCause;
+
+  /// The node whose nullability was changed.
+  ///
+  /// Any propagation step that took effect should have a non-null value here.
+  /// Propagation steps that are pending but have not taken effect yet, or that
+  /// never had an effect (e.g. because an edge was not triggered) will have a
+  /// `null` value for this field.
+  NullabilityNodeInfo get targetNode;
+}
+
 /// Information exposed to the migration client about an edge in the nullability
 /// graph.
 ///
@@ -284,6 +338,10 @@
   /// List of compound nodes wrapping this node.
   final List<NullabilityNodeInfo> outerCompoundNodes = <NullabilityNodeInfo>[];
 
+  /// Source code location corresponding to this nullability node, or `null` if
+  /// not known.
+  CodeReference get codeReference;
+
   /// Some nodes get nullability from downstream, so the downstream edges are
   /// available to query as well.
   Iterable<EdgeInfo> get downstreamEdges;
@@ -304,13 +362,13 @@
   /// The edges that caused this node to have the nullability that it has.
   Iterable<EdgeInfo> get upstreamEdges;
 
-  PropagationStepInfo get whyNullable;
+  /// If [isNullable] is true, the propagation step that caused this node to
+  /// become nullable.
+  DownstreamPropagationStepInfo get whyNullable;
 }
 
 abstract class PropagationStepInfo {
   CodeReference get codeReference;
-
-  PropagationStepInfo get principalCause;
 }
 
 /// Information exposed to the migration client about a node in the nullability
diff --git a/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart b/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart
index 76ef942..16f07b6 100644
--- a/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart
+++ b/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart
@@ -10,6 +10,7 @@
 import 'package:nnbd_migration/src/decorated_type.dart';
 import 'package:nnbd_migration/src/edge_origin.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/nullability_node_target.dart';
 
 /// This class transforms ordinary [DartType]s into their corresponding
 /// [DecoratedType]s, assuming the [DartType]s come from code that has already
@@ -23,55 +24,63 @@
 
   /// Transforms [type], which should have come from code that has already been
   /// migrated to NNBD, into the corresponding [DecoratedType].
-  DecoratedType decorate(DartType type, Element element) {
+  ///
+  /// TODO(paulberry): do we still need element or can we use target now?
+  DecoratedType decorate(
+      DartType type, Element element, NullabilityNodeTarget target) {
     if (type.isVoid || type.isDynamic) {
-      var node = NullabilityNode.forAlreadyMigrated();
-      _graph.makeNullable(node, AlwaysNullableTypeOrigin.forElement(element));
+      var node = NullabilityNode.forAlreadyMigrated(target);
+      _graph.makeNullableUnion(
+          node, AlwaysNullableTypeOrigin.forElement(element));
       return DecoratedType(type, node);
     }
     NullabilityNode node;
     var nullabilitySuffix = type.nullabilitySuffix;
     if (nullabilitySuffix == NullabilitySuffix.question) {
-      node = NullabilityNode.forAlreadyMigrated();
-      _graph.makeNullable(node, AlreadyMigratedTypeOrigin.forElement(element));
+      node = NullabilityNode.forAlreadyMigrated(target);
+      _graph.makeNullableUnion(
+          node, AlreadyMigratedTypeOrigin.forElement(element));
     } else {
-      node = NullabilityNode.forAlreadyMigrated();
+      node = NullabilityNode.forAlreadyMigrated(target);
       _graph.makeNonNullableUnion(
           node, AlreadyMigratedTypeOrigin.forElement(element));
     }
     if (type is FunctionType) {
       for (var element in type.typeFormals) {
-        var bound = element.bound;
-        DecoratedType decoratedBound;
-        if (bound == null) {
-          decoratedBound = decorate(
-              (_typeProvider.objectType as TypeImpl)
-                  .withNullability(NullabilitySuffix.question),
-              element);
-        } else {
-          decoratedBound = decorate(bound, element);
-        }
-        DecoratedTypeParameterBounds.current.put(element, decoratedBound);
+        DecoratedTypeParameterBounds.current.put(
+            element,
+            decorate(
+                element.bound ??
+                    (_typeProvider.objectType as TypeImpl)
+                        .withNullability(NullabilitySuffix.question),
+                element,
+                target.typeFormalBound(element.name)));
       }
       var positionalParameters = <DecoratedType>[];
       var namedParameters = <String, DecoratedType>{};
+      int index = 0;
       for (var parameter in type.parameters) {
         if (parameter.isPositional) {
-          positionalParameters.add(decorate(parameter.type, element));
+          positionalParameters.add(decorate(
+              parameter.type, element, target.positionalParameter(index++)));
         } else {
-          namedParameters[parameter.name] = decorate(parameter.type, element);
+          var name = parameter.name;
+          namedParameters[name] =
+              decorate(parameter.type, element, target.namedParameter(name));
         }
       }
       return DecoratedType(type, node,
-          returnType: decorate(type.returnType, element),
+          returnType: decorate(type.returnType, element, target.returnType()),
           namedParameters: namedParameters,
           positionalParameters: positionalParameters);
     } else if (type is InterfaceType) {
       var typeParameters = type.element.typeParameters;
       if (typeParameters.isNotEmpty) {
         assert(type.typeArguments.length == typeParameters.length);
+        int index = 0;
         return DecoratedType(type, node, typeArguments: [
-          for (var t in type.typeArguments) decorate(t, element)
+          for (var t in type.typeArguments)
+            decorate(t, element, target.typeArgument(index++))
         ]);
       }
       return DecoratedType(type, node);
@@ -100,6 +109,9 @@
       // Add FutureOr<T> as a supertype of Future<T>.
       allSupertypes.add(_typeProvider.futureOrType2(type.typeArguments.single));
     }
-    return [for (var t in allSupertypes) decorate(t, class_)];
+    return [
+      for (var t in allSupertypes)
+        decorate(t, class_, NullabilityNodeTarget.element(class_))
+    ];
   }
 }
diff --git a/pkg/nnbd_migration/lib/src/decorated_type.dart b/pkg/nnbd_migration/lib/src/decorated_type.dart
index 3a5b782..4c36029 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type.dart
@@ -9,9 +9,9 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
-import 'package:meta/meta.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/nullability_node_target.dart';
 
 /// Representation of a type in the code to be migrated.  In addition to
 /// tracking the (unmigrated) [DartType], we track the [ConstraintVariable]s
@@ -93,20 +93,24 @@
   /// Creates a decorated type corresponding to [type], with fresh nullability
   /// nodes everywhere that don't correspond to any source location.  These
   /// nodes can later be unioned with other nodes.
-  factory DecoratedType.forImplicitFunction(TypeProvider typeProvider,
-      FunctionType type, NullabilityNode node, NullabilityGraph graph,
-      {DecoratedType returnType, @required int offset}) {
+  factory DecoratedType.forImplicitFunction(
+      TypeProvider typeProvider,
+      FunctionType type,
+      NullabilityNode node,
+      NullabilityGraph graph,
+      NullabilityNodeTarget target,
+      {DecoratedType returnType}) {
     var positionalParameters = <DecoratedType>[];
     var namedParameters = <String, DecoratedType>{};
+    int index = 0;
     for (var parameter in type.parameters) {
       if (parameter.isPositional) {
-        positionalParameters.add(DecoratedType.forImplicitType(
-            typeProvider, parameter.type, graph,
-            offset: offset));
+        positionalParameters.add(DecoratedType.forImplicitType(typeProvider,
+            parameter.type, graph, target.positionalParameter(index++)));
       } else {
-        namedParameters[parameter.name] = DecoratedType.forImplicitType(
-            typeProvider, parameter.type, graph,
-            offset: offset);
+        var name = parameter.name;
+        namedParameters[name] = DecoratedType.forImplicitType(
+            typeProvider, parameter.type, graph, target.namedParameter(name));
       }
     }
     for (var element in type.typeFormals) {
@@ -114,14 +118,16 @@
         DecoratedTypeParameterBounds.current.put(
             element,
             DecoratedType.forImplicitType(
-                typeProvider, element.bound ?? typeProvider.objectType, graph,
-                offset: offset));
+                typeProvider,
+                element.bound ?? typeProvider.objectType,
+                graph,
+                target.typeFormalBound(element.name)));
       }
     }
     return DecoratedType(type, node,
         returnType: returnType ??
-            DecoratedType.forImplicitType(typeProvider, type.returnType, graph,
-                offset: offset),
+            DecoratedType.forImplicitType(
+                typeProvider, type.returnType, graph, target.returnType()),
         namedParameters: namedParameters,
         positionalParameters: positionalParameters);
   }
@@ -129,10 +135,10 @@
   /// Creates a DecoratedType corresponding to [type], with fresh nullability
   /// nodes everywhere that don't correspond to any source location.  These
   /// nodes can later be unioned with other nodes.
-  factory DecoratedType.forImplicitType(
-      TypeProvider typeProvider, DartType type, NullabilityGraph graph,
-      {List<DecoratedType> typeArguments, @required int offset}) {
-    var nullabilityNode = NullabilityNode.forInferredType(offset: offset);
+  factory DecoratedType.forImplicitType(TypeProvider typeProvider,
+      DartType type, NullabilityGraph graph, NullabilityNodeTarget target,
+      {List<DecoratedType> typeArguments}) {
+    var nullabilityNode = NullabilityNode.forInferredType(target);
     if (type is InterfaceType) {
       assert(() {
         if (typeArguments != null) {
@@ -144,9 +150,10 @@
         return true;
       }());
 
+      int index = 0;
       typeArguments ??= type.typeArguments
-          .map((t) => DecoratedType.forImplicitType(typeProvider, t, graph,
-              offset: offset))
+          .map((t) => DecoratedType.forImplicitType(
+              typeProvider, t, graph, target.typeArgument(index++)))
           .toList();
       return DecoratedType(type, nullabilityNode, typeArguments: typeArguments);
     } else if (type is FunctionType) {
@@ -154,8 +161,7 @@
         throw "Not supported: implicit function type with explicit type arguments";
       }
       return DecoratedType.forImplicitFunction(
-          typeProvider, type, nullabilityNode, graph,
-          offset: offset);
+          typeProvider, type, nullabilityNode, graph, target);
     } else {
       assert(typeArguments == null);
       return DecoratedType(type, nullabilityNode);
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 48517ac..6949482 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -25,6 +25,7 @@
 import 'package:nnbd_migration/src/expression_checks.dart';
 import 'package:nnbd_migration/src/node_builder.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/nullability_node_target.dart';
 import 'package:nnbd_migration/src/utilities/completeness_tracker.dart';
 import 'package:nnbd_migration/src/utilities/permissive_mode.dart';
 import 'package:nnbd_migration/src/utilities/resolution_utils.dart';
@@ -243,16 +244,18 @@
       var variable = baseElement.variable;
       var decoratedElementType = _variables.decoratedElementType(variable);
       if (baseElement.isGetter) {
+        var target = NullabilityNodeTarget.text('getter function');
         decoratedBaseType = DecoratedType(
-            baseElement.type, NullabilityNode.forInferredType(),
+            baseElement.type, NullabilityNode.forInferredType(target),
             returnType: decoratedElementType);
       } else {
         assert(baseElement.isSetter);
+        var target = NullabilityNodeTarget.text('setter function');
         decoratedBaseType = DecoratedType(
-            baseElement.type, NullabilityNode.forInferredType(),
+            baseElement.type, NullabilityNode.forInferredType(target),
             positionalParameters: [decoratedElementType],
-            returnType: DecoratedType(
-                VoidTypeImpl.instance, NullabilityNode.forInferredType()));
+            returnType: DecoratedType(VoidTypeImpl.instance,
+                NullabilityNode.forInferredType(target.returnType())));
       }
     } else {
       decoratedBaseType = _variables.decoratedElementType(baseElement);
@@ -398,7 +401,7 @@
         _postDominatedLocals.doScoped(action: () {
           rightType = rightOperand.accept(this);
         });
-        var ifNullNode = NullabilityNode.forIfNotNull();
+        var ifNullNode = NullabilityNode.forIfNotNull(node);
         expressionType = _decorateUpperOrLowerBound(
             node, node.staticType, leftType, rightType, true,
             node: ifNullNode);
@@ -890,6 +893,7 @@
     List<DecoratedType> decoratedTypeArguments;
     var typeArguments = node.constructorName.type.typeArguments;
     List<EdgeOrigin> parameterEdgeOrigins;
+    var target = NullabilityNodeTarget.codeRef('constructed type', node);
     if (typeArguments != null) {
       typeArguments.accept(this);
       typeArgumentTypes = typeArguments.arguments.map((t) => t.type);
@@ -903,10 +907,11 @@
       var staticType = node.staticType;
       if (staticType is InterfaceType) {
         typeArgumentTypes = staticType.typeArguments;
-        decoratedTypeArguments = typeArgumentTypes
-            .map((t) => DecoratedType.forImplicitType(typeProvider, t, _graph,
-                offset: node.offset))
-            .toList();
+        int index = 0;
+        decoratedTypeArguments = typeArgumentTypes.map((t) {
+          return DecoratedType.forImplicitType(
+              typeProvider, t, _graph, target.typeArgument(index++));
+        }).toList();
         instrumentation?.implicitTypeArguments(
             source, node, decoratedTypeArguments);
         parameterEdgeOrigins = List.filled(typeArgumentTypes.length,
@@ -925,7 +930,7 @@
           ListLengthConstructorOrigin(source, node));
     }
 
-    var nullabilityNode = NullabilityNode.forInferredType(offset: node.offset);
+    var nullabilityNode = NullabilityNode.forInferredType(target);
     _graph.makeNonNullable(
         nullabilityNode, InstanceCreationOrigin(source, node));
     var createdType = DecoratedType(node.staticType, nullabilityNode,
@@ -994,9 +999,9 @@
     try {
       var listType = node.staticType as InterfaceType;
       if (node.typeArguments == null) {
+        var target = NullabilityNodeTarget.codeRef('list element type', node);
         var elementType = DecoratedType.forImplicitType(
-            typeProvider, listType.typeArguments[0], _graph,
-            offset: node.offset);
+            typeProvider, listType.typeArguments[0], _graph, target);
         instrumentation?.implicitTypeArguments(source, node, [elementType]);
         _currentLiteralElementType = elementType;
       } else {
@@ -1099,9 +1104,9 @@
   @override
   DecoratedType visitNullLiteral(NullLiteral node) {
     _flowAnalysis.nullLiteral(node);
+    var target = NullabilityNodeTarget.codeRef('null literal', node);
     var decoratedType = DecoratedType.forImplicitType(
-        typeProvider, node.staticType, _graph,
-        offset: node.offset);
+        typeProvider, node.staticType, _graph, target);
     _graph.makeNullable(decoratedType.node, LiteralOrigin(source, node));
     return decoratedType;
   }
@@ -1218,7 +1223,8 @@
   @override
   DecoratedType visitRethrowExpression(RethrowExpression node) {
     _flowAnalysis.handleExit();
-    var nullabilityNode = NullabilityNode.forInferredType(offset: node.offset);
+    var target = NullabilityNodeTarget.codeRef('rethrow expression', node);
+    var nullabilityNode = NullabilityNode.forInferredType(target);
     _graph.makeNonNullable(nullabilityNode, ThrowOrigin(source, node));
     return DecoratedType(node.staticType, nullabilityNode);
   }
@@ -1229,15 +1235,14 @@
     Expression returnValue = node.expression;
     final isAsync = node.thisOrAncestorOfType<FunctionBody>().isAsynchronous;
     if (returnValue == null) {
+      var target = NullabilityNodeTarget.codeRef('implicit null return', node);
       var implicitNullType = DecoratedType.forImplicitType(
-          typeProvider, typeProvider.nullType, _graph,
-          offset: node.offset);
+          typeProvider, typeProvider.nullType, _graph, target);
       _graph.makeNullable(
           implicitNullType.node, AlwaysNullableTypeOrigin(source, node));
       _checkAssignment(ImplicitNullReturnOrigin(source, node),
-          source: isAsync
-              ? _futureOf(implicitNullType, offset: node.offset)
-              : implicitNullType,
+          source:
+              isAsync ? _futureOf(implicitNullType, node) : implicitNullType,
           destination: returnType,
           hard: false);
     } else {
@@ -1264,9 +1269,9 @@
       try {
         if (typeArguments == null) {
           assert(setOrMapType.typeArguments.length == 1);
+          var target = NullabilityNodeTarget.codeRef('set element type', node);
           var elementType = DecoratedType.forImplicitType(
-              typeProvider, setOrMapType.typeArguments[0], _graph,
-              offset: node.offset);
+              typeProvider, setOrMapType.typeArguments[0], _graph, target);
           instrumentation?.implicitTypeArguments(source, node, [elementType]);
           _currentLiteralElementType = elementType;
         } else {
@@ -1289,13 +1294,14 @@
       try {
         if (typeArguments == null) {
           assert(setOrMapType.typeArguments.length == 2);
+          var targetKey = NullabilityNodeTarget.codeRef('map key type', node);
           var keyType = DecoratedType.forImplicitType(
-              typeProvider, setOrMapType.typeArguments[0], _graph,
-              offset: node.offset);
+              typeProvider, setOrMapType.typeArguments[0], _graph, targetKey);
           _currentMapKeyType = keyType;
+          var targetValue =
+              NullabilityNodeTarget.codeRef('map value type', node);
           var valueType = DecoratedType.forImplicitType(
-              typeProvider, setOrMapType.typeArguments[1], _graph,
-              offset: node.offset);
+              typeProvider, setOrMapType.typeArguments[1], _graph, targetValue);
           _currentMapValueType = valueType;
           instrumentation
               ?.implicitTypeArguments(source, node, [keyType, valueType]);
@@ -1369,14 +1375,14 @@
   DecoratedType visitSpreadElement(SpreadElement node) {
     final spreadType = node.expression.staticType;
     DecoratedType spreadTypeDecorated;
+    var target = NullabilityNodeTarget.codeRef('spread element type', node);
     if (_typeSystem.isSubtypeOf(spreadType, typeProvider.mapObjectObjectType)) {
       assert(_currentMapKeyType != null && _currentMapValueType != null);
       final expectedType = typeProvider.mapType2(
           _currentMapKeyType.type, _currentMapValueType.type);
       final expectedDecoratedType = DecoratedType.forImplicitType(
-          typeProvider, expectedType, _graph,
-          typeArguments: [_currentMapKeyType, _currentMapValueType],
-          offset: node.offset);
+          typeProvider, expectedType, _graph, target,
+          typeArguments: [_currentMapKeyType, _currentMapValueType]);
 
       spreadTypeDecorated = _handleAssignment(node.expression,
           destinationType: expectedDecoratedType);
@@ -1386,8 +1392,8 @@
       final expectedType =
           typeProvider.iterableType2(_currentLiteralElementType.type);
       final expectedDecoratedType = DecoratedType.forImplicitType(
-          typeProvider, expectedType, _graph,
-          typeArguments: [_currentLiteralElementType], offset: node.offset);
+          typeProvider, expectedType, _graph, target,
+          typeArguments: [_currentLiteralElementType]);
 
       spreadTypeDecorated = _handleAssignment(node.expression,
           destinationType: expectedDecoratedType);
@@ -1412,7 +1418,9 @@
   DecoratedType visitSuperConstructorInvocation(
       SuperConstructorInvocation node) {
     var callee = node.staticElement;
-    var nullabilityNode = NullabilityNode.forInferredType(offset: node.offset);
+    var target =
+        NullabilityNodeTarget.codeRef('super constructor invocation', node);
+    var nullabilityNode = NullabilityNode.forInferredType(target);
     var class_ = node.thisOrAncestorOfType<ClassDeclaration>();
     var decoratedSupertype = _decoratedClassHierarchy.getDecoratedSupertype(
         class_.declaredElement, callee.enclosingElement);
@@ -1477,7 +1485,8 @@
     node.expression.accept(this);
     // TODO(paulberry): do we need to check the expression type?  I think not.
     _flowAnalysis.handleExit();
-    var nullabilityNode = NullabilityNode.forInferredType(offset: node.offset);
+    var target = NullabilityNodeTarget.codeRef('throw expression', node);
+    var nullabilityNode = NullabilityNode.forInferredType(target);
     _graph.makeNonNullable(nullabilityNode, ThrowOrigin(source, node));
     return DecoratedType(node.staticType, nullabilityNode);
   }
@@ -1711,12 +1720,12 @@
   /// Creates a type that can be used to check that an expression's value is
   /// non-nullable.
   DecoratedType _createNonNullableType(Expression expression) {
+    var target = NullabilityNodeTarget.codeRef('expression type', expression);
     // Note: it's not necessary for the type to precisely match the type of the
     // expression, since all we are going to do is cause a single graph edge to
     // be built; it is sufficient to pass in any decorated type whose node is
     // non-nullable.  So we use `Object`.
-    var nullabilityNode =
-        NullabilityNode.forInferredType(offset: expression.offset);
+    var nullabilityNode = NullabilityNode.forInferredType(target);
     _graph.makeNonNullableUnion(
         nullabilityNode, NonNullableUsageOrigin(source, expression));
     return DecoratedType(typeProvider.objectType, nullabilityNode);
@@ -1889,10 +1898,13 @@
     }
   }
 
-  DecoratedType _futureOf(DecoratedType type, {@required int offset}) =>
+  DecoratedType _futureOf(DecoratedType type, AstNode node) =>
       DecoratedType.forImplicitType(
-          typeProvider, typeProvider.futureType2(type.type), _graph,
-          typeArguments: [type], offset: offset);
+          typeProvider,
+          typeProvider.futureType2(type.type),
+          _graph,
+          NullabilityNodeTarget.codeRef('implicit future', node),
+          typeArguments: [type]);
 
   @override
   DecoratedType _getTypeParameterTypeBound(DecoratedType type) {
@@ -1946,7 +1958,7 @@
     try {
       sourceType = expression.accept(this);
       if (wrapFuture) {
-        sourceType = _wrapFuture(sourceType, offset: expression.offset);
+        sourceType = _wrapFuture(sourceType, expression);
       }
       if (sourceType == null) {
         throw StateError('No type computed for ${expression.runtimeType} '
@@ -2282,6 +2294,7 @@
       List<TypeParameterElement> constructorTypeParameters,
       {DartType invokeType}) {
     var typeFormals = constructorTypeParameters ?? calleeType.typeFormals;
+    var target = NullabilityNodeTarget.codeRef('invocation', node);
     if (typeFormals.isNotEmpty) {
       if (typeArguments != null) {
         var argumentTypes = typeArguments.arguments
@@ -2302,8 +2315,7 @@
         if (invokeType is FunctionType) {
           var argumentTypes = typeArgumentTypes
               .map((argType) => DecoratedType.forImplicitType(
-                  typeProvider, argType, _graph,
-                  offset: node.offset))
+                  typeProvider, argType, _graph, target))
               .toList();
           instrumentation?.implicitTypeArguments(source, node, argumentTypes);
           calleeType = _handleInstantiation(
@@ -2493,8 +2505,8 @@
 
   DecoratedType _makeNonNullableBoolType(Expression expression) {
     assert(expression.staticType.isDartCoreBool);
-    var nullabilityNode =
-        NullabilityNode.forInferredType(offset: expression.offset);
+    var target = NullabilityNodeTarget.codeRef('expression', expression);
+    var nullabilityNode = NullabilityNode.forInferredType(target);
     _graph.makeNonNullableUnion(
         nullabilityNode, NonNullableBoolTypeOrigin(source, expression));
     return DecoratedType(typeProvider.boolType, nullabilityNode);
@@ -2502,8 +2514,8 @@
 
   DecoratedType _makeNonNullLiteralType(Expression expression,
       {List<DecoratedType> typeArguments = const []}) {
-    var nullabilityNode =
-        NullabilityNode.forInferredType(offset: expression.offset);
+    var target = NullabilityNodeTarget.codeRef('expression', expression);
+    var nullabilityNode = NullabilityNode.forInferredType(target);
     _graph.makeNonNullableUnion(
         nullabilityNode, LiteralOrigin(source, expression));
     return DecoratedType(expression.staticType, nullabilityNode,
@@ -2511,18 +2523,18 @@
   }
 
   DecoratedType _makeNullableDynamicType(AstNode astNode) {
+    var target = NullabilityNodeTarget.codeRef('dynamic type', astNode);
     var decoratedType = DecoratedType.forImplicitType(
-        typeProvider, typeProvider.dynamicType, _graph,
-        offset: astNode.offset);
+        typeProvider, typeProvider.dynamicType, _graph, target);
     _graph.makeNullable(
         decoratedType.node, AlwaysNullableTypeOrigin(source, astNode));
     return decoratedType;
   }
 
   DecoratedType _makeNullableVoidType(SimpleIdentifier astNode) {
+    var target = NullabilityNodeTarget.codeRef('void type', astNode);
     var decoratedType = DecoratedType.forImplicitType(
-        typeProvider, typeProvider.voidType, _graph,
-        offset: astNode.offset);
+        typeProvider, typeProvider.voidType, _graph, target);
     _graph.makeNullable(
         decoratedType.node, AlwaysNullableTypeOrigin(source, astNode));
     return decoratedType;
@@ -2543,14 +2555,15 @@
       return null;
     }
 
-    NullabilityNode makeNonNullableNode() {
-      var nullabilityNode =
-          NullabilityNode.forInferredType(offset: node.offset);
+    NullabilityNode makeNonNullableNode(NullabilityNodeTarget target) {
+      var nullabilityNode = NullabilityNode.forInferredType(target);
       _graph.makeNonNullableUnion(
           nullabilityNode, ThisOrSuperOrigin(source, node));
       return nullabilityNode;
     }
 
+    var token = node.beginToken.lexeme;
+    var target = NullabilityNodeTarget.codeRef('$token expression', node);
     if (_currentClassOrExtension is ClassElement) {
       final type = (_currentClassOrExtension as ClassElement).thisType;
 
@@ -2559,20 +2572,24 @@
       // with no `?`s.  (Even if some of the type parameters are allowed to be
       // instantiated with nullable types at runtime, a reference to `this`
       // can't be migrated in such a way that forces them to be nullable.)
-      return DecoratedType(type, makeNonNullableNode(),
+      var index = 0;
+      return DecoratedType(type, makeNonNullableNode(target),
           typeArguments: type.typeArguments
-              .map((t) => DecoratedType(t, makeNonNullableNode()))
+              .map((t) => DecoratedType(
+                  t, makeNonNullableNode(target.typeArgument(index++))))
               .toList());
     } else {
       assert(_currentClassOrExtension is ExtensionElement);
       final type = (_currentClassOrExtension as ExtensionElement).extendedType;
 
       if (type is InterfaceType) {
-        return DecoratedType(
-            type, NullabilityNode.forInferredType(offset: node.offset),
+        var index = 0;
+        return DecoratedType(type, NullabilityNode.forInferredType(target),
             typeArguments: type.typeArguments
                 .map((t) => DecoratedType(
-                    t, NullabilityNode.forInferredType(offset: node.offset)))
+                    t,
+                    NullabilityNode.forInferredType(
+                        target.typeArgument(index++))))
                 .toList());
       } else {
         _unimplemented(node, 'extension of $type (${type.runtimeType}');
@@ -2598,9 +2615,9 @@
   /// Produce Future<flatten(T)> for some T, however, we would like to merely
   /// upcast T to that type if possible, skipping the flatten when not
   /// necessary.
-  DecoratedType _wrapFuture(DecoratedType type, {@required int offset}) {
+  DecoratedType _wrapFuture(DecoratedType type, AstNode node) {
     if (type.type.isDartCoreNull || type.type.isBottom) {
-      return _futureOf(type, offset: offset);
+      return _futureOf(type, node);
     }
 
     if (_typeSystem.isSubtypeOf(type.type, typeProvider.futureDynamicType)) {
@@ -2608,7 +2625,7 @@
           type, typeProvider.futureDynamicType.element);
     }
 
-    return _futureOf(type, offset: offset);
+    return _futureOf(type, node);
   }
 }
 
diff --git a/pkg/nnbd_migration/lib/src/edge_origin.dart b/pkg/nnbd_migration/lib/src/edge_origin.dart
index f5ada49..481783a 100644
--- a/pkg/nnbd_migration/lib/src/edge_origin.dart
+++ b/pkg/nnbd_migration/lib/src/edge_origin.dart
@@ -102,36 +102,10 @@
   /// created, or `null` if unknown.
   CodeReference get codeReference {
     if (node != null) {
-      var location = node
-          .thisOrAncestorOfType<CompilationUnit>()
-          .lineInfo
-          .getLocation(node.offset);
-      return CodeReference(source.fullName, location.lineNumber,
-          location.columnNumber, _computeEnclosingName(node));
+      return CodeReference.fromAstNode(node);
     }
     return null;
   }
-
-  static String _computeEnclosingName(AstNode node) {
-    List<String> parts = [];
-    while (node != null) {
-      var nodeName = _computeNodeDeclarationName(node);
-      if (nodeName != null) {
-        parts.add(nodeName);
-      }
-      node = node.parent;
-    }
-    if (parts.isEmpty) return null;
-    return parts.reversed.join('.');
-  }
-
-  static String _computeNodeDeclarationName(AstNode node) {
-    if (node is Declaration) {
-      return node.declaredElement?.name;
-    } else {
-      return null;
-    }
-  }
 }
 
 /// An edge origin used for edges that originated because of a reference to an
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 81abf14..132666e 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -18,6 +18,7 @@
 import 'package:nnbd_migration/src/decorated_type.dart';
 import 'package:nnbd_migration/src/expression_checks.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/nullability_node_target.dart';
 import 'package:nnbd_migration/src/potential_modification.dart';
 import 'package:nnbd_migration/src/utilities/completeness_tracker.dart';
 import 'package:nnbd_migration/src/utilities/permissive_mode.dart';
@@ -50,6 +51,11 @@
   /// seen so far.  Otherwise `null`.
   List<DecoratedType> _positionalParameters;
 
+  /// If the child types of a node are being visited, the
+  /// [NullabilityNodeTarget] that should be used in [visitTypeAnnotation].
+  /// Otherwise `null`.
+  NullabilityNodeTarget _target;
+
   final NullabilityMigrationListener /*?*/ listener;
 
   final NullabilityMigrationInstrumentation /*?*/ instrumentation;
@@ -68,9 +74,9 @@
     if (node.exceptionParameter != null) {
       // If there is no `on Type` part of the catch clause, the type is dynamic.
       if (exceptionType == null) {
+        var target = NullabilityNodeTarget.codeRef('exception', node);
         exceptionType = DecoratedType.forImplicitType(
-            _typeProvider, _typeProvider.dynamicType, _graph,
-            offset: node.offset);
+            _typeProvider, _typeProvider.dynamicType, _graph, target);
         instrumentation?.implicitType(
             source, node.exceptionParameter, exceptionType);
       }
@@ -79,8 +85,8 @@
     }
     if (node.stackTraceParameter != null) {
       // The type of stack traces is always StackTrace (non-nullable).
-      var nullabilityNode = NullabilityNode.forInferredType(
-          offset: node.stackTraceParameter.offset);
+      var target = NullabilityNodeTarget.codeRef('stack trace', node);
+      var nullabilityNode = NullabilityNode.forInferredType(target);
       _graph.makeNonNullableUnion(nullabilityNode,
           StackTraceTypeOrigin(source, node.stackTraceParameter));
       var stackTraceType =
@@ -134,9 +140,10 @@
       assert(constructorElement.isSynthetic);
       var decoratedReturnType =
           _createDecoratedTypeForClass(classElement, node);
+      var target = NullabilityNodeTarget.element(constructorElement);
       var functionType = DecoratedType.forImplicitFunction(
-          _typeProvider, constructorElement.type, _graph.never, _graph,
-          returnType: decoratedReturnType, offset: node.offset);
+          _typeProvider, constructorElement.type, _graph.never, _graph, target,
+          returnType: decoratedReturnType);
       _variables.recordDecoratedElementType(constructorElement, functionType);
     }
     return null;
@@ -170,9 +177,10 @@
     DecoratedType type = node.type?.accept(this);
     if (node.identifier != null) {
       if (type == null) {
+        var declaredElement = node.declaredElement;
+        var target = NullabilityNodeTarget.element(declaredElement);
         type = DecoratedType.forImplicitType(
-            _typeProvider, node.declaredElement.type, _graph,
-            offset: node.offset);
+            _typeProvider, declaredElement.type, _graph, target);
         instrumentation?.implicitType(source, node, type);
       }
       _variables.recordDecoratedElementType(
@@ -207,36 +215,44 @@
     _variables.recordDecoratedElementType(
         classElement, DecoratedType(classElement.thisType, _graph.never));
 
-    makeNonNullNode([AstNode forNode]) {
+    makeNonNullNode(NullabilityNodeTarget target, [AstNode forNode]) {
       forNode ??= node;
-      final graphNode = NullabilityNode.forInferredType(offset: forNode.offset);
+      final graphNode = NullabilityNode.forInferredType(target);
       _graph.makeNonNullableUnion(graphNode, EnumValueOrigin(source, forNode));
       return graphNode;
     }
 
     for (var item in node.constants) {
-      _variables.recordDecoratedElementType(item.declaredElement,
-          DecoratedType(classElement.thisType, makeNonNullNode(item)));
+      var declaredElement = item.declaredElement;
+      var target = NullabilityNodeTarget.element(declaredElement);
+      _variables.recordDecoratedElementType(declaredElement,
+          DecoratedType(classElement.thisType, makeNonNullNode(target, item)));
     }
     final valuesGetter = classElement.getGetter('values');
+    var valuesTarget = NullabilityNodeTarget.element(valuesGetter);
     _variables.recordDecoratedElementType(
         valuesGetter,
-        DecoratedType(valuesGetter.type, makeNonNullNode(),
-            returnType: DecoratedType(
-                valuesGetter.returnType, makeNonNullNode(), typeArguments: [
-              DecoratedType(classElement.thisType, makeNonNullNode())
-            ])));
+        DecoratedType(valuesGetter.type, makeNonNullNode(valuesTarget),
+            returnType: DecoratedType(valuesGetter.returnType,
+                makeNonNullNode(valuesTarget.returnType()),
+                typeArguments: [
+                  DecoratedType(classElement.thisType,
+                      makeNonNullNode(valuesTarget.typeArgument(0)))
+                ])));
     final indexGetter = classElement.getGetter('index');
+    var indexTarget = NullabilityNodeTarget.element(indexGetter);
     _variables.recordDecoratedElementType(
         indexGetter,
-        DecoratedType(indexGetter.type, makeNonNullNode(),
-            returnType:
-                DecoratedType(indexGetter.returnType, makeNonNullNode())));
+        DecoratedType(indexGetter.type, makeNonNullNode(indexTarget),
+            returnType: DecoratedType(indexGetter.returnType,
+                makeNonNullNode(indexTarget.returnType()))));
     final toString = classElement.getMethod('toString');
+    var toStringTarget = NullabilityNodeTarget.element(toString);
     _variables.recordDecoratedElementType(
         toString,
-        DecoratedType(toString.type, makeNonNullNode(),
-            returnType: DecoratedType(toString.returnType, makeNonNullNode())));
+        DecoratedType(toString.type, makeNonNullNode(toStringTarget),
+            returnType: DecoratedType(toString.returnType,
+                makeNonNullNode(toStringTarget.returnType()))));
     return null;
   }
 
@@ -285,13 +301,15 @@
     var functionType = declaredElement.function.type;
     var returnType = node.returnType;
     DecoratedType decoratedReturnType;
+    var target = NullabilityNodeTarget.element(declaredElement);
     if (returnType != null) {
-      decoratedReturnType = returnType.accept(this);
+      _pushNullabilityNodeTarget(target.returnType(), () {
+        decoratedReturnType = returnType.accept(this);
+      });
     } else {
       // Inferred return type.
       decoratedReturnType = DecoratedType.forImplicitType(
-          _typeProvider, functionType.returnType, _graph,
-          offset: node.offset);
+          _typeProvider, functionType.returnType, _graph, target.returnType());
       instrumentation?.implicitReturnType(source, node, decoratedReturnType);
     }
     var previousPositionalParameters = _positionalParameters;
@@ -330,7 +348,15 @@
     node.metadata.accept(this);
     DecoratedType decoratedFunctionType;
     node.typeParameters?.accept(this);
-    decoratedFunctionType = node.functionType.accept(this);
+    var target = NullabilityNodeTarget.element(node.declaredElement);
+    var returnType = node.functionType.returnType;
+    if (returnType != null) {
+      _pushNullabilityNodeTarget(target.returnType(), () {
+        decoratedFunctionType = node.functionType.accept(this);
+      });
+    } else {
+      decoratedFunctionType = node.functionType.accept(this);
+    }
     _variables.recordDecoratedElementType(
         (node.declaredElement as GenericTypeAliasElement).function,
         decoratedFunctionType);
@@ -372,8 +398,10 @@
   DecoratedType visitTypeAnnotation(TypeAnnotation node) {
     assert(node != null); // TODO(paulberry)
     var type = node.type;
+    var target =
+        _target ?? NullabilityNodeTarget.codeRef('explicit type', node);
     if (type.isVoid || type.isDynamic) {
-      var nullabilityNode = NullabilityNode.forTypeAnnotation(node.end);
+      var nullabilityNode = NullabilityNode.forTypeAnnotation(target);
       var decoratedType = DecoratedType(type, nullabilityNode);
       _variables.recordDecoratedTypeAnnotation(
           source, node, decoratedType, null);
@@ -386,10 +414,10 @@
     if (type is InterfaceType && type.element.typeParameters.isNotEmpty) {
       if (node is TypeName) {
         if (node.typeArguments == null) {
+          int index = 0;
           typeArguments = type.typeArguments
               .map((t) => DecoratedType.forImplicitType(
-                  _typeProvider, t, _graph,
-                  offset: node.offset))
+                  _typeProvider, t, _graph, target.typeArgument(index++)))
               .toList();
           instrumentation?.implicitTypeArguments(source, node, typeArguments);
         } else {
@@ -403,12 +431,16 @@
     if (node is GenericFunctionType) {
       var returnType = node.returnType;
       if (returnType == null) {
-        decoratedReturnType = DecoratedType.forImplicitType(
-            _typeProvider, DynamicTypeImpl.instance, _graph,
-            offset: node.offset);
+        decoratedReturnType = DecoratedType.forImplicitType(_typeProvider,
+            DynamicTypeImpl.instance, _graph, target.returnType());
         instrumentation?.implicitReturnType(source, node, decoratedReturnType);
       } else {
-        decoratedReturnType = returnType.accept(this);
+        // If [_target] is non-null, then it represents the return type for
+        // a FunctionTypeAlias. Otherwise, create a return type target for
+        // `target`.
+        _pushNullabilityNodeTarget(_target ?? target.returnType(), () {
+          decoratedReturnType = returnType.accept(this);
+        });
       }
       positionalParameters = <DecoratedType>[];
       namedParameters = <String, DecoratedType>{};
@@ -434,7 +466,7 @@
         parent is GenericTypeAlias) {
       nullabilityNode = _graph.never;
     } else {
-      nullabilityNode = NullabilityNode.forTypeAnnotation(node.end);
+      nullabilityNode = NullabilityNode.forTypeAnnotation(target);
     }
     DecoratedType decoratedType;
     if (type is FunctionType && node is! GenericFunctionType) {
@@ -443,8 +475,7 @@
       // synthesize new nodes for it).  These nodes will be unioned with the
       // typedef nodes by the edge builder.
       decoratedType = DecoratedType.forImplicitFunction(
-          _typeProvider, type, nullabilityNode, _graph,
-          offset: node.offset);
+          _typeProvider, type, nullabilityNode, _graph, target);
     } else {
       decoratedType = DecoratedType(type, nullabilityNode,
           typeArguments: typeArguments,
@@ -488,8 +519,8 @@
     if (bound != null) {
       decoratedBound = bound.accept(this);
     } else {
-      var nullabilityNode =
-          NullabilityNode.forInferredType(offset: node.offset);
+      var nullabilityNode = NullabilityNode.forInferredType(
+          NullabilityNodeTarget.typeParameterBound(element));
       decoratedBound = DecoratedType(_typeProvider.objectType, nullabilityNode);
       _graph.connect(_graph.always, nullabilityNode,
           AlwaysNullableTypeOrigin.forElement(element));
@@ -507,9 +538,9 @@
       variable.metadata.accept(this);
       var declaredElement = variable.declaredElement;
       if (type == null) {
+        var target = NullabilityNodeTarget.element(declaredElement);
         type = DecoratedType.forImplicitType(
-            _typeProvider, declaredElement.type, _graph,
-            offset: variable.offset);
+            _typeProvider, declaredElement.type, _graph, target);
         instrumentation?.implicitType(source, node, type);
       }
       _variables.recordDecoratedElementType(declaredElement, type);
@@ -557,8 +588,11 @@
     metadata?.accept(this);
     var functionType = declaredElement.type;
     DecoratedType decoratedReturnType;
+    var target = NullabilityNodeTarget.element(declaredElement);
     if (returnType != null) {
-      decoratedReturnType = returnType.accept(this);
+      _pushNullabilityNodeTarget(target.returnType(), () {
+        decoratedReturnType = returnType.accept(this);
+      });
     } else if (declaredElement is ConstructorElement) {
       // Constructors have no explicit return type annotation, so use the
       // implicit return type.
@@ -568,8 +602,7 @@
     } else {
       // Inferred return type.
       decoratedReturnType = DecoratedType.forImplicitType(
-          _typeProvider, functionType.returnType, _graph,
-          offset: node.offset);
+          _typeProvider, functionType.returnType, _graph, target);
       instrumentation?.implicitReturnType(source, node, decoratedReturnType);
     }
     var previousPositionalParameters = _positionalParameters;
@@ -603,21 +636,20 @@
     var declaredElement = node.declaredElement;
     node.metadata?.accept(this);
     DecoratedType decoratedType;
+    var target = NullabilityNodeTarget.element(declaredElement);
     if (parameters == null) {
       if (type != null) {
         decoratedType = type.accept(this);
       } else {
         decoratedType = DecoratedType.forImplicitType(
-            _typeProvider, declaredElement.type, _graph,
-            offset: node.offset);
+            _typeProvider, declaredElement.type, _graph, target);
         instrumentation?.implicitType(source, node, decoratedType);
       }
     } else {
       DecoratedType decoratedReturnType;
       if (type == null) {
-        decoratedReturnType = DecoratedType.forImplicitType(
-            _typeProvider, DynamicTypeImpl.instance, _graph,
-            offset: node.offset);
+        decoratedReturnType = DecoratedType.forImplicitType(_typeProvider,
+            DynamicTypeImpl.instance, _graph, target.returnType());
         instrumentation?.implicitReturnType(source, node, decoratedReturnType);
       } else {
         decoratedReturnType = type.accept(this);
@@ -640,7 +672,7 @@
         _namedParameters = previousNamedParameters;
       }
       decoratedType = DecoratedType(
-          declaredElement.type, NullabilityNode.forTypeAnnotation(node.end),
+          declaredElement.type, NullabilityNode.forTypeAnnotation(target),
           returnType: decoratedReturnType,
           positionalParameters: positionalParameters,
           namedParameters: namedParameters);
@@ -676,8 +708,9 @@
     for (var supertype in supertypes) {
       DecoratedType decoratedSupertype;
       if (supertype == null) {
-        var nullabilityNode =
-            NullabilityNode.forInferredType(offset: astNode.offset);
+        var target =
+            NullabilityNodeTarget.codeRef('implicit object supertype', astNode);
+        var nullabilityNode = NullabilityNode.forInferredType(target);
         _graph.makeNonNullableUnion(
             nullabilityNode, NonNullableObjectSuperclass(source, astNode));
         decoratedSupertype =
@@ -692,6 +725,16 @@
         declaredElement, decoratedSupertypes);
   }
 
+  void _pushNullabilityNodeTarget(NullabilityNodeTarget target, Function() fn) {
+    NullabilityNodeTarget previousTarget = _target;
+    try {
+      _target = target;
+      fn();
+    } finally {
+      _target = previousTarget;
+    }
+  }
+
   @alwaysThrows
   void _unimplemented(AstNode node, String message) {
     CompilationUnit unit = node.root as CompilationUnit;
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
index fe9bab5..bcbe748 100644
--- a/pkg/nnbd_migration/lib/src/nullability_node.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -2,23 +2,23 @@
 // 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:collection';
+
+import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:meta/meta.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nullability_state.dart';
+import 'package:nnbd_migration/src/nullability_node_target.dart';
 import 'package:nnbd_migration/src/postmortem_file.dart';
 
 import 'edge_origin.dart';
 
 /// Base class for steps that occur as part of downstream propagation, where the
 /// nullability of a node is changed to a new state.
-abstract class DownstreamPropagationStep extends PropagationStep {
-  /// The node whose nullability was changed.
-  ///
-  /// Any propagation step that took effect should have a non-null value here.
-  /// Propagation steps that are pending but have not taken effect yet, or that
-  /// never had an effect (e.g. because an edge was not triggered) will have a
-  /// `null` value for this field.
+abstract class DownstreamPropagationStep extends PropagationStep
+    implements DownstreamPropagationStepInfo {
+  @override
   NullabilityNodeMutable targetNode;
 
   /// The state that the node's nullability was changed to.
@@ -38,6 +38,9 @@
         newState = Nullability.fromJson(json['newState']);
 
   @override
+  DownstreamPropagationStep get principalCause;
+
+  @override
   Map<String, Object> toJson(NullabilityGraphSerializer serializer) {
     return {
       'target': serializer.idForNode(targetNode),
@@ -646,12 +649,8 @@
 /// variables.  Over time this will be replaced by a first class representation
 /// of the nullability inference graph.
 abstract class NullabilityNode implements NullabilityNodeInfo {
-  static final _debugNamesInUse = Set<String>();
-
   bool _isPossiblyOptional = false;
 
-  String _debugName;
-
   /// List of [NullabilityEdge] objects describing this node's relationship to
   /// other nodes that are "downstream" from it (meaning that if a key node is
   /// nullable, then all the nodes in the corresponding value will either have
@@ -667,25 +666,26 @@
 
   /// Creates a [NullabilityNode] representing the nullability of a variable
   /// whose type comes from an already-migrated library.
-  factory NullabilityNode.forAlreadyMigrated() =>
-      _NullabilityNodeSimple('migrated');
+  factory NullabilityNode.forAlreadyMigrated(NullabilityNodeTarget target) =>
+      _NullabilityNodeSimple(target);
 
   /// Creates a [NullabilityNode] representing the nullability of an expression
   /// which is nullable iff two other nullability nodes are both nullable.
   ///
   /// The caller is required to create the appropriate graph edges to ensure
   /// that the appropriate relationship between the nodes' nullabilities holds.
-  factory NullabilityNode.forGLB() => _NullabilityNodeSimple('GLB');
+  factory NullabilityNode.forGLB() => _NullabilityNodeSimple(
+      NullabilityNodeTarget.text('(greatest lower bound)'));
 
   /// Creates a [NullabilityNode] representing the nullability of a variable
   /// whose type is determined by the `??` operator.
-  factory NullabilityNode.forIfNotNull() =>
-      _NullabilityNodeSimple('?? operator');
+  factory NullabilityNode.forIfNotNull(AstNode node) => _NullabilityNodeSimple(
+      NullabilityNodeTarget.codeRef('?? operator', node));
 
   /// Creates a [NullabilityNode] representing the nullability of a variable
   /// whose type is determined by type inference.
-  factory NullabilityNode.forInferredType({int offset}) =>
-      _NullabilityNodeSimple('inferred${offset == null ? '' : '($offset)'}');
+  factory NullabilityNode.forInferredType(NullabilityNodeTarget target) =>
+      _NullabilityNodeSimple(target);
 
   /// Creates a [NullabilityNode] representing the nullability of an
   /// expression which is nullable iff either [a] or [b] is nullable.
@@ -708,8 +708,8 @@
 
   /// Creates a [NullabilityNode] representing the nullability of a type
   /// annotation appearing explicitly in the user's program.
-  factory NullabilityNode.forTypeAnnotation(int endOffset) =>
-      _NullabilityNodeSimple('type($endOffset)');
+  factory NullabilityNode.forTypeAnnotation(NullabilityNodeTarget target) =>
+      _NullabilityNodeSimple(target);
 
   NullabilityNode.fromJson(
       dynamic json, NullabilityGraphDeserializer deserializer) {
@@ -732,10 +732,17 @@
 
   NullabilityNode._();
 
+  @override
+  CodeReference get codeReference => null;
+
   /// Gets a string that can be appended to a type name during debugging to help
   /// annotate the nullability of that type.
   String get debugSuffix => '?($this)';
 
+  /// Gets a name for the nullability node that is suitable for display to the
+  /// user.
+  String get displayName;
+
   Iterable<EdgeInfo> get downstreamEdges => _downstreamEdges;
 
   /// After nullability propagation, this getter can be used to query whether
@@ -759,7 +766,9 @@
   @override
   Iterable<EdgeInfo> get upstreamEdges => _upstreamEdges;
 
-  String get _debugPrefix;
+  /// If this node has non-null intent, the propagation step that caused it to
+  /// have non-null intent, otherwise `null`.
+  UpstreamPropagationStep get whyNotNullable;
 
   String get _jsonKind;
 
@@ -801,24 +810,11 @@
   }
 
   String toString({NodeToIdMapper idMapper}) {
-    if (_debugName == null) {
-      var prefix = _debugPrefix;
-      if (_debugNamesInUse.add(prefix)) {
-        _debugName = prefix;
-      } else {
-        for (int i = 0;; i++) {
-          var name = '${prefix}_$i';
-          if (_debugNamesInUse.add(name)) {
-            _debugName = name;
-            break;
-          }
-        }
-      }
-    }
+    var name = displayName;
     if (idMapper == null) {
-      return _debugName;
+      return name;
     } else {
-      return '${idMapper.idForNode(this)}: $_debugName';
+      return '${idMapper.idForNode(this)}: $name';
     }
   }
 
@@ -828,11 +824,6 @@
   void trackPossiblyOptional() {
     _isPossiblyOptional = true;
   }
-
-  @visibleForTesting
-  static void clearDebugNames() {
-    _debugNamesInUse.clear();
-  }
 }
 
 /// Base class for nullability nodes that are nullable if at least one of a set
@@ -880,10 +871,10 @@
       {'left': left, 'right': right};
 
   @override
-  Iterable<NullabilityNode> get _components => [left, right];
+  String get displayName => '${left.displayName} or ${right.displayName}';
 
   @override
-  String get _debugPrefix => 'LUB($left, $right)';
+  Iterable<NullabilityNode> get _components => [left, right];
 
   @override
   String get _jsonKind => 'lub';
@@ -931,10 +922,11 @@
       {'inner': innerNode, 'outer': outerNode};
 
   @override
-  Iterable<NullabilityNode> get _components => [innerNode, outerNode];
+  String get displayName =>
+      '${innerNode.displayName} or ${outerNode.displayName}';
 
   @override
-  String get _debugPrefix => 'Substituted($innerNode, $outerNode)';
+  Iterable<NullabilityNode> get _components => [innerNode, outerNode];
 
   @override
   String get _jsonKind => 'substitution';
@@ -967,6 +959,8 @@
 
   DownstreamPropagationStep _whyNullable;
 
+  UpstreamPropagationStep _whyNotNullable;
+
   NullabilityNodeMutable.fromJson(
       dynamic json, NullabilityGraphDeserializer deserializer)
       : _nullability = json['nullability'] == null
@@ -996,7 +990,10 @@
   NonNullIntent get nonNullIntent => _nonNullIntent;
 
   @override
-  PropagationStepInfo get whyNullable => _whyNullable;
+  UpstreamPropagationStep get whyNotNullable => _whyNotNullable;
+
+  @override
+  DownstreamPropagationStepInfo get whyNullable => _whyNullable;
 
   @override
   void resetState() {
@@ -1021,7 +1018,7 @@
 /// Information produced by [NullabilityGraph.propagate] about the results of
 /// graph propagation.
 class PropagationResult {
-  /// A list of all edges that couldn't be satisfied.
+  /// A list of all edges that couldn't be satisfied.  May contain duplicates.
   final List<NullabilityEdge> unsatisfiedEdges = [];
 
   /// A list of all substitution nodes that couldn't be satisfied.
@@ -1136,7 +1133,7 @@
       '${edge.toString(idMapper: idMapper)}';
 }
 
-/// Propagation step where we mark the source of an edge as exactx nullable, due
+/// Propagation step where we mark the source of an edge as exact nullable, due
 /// to its destination becoming exact nullable.
 class SimpleExactNullablePropagationStep extends ExactNullablePropagationStep {
   @override
@@ -1226,16 +1223,16 @@
 
 class _NullabilityNodeImmutable extends NullabilityNode {
   @override
-  final String _debugPrefix;
+  final String displayName;
 
   @override
   final bool isNullable;
 
-  _NullabilityNodeImmutable(this._debugPrefix, this.isNullable) : super._();
+  _NullabilityNodeImmutable(this.displayName, this.isNullable) : super._();
 
   _NullabilityNodeImmutable.fromJson(
       dynamic json, NullabilityGraphDeserializer deserializer)
-      : _debugPrefix = json['debugPrefix'] as String,
+      : displayName = json['displayName'] as String,
         isNullable = json['isNullable'] as bool,
         super.fromJson(json, deserializer);
 
@@ -1257,7 +1254,10 @@
       isNullable ? NonNullIntent.none : NonNullIntent.direct;
 
   @override
-  PropagationStepInfo get whyNullable => null;
+  UpstreamPropagationStep get whyNotNullable => null;
+
+  @override
+  DownstreamPropagationStepInfo get whyNullable => null;
 
   @override
   String get _jsonKind => 'immutable';
@@ -1274,30 +1274,36 @@
   @override
   Map<String, Object> toJson(NullabilityGraphSerializer serializer) {
     var json = super.toJson(serializer);
-    json['debugPrefix'] = _debugPrefix;
+    json['displayName'] = displayName;
     json['isNullable'] = isNullable;
     return json;
   }
 }
 
 class _NullabilityNodeSimple extends NullabilityNodeMutable {
-  @override
-  final String _debugPrefix;
+  final NullabilityNodeTarget target;
 
-  _NullabilityNodeSimple(this._debugPrefix) : super._();
+  _NullabilityNodeSimple(this.target) : super._();
 
   _NullabilityNodeSimple.fromJson(
       dynamic json, NullabilityGraphDeserializer deserializer)
-      : _debugPrefix = json['debugPrefix'] as String,
+      : target =
+            NullabilityNodeTarget.text(json['targetDisplayName'] as String),
         super.fromJson(json, deserializer);
 
   @override
+  CodeReference get codeReference => target.codeReference;
+
+  @override
+  String get displayName => target.displayName;
+
+  @override
   String get _jsonKind => 'simple';
 
   @override
   Map<String, Object> toJson(NullabilityGraphSerializer serializer) {
     var json = super.toJson(serializer);
-    json['debugPrefix'] = _debugPrefix;
+    json['targetDisplayName'] = target.displayName;
     return json;
   }
 }
@@ -1317,9 +1323,10 @@
   /// The graph's one and only "never" node.
   final NullabilityNode _never;
 
-  /// During any given stage of nullability propagation, a list of all the edges
-  /// that need to be examined before the stage is complete.
-  final List<SimpleDownstreamPropagationStep> _pendingDownstreamSteps = [];
+  /// During any given stage of nullability propagation, a queue of all the
+  /// edges that need to be examined before the stage is complete.
+  final Queue<SimpleDownstreamPropagationStep> _pendingDownstreamSteps =
+      Queue();
 
   final PostmortemFileWriter _postmortemFileWriter;
 
@@ -1340,7 +1347,7 @@
     }
     while (true) {
       while (_pendingDownstreamSteps.isNotEmpty) {
-        var step = _pendingDownstreamSteps.removeLast();
+        var step = _pendingDownstreamSteps.removeFirst();
         var edge = step.edge;
         if (!edge.isTriggered) continue;
         var node = edge.destinationNode;
@@ -1379,11 +1386,11 @@
   /// Propagates non-null intent upstream along unconditional control flow
   /// lines.
   void _propagateUpstream() {
-    var pendingSteps = <UpstreamPropagationStep>[
-      UpstreamPropagationStep(null, _never, NonNullIntent.direct)
-    ];
+    Queue<UpstreamPropagationStep> pendingSteps = Queue();
+    pendingSteps
+        .add(UpstreamPropagationStep(null, _never, NonNullIntent.direct));
     while (pendingSteps.isNotEmpty) {
-      var cause = pendingSteps.removeLast();
+      var cause = pendingSteps.removeFirst();
       var pendingNode = cause.node;
       for (var edge in pendingNode._upstreamEdges) {
         // We only propagate for nodes that are "upstream triggered".  At this
@@ -1505,8 +1512,12 @@
   void _setNonNullIntent(UpstreamPropagationStep step) {
     var node = step.node as NullabilityNodeMutable;
     var newNonNullIntent = step.newNonNullIntent;
+    var oldNonNullIntent = node.nonNullIntent;
     node._nonNullIntent = newNonNullIntent;
     _postmortemFileWriter?.addPropagationStep(step);
+    if (!oldNonNullIntent.isPresent) {
+      node._whyNotNullable = step;
+    }
   }
 
   Nullability _setNullable(DownstreamPropagationStep step) {
diff --git a/pkg/nnbd_migration/lib/src/nullability_node_target.dart b/pkg/nnbd_migration/lib/src/nullability_node_target.dart
new file mode 100644
index 0000000..c83ae21
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/nullability_node_target.dart
@@ -0,0 +1,201 @@
+// 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 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:nnbd_migration/instrumentation.dart';
+
+String _computeElementName(Element element) {
+  List<String> parts = [];
+  while (element != null && element is! CompilationUnitElement) {
+    var name = element.name;
+    if (name == null || name.isEmpty) {
+      parts.add('<unnamed>');
+    } else {
+      parts.add(name);
+    }
+    element = element.enclosingElement;
+  }
+  if (parts.isEmpty) {
+    assert(false, 'Could not compute a name for $element');
+    return '<unknown>';
+  }
+  return parts.reversed.join('.');
+}
+
+/// Data structure tracking information about which type in the user's source
+/// code is referenced by a given nullability node.
+abstract class NullabilityNodeTarget {
+  /// Creates a [NullabilityNodeTarget] referring to a particular point in the
+  /// source code.
+  factory NullabilityNodeTarget.codeRef(String description, AstNode astNode) =
+      _NullabilityNodeTarget_CodeRef;
+
+  /// Creates a [NullabilityNodeTarget] referring to a particular element.
+  factory NullabilityNodeTarget.element(Element element) =
+      _NullabilityNodeTarget_Element;
+
+  /// Creates a [NullabilityNodeTarget] with a simple text description.
+  factory NullabilityNodeTarget.text(String name) = _NullabilityNodeTarget_Text;
+
+  /// Creates a new [NullabilityNodeTarget] representing the bound of a type
+  /// parameter.
+  factory NullabilityNodeTarget.typeParameterBound(
+      TypeParameterElement element) = _NullabilityNodeTarget_TypeParameterBound;
+
+  NullabilityNodeTarget._();
+
+  /// The source code location associated with this target, if known.  Otherwise
+  /// `null`.
+  CodeReference get codeReference => null;
+
+  /// Gets a short description of this nullability node target suitable for
+  /// displaying to the user.
+  String get displayName;
+
+  /// Creates a new [NullabilityNodeTarget] representing a named function
+  /// parameter of this target.
+  NullabilityNodeTarget namedParameter(String name) =>
+      _NullabilityNodeTarget_NamedParameter(this, name);
+
+  /// Creates a new [NullabilityNodeTarget] representing a positional function
+  /// parameter of this target.
+  NullabilityNodeTarget positionalParameter(int index) =>
+      _NullabilityNodeTarget_PositionalParameter(this, index);
+
+  /// Creates a new [NullabilityNodeTarget] representing a function return type
+  /// of this target.
+  NullabilityNodeTarget returnType() => _NullabilityNodeTarget_ReturnType(this);
+
+  /// Creates a new [NullabilityNodeTarget] representing a type argument of this
+  /// target.
+  NullabilityNodeTarget typeArgument(int index) =>
+      _NullabilityNodeTarget_TypeArgument(this, index);
+
+  /// Creates a new [NullabilityNodeTarget] representing the bound of a formal
+  /// function type parameter of this target.
+  NullabilityNodeTarget typeFormalBound(String typeFormalName) =>
+      _NullabilityNodeTarget_TypeFormalBound(this, typeFormalName);
+}
+
+/// Nullability node target representing a reference to a specific location in
+/// source code.
+class _NullabilityNodeTarget_CodeRef extends NullabilityNodeTarget {
+  final String description;
+
+  final CodeReference codeReference;
+
+  _NullabilityNodeTarget_CodeRef(this.description, AstNode astNode)
+      : codeReference = CodeReference.fromAstNode(astNode),
+        super._();
+
+  @override
+  String get displayName => '$description (${codeReference.shortName})';
+}
+
+/// Nullability node target representing the type of an element.
+class _NullabilityNodeTarget_Element extends NullabilityNodeTarget {
+  final String name;
+
+  _NullabilityNodeTarget_Element(Element element)
+      : name = _computeElementName(element),
+        super._();
+
+  @override
+  String get displayName => name;
+}
+
+/// Nullability node target representing the type of a named function parameter.
+class _NullabilityNodeTarget_NamedParameter
+    extends _NullabilityNodeTarget_Part {
+  final String name;
+
+  _NullabilityNodeTarget_NamedParameter(NullabilityNodeTarget inner, this.name)
+      : super(inner);
+
+  @override
+  String get displayName => 'parameter $name of ${inner.displayName}';
+}
+
+/// Nullability node target representing a type that forms part of a larger type
+/// (e.g. the `int` part of `List<int>`).
+abstract class _NullabilityNodeTarget_Part extends NullabilityNodeTarget {
+  final NullabilityNodeTarget inner;
+
+  _NullabilityNodeTarget_Part(this.inner) : super._();
+
+  @override
+  CodeReference get codeReference => inner.codeReference;
+}
+
+/// Nullability node target representing the type of a positional function
+/// parameter.
+class _NullabilityNodeTarget_PositionalParameter
+    extends _NullabilityNodeTarget_Part {
+  final int index;
+
+  _NullabilityNodeTarget_PositionalParameter(
+      NullabilityNodeTarget inner, this.index)
+      : super(inner);
+
+  @override
+  String get displayName => 'parameter $index of ${inner.displayName}';
+}
+
+/// Nullability node target representing a function's return type.
+class _NullabilityNodeTarget_ReturnType extends _NullabilityNodeTarget_Part {
+  _NullabilityNodeTarget_ReturnType(NullabilityNodeTarget inner) : super(inner);
+
+  @override
+  String get displayName => 'return type of ${inner.displayName}';
+}
+
+/// Nullability node target for which we only know a string description.
+class _NullabilityNodeTarget_Text extends NullabilityNodeTarget {
+  final String name;
+
+  _NullabilityNodeTarget_Text(this.name) : super._();
+
+  @override
+  String get displayName => name;
+}
+
+/// Nullability node target representing a type argument of an interface type or
+/// or typedef.
+class _NullabilityNodeTarget_TypeArgument extends _NullabilityNodeTarget_Part {
+  final int index;
+
+  _NullabilityNodeTarget_TypeArgument(NullabilityNodeTarget inner, this.index)
+      : super(inner);
+
+  @override
+  String get displayName => 'type argument $index of ${inner.displayName}';
+}
+
+/// Nullability node target representing a bound of a function type's formal
+/// type parameter.
+class _NullabilityNodeTarget_TypeFormalBound
+    extends _NullabilityNodeTarget_Part {
+  final String typeFormalName;
+
+  _NullabilityNodeTarget_TypeFormalBound(
+      NullabilityNodeTarget inner, this.typeFormalName)
+      : super(inner);
+
+  @override
+  String get displayName =>
+      'bound of type formal $typeFormalName of ${inner.displayName}';
+}
+
+/// Nullability node target representing a type parameter bound.
+class _NullabilityNodeTarget_TypeParameterBound extends NullabilityNodeTarget {
+  final String name;
+
+  _NullabilityNodeTarget_TypeParameterBound(TypeParameterElement element)
+      : name = _computeElementName(element),
+        super._();
+
+  @override
+  String get displayName => 'bound of $name';
+}
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index 3782d3b..2445e76 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -25,6 +25,7 @@
 import 'package:nnbd_migration/src/fix_builder.dart';
 import 'package:nnbd_migration/src/node_builder.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/nullability_node_target.dart';
 import 'package:nnbd_migration/src/postmortem_file.dart';
 import 'package:nnbd_migration/src/potential_modification.dart';
 
@@ -133,9 +134,11 @@
               'have been stored by the NodeBuilder via '
               'recordTypeParameterBound');
         }
+        var target = NullabilityNodeTarget.typeParameterBound(typeParameter);
         decoratedType = _alreadyMigratedCodeDecorator.decorate(
             typeParameter.preMigrationBound ?? DynamicTypeImpl.instance,
-            typeParameter);
+            typeParameter,
+            target);
         instrumentation?.externalDecoratedTypeParameterBound(
             typeParameter, decoratedType);
         DecoratedTypeParameterBounds.current.put(typeParameter, decoratedType);
@@ -331,12 +334,13 @@
       element = (element as FunctionTypeAliasElement).function;
     }
 
+    var target = NullabilityNodeTarget.element(element);
     if (element is FunctionTypedElement) {
       decoratedType = _alreadyMigratedCodeDecorator.decorate(
-          element.preMigrationType, element);
+          element.preMigrationType, element, target);
     } else if (element is VariableElement) {
       decoratedType = _alreadyMigratedCodeDecorator.decorate(
-          element.preMigrationType, element);
+          element.preMigrationType, element, target);
     } else {
       // TODO(paulberry)
       throw UnimplementedError('Decorating ${element.runtimeType}');
diff --git a/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart b/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
index eefbf6d..ebebc47 100644
--- a/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
+++ b/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
@@ -15,6 +15,7 @@
 import 'package:nnbd_migration/src/already_migrated_code_decorator.dart';
 import 'package:nnbd_migration/src/decorated_type.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/nullability_node_target.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -57,85 +58,100 @@
 
   NullabilityNode get never => graph.never;
 
-  void checkAlwaysNullable(NullabilityNode node) {
-    var edge = assertEdge(always, node, hard: false);
+  void checkAlwaysNullable(NullabilityNode node, String displayName) {
+    var edge = assertEdge(always, node, hard: true, checkable: false);
     var origin = graph.getEdgeOrigin(edge);
     expect(origin.kind, EdgeOriginKind.alwaysNullableType);
     expect(origin.element, same(element));
+    expect(node.displayName, displayName);
   }
 
-  void checkDynamic(DecoratedType decoratedType) {
+  void checkDynamic(DecoratedType decoratedType, String displayName) {
     expect(decoratedType.type, same(typeProvider.dynamicType));
-    checkAlwaysNullable(decoratedType.node);
+    checkAlwaysNullable(decoratedType.node, displayName);
   }
 
-  void checkExplicitlyNonNullable(NullabilityNode node) {
+  void checkExplicitlyNonNullable(NullabilityNode node, String displayName) {
     var edge = assertEdge(node, never, hard: true, checkable: false);
     var origin = graph.getEdgeOrigin(edge);
     expect(origin.kind, EdgeOriginKind.alreadyMigratedType);
     expect(origin.element, same(element));
+    expect(node.displayName, displayName);
   }
 
-  void checkExplicitlyNullable(NullabilityNode node) {
-    var edge = assertEdge(always, node, hard: false);
+  void checkExplicitlyNullable(NullabilityNode node, String displayName) {
+    var edge = assertEdge(always, node, hard: true, checkable: false);
     var origin = graph.getEdgeOrigin(edge);
     expect(origin.kind, EdgeOriginKind.alreadyMigratedType);
     expect(origin.element, same(element));
+    expect(node.displayName, displayName);
   }
 
   void checkFutureOr(
       DecoratedType decoratedType,
-      void Function(NullabilityNode) checkNullability,
-      void Function(DecoratedType) checkArgument) {
+      void Function(NullabilityNode, String) checkNullability,
+      void Function(DecoratedType, String) checkArgument,
+      String displayName) {
     expect(decoratedType.type.element, typeProvider.futureOrElement);
-    checkNullability(decoratedType.node);
-    checkArgument(decoratedType.typeArguments[0]);
+    checkNullability(decoratedType.node, displayName);
+    checkArgument(
+        decoratedType.typeArguments[0], 'type argument 0 of $displayName');
   }
 
-  void checkInt(DecoratedType decoratedType,
-      void Function(NullabilityNode) checkNullability) {
+  void checkInt(
+      DecoratedType decoratedType,
+      void Function(NullabilityNode, String) checkNullability,
+      String displayName) {
     expect(decoratedType.type.element, typeProvider.intType.element);
-    checkNullability(decoratedType.node);
+    checkNullability(decoratedType.node, displayName);
   }
 
   void checkIterable(
       DecoratedType decoratedType,
-      void Function(NullabilityNode) checkNullability,
-      void Function(DecoratedType) checkArgument) {
+      void Function(NullabilityNode, String) checkNullability,
+      void Function(DecoratedType, String) checkArgument,
+      String displayName) {
     expect(
         decoratedType.type.element, typeProvider.iterableDynamicType.element);
-    checkNullability(decoratedType.node);
-    checkArgument(decoratedType.typeArguments[0]);
+    checkNullability(decoratedType.node, displayName);
+    checkArgument(
+        decoratedType.typeArguments[0], 'type argument 0 of $displayName');
   }
 
-  void checkNum(DecoratedType decoratedType,
-      void Function(NullabilityNode) checkNullability) {
+  void checkNum(
+      DecoratedType decoratedType,
+      void Function(NullabilityNode, String) checkNullability,
+      String displayName) {
     expect(decoratedType.type.element, typeProvider.numType.element);
-    checkNullability(decoratedType.node);
+    checkNullability(decoratedType.node, displayName);
   }
 
-  void checkObject(DecoratedType decoratedType,
-      void Function(NullabilityNode) checkNullability) {
+  void checkObject(
+      DecoratedType decoratedType,
+      void Function(NullabilityNode, String) checkNullability,
+      String displayName) {
     expect(decoratedType.type.element, typeProvider.objectType.element);
-    checkNullability(decoratedType.node);
+    checkNullability(decoratedType.node, displayName);
   }
 
   void checkTypeParameter(
       DecoratedType decoratedType,
-      void Function(NullabilityNode) checkNullability,
-      TypeParameterElement expectedElement) {
+      void Function(NullabilityNode, String) checkNullability,
+      TypeParameterElement expectedElement,
+      String displayName) {
     var type = decoratedType.type as TypeParameterTypeImpl;
     expect(type.element, same(expectedElement));
-    checkNullability(decoratedType.node);
+    checkNullability(decoratedType.node, displayName);
   }
 
-  void checkVoid(DecoratedType decoratedType) {
+  void checkVoid(DecoratedType decoratedType, String displayName) {
     expect(decoratedType.type, same(typeProvider.voidType));
-    checkAlwaysNullable(decoratedType.node);
+    checkAlwaysNullable(decoratedType.node, displayName);
   }
 
   DecoratedType decorate(DartType type) {
-    var decoratedType = decorator.decorate(type, element);
+    var decoratedType = decorator.decorate(
+        type, element, NullabilityNodeTarget.text('test type'));
     expect(decoratedType.type, same(type));
     return decoratedType;
   }
@@ -152,7 +168,7 @@
   }
 
   void test_decorate_dynamic() {
-    checkDynamic(decorate(typeProvider.dynamicType));
+    checkDynamic(decorate(typeProvider.dynamicType), 'test type');
   }
 
   void test_decorate_functionType_generic_bounded() {
@@ -169,9 +185,10 @@
         nullabilitySuffix: suffix,
       ),
     );
-    checkNum(getDecoratedBound(typeFormal), checkExplicitlyNonNullable);
-    checkTypeParameter(
-        decoratedType.returnType, checkExplicitlyNonNullable, typeFormal);
+    checkNum(getDecoratedBound(typeFormal), checkExplicitlyNonNullable,
+        'bound of type formal T of test type');
+    checkTypeParameter(decoratedType.returnType, checkExplicitlyNonNullable,
+        typeFormal, 'return type of test type');
   }
 
   void test_decorate_functionType_generic_no_explicit_bound() {
@@ -187,136 +204,156 @@
         nullabilitySuffix: suffix,
       ),
     );
-    checkObject(getDecoratedBound(typeFormal), checkExplicitlyNullable);
-    checkTypeParameter(
-        decoratedType.returnType, checkExplicitlyNonNullable, typeFormal);
+    checkObject(getDecoratedBound(typeFormal), checkExplicitlyNullable,
+        'bound of type formal T of test type');
+    checkTypeParameter(decoratedType.returnType, checkExplicitlyNonNullable,
+        typeFormal, 'return type of test type');
   }
 
   void test_decorate_functionType_named_parameter() {
     checkDynamic(
-      decorate(
-        FunctionTypeImpl(
-          typeFormals: const [],
-          parameters: [
-            ParameterElementImpl.synthetic(
-              'x',
-              typeProvider.dynamicType,
-              ParameterKind.NAMED,
-            )
-          ],
-          returnType: typeProvider.voidType,
-          nullabilitySuffix: suffix,
-        ),
-      ).namedParameters['x'],
-    );
+        decorate(
+          FunctionTypeImpl(
+            typeFormals: const [],
+            parameters: [
+              ParameterElementImpl.synthetic(
+                'x',
+                typeProvider.dynamicType,
+                ParameterKind.NAMED,
+              )
+            ],
+            returnType: typeProvider.voidType,
+            nullabilitySuffix: suffix,
+          ),
+        ).namedParameters['x'],
+        'parameter x of test type');
   }
 
-  void test_decorate_functionType_ordinary_parameter() {
-    checkDynamic(
-      decorate(
-        FunctionTypeImpl(
-          typeFormals: const [],
-          parameters: [
-            ParameterElementImpl.synthetic(
-              'x',
-              typeProvider.dynamicType,
-              ParameterKind.REQUIRED,
-            )
-          ],
-          returnType: typeProvider.voidType,
-          nullabilitySuffix: suffix,
-        ),
-      ).positionalParameters[0],
+  void test_decorate_functionType_ordinary_parameters() {
+    var decoratedType = decorate(
+      FunctionTypeImpl(
+        typeFormals: const [],
+        parameters: [
+          ParameterElementImpl.synthetic(
+            'x',
+            typeProvider.dynamicType,
+            ParameterKind.REQUIRED,
+          ),
+          ParameterElementImpl.synthetic(
+            'y',
+            typeProvider.dynamicType,
+            ParameterKind.REQUIRED,
+          )
+        ],
+        returnType: typeProvider.voidType,
+        nullabilitySuffix: suffix,
+      ),
     );
+    checkDynamic(
+        decoratedType.positionalParameters[0], 'parameter 0 of test type');
+    checkDynamic(
+        decoratedType.positionalParameters[1], 'parameter 1 of test type');
   }
 
   void test_decorate_functionType_positional_parameter() {
     checkDynamic(
-      decorate(
-        FunctionTypeImpl(
-          typeFormals: const [],
-          parameters: [
-            ParameterElementImpl.synthetic(
-              'x',
-              typeProvider.dynamicType,
-              ParameterKind.POSITIONAL,
-            )
-          ],
-          returnType: typeProvider.voidType,
-          nullabilitySuffix: suffix,
-        ),
-      ).positionalParameters[0],
-    );
+        decorate(
+          FunctionTypeImpl(
+            typeFormals: const [],
+            parameters: [
+              ParameterElementImpl.synthetic(
+                'x',
+                typeProvider.dynamicType,
+                ParameterKind.POSITIONAL,
+              )
+            ],
+            returnType: typeProvider.voidType,
+            nullabilitySuffix: suffix,
+          ),
+        ).positionalParameters[0],
+        'parameter 0 of test type');
   }
 
   void test_decorate_functionType_question() {
     checkExplicitlyNullable(
-      decorate(
-        FunctionTypeImpl(
-          typeFormals: const [],
-          parameters: const [],
-          returnType: typeProvider.voidType,
-          nullabilitySuffix: NullabilitySuffix.question,
-        ),
-      ).node,
-    );
+        decorate(
+          FunctionTypeImpl(
+            typeFormals: const [],
+            parameters: const [],
+            returnType: typeProvider.voidType,
+            nullabilitySuffix: NullabilitySuffix.question,
+          ),
+        ).node,
+        'test type');
   }
 
   void test_decorate_functionType_returnType() {
     checkDynamic(
-      decorate(
-        FunctionTypeImpl(
-          typeFormals: const [],
-          parameters: const [],
-          returnType: typeProvider.dynamicType,
-          nullabilitySuffix: suffix,
-        ),
-      ).returnType,
-    );
+        decorate(
+          FunctionTypeImpl(
+            typeFormals: const [],
+            parameters: const [],
+            returnType: typeProvider.dynamicType,
+            nullabilitySuffix: suffix,
+          ),
+        ).returnType,
+        'return type of test type');
   }
 
   void test_decorate_functionType_star() {
     checkExplicitlyNonNullable(
-      decorate(
-        FunctionTypeImpl(
-          typeFormals: const [],
-          parameters: const [],
-          returnType: typeProvider.voidType,
-          nullabilitySuffix: suffix,
-        ),
-      ).node,
-    );
+        decorate(
+          FunctionTypeImpl(
+            typeFormals: const [],
+            parameters: const [],
+            returnType: typeProvider.voidType,
+            nullabilitySuffix: suffix,
+          ),
+        ).node,
+        'test type');
+  }
+
+  void test_decorate_interfaceType_parameters() {
+    var decoratedType = decorate(InterfaceTypeImpl(
+        element: typeProvider.mapElement,
+        typeArguments: [typeProvider.intType, typeProvider.numType],
+        nullabilitySuffix: suffix));
+    checkInt(decoratedType.typeArguments[0], checkExplicitlyNonNullable,
+        'type argument 0 of test type');
+    checkNum(decoratedType.typeArguments[1], checkExplicitlyNonNullable,
+        'type argument 1 of test type');
   }
 
   void test_decorate_interfaceType_simple_question() {
     checkInt(
-      decorate(
-        InterfaceTypeImpl(
-          element: typeProvider.intElement,
-          typeArguments: const [],
-          nullabilitySuffix: NullabilitySuffix.question,
+        decorate(
+          InterfaceTypeImpl(
+            element: typeProvider.intElement,
+            typeArguments: const [],
+            nullabilitySuffix: NullabilitySuffix.question,
+          ),
         ),
-      ),
-      checkExplicitlyNullable,
-    );
+        checkExplicitlyNullable,
+        'test type');
   }
 
   void test_decorate_interfaceType_simple_star() {
     checkInt(
-      decorate(
-        InterfaceTypeImpl(
-          element: typeProvider.intElement,
-          typeArguments: const [],
-          nullabilitySuffix: suffix,
+        decorate(
+          InterfaceTypeImpl(
+            element: typeProvider.intElement,
+            typeArguments: const [],
+            nullabilitySuffix: suffix,
+          ),
         ),
-      ),
-      checkExplicitlyNonNullable,
-    );
+        checkExplicitlyNonNullable,
+        'test type');
   }
 
   void test_decorate_iterable_dynamic() {
     var decorated = decorate(typeProvider.iterableDynamicType);
-    checkIterable(decorated, checkExplicitlyNonNullable, checkDynamic);
+    checkIterable(
+        decorated, checkExplicitlyNonNullable, checkDynamic, 'test type');
   }
 
   void test_decorate_typeParameterType_question() {
@@ -325,7 +362,8 @@
         decorate(TypeParameterTypeImpl(
             element: element, nullabilitySuffix: NullabilitySuffix.question)),
         checkExplicitlyNullable,
-        element);
+        element,
+        'test type');
   }
 
   void test_decorate_typeParameterType_star() {
@@ -334,11 +372,12 @@
         decorate(
             TypeParameterTypeImpl(element: element, nullabilitySuffix: suffix)),
         checkExplicitlyNonNullable,
-        element);
+        element,
+        'test type');
   }
 
   void test_decorate_void() {
-    checkVoid(decorate(typeProvider.voidType));
+    checkVoid(decorate(typeProvider.voidType), 'test type');
   }
 
   void test_getImmediateSupertypes_future() {
@@ -346,12 +385,16 @@
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     var typeParam = class_.typeParameters[0];
     expect(decoratedSupertypes, hasLength(2));
-    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable);
+    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable, 'Future');
     // Since Future<T> is a subtype of FutureOr<T>, we consider FutureOr<T> to
     // be an immediate supertype, even though the class declaration for Future
     // doesn't mention FutureOr.
-    checkFutureOr(decoratedSupertypes[1], checkExplicitlyNonNullable,
-        (t) => checkTypeParameter(t, checkExplicitlyNonNullable, typeParam));
+    checkFutureOr(
+        decoratedSupertypes[1],
+        checkExplicitlyNonNullable,
+        (t, displayName) => checkTypeParameter(
+            t, checkExplicitlyNonNullable, typeParam, displayName),
+        'Future');
   }
 
   void test_getImmediateSupertypes_generic() {
@@ -365,8 +408,12 @@
     );
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     expect(decoratedSupertypes, hasLength(1));
-    checkIterable(decoratedSupertypes[0], checkExplicitlyNonNullable,
-        (type) => checkTypeParameter(type, checkExplicitlyNonNullable, t));
+    checkIterable(
+        decoratedSupertypes[0],
+        checkExplicitlyNonNullable,
+        (type, displayName) => checkTypeParameter(
+            type, checkExplicitlyNonNullable, t, displayName),
+        'C');
   }
 
   void test_getImmediateSupertypes_interface() {
@@ -375,8 +422,8 @@
     class_.interfaces = [typeProvider.numType];
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     expect(decoratedSupertypes, hasLength(2));
-    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable);
-    checkNum(decoratedSupertypes[1], checkExplicitlyNonNullable);
+    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable, 'C');
+    checkNum(decoratedSupertypes[1], checkExplicitlyNonNullable, 'C');
   }
 
   void test_getImmediateSupertypes_mixin() {
@@ -385,8 +432,8 @@
     class_.mixins = [typeProvider.numType];
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     expect(decoratedSupertypes, hasLength(2));
-    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable);
-    checkNum(decoratedSupertypes[1], checkExplicitlyNonNullable);
+    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable, 'C');
+    checkNum(decoratedSupertypes[1], checkExplicitlyNonNullable, 'C');
   }
 
   void test_getImmediateSupertypes_superclassConstraint() {
@@ -394,7 +441,7 @@
         name: 'C', constraints: [typeProvider.numType]);
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     expect(decoratedSupertypes, hasLength(1));
-    checkNum(decoratedSupertypes[0], checkExplicitlyNonNullable);
+    checkNum(decoratedSupertypes[0], checkExplicitlyNonNullable, 'C');
   }
 
   void test_getImmediateSupertypes_supertype() {
@@ -402,7 +449,8 @@
         element = ElementFactory.classElement('C', typeProvider.objectType);
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     expect(decoratedSupertypes, hasLength(1));
-    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable);
+    // TODO(paulberry): displayName should be 'Object supertype of C'
+    checkObject(decoratedSupertypes[0], checkExplicitlyNonNullable, 'C');
   }
 }
 
diff --git a/pkg/nnbd_migration/test/decorated_type_test.dart b/pkg/nnbd_migration/test/decorated_type_test.dart
index 6c4e507..b114798 100644
--- a/pkg/nnbd_migration/test/decorated_type_test.dart
+++ b/pkg/nnbd_migration/test/decorated_type_test.dart
@@ -61,7 +61,6 @@
   void setUp() {
     DecoratedTypeParameterBounds.current = decoratedTypeParameterBounds;
     ElementTypeProvider.current = elementTypeProvider;
-    NullabilityNode.clearDebugNames();
   }
 
   void tearDown() {
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index 9296346..a410270 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -1781,6 +1781,7 @@
     var right = decoratedTypeAnnotation('int j').node;
     var expression = decoratedExpressionType('??').node;
     assertEdge(right, expression, guards: [left], hard: false);
+    expect(expression.displayName, '?? operator (test.dart:1:24)');
   }
 
   Future<void>
@@ -3816,6 +3817,27 @@
         assertEdge(nullable_i, nullable_c_t_or_nullable_t, hard: true));
   }
 
+  Future<void> test_instanceCreation_implicit_type_params_names() async {
+    await analyze('''
+class C<T, U> {}
+void main() {
+  C<Object, Object> x = C();
+}
+''');
+    var edge0 = assertEdge(
+        anyNode, decoratedTypeAnnotation('C<Object, Object>').node,
+        hard: false);
+    expect(edge0.sourceNode.displayName, 'constructed type (test.dart:3:25)');
+    var edge1 = assertEdge(anyNode, decoratedTypeAnnotation('Object,').node,
+        hard: false, checkable: false);
+    expect(edge1.sourceNode.displayName,
+        'type argument 0 of constructed type (test.dart:3:25)');
+    var edge2 = assertEdge(anyNode, decoratedTypeAnnotation('Object>').node,
+        hard: false, checkable: false);
+    expect(edge2.sourceNode.displayName,
+        'type argument 1 of constructed type (test.dart:3:25)');
+  }
+
   Future<void> test_instanceCreation_parameter_named_optional() async {
     await analyze('''
 class C {
@@ -4066,6 +4088,7 @@
 
     final listArgType = returnTypeEdge.sourceNode;
     assertNoUpstreamNullability(listArgType);
+    expect(listArgType.displayName, 'list element type (test.dart:2:10)');
   }
 
   Future<void> test_listLiteral_noTypeArgument_nullableElement() async {
@@ -6315,8 +6338,10 @@
 }
 ''');
 
-    assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int').node,
+    var edge = assertEdge(
+        inSet(alwaysPlus), decoratedTypeAnnotation('int').node,
         hard: false);
+    expect(edge.sourceNode.displayName, 'implicit null return (test.dart:2:3)');
   }
 
   Future<void> test_return_null() async {
@@ -6326,10 +6351,11 @@
 }
 ''');
 
-    assertNullCheck(
-        checkExpression('null'),
-        assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int').node,
-            hard: false));
+    var edge = assertEdge(
+        inSet(alwaysPlus), decoratedTypeAnnotation('int').node,
+        hard: false);
+    assertNullCheck(checkExpression('null'), edge);
+    expect(edge.sourceNode.displayName, 'null literal (test.dart:2:10)');
   }
 
   Future<void> test_return_null_generic() async {
@@ -6358,11 +6384,13 @@
     var mapNode = decoratedTypeAnnotation('Map').node;
 
     assertNoUpstreamNullability(mapNode);
-    assertNoUpstreamNullability(
-        assertEdge(anyNode, keyNode, hard: false, checkable: false).sourceNode);
-    assertNoUpstreamNullability(
-        assertEdge(anyNode, valueNode, hard: false, checkable: false)
-            .sourceNode);
+    var keyEdge = assertEdge(anyNode, keyNode, hard: false, checkable: false);
+    assertNoUpstreamNullability(keyEdge.sourceNode);
+    expect(keyEdge.sourceNode.displayName, 'map key type (test.dart:2:10)');
+    var valueEdge =
+        assertEdge(anyNode, valueNode, hard: false, checkable: false);
+    assertNoUpstreamNullability(valueEdge.sourceNode);
+    expect(valueEdge.sourceNode.displayName, 'map value type (test.dart:2:10)');
   }
 
   Future<void> test_setOrMapLiteral_map_noTypeArgument_nullableKey() async {
@@ -6496,9 +6524,9 @@
     var setNode = decoratedTypeAnnotation('Set').node;
 
     assertNoUpstreamNullability(setNode);
-    assertNoUpstreamNullability(
-        assertEdge(anyNode, valueNode, hard: false, checkable: false)
-            .sourceNode);
+    var edge = assertEdge(anyNode, valueNode, hard: false, checkable: false);
+    assertNoUpstreamNullability(edge.sourceNode);
+    expect(edge.sourceNode.displayName, 'set element type (test.dart:2:10)');
   }
 
   Future<void> test_setOrMapLiteral_set_noTypeArgument_nullableElement() async {
@@ -6817,7 +6845,10 @@
   return throw null;
 }
 ''');
-    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
+    var intNode = decoratedTypeAnnotation('int').node;
+    assertNoUpstreamNullability(intNode);
+    var edge = assertEdge(anyNode, intNode, hard: false);
+    expect(edge.sourceNode.displayName, 'throw expression (test.dart:2:10)');
   }
 
   Future<void> test_topLevelSetter() async {
diff --git a/pkg/nnbd_migration/test/fix_aggregator_test.dart b/pkg/nnbd_migration/test/fix_aggregator_test.dart
index 54dd710..10cc5a8 100644
--- a/pkg/nnbd_migration/test/fix_aggregator_test.dart
+++ b/pkg/nnbd_migration/test/fix_aggregator_test.dart
@@ -9,6 +9,7 @@
 import 'package:nnbd_migration/src/edit_plan.dart';
 import 'package:nnbd_migration/src/fix_aggregator.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/nullability_node_target.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -785,7 +786,8 @@
   const MockDecoratedType(this.type);
 
   @override
-  NullabilityNode get node => NullabilityNode.forTypeAnnotation(0);
+  NullabilityNode get node =>
+      NullabilityNode.forTypeAnnotation(NullabilityNodeTarget.text('test'));
 
   @override
   noSuchMethod(Invocation invocation) {
diff --git a/pkg/nnbd_migration/test/migration_visitor_test_base.dart b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
index 34716eb..1224e07 100644
--- a/pkg/nnbd_migration/test/migration_visitor_test_base.dart
+++ b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
@@ -20,6 +20,7 @@
 import 'package:nnbd_migration/src/expression_checks.dart';
 import 'package:nnbd_migration/src/node_builder.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/nullability_node_target.dart';
 import 'package:nnbd_migration/src/variables.dart';
 import 'package:test/test.dart';
 
@@ -35,7 +36,7 @@
 
 /// Mixin allowing unit tests to create decorated types easily.
 mixin DecoratedTypeTester implements DecoratedTypeTesterBase {
-  int _offset = 0;
+  int nodeId = 0;
 
   NullabilityNode get always => graph.always;
 
@@ -101,7 +102,8 @@
       DecoratedType(typeProvider.listType2(elementType.type), node ?? newNode(),
           typeArguments: [elementType]);
 
-  NullabilityNode newNode() => NullabilityNode.forTypeAnnotation(_offset++);
+  NullabilityNode newNode() => NullabilityNode.forTypeAnnotation(
+      NullabilityNodeTarget.text('node ${nodeId++}'));
 
   DecoratedType num_({NullabilityNode node}) =>
       DecoratedType(typeProvider.numType, node ?? newNode());
diff --git a/pkg/nnbd_migration/test/node_builder_test.dart b/pkg/nnbd_migration/test/node_builder_test.dart
index 149cee4..f6e8bbc 100644
--- a/pkg/nnbd_migration/test/node_builder_test.dart
+++ b/pkg/nnbd_migration/test/node_builder_test.dart
@@ -649,6 +649,16 @@
     // field.
   }
 
+  Future<void> test_function_explicit_returnType() async {
+    await analyze('''
+class C {
+  int f() => null;
+}
+''');
+    var decoratedType = decoratedTypeAnnotation('int');
+    expect(decoratedType.node.displayName, 'return type of C.f');
+  }
+
   Future<void> test_function_generic_bounded() async {
     await analyze('''
 T f<T extends Object>(T t) => t;
@@ -844,20 +854,6 @@
     expect(gType.returnType.node.isImmutable, false);
   }
 
-  Future<void>
-      test_generic_function_type_syntax_inferred_dynamic_return() async {
-    await analyze('''
-abstract class C {
-  Function() f();
-}
-''');
-    var decoratedFType = decoratedMethodType('f');
-    var decoratedFReturnType = decoratedFType.returnType;
-    var decoratedFReturnReturnType = decoratedFReturnType.returnType;
-    _assertType(decoratedFReturnReturnType.type, 'dynamic');
-    expect(decoratedFReturnReturnType.node.isImmutable, false);
-  }
-
   Future<void> test_genericFunctionType_formals() async {
     await analyze('''
 void f(T Function<T, U>(U) x) {}
@@ -906,6 +902,21 @@
     expect(decoratedType.returnType, same(decoratedIntType));
     expect(decoratedIntType.node, isNotNull);
     expect(decoratedIntType.node, isNot(never));
+    expect(decoratedType.returnType.node.displayName,
+        'return type of explicit type (test.dart:1:8)');
+  }
+
+  Future<void> test_genericFunctionType_syntax_inferred_dynamic_return() async {
+    await analyze('''
+abstract class C {
+  Function() f();
+}
+''');
+    var decoratedFType = decoratedMethodType('f');
+    var decoratedFReturnType = decoratedFType.returnType;
+    var decoratedFReturnReturnType = decoratedFReturnType.returnType;
+    _assertType(decoratedFReturnReturnType.type, 'dynamic');
+    expect(decoratedFReturnReturnType.node.isImmutable, false);
   }
 
   Future<void> test_genericFunctionType_unnamedParameterType() async {
@@ -999,6 +1010,7 @@
     expect(decoratedType.typeFormals, isEmpty);
     expect(decoratedType.positionalParameters[0],
         same(decoratedTypeAnnotation('String')));
+    expect(decoratedType.returnType.node.displayName, 'return type of F');
   }
 
   Future<void> test_interfaceType_generic_instantiate_to_dynamic() async {
@@ -1179,6 +1191,31 @@
     expect(decoratedType.node.isImmutable, false);
   }
 
+  Future<void> test_localVariable_type_inferred_function() async {
+    await analyze('''
+main() {
+  var x = () => 1;
+}
+''');
+    var decoratedType =
+        variables.decoratedElementType(findNode.simple('x').staticElement);
+    expect(decoratedType.returnType.node.displayName, 'return type of main.x');
+  }
+
+  Future<void> test_localVariable_type_inferred_generic() async {
+    await analyze('''
+main() {
+  var x = {1: 2};
+}
+''');
+    var decoratedType =
+        variables.decoratedElementType(findNode.simple('x').staticElement);
+    expect(decoratedType.typeArguments[0].node.displayName,
+        'type argument 0 of main.x');
+    expect(decoratedType.typeArguments[1].node.displayName,
+        'type argument 1 of main.x');
+  }
+
   Future<void> test_method_generic_bounded() async {
     await analyze('''
 class C {
@@ -1578,6 +1615,8 @@
     var decoratedTypeFormalBound = decoratedTypeParameterBounds
         .get((decoratedType.type as FunctionType).typeFormals[0]);
     _assertType(decoratedTypeFormalBound.type, 'num');
+    expect(decoratedTypeFormalBound.node.displayName,
+        'bound of type formal T of explicit type (test.dart:2:1)');
     var decoratedTypedefTypeFormalBound = decoratedTypeParameterBounds
         .get((typedefDecoratedType.type as FunctionType).typeFormals[0]);
     expect(decoratedTypeFormalBound.node,
@@ -1603,11 +1642,47 @@
         decoratedType.returnType.node, TypeMatcher<NullabilityNodeMutable>());
     expect(decoratedType.returnType.node,
         isNot(same(typedefDecoratedType.returnType.node)));
+    expect(
+        typedefDecoratedType.returnType.node.displayName, 'return type of F');
+    expect(decoratedType.returnType.node.displayName,
+        'return type of explicit type (test.dart:2:1)');
     _assertType(decoratedType.positionalParameters[0].type, 'String');
     expect(decoratedType.positionalParameters[0].node,
         TypeMatcher<NullabilityNodeMutable>());
     expect(decoratedType.positionalParameters[0].node,
         isNot(same(typedefDecoratedType.positionalParameters[0].node)));
+    expect(decoratedType.positionalParameters[0].node.displayName,
+        'parameter 0 of explicit type (test.dart:2:1)');
+  }
+
+  Future<void> test_typedef_reference_simple_named_parameter() async {
+    await analyze('''
+typedef int F({String s});
+F f;
+''');
+    // The instantiation of F should produce fresh nullability nodes, distinct
+    // from the ones in the typedef (they will be unified by the edge builder).
+    // This is necessary because there is no guarantee of whether the typedef or
+    // its usage will be visited first.
+    var decoratedType = decoratedTypeAnnotation('F f');
+    expect(decoratedType.namedParameters['s'].node.displayName,
+        'parameter s of explicit type (test.dart:2:1)');
+  }
+
+  Future<void> test_typedef_reference_simple_two_parameters() async {
+    await analyze('''
+typedef int F(String s, int i);
+F f;
+''');
+    // The instantiation of F should produce fresh nullability nodes, distinct
+    // from the ones in the typedef (they will be unified by the edge builder).
+    // This is necessary because there is no guarantee of whether the typedef or
+    // its usage will be visited first.
+    var decoratedType = decoratedTypeAnnotation('F f');
+    expect(decoratedType.positionalParameters[0].node.displayName,
+        'parameter 0 of explicit type (test.dart:2:1)');
+    expect(decoratedType.positionalParameters[1].node.displayName,
+        'parameter 1 of explicit type (test.dart:2:1)');
   }
 
   Future<void> test_typedef_rhs_nullability() async {
diff --git a/pkg/nnbd_migration/test/nullability_node_test.dart b/pkg/nnbd_migration/test/nullability_node_test.dart
index e674000..9a5444f 100644
--- a/pkg/nnbd_migration/test/nullability_node_test.dart
+++ b/pkg/nnbd_migration/test/nullability_node_test.dart
@@ -5,6 +5,7 @@
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/src/edge_origin.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
+import 'package:nnbd_migration/src/nullability_node_target.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -18,6 +19,7 @@
 class NullabilityNodeTest {
   final graph = NullabilityGraphForTesting();
 
+  /// A list of all edges that couldn't be satisfied.  May contain duplicates.
   List<NullabilityEdge> unsatisfiedEdges;
 
   List<NullabilityNodeForSubstitution> unsatisfiedSubstitutions;
@@ -27,7 +29,7 @@
   NullabilityNode get never => graph.never;
 
   void assertUnsatisfied(List<NullabilityEdge> expectedUnsatisfiedEdges) {
-    expect(unsatisfiedEdges, unorderedEquals(expectedUnsatisfiedEdges));
+    expect(unsatisfiedEdges.toSet(), expectedUnsatisfiedEdges.toSet());
   }
 
   NullabilityEdge connect(NullabilityNode source, NullabilityNode destination,
@@ -42,8 +44,8 @@
     return NullabilityNode.forLUB(left, right);
   }
 
-  NullabilityNode newNode(int offset) =>
-      NullabilityNode.forTypeAnnotation(offset);
+  NullabilityNode newNode(int id) =>
+      NullabilityNode.forTypeAnnotation(NullabilityNodeTarget.text('node $id'));
 
   void propagate() {
     var propagationResult = graph.propagate(null);
@@ -179,6 +181,32 @@
     assertUnsatisfied([edge_1_never, edge_1_3]);
   }
 
+  void test_propagation_downstream_breadth_first() {
+    // always -> 1 -> 2
+    //           1 -> 3 -> 4
+    // always -> 5 -> 4
+    //           5 -> 6 -> 2
+    var n1 = newNode(1);
+    var n2 = newNode(2);
+    var n3 = newNode(3);
+    var n4 = newNode(4);
+    var n5 = newNode(5);
+    var n6 = newNode(6);
+    connect(always, n1);
+    connect(n1, n2);
+    connect(n1, n3);
+    connect(n3, n4);
+    connect(always, n5);
+    connect(n5, n4);
+    connect(n5, n6);
+    connect(n6, n2);
+    propagate();
+    // Node 2 should be caused by node 1, since that's the shortest path back to
+    // "always".  Similarly, node 4 should be caused by node 5.
+    expect(_downstreamCauseNode(n2), same(n1));
+    expect(_downstreamCauseNode(n4), same(n5));
+  }
+
   void test_propagation_downstream_guarded_multiple_guards_all_satisfied() {
     // always -> 1
     // always -> 2
@@ -545,6 +573,32 @@
     assertUnsatisfied([edge_1_2]);
   }
 
+  void test_propagation_upstream_breadth_first() {
+    // never <- 1 <- 2
+    //          1 <- 3 <- 4
+    // never <- 5 <- 4
+    //          5 <- 6 <- 2
+    var n1 = newNode(1);
+    var n2 = newNode(2);
+    var n3 = newNode(3);
+    var n4 = newNode(4);
+    var n5 = newNode(5);
+    var n6 = newNode(6);
+    connect(n1, never, hard: true);
+    connect(n2, n1, hard: true);
+    connect(n3, n1, hard: true);
+    connect(n4, n3, hard: true);
+    connect(n5, never, hard: true);
+    connect(n4, n5, hard: true);
+    connect(n6, n5, hard: true);
+    connect(n2, n6, hard: true);
+    propagate();
+    // Node 2 should be caused by node 1, since that's the shortest path back to
+    // "always".  Similarly, node 4 should be caused by node 5.
+    expect(_upstreamCauseNode(n2), same(n1));
+    expect(_upstreamCauseNode(n4), same(n5));
+  }
+
   void test_propagation_upstream_through_union() {
     // always -> 1
     // always -> 2
@@ -669,6 +723,12 @@
   void union(NullabilityNode x, NullabilityNode y) {
     graph.union(x, y, _TestEdgeOrigin());
   }
+
+  NullabilityNode _downstreamCauseNode(NullabilityNode node) =>
+      (node.whyNullable as SimpleDownstreamPropagationStep).edge.sourceNode;
+
+  NullabilityNode _upstreamCauseNode(NullabilityNode node) =>
+      node.whyNotNullable.principalCause.node;
 }
 
 class _TestEdgeOrigin implements EdgeOrigin {
diff --git a/pkg/test_runner/lib/src/command_output.dart b/pkg/test_runner/lib/src/command_output.dart
index cc361ca..3c1eae4 100644
--- a/pkg/test_runner/lib/src/command_output.dart
+++ b/pkg/test_runner/lib/src/command_output.dart
@@ -695,6 +695,7 @@
   static const _dfeErrorExitCode = 252;
   static const _compileErrorExitCode = 254;
   static const _uncaughtExceptionExitCode = 255;
+  static const _adbInfraFailureCodes = [10];
 
   VMCommandOutput(Command command, int exitCode, bool timedOut,
       List<int> stdout, List<int> stderr, Duration time, int pid)
@@ -751,8 +752,20 @@
     if (exitCode == _compileErrorExitCode) return Expectation.compileTimeError;
     if (exitCode == _uncaughtExceptionExitCode) return Expectation.runtimeError;
     if (exitCode != 0) {
-      // This is a general fail, in case we get an unknown nonzero exitcode.
-      return Expectation.fail;
+      var ourExit = 5;
+      // Unknown nonzero exit code from vm command.
+      // Consider this a failure of testing, and exit the test script.
+      if (testCase.configuration.system == System.android &&
+          _adbInfraFailureCodes.contains(exitCode)) {
+        print('Android device failed to run test');
+        ourExit = 3;
+      } else {
+        print('Unexpected exit code $exitCode');
+      }
+      print(command);
+      print(decodeUtf8(stdout));
+      print(decodeUtf8(stderr));
+      io.exit(ourExit);
     }
     var testOutput = decodeUtf8(stdout);
     if (_isAsyncTest(testOutput) && !_isAsyncTestSuccessful(testOutput)) {
diff --git a/runtime/tests/vm/dart/regress_40710_test.dart b/runtime/tests/vm/dart/regress_40710_test.dart
index 4c5b560..162cbae 100644
--- a/runtime/tests/vm/dart/regress_40710_test.dart
+++ b/runtime/tests/vm/dart/regress_40710_test.dart
@@ -23,7 +23,7 @@
   for (int i = 0; i < 20; ++i) {
     final a = new A<B<String>>();
     a.foo(new B<String>());
-    Expect.throwsCastError(() {
+    Expect.throwsTypeError(() {
       a.foo(new B<dynamic>());
     });
   }
diff --git a/runtime/vm/bit_vector.cc b/runtime/vm/bit_vector.cc
index c48324b..49dd496 100644
--- a/runtime/vm/bit_vector.cc
+++ b/runtime/vm/bit_vector.cc
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/bit_vector.h"
-
+#include "vm/log.h"
 #include "vm/os.h"
 
 namespace dart {
@@ -39,8 +39,10 @@
     if (data_[i] != other.data_[i]) return false;
   }
   if (i < data_length_) {
+    if (length_ % kBitsPerWord == 0) return data_[i] == other.data_[i];
+
     // Don't compare bits beyond length_.
-    const intptr_t shift_size = (kBitsPerWord - length_) & (kBitsPerWord - 1);
+    const intptr_t shift_size = kBitsPerWord - (length_ % kBitsPerWord);
     const uword mask = static_cast<uword>(-1) >> shift_size;
     if ((data_[i] & mask) != (other.data_[i] & mask)) return false;
   }
@@ -105,11 +107,11 @@
 }
 
 void BitVector::Print() const {
-  OS::PrintErr("[");
+  THR_Print("[");
   for (intptr_t i = 0; i < length_; i++) {
-    OS::PrintErr(Contains(i) ? "1" : "0");
+    THR_Print(Contains(i) ? "1" : "0");
   }
-  OS::PrintErr("]");
+  THR_Print("]");
 }
 
 }  // namespace dart
diff --git a/runtime/vm/bit_vector.h b/runtime/vm/bit_vector.h
index b04c6ec..a6a61f7 100644
--- a/runtime/vm/bit_vector.h
+++ b/runtime/vm/bit_vector.h
@@ -70,6 +70,8 @@
     data_[i / kBitsPerWord] &= ~(static_cast<uword>(1) << (i % kBitsPerWord));
   }
 
+  void Set(intptr_t i, bool value) { value ? Add(i) : Remove(i); }
+
   bool Equals(const BitVector& other) const;
 
   // Add all elements that are in the bitvector from.
@@ -92,6 +94,14 @@
     return (block & (static_cast<uword>(1) << (i % kBitsPerWord))) != 0;
   }
 
+  bool SubsetOf(const BitVector& other) {
+    ASSERT(length_ == other.length_);
+    for (intptr_t i = 0; i < data_length_; ++i) {
+      if ((data_[i] & other.data_[i]) != data_[i]) return false;
+    }
+    return true;
+  }
+
   void Clear() {
     for (intptr_t i = 0; i < data_length_; i++) {
       data_[i] = 0;
diff --git a/runtime/vm/compiler/backend/compile_type.h b/runtime/vm/compiler/backend/compile_type.h
index 8dd4c06..f068bf0 100644
--- a/runtime/vm/compiler/backend/compile_type.h
+++ b/runtime/vm/compiler/backend/compile_type.h
@@ -81,7 +81,11 @@
 
   // Return true if value of this type is assignable to a location of the
   // given type.
-  bool IsAssignableTo(const AbstractType& type);
+  bool IsAssignableTo(const AbstractType& other);
+
+  // Return true if value of this type always passes 'is' test
+  // against given type.
+  bool IsInstanceOf(const AbstractType& other);
 
   // Create a new CompileType representing given combination of class id and
   // abstract type. The pair is assumed to be coherent.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index a12c9a0..82b69ae 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -615,7 +615,9 @@
         EmitInstructionPrologue(instr);
         ASSERT(pending_deoptimization_env_ == NULL);
         pending_deoptimization_env_ = instr->env();
+        DEBUG_ONLY(current_instruction_ = instr);
         instr->EmitNativeCode(this);
+        DEBUG_ONLY(current_instruction_ = nullptr);
         pending_deoptimization_env_ = NULL;
         if (IsPeephole(instr)) {
           ASSERT(top_of_stack_ == nullptr);
@@ -708,7 +710,9 @@
     set_current_instruction(slow_path->instruction());
     SpecialStatsBegin(stats_tag);
     BeginCodeSourceRange();
+    DEBUG_ONLY(current_instruction_ = slow_path->instruction());
     slow_path->GenerateCode(this);
+    DEBUG_ONLY(current_instruction_ = nullptr);
     EndCodeSourceRange(slow_path->instruction()->token_pos());
     SpecialStatsEnd(stats_tag);
     set_current_instruction(nullptr);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index fc573cc..f34e9e7 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -1121,6 +1121,15 @@
   // is amenable to a peephole optimization.
   bool IsPeephole(Instruction* instr) const;
 
+#if defined(DEBUG)
+  bool CanCallDart() const {
+    return current_instruction_ == nullptr ||
+           current_instruction_->CanCallDart();
+  }
+#else
+  bool CanCallDart() const { return true; }
+#endif
+
   // This struct contains either function or code, the other one being NULL.
   class StaticCallsStruct : public ZoneAllocated {
    public:
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 5aad6fd..30499dc 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -995,6 +995,7 @@
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   __ BranchLinkPatchable(stub, entry_kind);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
 }
@@ -1005,6 +1006,7 @@
                                                LocationSummary* locs,
                                                const Function& target,
                                                Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     __ GenerateUnRelocatedPcRelativeCall();
     AddPcRelativeCallTarget(target, entry_kind);
@@ -1061,6 +1063,7 @@
                                                   TokenPosition token_pos,
                                                   LocationSummary* locs,
                                                   Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
   // function that corresponds to the Dart function of that IC call. Due
@@ -1084,6 +1087,7 @@
                                             TokenPosition token_pos,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(entry_kind == Code::EntryKind::kNormal ||
          entry_kind == Code::EntryKind::kUnchecked);
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
@@ -1109,6 +1113,7 @@
     LocationSummary* locs,
     intptr_t try_index,
     intptr_t slow_path_argument_count) {
+  ASSERT(CanCallDart());
   ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
   const ArgumentsDescriptor args_desc(arguments_descriptor);
   const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
@@ -1156,6 +1161,7 @@
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind,
                                             bool receiver_can_be_smi) {
+  ASSERT(CanCallDart());
   ASSERT(entry_kind == Code::EntryKind::kNormal ||
          entry_kind == Code::EntryKind::kUnchecked);
   ASSERT(ic_data.NumArgsTested() == 1);
@@ -1200,6 +1206,7 @@
                                                   LocationSummary* locs,
                                                   const ICData& ic_data,
                                                   Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   const Code& stub =
       StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(R9, ic_data);
@@ -1216,6 +1223,7 @@
     TokenPosition token_pos,
     LocationSummary* locs,
     Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(!function.IsClosureFunction());
   if (function.HasOptionalParameters() || function.IsGeneric()) {
     __ LoadObject(R4, arguments_descriptor);
@@ -1235,6 +1243,7 @@
     Register cid_reg,
     int32_t selector_offset,
     const Array& arguments_descriptor) {
+  ASSERT(CanCallDart());
   ASSERT(cid_reg != ARGS_DESC_REG);
   if (!arguments_descriptor.IsNull()) {
     __ LoadObject(ARGS_DESC_REG, arguments_descriptor);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 2958722..acaa121 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -966,6 +966,7 @@
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   __ BranchLinkPatchable(stub, entry_kind);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
 }
@@ -976,6 +977,7 @@
                                                LocationSummary* locs,
                                                const Function& target,
                                                Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     __ GenerateUnRelocatedPcRelativeCall();
     AddPcRelativeCallTarget(target, entry_kind);
@@ -1023,6 +1025,7 @@
                                                   TokenPosition token_pos,
                                                   LocationSummary* locs,
                                                   Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
   // function that corresponds to the Dart function of that IC call. Due
@@ -1045,6 +1048,7 @@
                                             TokenPosition token_pos,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(entry_kind == Code::EntryKind::kNormal ||
          entry_kind == Code::EntryKind::kUnchecked);
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
@@ -1076,6 +1080,7 @@
     LocationSummary* locs,
     intptr_t try_index,
     intptr_t slow_path_argument_count) {
+  ASSERT(CanCallDart());
   ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
   const ArgumentsDescriptor args_desc(arguments_descriptor);
   const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
@@ -1120,6 +1125,7 @@
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind,
                                             bool receiver_can_be_smi) {
+  ASSERT(CanCallDart());
   ASSERT(ic_data.NumArgsTested() == 1);
   const Code& initial_stub = StubCode::UnlinkedCall();
   const char* switchable_call_mode = "smiable";
@@ -1170,6 +1176,7 @@
                                                   LocationSummary* locs,
                                                   const ICData& ic_data,
                                                   Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   const Code& stub =
       StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(R5, ic_data);
@@ -1186,6 +1193,7 @@
     TokenPosition token_pos,
     LocationSummary* locs,
     Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(!function.IsClosureFunction());
   if (function.HasOptionalParameters() || function.IsGeneric()) {
     __ LoadObject(R4, arguments_descriptor);
@@ -1205,6 +1213,7 @@
     Register cid_reg,
     int32_t selector_offset,
     const Array& arguments_descriptor) {
+  ASSERT(CanCallDart());
   ASSERT(cid_reg != ARGS_DESC_REG);
   if (!arguments_descriptor.IsNull()) {
     __ LoadObject(ARGS_DESC_REG, arguments_descriptor);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 673e253..0605ba8 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -861,6 +861,7 @@
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   __ Call(stub, /*moveable_target=*/false, entry_kind);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
 }
@@ -871,6 +872,7 @@
                                                LocationSummary* locs,
                                                const Function& target,
                                                Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   const auto& stub = StubCode::CallStaticFunction();
   __ Call(stub, /*movable_target=*/true, entry_kind);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
@@ -892,6 +894,7 @@
                                                   LocationSummary* locs,
                                                   const ICData& ic_data,
                                                   Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   const Code& stub =
       StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(ECX, ic_data);
@@ -919,6 +922,7 @@
                                                   TokenPosition token_pos,
                                                   LocationSummary* locs,
                                                   Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
   // function that corresponds to the Dart function of that IC call. Due
@@ -942,6 +946,7 @@
                                             TokenPosition token_pos,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(entry_kind == Code::EntryKind::kNormal ||
          entry_kind == Code::EntryKind::kUnchecked);
   ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
@@ -967,6 +972,7 @@
     LocationSummary* locs,
     intptr_t try_index,
     intptr_t slow_path_argument_count) {
+  ASSERT(CanCallDart());
   ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
   const ArgumentsDescriptor args_desc(arguments_descriptor);
   const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
@@ -1014,6 +1020,7 @@
     TokenPosition token_pos,
     LocationSummary* locs,
     Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   if (function.HasOptionalParameters() || function.IsGeneric()) {
     __ LoadObject(EDX, arguments_descriptor);
   } else {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 1a6d288..ab879bc 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -977,6 +977,7 @@
                                          RawPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   __ CallPatchable(stub, entry_kind);
   EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
 }
@@ -987,6 +988,7 @@
                                                LocationSummary* locs,
                                                const Function& target,
                                                Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(is_optimizing());
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     __ GenerateUnRelocatedPcRelativeCall();
@@ -1019,6 +1021,7 @@
                                                   LocationSummary* locs,
                                                   const ICData& ic_data,
                                                   Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   const Code& stub =
       StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(RBX, ic_data);
@@ -1047,6 +1050,7 @@
                                                   TokenPosition token_pos,
                                                   LocationSummary* locs,
                                                   Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
   // function that corresponds to the Dart function of that IC call. Due
@@ -1070,6 +1074,7 @@
                                             TokenPosition token_pos,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(entry_kind == Code::EntryKind::kNormal ||
          entry_kind == Code::EntryKind::kUnchecked);
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
@@ -1095,6 +1100,7 @@
     LocationSummary* locs,
     intptr_t try_index,
     intptr_t slow_path_argument_count) {
+  ASSERT(CanCallDart());
   ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
   const ArgumentsDescriptor args_desc(arguments_descriptor);
   const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
@@ -1136,6 +1142,7 @@
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind,
                                             bool receiver_can_be_smi) {
+  ASSERT(CanCallDart());
   ASSERT(entry_kind == Code::EntryKind::kNormal ||
          entry_kind == Code::EntryKind::kUnchecked);
   ASSERT(ic_data.NumArgsTested() == 1);
@@ -1178,6 +1185,7 @@
     TokenPosition token_pos,
     LocationSummary* locs,
     Code::EntryKind entry_kind) {
+  ASSERT(CanCallDart());
   ASSERT(!function.IsClosureFunction());
   if (function.HasOptionalParameters() || function.IsGeneric()) {
     __ LoadObject(R10, arguments_descriptor);
@@ -1197,6 +1205,7 @@
     Register cid_reg,
     int32_t selector_offset,
     const Array& arguments_descriptor) {
+  ASSERT(CanCallDart());
   const Register table_reg = RAX;
   ASSERT(cid_reg != table_reg);
   ASSERT(cid_reg != ARGS_DESC_REG);
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 80c224c..0e78547 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -1024,6 +1024,15 @@
   // See StoreInstanceFieldInstr::HasUnknownSideEffects() for rationale.
   virtual bool HasUnknownSideEffects() const = 0;
 
+  // Whether this instruction can call Dart code without going through
+  // the runtime.
+  //
+  // Must be true for any instruction which can call Dart code without
+  // first creating an exit frame to transition into the runtime.
+  //
+  // See also WriteBarrierElimination and Thread::RememberLiveTemporaries().
+  virtual bool CanCallDart() const { return false; }
+
   virtual bool CanTriggerGC() const;
 
   // Get the block entry for this instruction.
@@ -3181,6 +3190,8 @@
     return comparison()->HasUnknownSideEffects();
   }
 
+  virtual bool CanCallDart() const { return comparison()->CanCallDart(); }
+
   ComparisonInstr* comparison() const { return comparison_; }
   void SetComparison(ComparisonInstr* comp);
 
@@ -3661,6 +3672,7 @@
   }
 
   virtual bool MayThrow() const { return true; }
+  virtual bool CanCallDart() const { return true; }
 
   virtual intptr_t InputCount() const { return inputs_->length(); }
   virtual Value* InputAt(intptr_t i) const { return inputs_->At(i); }
@@ -4411,6 +4423,7 @@
   virtual bool HasUnknownSideEffects() const {
     return comparison()->HasUnknownSideEffects();
   }
+  virtual bool CanCallDart() const { return comparison()->CanCallDart(); }
 
   virtual bool AttributesEqual(Instruction* other) const {
     IfThenElseInstr* other_if_then_else = other->AsIfThenElse();
@@ -4539,6 +4552,7 @@
   }
 
   virtual bool HasUnknownSideEffects() const { return true; }
+  virtual bool CanCallDart() const { return true; }
 
   // Initialize result type of this call instruction if target is a recognized
   // method or has pragma annotation.
@@ -4816,6 +4830,9 @@
 
   virtual bool HasUnknownSideEffects() const { return true; }
 
+  // Always creates an exit frame before more Dart code can be called.
+  virtual bool CanCallDart() const { return false; }
+
   void SetupNative();
 
   PRINT_OPERANDS_TO_SUPPORT
@@ -4875,6 +4892,9 @@
 
   virtual bool HasUnknownSideEffects() const { return true; }
 
+  // Always creates an exit frame before more Dart code can be called.
+  virtual bool CanCallDart() const { return false; }
+
   virtual Representation RequiredInputRepresentation(intptr_t idx) const;
   virtual Representation representation() const;
 
@@ -5435,6 +5455,7 @@
   virtual CompileType ComputeType() const;
   // Issues a static call to Dart code which calls toString on objects.
   virtual bool HasUnknownSideEffects() const { return true; }
+  virtual bool CanCallDart() const { return true; }
   virtual bool ComputeCanDeoptimize() const { return !FLAG_precompiled_mode; }
 
   const Function& CallFunction() const;
@@ -5489,6 +5510,10 @@
            (emit_store_barrier_ == kEmitStoreBarrier);
   }
 
+  void set_emit_store_barrier(StoreBarrierType value) {
+    emit_store_barrier_ = value;
+  }
+
   virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
     return speculative_mode_;
   }
@@ -5509,6 +5534,8 @@
 
   virtual bool HasUnknownSideEffects() const { return false; }
 
+  void PrintOperandsTo(BufferFormatter* f) const;
+
   ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
@@ -5516,7 +5543,7 @@
     return compiler::Assembler::kValueCanBeSmi;
   }
 
-  const StoreBarrierType emit_store_barrier_;
+  StoreBarrierType emit_store_barrier_;
   const bool index_unboxed_;
   const intptr_t index_scale_;
   const intptr_t class_id_;
@@ -7102,6 +7129,7 @@
   virtual bool RecomputeType();
 
   virtual bool HasUnknownSideEffects() const { return true; }
+  virtual bool CanCallDart() const { return true; }
 
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
@@ -7150,6 +7178,7 @@
   bool is_negated() const { return is_negated_; }
 
   virtual bool HasUnknownSideEffects() const { return true; }
+  virtual bool CanCallDart() const { return true; }
 
   PRINT_OPERANDS_TO_SUPPORT
 
@@ -7785,6 +7814,8 @@
 
   virtual bool HasUnknownSideEffects() const { return false; }
 
+  virtual bool CanCallDart() const { return true; }
+
  private:
   InstanceCallInstr* instance_call_;
 
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index f4f7115..d63d92b 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -1125,6 +1125,13 @@
   value()->PrintTo(f);
 }
 
+void StoreIndexedInstr::PrintOperandsTo(BufferFormatter* f) const {
+  Instruction::PrintOperandsTo(f);
+  if (!ShouldEmitStoreBarrier()) {
+    f->Print(", NoStoreBarrier");
+  }
+}
+
 void TailCallInstr::PrintOperandsTo(BufferFormatter* f) const {
   const char* name = "<unknown code>";
   if (code_.IsStubCode()) {
diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc
index 9f53b4b..6e7f51d 100644
--- a/runtime/vm/compiler/backend/il_test_helper.cc
+++ b/runtime/vm/compiler/backend/il_test_helper.cc
@@ -44,6 +44,14 @@
   return func.raw();
 }
 
+RawClass* GetClass(const Library& lib, const char* name) {
+  Thread* thread = Thread::Current();
+  const auto& cls = Class::Handle(
+      lib.LookupClassAllowPrivate(String::Handle(Symbols::New(thread, name))));
+  EXPECT(!cls.IsNull());
+  return cls.raw();
+}
+
 void Invoke(const Library& lib, const char* name) {
   // These tests rely on running unoptimized code to collect type feedback. The
   // interpreter does not collect type feedback for interface calls, so set
diff --git a/runtime/vm/compiler/backend/il_test_helper.h b/runtime/vm/compiler/backend/il_test_helper.h
index bdb7be1..95b6526 100644
--- a/runtime/vm/compiler/backend/il_test_helper.h
+++ b/runtime/vm/compiler/backend/il_test_helper.h
@@ -58,6 +58,7 @@
                            const char* lib_uri = RESOLVED_USER_TEST_URI);
 
 RawFunction* GetFunction(const Library& lib, const char* name);
+RawClass* GetClass(const Library& lib, const char* name);
 
 void Invoke(const Library& lib, const char* name);
 
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index 5b20762..b5572d7 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -51,7 +51,7 @@
 
 const char* Slot::KindToCString(Kind k) {
   switch (k) {
-#define NATIVE_CASE(C, F, id, M)                                               \
+#define NATIVE_CASE(C, U, F, id, M)                                            \
   case NATIVE_SLOT_NAME(C, F, id, M):                                          \
     return NATIVE_TO_STR(C, F, id, M);
     NATIVE_SLOTS_LIST(NATIVE_CASE)
@@ -70,7 +70,7 @@
 
 bool Slot::ParseKind(const char* str, Kind* out) {
   ASSERT(str != nullptr && out != nullptr);
-#define NATIVE_CASE(C, F, id, M)                                               \
+#define NATIVE_CASE(C, U, F, id, M)                                            \
   if (strcmp(str, NATIVE_TO_STR(C, F, id, M)) == 0) {                          \
     *out = NATIVE_SLOT_NAME(C, F, id, M);                                      \
     return true;                                                               \
@@ -101,7 +101,8 @@
   static const Slot fields[] = {
 #define FIELD_FINAL (IsImmutableBit::encode(true))
 #define FIELD_VAR (0)
-#define DEFINE_NATIVE_FIELD(ClassName, FieldName, cid, mutability)             \
+#define DEFINE_NATIVE_FIELD(ClassName, UnderlyingType, FieldName, cid,         \
+                            mutability)                                        \
   Slot(Kind::k##ClassName##_##FieldName, FIELD_##mutability, k##cid##Cid,      \
        compiler::target::ClassName::FieldName##_offset(),                      \
        #ClassName "." #FieldName, nullptr),
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 83f819a..6f6faa8 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -36,10 +36,11 @@
 // List of slots that correspond to fields of native objects in the following
 // format:
 //
-//     V(class_name, field_name, exact_type, FINAL|VAR)
+//     V(class_name, underlying_type, field_name, exact_type, FINAL|VAR)
 //
 // - class_name and field_name specify the name of the host class and the name
 //   of the field respectively;
+// - underlying_type: the Raw class which holds the field;
 // - exact_type specifies exact type of the field (any load from this field
 //   would only yield instances of this type);
 // - the last component specifies whether field behaves like a final field
@@ -48,31 +49,31 @@
 //
 // Note: native slots are expected to be non-nullable.
 #define NATIVE_SLOTS_LIST(V)                                                   \
-  V(Array, length, Smi, FINAL)                                                 \
-  V(Context, parent, Context, FINAL)                                           \
-  V(Closure, instantiator_type_arguments, TypeArguments, FINAL)                \
-  V(Closure, delayed_type_arguments, TypeArguments, FINAL)                     \
-  V(Closure, function_type_arguments, TypeArguments, FINAL)                    \
-  V(Closure, function, Function, FINAL)                                        \
-  V(Closure, context, Context, FINAL)                                          \
-  V(Closure, hash, Context, VAR)                                               \
-  V(GrowableObjectArray, length, Smi, VAR)                                     \
-  V(GrowableObjectArray, data, Array, VAR)                                     \
-  V(TypedDataBase, length, Smi, FINAL)                                         \
-  V(TypedDataView, offset_in_bytes, Smi, FINAL)                                \
-  V(TypedDataView, data, Dynamic, FINAL)                                       \
-  V(String, length, Smi, FINAL)                                                \
-  V(LinkedHashMap, index, TypedDataUint32Array, VAR)                           \
-  V(LinkedHashMap, data, Array, VAR)                                           \
-  V(LinkedHashMap, hash_mask, Smi, VAR)                                        \
-  V(LinkedHashMap, used_data, Smi, VAR)                                        \
-  V(LinkedHashMap, deleted_keys, Smi, VAR)                                     \
-  V(ArgumentsDescriptor, type_args_len, Smi, FINAL)                            \
-  V(ArgumentsDescriptor, positional_count, Smi, FINAL)                         \
-  V(ArgumentsDescriptor, count, Smi, FINAL)                                    \
-  V(ArgumentsDescriptor, size, Smi, FINAL)                                     \
-  V(PointerBase, data_field, Dynamic, FINAL)                                   \
-  V(Type, arguments, TypeArguments, FINAL)
+  V(Array, RawArray, length, Smi, FINAL)                                       \
+  V(Context, RawContext, parent, Context, FINAL)                               \
+  V(Closure, RawClosure, instantiator_type_arguments, TypeArguments, FINAL)    \
+  V(Closure, RawClosure, delayed_type_arguments, TypeArguments, FINAL)         \
+  V(Closure, RawClosure, function_type_arguments, TypeArguments, FINAL)        \
+  V(Closure, RawClosure, function, Function, FINAL)                            \
+  V(Closure, RawClosure, context, Context, FINAL)                              \
+  V(Closure, RawClosure, hash, Context, VAR)                                   \
+  V(GrowableObjectArray, RawGrowableObjectArray, length, Smi, VAR)             \
+  V(GrowableObjectArray, RawGrowableObjectArray, data, Array, VAR)             \
+  V(TypedDataBase, RawTypedDataBase, length, Smi, FINAL)                       \
+  V(TypedDataView, RawTypedDataView, offset_in_bytes, Smi, FINAL)              \
+  V(TypedDataView, RawTypedDataView, data, Dynamic, FINAL)                     \
+  V(String, RawString, length, Smi, FINAL)                                     \
+  V(LinkedHashMap, RawLinkedHashMap, index, TypedDataUint32Array, VAR)         \
+  V(LinkedHashMap, RawLinkedHashMap, data, Array, VAR)                         \
+  V(LinkedHashMap, RawLinkedHashMap, hash_mask, Smi, VAR)                      \
+  V(LinkedHashMap, RawLinkedHashMap, used_data, Smi, VAR)                      \
+  V(LinkedHashMap, RawLinkedHashMap, deleted_keys, Smi, VAR)                   \
+  V(ArgumentsDescriptor, RawArray, type_args_len, Smi, FINAL)                  \
+  V(ArgumentsDescriptor, RawArray, positional_count, Smi, FINAL)               \
+  V(ArgumentsDescriptor, RawArray, count, Smi, FINAL)                          \
+  V(ArgumentsDescriptor, RawArray, size, Smi, FINAL)                           \
+  V(PointerBase, RawPointerBase, data_field, Dynamic, FINAL)                   \
+  V(Type, RawType, arguments, TypeArguments, FINAL)
 
 // Slot is an abstraction that describes an readable (and possibly writeable)
 // location within an object.
@@ -86,7 +87,7 @@
   // clang-format off
   enum class Kind : uint8_t {
     // Native slots are identified by their kind - each native slot has its own.
-#define DECLARE_KIND(ClassName, FieldName, cid, mutability)                    \
+#define DECLARE_KIND(ClassName, UnderlyingType, FieldName, cid, mutability)    \
   k##ClassName##_##FieldName,
     NATIVE_SLOTS_LIST(DECLARE_KIND)
 #undef DECLARE_KIND
@@ -134,7 +135,7 @@
                          const ParsedFunction* parsed_function);
 
   // Convenience getters for native slots.
-#define DEFINE_GETTER(ClassName, FieldName, cid, mutability)                   \
+#define DEFINE_GETTER(ClassName, UnderlyingType, FieldName, cid, mutability)   \
   static const Slot& ClassName##_##FieldName() {                               \
     return GetNativeSlot(Kind::k##ClassName##_##FieldName);                    \
   }
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 094f2dd..7b65475 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -828,6 +828,19 @@
   return compile_type.IsSubtypeOf(other, Heap::kOld);
 }
 
+bool CompileType::IsInstanceOf(const AbstractType& other) {
+  if (other.IsTopType()) {
+    return true;
+  }
+  if (IsNone() || !other.IsInstantiated()) {
+    return false;
+  }
+  if (is_nullable() && !other.IsNullable()) {
+    return false;
+  }
+  return ToAbstractType()->IsSubtypeOf(other, Heap::kOld);
+}
+
 bool CompileType::Specialize(GrowableArray<intptr_t>* class_ids) {
   ToNullableCid();
   if (cid_ != kDynamicCid) {
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 70b5134..11481a0 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -1197,38 +1197,38 @@
     const AbstractType& type) {
   ASSERT(I->can_use_strong_mode_types());
   ASSERT(Token::IsTypeTestOperator(call->token_kind()));
-
-  // The goal is to emit code that will determine the result of 'x is type'
-  // depending solely on the fact that x == null or not.
-  // 'null' is an instance of Null, Object*, Never*, void, and dynamic.
-  // In addition, 'null' is an instance of any nullable type.
-  // It is also an instance of FutureOr<T> if it is an instance of T.
-  const AbstractType& unwrapped_type =
-      AbstractType::Handle(type.UnwrapFutureOr());
-  if (unwrapped_type.IsTopType() || !unwrapped_type.IsInstantiated()) {
-    return false;  // Always true or cannot tell.
-  }
-
-  // Checking whether the receiver is null can only help if the tested type is
-  // legacy (including Never*) or the Null type.
-  if (!unwrapped_type.IsLegacy() && !unwrapped_type.IsNullType()) {
-    // TODO(regis): We should optimize this into a constant if the type
-    // is nullable or non-nullable.
+  if (!type.IsInstantiated()) {
     return false;
   }
 
-  const intptr_t receiver_index = call->FirstArgIndex();
-  Value* left_value = call->ArgumentValueAt(receiver_index);
+  Value* left_value = call->Receiver();
+  if (left_value->Type()->IsInstanceOf(type)) {
+    ConstantInstr* replacement = flow_graph()->GetConstant(Bool::True());
+    call->ReplaceUsesWith(replacement);
+    ASSERT(current_iterator()->Current() == call);
+    current_iterator()->RemoveCurrentFromGraph();
+    return true;
+  }
 
-  // If the static type of the receiver is a subtype of the tested type,
-  // replace 'receiver is type' with 'receiver == null' if type is Null
-  // or with 'receiver != null' otherwise.
-  if (left_value->Type()->IsSubtypeOf(type)) {
+  // The goal is to emit code that will determine the result of 'x is type'
+  // depending solely on the fact that x == null or not.
+  // Checking whether the receiver is null can only help if the tested type is
+  // non-nullable or legacy (including Never*) or the Null type.
+  // Also, testing receiver for null cannot help with FutureOr.
+  if ((type.IsNullable() && !type.IsNullType()) || type.IsFutureOrType()) {
+    return false;
+  }
+
+  // If type is Null or Never*, or the static type of the receiver is a
+  // subtype of the tested type, replace 'receiver is type' with
+  //  - 'receiver == null' if type is Null or Never*,
+  //  - 'receiver != null' otherwise.
+  if (type.IsNullType() || type.IsNeverType() ||
+      left_value->Type()->IsSubtypeOf(type)) {
     Definition* replacement = new (Z) StrictCompareInstr(
         call->token_pos(),
-        (unwrapped_type.IsNullType() || unwrapped_type.IsNeverType())
-            ? Token::kEQ_STRICT
-            : Token::kNE_STRICT,
+        (type.IsNullType() || type.IsNeverType()) ? Token::kEQ_STRICT
+                                                  : Token::kNE_STRICT,
         left_value->CopyWithType(Z),
         new (Z) Value(flow_graph()->constant_null()),
         /* number_check = */ false, DeoptId::kNone);
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index b13d72a..80cbb59 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -19,6 +19,7 @@
 #include "vm/compiler/backend/redundancy_elimination.h"
 #include "vm/compiler/backend/type_propagator.h"
 #include "vm/compiler/call_specializer.h"
+#include "vm/compiler/write_barrier_elimination.h"
 #if defined(DART_PRECOMPILER)
 #include "vm/compiler/aot/aot_call_specializer.h"
 #include "vm/compiler/aot/precompiler.h"
@@ -266,7 +267,7 @@
   // so it should not be lifted earlier than that pass.
   INVOKE_PASS(DCE);
   INVOKE_PASS(Canonicalize);
-  INVOKE_PASS(WriteBarrierElimination);
+  INVOKE_PASS(EliminateWriteBarriers);
   INVOKE_PASS(FinalizeGraph);
 #if defined(DART_PRECOMPILER)
   if (mode == kAOT) {
@@ -349,7 +350,7 @@
   INVOKE_PASS(EliminateStackOverflowChecks);
   INVOKE_PASS(Canonicalize);
   INVOKE_PASS(AllocationSinking_DetachMaterializations);
-  INVOKE_PASS(WriteBarrierElimination);
+  INVOKE_PASS(EliminateWriteBarriers);
   INVOKE_PASS(FinalizeGraph);
 #if defined(DART_PRECOMPILER)
   if (mode == kAOT) {
@@ -529,38 +530,7 @@
   }
 });
 
-static void WriteBarrierElimination(FlowGraph* flow_graph) {
-  for (BlockIterator block_it = flow_graph->reverse_postorder_iterator();
-       !block_it.Done(); block_it.Advance()) {
-    BlockEntryInstr* block = block_it.Current();
-    Definition* last_allocated = nullptr;
-    for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
-      Instruction* current = it.Current();
-      if (!current->CanTriggerGC()) {
-        if (StoreInstanceFieldInstr* instr = current->AsStoreInstanceField()) {
-          if (instr->instance()->definition() == last_allocated) {
-            instr->set_emit_store_barrier(kNoStoreBarrier);
-          }
-          continue;
-        }
-      }
-
-      if (AllocationInstr* alloc = current->AsAllocation()) {
-        if (alloc->WillAllocateNewOrRemembered()) {
-          last_allocated = alloc;
-          continue;
-        }
-      }
-
-      if (current->CanTriggerGC()) {
-        last_allocated = nullptr;
-      }
-    }
-  }
-}
-
-COMPILER_PASS(WriteBarrierElimination,
-              { WriteBarrierElimination(flow_graph); });
+COMPILER_PASS(EliminateWriteBarriers, { EliminateWriteBarriers(flow_graph); });
 
 COMPILER_PASS(FinalizeGraph, {
   // At the end of the pipeline, force recomputing and caching graph
diff --git a/runtime/vm/compiler/compiler_pass.h b/runtime/vm/compiler/compiler_pass.h
index 54570dd..f3333b91 100644
--- a/runtime/vm/compiler/compiler_pass.h
+++ b/runtime/vm/compiler/compiler_pass.h
@@ -50,7 +50,7 @@
   V(TypePropagation)                                                           \
   V(UseTableDispatch)                                                          \
   V(WidenSmiToInt32)                                                           \
-  V(WriteBarrierElimination)
+  V(EliminateWriteBarriers)
 
 class AllocationSinking;
 class BlockScheduler;
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index d2b651c..8cf2d6c 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -166,6 +166,8 @@
   "stub_code_compiler_arm64.cc",
   "stub_code_compiler_ia32.cc",
   "stub_code_compiler_x64.cc",
+  "write_barrier_elimination.cc",
+  "write_barrier_elimination.h",
 ]
 
 compiler_sources_tests = [
@@ -190,4 +192,5 @@
   "backend/typed_data_aot_test.cc",
   "backend/yield_position_test.cc",
   "cha_test.cc",
+  "write_barrier_elimination_test.cc",
 ]
diff --git a/runtime/vm/compiler/write_barrier_elimination.cc b/runtime/vm/compiler/write_barrier_elimination.cc
new file mode 100644
index 0000000..162f8e1
--- /dev/null
+++ b/runtime/vm/compiler/write_barrier_elimination.cc
@@ -0,0 +1,388 @@
+// 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.
+
+#include <functional>
+
+#include "vm/compiler/backend/flow_graph.h"
+#include "vm/compiler/compiler_pass.h"
+#include "vm/compiler/write_barrier_elimination.h"
+
+namespace dart {
+
+#if defined(DEBUG)
+DEFINE_FLAG(bool,
+            trace_write_barrier_elimination,
+            false,
+            "Trace WriteBarrierElimination pass.");
+#endif
+
+class DefinitionIndexPairTrait {
+ public:
+  typedef Definition* Key;
+  typedef intptr_t Value;
+  struct Pair {
+    Definition* definition = nullptr;
+    intptr_t index = -1;
+    Pair() {}
+    Pair(Definition* definition, intptr_t index)
+        : definition(definition), index(index) {}
+  };
+
+  static Key KeyOf(Pair kv) { return kv.definition; }
+  static Value ValueOf(Pair kv) { return kv.index; }
+  static inline intptr_t Hashcode(Key key) { return std::hash<Key>()(key); }
+  static inline bool IsKeyEqual(Pair kv, Key key) {
+    return kv.definition == key;
+  }
+};
+
+typedef DirectChainedHashMap<DefinitionIndexPairTrait> DefinitionIndexMap;
+
+// Inter-block write-barrier elimination.
+//
+// This optimization removes write barriers from some store instructions under
+// certain assumptions which the runtime is responsible to sustain.
+//
+// We can skip a write barrier on a StoreInstanceField to a container object X
+// if we know that either:
+//   - X is in new-space, or
+//   - X is in old-space, and:
+//     - X is in the store buffer, and
+//     - X is in the deferred marking stack (if concurrent marking is enabled)
+//
+// The result of an Allocation instruction (Instruction::IsAllocation()) will
+// satisfy one of these requirements immediately after the instruction
+// if WillAllocateNewOrRemembered() is true.
+//
+// Without runtime support, we would have to assume that any instruction which
+// can trigger a new-space scavenge (Instruction::CanTriggerGC()) might promote
+// a new-space temporary into old-space, and we could not skip a store barrier
+// on a write into it afterward.
+//
+// However, many instructions can trigger GC in unlikely cases, like
+// CheckStackOverflow and Box. To avoid interrupting write barrier elimination
+// across these instructions, the runtime ensures that any live temporaries
+// (except arrays) promoted during a scavenge caused by a non-Dart-call
+// instruction (see Instruction::CanCallDart()) will be added to the store
+// buffer. Additionally, if concurrent marking was initiated, the runtime
+// ensures that all live temporaries are also in the deferred marking stack.
+//
+// See also Thread::RememberLiveTemporaries() and
+// Thread::DeferredMarkLiveTemporaries().
+class WriteBarrierElimination : public ValueObject {
+ public:
+  WriteBarrierElimination(Zone* zone, FlowGraph* flow_graph);
+
+  void Analyze();
+  void SaveResults();
+
+ private:
+  void IndexDefinitions(Zone* zone);
+
+  bool AnalyzeBlock(BlockEntryInstr* entry);
+  void MergePredecessors(BlockEntryInstr* entry);
+
+  void UpdateVectorForBlock(BlockEntryInstr* entry, bool finalize);
+
+  static intptr_t Index(BlockEntryInstr* entry) {
+    return entry->postorder_number();
+  }
+
+  intptr_t Index(Definition* def) {
+    ASSERT(IsUsable(def));
+    return definition_indices_.LookupValue(def);
+  }
+
+  bool IsUsable(Definition* def) {
+    return def->IsPhi() || (def->IsAllocation() &&
+                            def->AsAllocation()->WillAllocateNewOrRemembered());
+  }
+
+#if defined(DEBUG)
+  static bool SlotEligibleForWBE(const Slot& slot);
+#endif
+
+  FlowGraph* const flow_graph_;
+  const GrowableArray<BlockEntryInstr*>* const block_order_;
+
+  // Number of usable definitions in the graph.
+  intptr_t definition_count_ = 0;
+
+  // Maps each usable definition to its index in the bitvectors.
+  DefinitionIndexMap definition_indices_;
+
+  // Bitvector with all non-Array-allocation instructions set. Used to
+  // un-mark Array allocations as usable.
+  BitVector* array_allocations_mask_;
+
+  // Bitvectors for each block of which allocations are new or remembered
+  // at the start (after Phis).
+  GrowableArray<BitVector*> usable_allocs_in_;
+
+  // Bitvectors for each block of which allocations are new or remembered
+  // at the end of the block.
+  GrowableArray<BitVector*> usable_allocs_out_;
+
+  // Remaining blocks to process.
+  GrowableArray<BlockEntryInstr*> worklist_;
+
+  // Temporary used in many functions to avoid repeated zone allocation.
+  BitVector* vector_;
+
+  // Bitvector of blocks which have been processed, to ensure each block
+  // is processed at least once.
+  BitVector* processed_blocks_;
+
+#if defined(DEBUG)
+  bool tracing_ = false;
+#else
+  static constexpr bool tracing_ = false;
+#endif
+};
+
+WriteBarrierElimination::WriteBarrierElimination(Zone* zone,
+                                                 FlowGraph* flow_graph)
+    : flow_graph_(flow_graph), block_order_(&flow_graph->postorder()) {
+#if defined(DEBUG)
+  if (flow_graph->should_print() && FLAG_trace_write_barrier_elimination) {
+    tracing_ = true;
+  }
+#endif
+
+  IndexDefinitions(zone);
+
+  for (intptr_t i = 0; i < block_order_->length(); ++i) {
+    usable_allocs_in_.Add(new (zone) BitVector(zone, definition_count_));
+    usable_allocs_in_[i]->CopyFrom(vector_);
+
+    usable_allocs_out_.Add(new (zone) BitVector(zone, definition_count_));
+    usable_allocs_out_[i]->CopyFrom(vector_);
+  }
+
+  processed_blocks_ = new (zone) BitVector(zone, block_order_->length());
+}
+
+void WriteBarrierElimination::Analyze() {
+  for (intptr_t i = 0; i < block_order_->length(); ++i) {
+    worklist_.Add(block_order_->At(i));
+  }
+
+  while (!worklist_.is_empty()) {
+    auto* const entry = worklist_.RemoveLast();
+    if (AnalyzeBlock(entry)) {
+      for (intptr_t i = 0; i < entry->last_instruction()->SuccessorCount();
+           ++i) {
+        if (tracing_) {
+          THR_Print("Enqueueing block %" Pd "\n", entry->block_id());
+        }
+        worklist_.Add(entry->last_instruction()->SuccessorAt(i));
+      }
+    }
+  }
+}
+
+void WriteBarrierElimination::SaveResults() {
+  for (intptr_t i = 0; i < block_order_->length(); ++i) {
+    vector_->CopyFrom(usable_allocs_in_[i]);
+    UpdateVectorForBlock(block_order_->At(i), /*finalize=*/true);
+  }
+}
+
+void WriteBarrierElimination::IndexDefinitions(Zone* zone) {
+  BitmapBuilder array_allocations;
+
+  for (intptr_t i = 0; i < block_order_->length(); ++i) {
+    BlockEntryInstr* const block = block_order_->At(i);
+    if (auto join_block = block->AsJoinEntry()) {
+      for (PhiIterator it(join_block); !it.Done(); it.Advance()) {
+        array_allocations.Set(definition_count_, false);
+        definition_indices_.Insert({it.Current(), definition_count_++});
+#if defined(DEBUG)
+        if (tracing_) {
+          THR_Print("Definition (%" Pd ") has index %" Pd ".\n",
+                    it.Current()->ssa_temp_index(), definition_count_ - 1);
+        }
+#endif
+      }
+    }
+    for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
+      if (Definition* current = it.Current()->AsDefinition()) {
+        if (IsUsable(current)) {
+          array_allocations.Set(definition_count_, current->IsCreateArray());
+          definition_indices_.Insert({current, definition_count_++});
+#if defined(DEBUG)
+          if (tracing_) {
+            THR_Print("Definition (%" Pd ") has index %" Pd ".\n",
+                      current->ssa_temp_index(), definition_count_ - 1);
+          }
+#endif
+        }
+      }
+    }
+  }
+
+  vector_ = new (zone) BitVector(zone, definition_count_);
+  vector_->SetAll();
+  array_allocations_mask_ = new (zone) BitVector(zone, definition_count_);
+  for (intptr_t i = 0; i < definition_count_; ++i) {
+    if (!array_allocations.Get(i)) array_allocations_mask_->Add(i);
+  }
+}
+
+void WriteBarrierElimination::MergePredecessors(BlockEntryInstr* entry) {
+  vector_->Clear();
+  for (intptr_t i = 0; i < entry->PredecessorCount(); ++i) {
+    BitVector* predecessor_set =
+        usable_allocs_out_[Index(entry->PredecessorAt(i))];
+    if (i == 0) {
+      vector_->AddAll(predecessor_set);
+    } else {
+      vector_->Intersect(predecessor_set);
+    }
+  }
+
+  if (JoinEntryInstr* join = entry->AsJoinEntry()) {
+    // A Phi is usable if and only if all its inputs are usable.
+    for (PhiIterator it(join); !it.Done(); it.Advance()) {
+      PhiInstr* phi = it.Current();
+      ASSERT(phi->InputCount() == entry->PredecessorCount());
+      bool is_usable = true;
+      for (intptr_t i = 0; i < phi->InputCount(); ++i) {
+        BitVector* const predecessor_set =
+            usable_allocs_out_[Index(entry->PredecessorAt(i))];
+        Definition* const origin = phi->InputAt(i)->definition();
+        if (!IsUsable(origin) || !predecessor_set->Contains(Index(origin))) {
+          is_usable = false;
+          break;
+        }
+      }
+      vector_->Set(Index(phi), is_usable);
+    }
+
+#if defined(DEBUG)
+    if (tracing_) {
+      THR_Print("Merge predecessors for %" Pd ".\n", entry->block_id());
+      for (PhiIterator it(join); !it.Done(); it.Advance()) {
+        PhiInstr* phi = it.Current();
+        THR_Print("%" Pd ": %s\n", phi->ssa_temp_index(),
+                  vector_->Contains(Index(phi)) ? "true" : "false");
+      }
+    }
+#endif
+  }
+}
+
+bool WriteBarrierElimination::AnalyzeBlock(BlockEntryInstr* entry) {
+  // Recompute the usable allocs in-set.
+  MergePredecessors(entry);
+
+  // If the in-set has not changed, there's no work to do.
+  BitVector* const in_set = usable_allocs_in_[Index(entry)];
+  ASSERT(vector_->SubsetOf(*in_set));  // convergence
+  if (vector_->Equals(*in_set) && processed_blocks_->Contains(Index(entry))) {
+    if (tracing_) {
+      THR_Print("Bailout of block %" Pd ": inputs didn't change.\n",
+                entry->block_id());
+    }
+    return false;
+  } else if (tracing_) {
+    THR_Print("Inputs of block %" Pd " changed: ", entry->block_id());
+    in_set->Print();
+    THR_Print(" -> ");
+    vector_->Print();
+    THR_Print("\n");
+  }
+
+  usable_allocs_in_[Index(entry)]->CopyFrom(vector_);
+  UpdateVectorForBlock(entry, /*finalize=*/false);
+
+  processed_blocks_->Add(Index(entry));
+
+  // Successors only need to be updated if the out-set changes.
+  if (vector_->Equals(*usable_allocs_out_[Index(entry)])) {
+    if (tracing_) {
+      THR_Print("Bailout of block %" Pd ": out-set didn't change.\n",
+                entry->block_id());
+    }
+    return false;
+  }
+
+  BitVector* const out_set = usable_allocs_out_[Index(entry)];
+  ASSERT(vector_->SubsetOf(*out_set));  // convergence
+  out_set->CopyFrom(vector_);
+  if (tracing_) {
+    THR_Print("Block %" Pd " changed.\n", entry->block_id());
+  }
+  return true;
+}
+
+#if defined(DEBUG)
+bool WriteBarrierElimination::SlotEligibleForWBE(const Slot& slot) {
+  // We assume that Dart code only stores into Instances or Contexts.
+  // This assumption is used in
+  // RestoreWriteBarrierInvariantVisitor::VisitPointers.
+
+  switch (slot.kind()) {
+    case Slot::Kind::kCapturedVariable:  // Context
+      return true;
+    case Slot::Kind::kDartField:  // Instance
+      return true;
+
+#define FOR_EACH_NATIVE_SLOT(class, underlying_type, field, type, modifiers)   \
+  case Slot::Kind::k##class##_##field:                                         \
+    return std::is_base_of<RawInstance, underlying_type>::value ||             \
+           std::is_base_of<RawContext, underlying_type>::value;
+
+      NATIVE_SLOTS_LIST(FOR_EACH_NATIVE_SLOT)
+#undef FOR_EACH_NATIVE_SLOT
+
+    default:
+      return false;
+  }
+}
+#endif
+
+void WriteBarrierElimination::UpdateVectorForBlock(BlockEntryInstr* entry,
+                                                   bool finalize) {
+  for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
+    Instruction* const current = it.Current();
+
+    if (finalize) {
+      if (StoreInstanceFieldInstr* instr = current->AsStoreInstanceField()) {
+        Definition* const container = instr->instance()->definition();
+        if (IsUsable(container) && vector_->Contains(Index(container))) {
+          DEBUG_ASSERT(SlotEligibleForWBE(instr->slot()));
+          instr->set_emit_store_barrier(kNoStoreBarrier);
+        }
+      } else if (StoreIndexedInstr* instr = current->AsStoreIndexed()) {
+        Definition* const array = instr->array()->definition();
+        if (IsUsable(array) && vector_->Contains(Index(array))) {
+          instr->set_emit_store_barrier(StoreBarrierType::kNoStoreBarrier);
+        }
+      }
+    }
+
+    if (current->CanCallDart()) {
+      vector_->Clear();
+    } else if (current->CanTriggerGC()) {
+      // Clear array allocations. These are not added to the remembered set
+      // by Thread::RememberLiveTemporaries() after a scavenge.
+      vector_->Intersect(array_allocations_mask_);
+    }
+
+    if (AllocationInstr* const alloc = current->AsAllocation()) {
+      if (alloc->WillAllocateNewOrRemembered()) {
+        vector_->Add(Index(alloc));
+      }
+    }
+  }
+}
+
+void EliminateWriteBarriers(FlowGraph* flow_graph) {
+  WriteBarrierElimination elimination(Thread::Current()->zone(), flow_graph);
+  elimination.Analyze();
+  elimination.SaveResults();
+}
+
+}  // namespace dart
diff --git a/runtime/vm/compiler/write_barrier_elimination.h b/runtime/vm/compiler/write_barrier_elimination.h
new file mode 100644
index 0000000..88109e7
--- /dev/null
+++ b/runtime/vm/compiler/write_barrier_elimination.h
@@ -0,0 +1,15 @@
+// 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.
+
+#ifndef RUNTIME_VM_COMPILER_WRITE_BARRIER_ELIMINATION_H_
+#define RUNTIME_VM_COMPILER_WRITE_BARRIER_ELIMINATION_H_
+
+namespace dart {
+
+class FlowGraph;
+void EliminateWriteBarriers(FlowGraph* flow_graph);
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_COMPILER_WRITE_BARRIER_ELIMINATION_H_
diff --git a/runtime/vm/compiler/write_barrier_elimination_test.cc b/runtime/vm/compiler/write_barrier_elimination_test.cc
new file mode 100644
index 0000000..737e213
--- /dev/null
+++ b/runtime/vm/compiler/write_barrier_elimination_test.cc
@@ -0,0 +1,198 @@
+// 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.
+
+#include "platform/assert.h"
+#include "vm/compiler/backend/il_printer.h"
+#include "vm/compiler/backend/il_test_helper.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+DEBUG_ONLY(DECLARE_FLAG(bool, trace_write_barrier_elimination);)
+
+ISOLATE_UNIT_TEST_CASE(IRTest_WriteBarrierElimination_JoinSuccessors) {
+  DEBUG_ONLY(FLAG_trace_write_barrier_elimination = true);
+
+  // This is a regression test for a bug where we were using
+  // JoinEntry::SuccessorCount() to determine the number of outgoing blocks
+  // from the join block. JoinEntry::SuccessorCount() is in fact always 0;
+  // JoinEntry::last_instruction()->SuccessorCount() should be used instead.
+  const char* kScript =
+      R"(
+      class C {
+        int value;
+        C next;
+        C prev;
+      }
+
+      @pragma("vm:never-inline")
+      fn() {}
+
+      foo(int x) {
+        C prev = C();
+        C next;
+        while (x --> 0) {
+          next = C();
+          next.prev = prev;
+          prev?.next = next;
+          prev = next;
+          fn();
+        }
+        return next;
+      }
+
+      main() { foo(10); }
+      )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+
+  Invoke(root_library, "main");
+
+  const auto& function = Function::Handle(GetFunction(root_library, "foo"));
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({});
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  StoreInstanceFieldInstr* store1 = nullptr;
+  StoreInstanceFieldInstr* store2 = nullptr;
+
+  ILMatcher cursor(flow_graph, entry);
+  RELEASE_ASSERT(cursor.TryMatch({
+      kMoveGlob,
+      kMatchAndMoveGoto,
+      kMoveGlob,
+      kMatchAndMoveBranchTrue,
+      kMoveGlob,
+      {kMatchAndMoveStoreInstanceField, &store1},
+      kMoveGlob,
+      {kMatchAndMoveStoreInstanceField, &store2},
+  }));
+
+  EXPECT(store1->ShouldEmitStoreBarrier() == false);
+  EXPECT(store2->ShouldEmitStoreBarrier() == true);
+}
+
+ISOLATE_UNIT_TEST_CASE(IRTest_WriteBarrierElimination_AtLeastOnce) {
+  DEBUG_ONLY(FLAG_trace_write_barrier_elimination = true);
+
+  // Ensure that we process every block at least once during the analysis
+  // phase so that the out-sets will be initialized. If we don't process
+  // each block at least once, the store "c.next = n" will be marked
+  // NoWriteBarrier.
+  const char* kScript =
+      R"(
+      class C {
+        C next;
+      }
+
+      @pragma("vm:never-inline")
+      fn() {}
+
+      foo(int x) {
+        C c = C();
+        C n = C();
+        if (x > 5) {
+          fn();
+        }
+        c.next = n;
+        return c;
+      }
+
+      main() { foo(0); foo(10); }
+      )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+
+  Invoke(root_library, "main");
+
+  const auto& function = Function::Handle(GetFunction(root_library, "foo"));
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({});
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  StoreInstanceFieldInstr* store = nullptr;
+
+  ILMatcher cursor(flow_graph, entry);
+  RELEASE_ASSERT(cursor.TryMatch({
+      kMoveGlob,
+      kMatchAndMoveBranchFalse,
+      kMoveGlob,
+      kMatchAndMoveGoto,
+      kMoveGlob,
+      {kMatchAndMoveStoreInstanceField, &store},
+  }));
+
+  EXPECT(store->ShouldEmitStoreBarrier() == true);
+}
+
+ISOLATE_UNIT_TEST_CASE(IRTest_WriteBarrierElimination_Arrays) {
+  DEBUG_ONLY(FLAG_trace_write_barrier_elimination = true);
+
+  // Test that array allocations are not considered usable after a
+  // may-trigger-GC instruction (in this case CheckStackOverflow), unlike
+  // normal allocations, which are only interruped by a Dart call.
+  const char* kScript =
+      R"(
+      class C {
+        C next;
+      }
+
+      @pragma("vm:never-inline")
+      fn() {}
+
+      foo(int x) {
+        C c = C();
+        C n = C();
+        List<C> array = List<C>(1);
+        while (x --> 0) {
+          c.next = n;
+          n = c;
+          c = C();
+        }
+        array[0] = c;
+        return c;
+      }
+
+      main() { foo(10); }
+      )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+
+  Invoke(root_library, "main");
+
+  const auto& function = Function::Handle(GetFunction(root_library, "foo"));
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({});
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  StoreInstanceFieldInstr* store_into_c = nullptr;
+  StoreIndexedInstr* store_into_array = nullptr;
+
+  ILMatcher cursor(flow_graph, entry);
+  RELEASE_ASSERT(cursor.TryMatch({
+      kMoveGlob,
+      kMatchAndMoveGoto,
+      kMoveGlob,
+      kMatchAndMoveBranchTrue,
+      kMoveGlob,
+      {kMatchAndMoveStoreInstanceField, &store_into_c},
+      kMoveGlob,
+      kMatchAndMoveGoto,
+      kMoveGlob,
+      kMatchAndMoveBranchFalse,
+      kMoveGlob,
+      {kMatchAndMoveStoreIndexed, &store_into_array},
+  }));
+
+  EXPECT(store_into_c->ShouldEmitStoreBarrier() == false);
+  EXPECT(store_into_array->ShouldEmitStoreBarrier() == true);
+}
+
+}  // namespace dart
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index 5455ea7..994a268 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -819,6 +819,8 @@
     ASSERT(result);
   }
 
+  isolate_group_->DeferredMarkLiveTemporaries();
+
   // Wait for roots to be marked before exiting safepoint.
   MonitorLocker ml(&root_slices_monitor_);
   while (root_slices_finished_ != kNumRootSlices) {
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index d3c20b2..3de0aa3 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -1187,6 +1187,9 @@
     ProcessWeakReferences();
     page_space->ReleaseDataLock();
 
+    // Restore write-barrier assumptions.
+    isolate_group->RememberLiveTemporaries();
+
     // Scavenge finished. Run accounting.
     int64_t end = OS::GetCurrentMonotonicMicros();
     heap_->RecordTime(kProcessToSpace, process_to_space - iterate_roots);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 84927d1..633d468 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2366,7 +2366,7 @@
   // after a potential shutdown of the group, which would turn down any pending
   // GC tasks as well as the heap.
   Isolate::MarkIsolateDead(is_application_isolate);
-}
+}  // namespace dart
 
 Dart_InitializeIsolateCallback Isolate::initialize_callback_ = nullptr;
 Dart_IsolateGroupCreateCallback Isolate::create_group_callback_ = nullptr;
@@ -2461,6 +2461,18 @@
   thread_registry()->ReleaseStoreBuffers();
 }
 
+void Isolate::RememberLiveTemporaries() {
+  if (mutator_thread_ != nullptr) {
+    mutator_thread_->RememberLiveTemporaries();
+  }
+}
+
+void Isolate::DeferredMarkLiveTemporaries() {
+  if (mutator_thread_ != nullptr) {
+    mutator_thread_->DeferredMarkLiveTemporaries();
+  }
+}
+
 void IsolateGroup::EnableIncrementalBarrier(
     MarkingStack* marking_stack,
     MarkingStack* deferred_marking_stack) {
@@ -2578,6 +2590,17 @@
   return 0;
 }
 
+void IsolateGroup::DeferredMarkLiveTemporaries() {
+  ForEachIsolate(
+      [&](Isolate* isolate) { isolate->DeferredMarkLiveTemporaries(); },
+      /*at_safepoint=*/true);
+}
+
+void IsolateGroup::RememberLiveTemporaries() {
+  ForEachIsolate([&](Isolate* isolate) { isolate->RememberLiveTemporaries(); },
+                 /*at_safepoint=*/true);
+}
+
 RawClass* Isolate::GetClassForHeapWalkAt(intptr_t cid) {
   RawClass* raw_class = nullptr;
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 5ee8098..554398b 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -479,6 +479,9 @@
 
   uword FindPendingDeoptAtSafepoint(uword fp);
 
+  void RememberLiveTemporaries();
+  void DeferredMarkLiveTemporaries();
+
  private:
   friend class Heap;
   friend class StackFrame;  // For `[isolates_].First()`.
@@ -1149,6 +1152,9 @@
 
   static void NotifyLowMemory();
 
+  void RememberLiveTemporaries();
+  void DeferredMarkLiveTemporaries();
+
  private:
   friend class Dart;                  // Init, InitOnce, Shutdown.
   friend class IsolateKillerVisitor;  // Kill().
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 4b65a02..f586e9d 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -107,13 +107,8 @@
   }
   ASSERT(initialized_);
   ThreadInterrupter::Cleanup();
-#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
-  // TODO(30309): Free the sample buffer on platforms that use a signal-based
-  // thread interrupter.
-#else
   delete sample_buffer_;
   sample_buffer_ = NULL;
-#endif
   initialized_ = false;
 }
 
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 325e23c..c05cd6a 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -1536,6 +1536,10 @@
 void Profile::Build(Thread* thread,
                     SampleFilter* filter,
                     SampleBuffer* sample_buffer) {
+  // Disable thread interrupts while processing the buffer.
+  DisableThreadInterruptsScope dtis(thread);
+  ThreadInterrupter::SampleBufferReaderScope scope;
+
   ProfileBuilder builder(thread, filter, sample_buffer, this);
   builder.Build();
 }
@@ -1825,8 +1829,6 @@
                                     SampleBuffer* sample_buffer,
                                     bool include_code_samples) {
   Isolate* isolate = thread->isolate();
-  // Disable thread interrupts while processing the buffer.
-  DisableThreadInterruptsScope dtis(thread);
 
   // We should bail out in service.cc if the profiler is disabled.
   ASSERT(sample_buffer != NULL);
@@ -1921,6 +1923,7 @@
 
   // Disable thread interrupts while processing the buffer.
   DisableThreadInterruptsScope dtis(thread);
+  ThreadInterrupter::SampleBufferReaderScope scope;
 
   ClearProfileVisitor clear_profile(isolate);
   sample_buffer->VisitSamples(&clear_profile);
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 7f554a1..12e21e5 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -160,7 +160,7 @@
   return false;
 }
 
-bool StackFrame::IsStubFrame() const {
+bool StackFrame::IsStubFrame(bool needed_for_gc) const {
   if (is_interpreted()) {
     return false;
   }
@@ -176,7 +176,7 @@
   NoSafepointScope no_safepoint;
 #endif
 
-  RawCode* code = GetCodeObject();
+  RawCode* code = GetCodeObject(needed_for_gc);
   ASSERT(code != Object::null());
   const intptr_t cid = code->ptr()->owner_->GetClassId();
   ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid);
@@ -418,9 +418,9 @@
   return Code::null();
 }
 
-RawCode* StackFrame::GetCodeObject() const {
+RawCode* StackFrame::GetCodeObject(bool needed_for_gc) const {
   ASSERT(!is_interpreted());
-  if (auto isolate = IsolateOfBareInstructionsFrame(/*needed_for_gc=*/false)) {
+  if (auto isolate = IsolateOfBareInstructionsFrame(needed_for_gc)) {
     auto const rct = isolate->reverse_pc_lookup_cache();
     return rct->Lookup(pc(), /*is_return_address=*/true);
   } else {
@@ -546,8 +546,8 @@
   return TokenPosition::kNoSource;
 }
 
-bool StackFrame::IsValid() const {
-  if (IsEntryFrame() || IsExitFrame() || IsStubFrame()) {
+bool StackFrame::IsValid(bool needed_for_gc) const {
+  if (IsEntryFrame() || IsExitFrame() || IsStubFrame(needed_for_gc)) {
     return true;
   }
   if (is_interpreted()) {
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index 39af4d5..8427dd2 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -94,7 +94,7 @@
   const char* ToCString() const;
 
   // Check validity of a frame, used for assertion purposes.
-  virtual bool IsValid() const;
+  virtual bool IsValid(bool needed_for_gc = false) const;
 
   // Returns the isolate containing the bare instructions of the current frame.
   //
@@ -112,11 +112,12 @@
   bool IsBareInstructionsStubFrame() const;
 
   // Frame type.
-  virtual bool IsDartFrame(bool validate = true) const {
-    ASSERT(!validate || IsValid());
-    return !(IsEntryFrame() || IsExitFrame() || IsStubFrame());
+  virtual bool IsDartFrame(bool validate = true,
+                           bool needed_for_gc = false) const {
+    ASSERT(!validate || IsValid(needed_for_gc));
+    return !(IsEntryFrame() || IsExitFrame() || IsStubFrame(needed_for_gc));
   }
-  virtual bool IsStubFrame() const;
+  virtual bool IsStubFrame(bool neede_for_gc = false) const;
   virtual bool IsEntryFrame() const { return false; }
   virtual bool IsExitFrame() const { return false; }
 
@@ -158,7 +159,7 @@
   Thread* thread() const { return thread_; }
 
  private:
-  RawCode* GetCodeObject() const;
+  RawCode* GetCodeObject(bool needed_for_gc = false) const;
   RawBytecode* GetBytecodeObject() const;
 
 
@@ -199,9 +200,11 @@
 // runtime code.
 class ExitFrame : public StackFrame {
  public:
-  bool IsValid() const { return sp() == 0; }
-  bool IsDartFrame(bool validate = true) const { return false; }
-  bool IsStubFrame() const { return false; }
+  bool IsValid(bool needed_for_gc = false) const { return sp() == 0; }
+  bool IsDartFrame(bool validate = true, bool needed_for_gc = false) const {
+    return false;
+  }
+  bool IsStubFrame(bool needed_for_gc = false) const { return false; }
   bool IsExitFrame() const { return true; }
 
   // Visit objects in the frame.
@@ -221,11 +224,13 @@
 // dart code.
 class EntryFrame : public StackFrame {
  public:
-  bool IsValid() const {
+  bool IsValid(bool needed_for_gc = false) const {
     return StubCode::InInvocationStub(pc(), is_interpreted());
   }
-  bool IsDartFrame(bool validate = true) const { return false; }
-  bool IsStubFrame() const { return false; }
+  bool IsDartFrame(bool validate = true, bool needed_for_gc = false) const {
+    return false;
+  }
+  bool IsStubFrame(bool needed_for_gc = false) const { return false; }
   bool IsEntryFrame() const { return true; }
 
   // Visit objects in the frame.
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 52de00b..c69446c 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -558,6 +558,7 @@
 }
 
 void Thread::StoreBufferAddObject(RawObject* obj) {
+  ASSERT(this == Thread::Current());
   store_buffer_block_->Push(obj);
   if (store_buffer_block_->IsFull()) {
     StoreBufferBlockProcess(StoreBuffer::kCheckThreshold);
@@ -728,6 +729,108 @@
   }
 }
 
+class RestoreWriteBarrierInvariantVisitor : public ObjectPointerVisitor {
+ public:
+  RestoreWriteBarrierInvariantVisitor(IsolateGroup* group,
+                                      Thread* thread,
+                                      Thread::RestoreWriteBarrierInvariantOp op)
+      : ObjectPointerVisitor(group),
+        thread_(thread),
+        current_(Thread::Current()),
+        op_(op) {}
+
+  void VisitPointers(RawObject** first, RawObject** last) {
+    for (; first != last + 1; first++) {
+      RawObject* obj = *first;
+      // Stores into new-space objects don't need a write barrier.
+      if (obj->IsSmiOrNewObject()) continue;
+
+      // To avoid adding too much work into the remembered set, skip
+      // arrays. Write barrier elimination will not remove the barrier
+      // if we can trigger GC between array allocation and store.
+      if (obj->GetClassId() == kArrayCid) continue;
+
+      // Dart code won't store into VM-internal objects except Contexts.
+      // This assumption is checked by an assertion in
+      // WriteBarrierElimination::UpdateVectorForBlock.
+      if (!obj->IsDartInstance() && !obj->IsContext()) continue;
+
+      // Dart code won't store into canonical instances.
+      if (obj->IsCanonical()) continue;
+
+      // Objects in the VM isolate heap are immutable and won't be
+      // stored into. Check this condition last because there's no bit
+      // in the header for it.
+      if (obj->InVMIsolateHeap()) continue;
+
+      switch (op_) {
+        case Thread::RestoreWriteBarrierInvariantOp::kAddToRememberedSet:
+          if (!obj->IsRemembered()) {
+            obj->AddToRememberedSet(current_);
+          }
+          if (current_->is_marking()) {
+            current_->DeferredMarkingStackAddObject(obj);
+          }
+          break;
+        case Thread::RestoreWriteBarrierInvariantOp::kAddToDeferredMarkingStack:
+          // Re-scan obj when finalizing marking.
+          current_->DeferredMarkingStackAddObject(obj);
+          break;
+      }
+    }
+  }
+
+ private:
+  Thread* const thread_;
+  Thread* const current_;
+  Thread::RestoreWriteBarrierInvariantOp op_;
+};
+
+// Write barrier elimination assumes that all live temporaries will be
+// in the remembered set after a scavenge triggered by a non-Dart-call
+// instruction (see Instruction::CanCallDart()), and additionally they will be
+// in the deferred marking stack if concurrent marking started. Specifically,
+// this includes any instruction which will always create an exit frame
+// below the current frame before any other Dart frames.
+//
+// Therefore, to support this assumption, we scan the stack after a scavenge
+// or when concurrent marking begins and add all live temporaries in
+// Dart frames preceeding an exit frame to the store buffer or deferred
+// marking stack.
+void Thread::RestoreWriteBarrierInvariant(RestoreWriteBarrierInvariantOp op) {
+  ASSERT(IsAtSafepoint());
+  ASSERT(IsMutatorThread());
+
+  const StackFrameIterator::CrossThreadPolicy cross_thread_policy =
+      StackFrameIterator::kAllowCrossThreadIteration;
+  StackFrameIterator frames_iterator(top_exit_frame_info(),
+                                     ValidationPolicy::kDontValidateFrames,
+                                     this, cross_thread_policy);
+  RestoreWriteBarrierInvariantVisitor visitor(isolate_group(), this, op);
+  bool scan_next_dart_frame = false;
+  for (StackFrame* frame = frames_iterator.NextFrame(); frame != NULL;
+       frame = frames_iterator.NextFrame()) {
+    if (frame->IsExitFrame()) {
+      scan_next_dart_frame = true;
+    } else if (frame->IsDartFrame(/*validate=*/false, /*needed_for_gc=*/true)) {
+      if (scan_next_dart_frame) {
+        frame->VisitObjectPointers(&visitor);
+      }
+      scan_next_dart_frame = false;
+    }
+  }
+}
+
+void Thread::DeferredMarkLiveTemporaries() {
+  RestoreWriteBarrierInvariant(
+      RestoreWriteBarrierInvariantOp::kAddToDeferredMarkingStack);
+}
+
+void Thread::RememberLiveTemporaries() {
+  RestoreWriteBarrierInvariant(
+      RestoreWriteBarrierInvariantOp::kAddToRememberedSet);
+}
+
 bool Thread::CanLoadFromThread(const Object& object) {
   // In order to allow us to use assembler helper routines with non-[Code]
   // objects *before* stubs are initialized, we only loop ver the stubs if the
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index cf563c4..78b610e 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -826,6 +826,8 @@
   // Visit all object pointers.
   void VisitObjectPointers(ObjectPointerVisitor* visitor,
                            ValidationPolicy validate_frames);
+  void RememberLiveTemporaries();
+  void DeferredMarkLiveTemporaries();
 
   bool IsValidHandle(Dart_Handle object) const;
   bool IsValidLocalHandle(Dart_Handle object) const;
@@ -856,6 +858,13 @@
   template <class T>
   T* AllocateReusableHandle();
 
+  enum class RestoreWriteBarrierInvariantOp {
+    kAddToRememberedSet,
+    kAddToDeferredMarkingStack
+  };
+  friend class RestoreWriteBarrierInvariantVisitor;
+  void RestoreWriteBarrierInvariant(RestoreWriteBarrierInvariantOp op);
+
   // Set the current compiler state and return the previous compiler state.
   CompilerState* SetCompilerState(CompilerState* state) {
     CompilerState* previous = compiler_state_;
diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc
index a7becbe..6f57f4fc 100644
--- a/runtime/vm/thread_interrupter.cc
+++ b/runtime/vm/thread_interrupter.cc
@@ -48,6 +48,11 @@
 Monitor* ThreadInterrupter::monitor_ = NULL;
 intptr_t ThreadInterrupter::interrupt_period_ = 1000;
 intptr_t ThreadInterrupter::current_wait_time_ = Monitor::kNoTimeout;
+// Note this initial state means there is one sample buffer reader. This
+// allows the EnterSampleReader during Cleanup (needed to ensure the buffer can
+// be safely freed) to be balanced by a ExitSampleReader during Init.
+std::atomic<intptr_t> ThreadInterrupter::sample_buffer_lock_ = {-1};
+std::atomic<intptr_t> ThreadInterrupter::sample_buffer_waiters_ = {1};
 
 void ThreadInterrupter::Init() {
   ASSERT(!initialized_);
@@ -85,6 +90,8 @@
   if (FLAG_trace_thread_interrupter) {
     OS::PrintErr("ThreadInterrupter running.\n");
   }
+
+  ExitSampleReader();
 }
 
 void ThreadInterrupter::Cleanup() {
@@ -112,6 +119,9 @@
   if (FLAG_trace_thread_interrupter) {
     OS::PrintErr("ThreadInterrupter shut down.\n");
   }
+
+  // Wait for outstanding signals.
+  EnterSampleReader();
 }
 
 // Delay between interrupts.
@@ -130,13 +140,16 @@
 }
 
 void ThreadInterrupter::WakeUp() {
-  if (!initialized_) {
+  if (monitor_ == NULL) {
     // Early call.
     return;
   }
-  ASSERT(initialized_);
   {
     MonitorLocker ml(monitor_);
+    if (!initialized_) {
+      // Early call.
+      return;
+    }
     woken_up_ = true;
     if (!InDeepSleep()) {
       // No need to notify, regularly waking up.
diff --git a/runtime/vm/thread_interrupter.h b/runtime/vm/thread_interrupter.h
index 11c6584..65706da 100644
--- a/runtime/vm/thread_interrupter.h
+++ b/runtime/vm/thread_interrupter.h
@@ -36,6 +36,52 @@
   // Interrupt a thread.
   static void InterruptThread(OSThread* thread);
 
+  class SampleBufferWriterScope : public ValueObject {
+   public:
+    SampleBufferWriterScope() {
+      intptr_t old_value = sample_buffer_lock_.load(std::memory_order_relaxed);
+      intptr_t new_value;
+      do {
+        if (old_value < 0) {
+          entered_lock_ = false;
+          return;
+        }
+        new_value = old_value + 1;
+      } while (!sample_buffer_lock_.compare_exchange_weak(
+          old_value, new_value, std::memory_order_relaxed));
+      entered_lock_ = true;
+    }
+
+    ~SampleBufferWriterScope() {
+      if (!entered_lock_) return;
+      intptr_t old_value = sample_buffer_lock_.load(std::memory_order_relaxed);
+      intptr_t new_value;
+      do {
+        ASSERT(old_value > 0);
+        new_value = old_value - 1;
+      } while (!sample_buffer_lock_.compare_exchange_weak(
+          old_value, new_value, std::memory_order_release));
+    }
+
+    bool CanSample() const {
+      return entered_lock_ &&
+             sample_buffer_waiters_.load(std::memory_order_relaxed) == 0;
+    }
+
+   private:
+    bool entered_lock_;
+    DISALLOW_COPY_AND_ASSIGN(SampleBufferWriterScope);
+  };
+
+  class SampleBufferReaderScope : public ValueObject {
+   public:
+    SampleBufferReaderScope() { EnterSampleReader(); }
+    ~SampleBufferReaderScope() { ExitSampleReader(); }
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(SampleBufferReaderScope);
+  };
+
  private:
   static const intptr_t kMaxThreads = 4096;
   static bool initialized_;
@@ -47,6 +93,15 @@
   static intptr_t interrupt_period_;
   static intptr_t current_wait_time_;
 
+  // Something like a reader-writer lock. Positive values indictate there are
+  // outstanding signal handlers that can write to the sample buffer. Negative
+  // values indicate there are outstanding sample buffer processors that can
+  // read from the sample buffer. A reader will spin-wait to enter the lock. A
+  // writer will give up if it fails to enter lock, causing samples to be
+  // skipping while we are processing the sample buffer or trying to shut down.
+  static std::atomic<intptr_t> sample_buffer_lock_;
+  static std::atomic<intptr_t> sample_buffer_waiters_;
+
   static bool IsDebuggerAttached();
 
   static bool InDeepSleep() {
@@ -59,6 +114,33 @@
 
   static void RemoveSignalHandler();
 
+  static void EnterSampleReader() {
+    sample_buffer_waiters_.fetch_add(1, std::memory_order_relaxed);
+
+    intptr_t old_value = sample_buffer_lock_.load(std::memory_order_relaxed);
+    intptr_t new_value;
+    do {
+      if (old_value > 0) {
+        old_value = sample_buffer_lock_.load(std::memory_order_relaxed);
+        continue;  // Spin waiting for outstanding SIGPROFs to complete.
+      }
+      new_value = old_value - 1;
+    } while (!sample_buffer_lock_.compare_exchange_weak(
+        old_value, new_value, std::memory_order_acquire));
+  }
+
+  static void ExitSampleReader() {
+    sample_buffer_waiters_.fetch_sub(1, std::memory_order_relaxed);
+
+    intptr_t old_value = sample_buffer_lock_.load(std::memory_order_relaxed);
+    intptr_t new_value;
+    do {
+      ASSERT(old_value < 0);
+      new_value = old_value + 1;
+    } while (!sample_buffer_lock_.compare_exchange_weak(
+        old_value, new_value, std::memory_order_relaxed));
+  }
+
   friend class ThreadInterrupterVisitIsolates;
 };
 
diff --git a/runtime/vm/thread_interrupter_android.cc b/runtime/vm/thread_interrupter_android.cc
index 92a21f5..87eb5fc 100644
--- a/runtime/vm/thread_interrupter_android.cc
+++ b/runtime/vm/thread_interrupter_android.cc
@@ -32,6 +32,10 @@
     if (thread == NULL) {
       return;
     }
+    ThreadInterrupter::SampleBufferWriterScope scope;
+    if (!scope.CanSample()) {
+      return;
+    }
     // Extract thread state.
     ucontext_t* context = reinterpret_cast<ucontext_t*>(context_);
     mcontext_t mcontext = context->uc_mcontext;
diff --git a/runtime/vm/thread_interrupter_linux.cc b/runtime/vm/thread_interrupter_linux.cc
index dc2bfd0..04b0686 100644
--- a/runtime/vm/thread_interrupter_linux.cc
+++ b/runtime/vm/thread_interrupter_linux.cc
@@ -31,6 +31,10 @@
     if (thread == NULL) {
       return;
     }
+    ThreadInterrupter::SampleBufferWriterScope scope;
+    if (!scope.CanSample()) {
+      return;
+    }
     // Extract thread state.
     ucontext_t* context = reinterpret_cast<ucontext_t*>(context_);
     mcontext_t mcontext = context->uc_mcontext;
diff --git a/runtime/vm/thread_interrupter_macos.cc b/runtime/vm/thread_interrupter_macos.cc
index 9ea36b4..eb89fe7 100644
--- a/runtime/vm/thread_interrupter_macos.cc
+++ b/runtime/vm/thread_interrupter_macos.cc
@@ -57,6 +57,10 @@
     if (thread == NULL) {
       return;
     }
+    ThreadInterrupter::SampleBufferWriterScope scope;
+    if (!scope.CanSample()) {
+      return;
+    }
     // Extract thread state.
     ucontext_t* context = reinterpret_cast<ucontext_t*>(context_);
     mcontext_t mcontext = context->uc_mcontext;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
index a6edb37..d14d9ed 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
@@ -705,7 +705,7 @@
 abstract class JavaScriptIndexingBehavior<E> {}
 
 /// Thrown by type assertions that fail.
-class TypeErrorImpl extends Error implements TypeError {
+class TypeErrorImpl extends Error implements TypeError, CastError {
   final String _message;
 
   TypeErrorImpl(this._message);
@@ -714,7 +714,7 @@
 }
 
 /// Thrown by the 'as' operator if the cast isn't valid.
-class CastErrorImpl extends Error implements CastError {
+class CastErrorImpl extends Error implements CastError, TypeError {
   final String _message;
 
   CastErrorImpl(this._message);
diff --git a/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
index 0a02d3f..0a79d98 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
@@ -203,7 +203,7 @@
   }
 
   String namedGroup(String name) {
-    var groups = JS('Object', '#.groups', _match);
+    var groups = JS('Object|Null', '#.groups', _match);
     if (groups != null) {
       var result = JS('String|Null', '#[#]', groups, name);
       if (result != null || JS<bool>('!', '# in #', name, groups)) {
@@ -214,7 +214,7 @@
   }
 
   Iterable<String> get groupNames {
-    var groups = JS('Object', '#.groups', _match);
+    var groups = JS('Object|Null', '#.groups', _match);
     if (groups != null) {
       var keys = JSArray<String>.of(JS('', 'Object.keys(#)', groups));
       return SubListIterable(keys, 0, null);
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 113d7c9..296c213 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -3089,7 +3089,7 @@
 abstract class JavaScriptIndexingBehavior<E> extends JSMutableIndexable<E> {}
 
 /// Thrown by type assertions that fail.
-class TypeErrorImplementation extends Error implements TypeError {
+class TypeErrorImplementation extends Error implements TypeError, CastError {
   final String _message;
 
   /// Normal type error caused by a failed subtype test.
@@ -3103,12 +3103,12 @@
 }
 
 /// Thrown by the 'as' operator if the cast isn't valid.
-class CastErrorImplementation extends Error implements CastError {
+class CastErrorImplementation extends Error implements CastError, TypeError {
   final String _message;
 
   /// Normal cast error caused by a failed type cast.
   CastErrorImplementation(Object value, Object type)
-      : _message = "CastError: ${Error.safeToString(value)}: type "
+      : _message = "TypeError: ${Error.safeToString(value)}: type "
             "'${_typeDescription(value)}' is not a subtype of type '$type'";
 
   String toString() => _message;
diff --git a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
index 576caaa..dc59c10 100644
--- a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
@@ -212,7 +212,7 @@
   }
 
   String namedGroup(String name) {
-    var groups = JS('Object', '#.groups', _match);
+    var groups = JS('Object|Null', '#.groups', _match);
     if (groups != null) {
       var result = JS('String|Null', '#[#]', groups, name);
       if (result != null || JS('bool', '# in #', name, groups)) {
@@ -223,7 +223,7 @@
   }
 
   Iterable<String> get groupNames {
-    var groups = JS('Object', '#.groups', _match);
+    var groups = JS('Object|Null', '#.groups', _match);
     if (groups != null) {
       var keys = new JSArray<String>.markGrowable(
           JS('returns:JSExtendableArray;new:true', 'Object.keys(#)', groups));
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index 3676147..1adc744 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -960,15 +960,15 @@
   String toString() => _message;
 }
 
-class _CastError extends _Error implements CastError {
-  _CastError.fromMessage(String message) : super('CastError: $message');
+class _CastError extends _Error implements CastError, TypeError {
+  _CastError.fromMessage(String message) : super('TypeError: $message');
 
   factory _CastError.forType(object, String type) {
     return _CastError.fromMessage(_Error.compose(object, null, type));
   }
 }
 
-class _TypeError extends _Error implements TypeError {
+class _TypeError extends _Error implements TypeError, CastError {
   _TypeError.fromMessage(String message) : super('TypeError: $message');
 
   factory _TypeError.forType(object, String type) {
@@ -1154,7 +1154,8 @@
       typeParametersText += typeSep;
       typeParametersText += genericContext[genericContext.length - 1 - i];
       Rti boundRti = _castToRti(_Utils.arrayAt(bounds, i));
-      if (!isTopType(boundRti)) {
+      if (!isTopType(boundRti) &&
+          (!JS_GET_FLAG('LEGACY') || !isObjectType(boundRti))) {
         typeParametersText +=
             ' extends ' + _rtiToString(boundRti, genericContext);
       }
diff --git a/sdk/lib/_internal/vm/lib/errors_patch.dart b/sdk/lib/_internal/vm/lib/errors_patch.dart
index 9457152..c96e920 100644
--- a/sdk/lib/_internal/vm/lib/errors_patch.dart
+++ b/sdk/lib/_internal/vm/lib/errors_patch.dart
@@ -82,7 +82,7 @@
   final Object message;
 }
 
-class _TypeError extends Error implements TypeError {
+class _TypeError extends Error implements TypeError, CastError {
   @pragma("vm:entry-point")
   _TypeError._create(this._url, this._line, this._column, this._message);
 
@@ -97,7 +97,7 @@
   final Object _message;
 }
 
-class _CastError extends Error implements CastError {
+class _CastError extends Error implements CastError, TypeError {
   @pragma("vm:entry-point")
   _CastError._create(this._url, this._line, this._column, this._errorMsg);
 
diff --git a/sdk/lib/_internal/vm/lib/regexp_patch.dart b/sdk/lib/_internal/vm/lib/regexp_patch.dart
index dd04e8d..d4c875e 100644
--- a/sdk/lib/_internal/vm/lib/regexp_patch.dart
+++ b/sdk/lib/_internal/vm/lib/regexp_patch.dart
@@ -274,13 +274,18 @@
 
   int get _groupCount native "RegExp_getGroupCount";
 
-  // Returns a List [String, int, String, int, ...] where each
-  // String is the name of a capture group and the following
-  // int is that capture group's index.
+  /// The names and indices of named capture group.
+  ///
+  /// Returns a [List] of alternating strings and integers,
+  /// `[String, int, String, int, ...]` where each
+  /// [String] is the name of a capture group and the following
+  /// [int] is that capture group's index.
+  /// Returns `null` if there are no group names.
   List get _groupNameList native "RegExp_getGroupNameMap";
 
   Iterable<String> get _groupNames sync* {
     final nameList = _groupNameList;
+    if (nameList == null) return;
     for (var i = 0; i < nameList.length; i += 2) {
       yield nameList[i] as String;
     }
@@ -288,9 +293,10 @@
 
   int _groupNameIndex(String name) {
     var nameList = _groupNameList;
+    if (nameList == null) return -1;
     for (var i = 0; i < nameList.length; i += 2) {
       if (name == nameList[i]) {
-        return nameList[i + 1];
+        return nameList[i + 1] as int;
       }
     }
     return -1;
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index 5a8deb8..dc3718a 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -670,9 +670,10 @@
   return 0x10000 + ((start & 0x3FF) << 10) + (end & 0x3FF);
 }
 
-/** [Iterator] for reading runes (integer Unicode code points) out of a Dart
-  * string.
-  */
+/**
+ * [Iterator] for reading runes (integer Unicode code points) out of a Dart
+ * string.
+ */
 class RuneIterator implements BidirectionalIterator<int> {
   /** String being iterated. */
   final String string;
@@ -683,10 +684,10 @@
   /**
    * Current code point.
    *
-   * If the iterator has hit either end, the [_currentCodePoint] is null
+   * If the iterator has hit either end, the [_currentCodePoint] is -1
    * and [: _position == _nextPosition :].
    */
-  int _currentCodePoint;
+  int _currentCodePoint = -1;
 
   /** Create an iterator positioned at the beginning of the string. */
   RuneIterator(String string)
@@ -725,9 +726,9 @@
   /**
    * Returns the starting position of the current rune in the string.
    *
-   * Returns null if the [current] rune is null.
+   * Returns -1 if there is no current rune ([current] is -1).
    */
-  int get rawIndex => (_position != _nextPosition) ? _position : null;
+  int get rawIndex => (_position != _nextPosition) ? _position : -1;
 
   /**
    * Resets the iterator to the rune at the specified index of the string.
@@ -758,18 +759,21 @@
     RangeError.checkValueInInterval(rawIndex, 0, string.length, "rawIndex");
     _checkSplitSurrogate(rawIndex);
     _position = _nextPosition = rawIndex;
-    _currentCodePoint = null;
+    _currentCodePoint = -1;
   }
 
-  /** The rune (integer Unicode code point) starting at the current position in
-   *  the string.
+  /**
+   * The rune (integer Unicode code point) starting at the current position in
+   * the string.
+   *
+   * If there is no current rune, the value -1 is used instead.
    */
   int get current => _currentCodePoint;
 
   /**
    * The number of code units comprising the current rune.
    *
-   * Returns zero if there is no current rune ([current] is null).
+   * Returns zero if there is no current rune ([current] is -1).
    */
   int get currentSize => _nextPosition - _position;
 
@@ -777,12 +781,12 @@
    * A string containing the current rune.
    *
    * For runes outside the basic multilingual plane, this will be
-   * a String of length 2, containing two code units.
+   * a [String] of length 2, containing two code units.
    *
-   * Returns null if [current] is null.
+   * Returns an empty string if there is no current rune ([current] is -1).
    */
   String get currentAsString {
-    if (_position == _nextPosition) return null;
+    if (_position == _nextPosition) return "";
     if (_position + 1 == _nextPosition) return string[_position];
     return string.substring(_position, _nextPosition);
   }
@@ -790,7 +794,7 @@
   bool moveNext() {
     _position = _nextPosition;
     if (_position == string.length) {
-      _currentCodePoint = null;
+      _currentCodePoint = -1;
       return false;
     }
     int codeUnit = string.codeUnitAt(_position);
@@ -811,7 +815,7 @@
   bool movePrevious() {
     _nextPosition = _position;
     if (_position == 0) {
-      _currentCodePoint = null;
+      _currentCodePoint = -1;
       return false;
     }
     int position = _position - 1;
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 496ecba..3f45ca5 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -59,7 +59,9 @@
   static const _mode = 4;
   static const _size = 5;
 
-  static const _notFound = const FileStat._internalNotFound();
+  static final _epoch = DateTime.fromMillisecondsSinceEpoch(0, isUtc: true);
+  static final _notFound = new FileStat._internal(
+      _epoch, _epoch, _epoch, FileSystemEntityType.notFound, 0, -1);
 
   /**
    * The time of the last change to the data or metadata of the file system
@@ -105,14 +107,6 @@
   FileStat._internal(this.changed, this.modified, this.accessed, this.type,
       this.mode, this.size);
 
-  const FileStat._internalNotFound()
-      : changed = null,
-        modified = null,
-        accessed = null,
-        type = FileSystemEntityType.notFound,
-        mode = 0,
-        size = -1;
-
   external static _statSync(_Namespace namespace, String path);
 
   /**
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
index 39944a0..48d41f9 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
@@ -140,8 +140,10 @@
     // Normalize raw FutureOr --> dynamic
     if (JS<bool>('!', '# == void 0', typeArg)) return _dynamic;
 
-    // FutureOr<dynamic|void|Object?|Object*> --> dynamic|void|Object?|Object*
+    // FutureOr<dynamic|void|Object?|Object*|Object> -->
+    //   dynamic|void|Object?|Object*|Object
     if (_isTop(typeArg) ||
+        _equalType(typeArg, Object) ||
         (_jsInstanceOf(typeArg, LegacyType) &&
             JS<bool>('!', '#.type === #', typeArg, Object))) {
       return typeArg;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index 77affd3..d424a31 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -876,10 +876,14 @@
       if (i != 0) s += ", ";
       s += JS<String>('!', '#[#].name', typeFormals, i);
       var bound = typeBounds[i];
-      if (JS(
-          '!', '# !== # && # !== #', bound, dynamic, bound, nullable(Object))) {
-        s += " extends $bound";
+      if (_equalType(bound, dynamic) ||
+          JS<bool>('!', '# === #', bound, nullable(unwrapType(Object))) ||
+          (!_strictSubtypeChecks && _equalType(bound, Object))) {
+        // Do not print the bound when it is a top type. In weak mode the bounds
+        // of Object and Object* will also be elided.
+        continue;
       }
+      s += " extends $bound";
     }
     s += ">" + this.function.toString();
     return this._stringValue = s;
@@ -924,10 +928,11 @@
 
   List instantiateTypeBounds(List typeArgs) {
     if (!hasTypeBounds) {
-      // The Dart 1 spec says omitted type parameters have an upper bound of
-      // Object. However Dart 2 uses `dynamic` for the purpose of instantiate to
-      // bounds, so we use that here.
-      return List.filled(formalCount, _dynamic);
+      // We ommit the a bound to represent Object*. Other bounds are explicitly
+      // represented, including Object, Object? and dynamic.
+      // TODO(nshahan) Revisit this representation when more libraries have
+      // migrated to null safety.
+      return List.filled(formalCount, legacy(unwrapType(Object)));
     }
     // Bounds can be recursive or depend on other type parameters, so we need to
     // apply type arguments and return the resulting bounds.
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
index d084aeb..6218ba6 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
@@ -705,7 +705,7 @@
 abstract class JavaScriptIndexingBehavior<E> {}
 
 /// Thrown by type assertions that fail.
-class TypeErrorImpl extends Error implements TypeError {
+class TypeErrorImpl extends Error implements TypeError, CastError {
   final String _message;
 
   TypeErrorImpl(this._message);
@@ -714,7 +714,7 @@
 }
 
 /// Thrown by the 'as' operator if the cast isn't valid.
-class CastErrorImpl extends Error implements CastError {
+class CastErrorImpl extends Error implements CastError, TypeError {
   final String _message;
 
   CastErrorImpl(this._message);
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/regexp_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/regexp_helper.dart
index 8730c1c..6ce53ac 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/regexp_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/regexp_helper.dart
@@ -204,7 +204,7 @@
   }
 
   String? namedGroup(String name) {
-    var groups = JS<Object?>('', '#.groups', _match);
+    var groups = JS<Object?>('Object|Null', '#.groups', _match);
     if (groups != null) {
       var result = JS<String?>('', '#[#]', groups, name);
       if (result != null || JS<bool>('!', '# in #', name, groups)) {
@@ -215,7 +215,7 @@
   }
 
   Iterable<String> get groupNames {
-    var groups = JS<Object?>('', '#.groups', _match);
+    var groups = JS<Object?>('Object|Null', '#.groups', _match);
     if (groups != null) {
       var keys = JSArray<String>.of(JS('', 'Object.keys(#)', groups));
       return SubListIterable(keys, 0, null);
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
index 8c81b95..bd293d6 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
@@ -3088,7 +3088,7 @@
 abstract class JavaScriptIndexingBehavior<E> extends JSMutableIndexable<E> {}
 
 /// Thrown by type assertions that fail.
-class TypeErrorImplementation extends Error implements TypeError {
+class TypeErrorImplementation extends Error implements TypeError, CastError {
   final String _message;
 
   /// Normal type error caused by a failed subtype test.
@@ -3102,12 +3102,12 @@
 }
 
 /// Thrown by the 'as' operator if the cast isn't valid.
-class CastErrorImplementation extends Error implements CastError {
+class CastErrorImplementation extends Error implements CastError, TypeError {
   final String _message;
 
   /// Normal cast error caused by a failed type cast.
   CastErrorImplementation(Object value, Object type)
-      : _message = "CastError: ${Error.safeToString(value)}: type "
+      : _message = "TypeError: ${Error.safeToString(value)}: type "
             "'${_typeDescription(value)}' is not a subtype of type '$type'";
 
   String toString() => _message;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/regexp_helper.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/regexp_helper.dart
index 9560250..8eaad60 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/regexp_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/regexp_helper.dart
@@ -209,7 +209,7 @@
   }
 
   String namedGroup(String name) {
-    var groups = JS('Object', '#.groups', _match);
+    var groups = JS('Object|Null', '#.groups', _match);
     if (groups != null) {
       var result = JS('String|Null', '#[#]', groups, name);
       if (result != null || JS('bool', '# in #', name, groups)) {
@@ -220,7 +220,7 @@
   }
 
   Iterable<String> get groupNames {
-    var groups = JS('Object', '#.groups', _match);
+    var groups = JS('Object|Null', '#.groups', _match);
     if (groups != null) {
       var keys = new JSArray<String>.markGrowable(
           JS('returns:JSExtendableArray;new:true', 'Object.keys(#)', groups));
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
index ddbade4..838643b 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
@@ -960,15 +960,15 @@
   String toString() => _message;
 }
 
-class _CastError extends _Error implements CastError {
-  _CastError.fromMessage(String message) : super('CastError: $message');
+class _CastError extends _Error implements CastError, TypeError {
+  _CastError.fromMessage(String message) : super('TypeError: $message');
 
   factory _CastError.forType(object, String type) {
     return _CastError.fromMessage(_Error.compose(object, null, type));
   }
 }
 
-class _TypeError extends _Error implements TypeError {
+class _TypeError extends _Error implements TypeError, CastError {
   _TypeError.fromMessage(String message) : super('TypeError: $message');
 
   factory _TypeError.forType(object, String type) {
@@ -1154,7 +1154,8 @@
       typeParametersText += typeSep;
       typeParametersText += genericContext[genericContext.length - 1 - i];
       Rti boundRti = _castToRti(_Utils.arrayAt(bounds, i));
-      if (!isTopType(boundRti)) {
+      if (!isTopType(boundRti) &&
+          (!JS_GET_FLAG('LEGACY') || !isObjectType(boundRti))) {
         typeParametersText +=
             ' extends ' + _rtiToString(boundRti, genericContext);
       }
diff --git a/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
index 070a146..8b5638d 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
@@ -1016,7 +1016,7 @@
               isInternal ||
               isInternalSignal);
           if (resourceInformation != null) {
-            _SocketResourceInfo.SocketClosed(resourceInformation!);
+            _SocketResourceInfo.SocketClosed(resourceInformation);
           }
           isClosed = true;
           closeCompleter.complete();
diff --git a/sdk_nnbd/lib/_internal/vm/lib/double_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/double_patch.dart
index 0c706ce..e6ccf5c 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/double_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/double_patch.dart
@@ -8,7 +8,7 @@
 
 @patch
 class double {
-  static double _nativeParse(String str, int start, int end)
+  static double? _nativeParse(String str, int start, int end)
       native "Double_parse";
 
   static double? _tryParseDouble(String str, int start, int end) {
diff --git a/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
index c9dd54d..12960b5 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
@@ -81,7 +81,7 @@
   final Object? message;
 }
 
-class _TypeError extends Error implements TypeError {
+class _TypeError extends Error implements TypeError, CastError {
   @pragma("vm:entry-point")
   _TypeError._create(this._url, this._line, this._column, this._message);
 
@@ -96,7 +96,7 @@
   final String _message;
 }
 
-class _CastError extends Error implements CastError {
+class _CastError extends Error implements CastError, TypeError {
   @pragma("vm:entry-point")
   _CastError._create(this._url, this._line, this._column, this._errorMsg);
 
@@ -276,7 +276,7 @@
                 ? _NamedArgumentsMap(arguments, argumentNames)
                 : null);
 
-  static String _existingMethodSignature(Object receiver, String methodName,
+  static String? _existingMethodSignature(Object receiver, String methodName,
       int invocationType) native "NoSuchMethodError_existingMethodSignature";
 
   @patch
@@ -336,7 +336,7 @@
         argumentCount++;
       });
     }
-    String existingSig =
+    String? existingSig =
         _existingMethodSignature(_receiver, memberName, localInvocation._type);
     String argsMsg = existingSig != null ? " with matching arguments" : "";
 
diff --git a/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
index 3aa7694..7379f0c 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
@@ -145,7 +145,7 @@
     return result;
   }
 
-  static LibraryMirror _loadUri(String uri) native "IsolateMirror_loadUri";
+  static LibraryMirror? _loadUri(String uri) native "IsolateMirror_loadUri";
 }
 
 class _SyntheticAccessor implements MethodMirror {
@@ -443,7 +443,7 @@
   _ClassMirror? _trueSuperclassField;
   _ClassMirror? get _trueSuperclass {
     if (_trueSuperclassField == null) {
-      Type supertype = isOriginalDeclaration
+      Type? supertype = isOriginalDeclaration
           ? _supertype(_reflectedType)
           : _supertypeInstantiated(_reflectedType);
       if (supertype == null) {
@@ -497,7 +497,7 @@
     var m = _mixin;
     if (m != null) return m;
 
-    Type mixinType = _nativeMixinInstantiated(_reflectedType, _instantiator);
+    Type? mixinType = _nativeMixinInstantiated(_reflectedType, _instantiator);
     if (mixinType == null) {
       // The reflectee is not a mixin application.
       return _mixin = this;
@@ -714,9 +714,9 @@
 
   static String _libraryUri(reflectee) native "ClassMirror_libraryUri";
 
-  static Type _supertype(reflectedType) native "ClassMirror_supertype";
+  static Type? _supertype(reflectedType) native "ClassMirror_supertype";
 
-  static Type _supertypeInstantiated(reflectedType)
+  static Type? _supertypeInstantiated(reflectedType)
       native "ClassMirror_supertype_instantiated";
 
   static List<dynamic> _nativeInterfaces(reflectedType)
@@ -725,9 +725,9 @@
   static List<dynamic> _nativeInterfacesInstantiated(reflectedType)
       native "ClassMirror_interfaces_instantiated";
 
-  static Type _nativeMixin(reflectedType) native "ClassMirror_mixin";
+  static Type? _nativeMixin(reflectedType) native "ClassMirror_mixin";
 
-  static Type _nativeMixinInstantiated(reflectedType, instantiator)
+  static Type? _nativeMixinInstantiated(reflectedType, instantiator)
       native "ClassMirror_mixin_instantiated";
 
   static List<dynamic> _computeMembers(owner, reflectee, instantiator)
diff --git a/sdk_nnbd/lib/_internal/vm/lib/regexp_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/regexp_patch.dart
index a2390a4..7a57583 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/regexp_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/regexp_patch.dart
@@ -277,13 +277,18 @@
 
   int get _groupCount native "RegExp_getGroupCount";
 
-  // Returns a List [String, int, String, int, ...] where each
-  // String is the name of a capture group and the following
-  // int is that capture group's index.
-  List get _groupNameList native "RegExp_getGroupNameMap";
+  /// The names and indices of named capture group.
+  ///
+  /// Returns a [List] of alternating strings and integers,
+  /// `[String, int, String, int, ...]` where each
+  /// [String] is the name of a capture group and the following
+  /// [int] is that capture group's index.
+  /// Returns `null` if there are no group names.
+  List? get _groupNameList native "RegExp_getGroupNameMap";
 
   Iterable<String> get _groupNames sync* {
     final nameList = _groupNameList;
+    if (nameList == null) return;
     for (var i = 0; i < nameList.length; i += 2) {
       yield nameList[i] as String;
     }
@@ -291,9 +296,10 @@
 
   int _groupNameIndex(String name) {
     var nameList = _groupNameList;
+    if (nameList == null) return -1;
     for (var i = 0; i < nameList.length; i += 2) {
       if (name == nameList[i]) {
-        return nameList[i + 1];
+        return nameList[i + 1] as int;
       }
     }
     return -1;
diff --git a/sdk_nnbd/lib/core/string.dart b/sdk_nnbd/lib/core/string.dart
index 95f27b6..e65f8e9 100644
--- a/sdk_nnbd/lib/core/string.dart
+++ b/sdk_nnbd/lib/core/string.dart
@@ -299,7 +299,8 @@
    *
    *     string.lastIndexOf(new RegExp(r'DART'));    // -1
    *
-   * The [start] must be non-negative and not greater than [length].
+   * If [start] is omitted, search starts from the end of the string.
+   * If supplied, [start] must be non-negative and not greater than [length].
    */
   int lastIndexOf(Pattern pattern, [int? start]);
 
@@ -607,7 +608,7 @@
 
   /**
    * Converts all characters in this string to lower case.
-   * If the string is already in all lower case, this method returns [:this:].
+   * If the string is already in all lower case, this method returns `this`.
    *
    *     'ALPHABET'.toLowerCase(); // 'alphabet'
    *     'abc'.toLowerCase();      // 'abc'
@@ -620,7 +621,7 @@
 
   /**
    * Converts all characters in this string to upper case.
-   * If the string is already in all upper case, this method returns [:this:].
+   * If the string is already in all upper case, this method returns `this`.
    *
    *     'alphabet'.toUpperCase(); // 'ALPHABET'
    *     'ABC'.toUpperCase();      // 'ABC'
@@ -682,7 +683,7 @@
    * Current code point.
    *
    * If the iterator has hit either end, the [_currentCodePoint] is -1
-   * and [: _position == _nextPosition :].
+   * and `_position == _nextPosition`.
    */
   int _currentCodePoint = -1;
 
@@ -721,9 +722,9 @@
   }
 
   /**
-   * Returns the starting position of the current rune in the string.
+   * The starting position of the current rune in the string.
    *
-   * Returns -1 if the [current] rune is `null`.
+   * Returns -1 if there is no current rune ([current] is -1).
    */
   int get rawIndex => (_position != _nextPosition) ? _position : -1;
 
@@ -734,8 +735,8 @@
    * `string.length`, is an error. So is setting it in the middle of a surrogate
    *  pair.
    *
-   * Setting the position to the end of then string will set [current] to
-   * `null`.
+   * Setting the position to the end of then string means that there is no
+   * current rune.
    */
   void set rawIndex(int rawIndex) {
     RangeError.checkValidIndex(rawIndex, string, "rawIndex");
@@ -750,8 +751,9 @@
    * You must call [moveNext] make the rune at the position current,
    * or [movePrevious] for the last rune before the position.
    *
-   * Setting a negative [rawIndex], or one greater than [:string.length:],
-   * is an error. So is setting it in the middle of a surrogate pair.
+   * The [rawIndex] must be non-negative and no greater than `string.length`.
+   * It must also not be the index of the trailing surrogate of a surrogate
+   * pair.
    */
   void reset([int rawIndex = 0]) {
     RangeError.checkValueInInterval(rawIndex, 0, string.length, "rawIndex");
@@ -771,7 +773,7 @@
   /**
    * The number of code units comprising the current rune.
    *
-   * Returns zero if there is no current rune ([current] is null).
+   * Returns zero if there is no current rune ([current] is -1).
    */
   int get currentSize => _nextPosition - _position;
 
diff --git a/tests/corelib/core_runtime_types_test.dart b/tests/corelib/core_runtime_types_test.dart
index 8ce8892..180dc08 100644
--- a/tests/corelib/core_runtime_types_test.dart
+++ b/tests/corelib/core_runtime_types_test.dart
@@ -51,7 +51,6 @@
         f,
         (exception) =>
             (exception is TypeError) ||
-            (exception is CastError) ||
             (exception is AssertionError) ||
             (exception is NoSuchMethodError) ||
             (exception is ArgumentError),
diff --git a/tests/corelib/map_of_test.dart b/tests/corelib/map_of_test.dart
index 5620072..62b137b 100644
--- a/tests/corelib/map_of_test.dart
+++ b/tests/corelib/map_of_test.dart
@@ -34,9 +34,7 @@
       ..[3] = 13,
   ]) {
     expectThrows(void operation()) {
-      // Allow CastError as well as TypeError. Dart2js creates a CastError
-      // here for some reason, and it's not wront.
-      Expect.throws(operation, (e) => e is TypeError || e is CastError);
+      Expect.throwsTypeError(operation);
     }
 
     var sourceType = map.runtimeType.toString();
diff --git a/tests/corelib/regexp/regexp_regression_39406_test.dart b/tests/corelib/regexp/regexp_regression_39406_test.dart
new file mode 100644
index 0000000..0104a07
--- /dev/null
+++ b/tests/corelib/regexp/regexp_regression_39406_test.dart
@@ -0,0 +1,18 @@
+// 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 "package:expect/expect.dart";
+
+// See http://dartbug.com/39406
+//
+// The following code must not throw.
+
+void main() {
+  var regExp = RegExp(r'\w+');
+  var message = 'Hello world!';
+  var match = regExp.firstMatch(message);
+  var groupNames = match!.groupNames.toList();
+  Expect.listEquals([], groupNames);
+  Expect.throwsArgumentError(() => match.namedGroup("x"));
+}
\ No newline at end of file
diff --git a/tests/corelib_2/core_runtime_types_test.dart b/tests/corelib_2/core_runtime_types_test.dart
index 7176feb..628bb22 100644
--- a/tests/corelib_2/core_runtime_types_test.dart
+++ b/tests/corelib_2/core_runtime_types_test.dart
@@ -51,7 +51,6 @@
         f,
         (exception) =>
             (exception is TypeError) ||
-            (exception is CastError) ||
             (exception is AssertionError) ||
             (exception is NoSuchMethodError) ||
             (exception is ArgumentError),
diff --git a/tests/corelib_2/map_of_test.dart b/tests/corelib_2/map_of_test.dart
index 4761b61..7d92ecc 100644
--- a/tests/corelib_2/map_of_test.dart
+++ b/tests/corelib_2/map_of_test.dart
@@ -34,9 +34,7 @@
       ..[3] = 13,
   ]) {
     expectThrows(void operation()) {
-      // Allow CastError as well as TypeError. Dart2js creates a CastError
-      // here for some reason, and it's not wront.
-      Expect.throws(operation, (e) => e is TypeError || e is CastError);
+      Expect.throwsTypeError(operation);
     }
 
     var sourceType = map.runtimeType.toString();
diff --git a/tests/corelib_2/regexp/regexp_regression_39406_test.dart b/tests/corelib_2/regexp/regexp_regression_39406_test.dart
new file mode 100644
index 0000000..64b4634
--- /dev/null
+++ b/tests/corelib_2/regexp/regexp_regression_39406_test.dart
@@ -0,0 +1,18 @@
+// 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 "package:expect/expect.dart";
+
+// See http://dartbug.com/39406
+//
+// The following code must not throw.
+
+void main() {
+  var regExp = RegExp(r'\w+');
+  var message = 'Hello world!';
+  var match = regExp.firstMatch(message);
+  var groupNames = match.groupNames.toList();
+  Expect.listEquals([], groupNames);
+  Expect.throwsArgumentError(() => match.namedGroup("x"));
+}
\ No newline at end of file
diff --git a/tests/corelib_2/string_runes_test.dart b/tests/corelib_2/string_runes_test.dart
index fd0f4f3..9e988b8 100644
--- a/tests/corelib_2/string_runes_test.dart
+++ b/tests/corelib_2/string_runes_test.dart
@@ -41,16 +41,16 @@
 
     // Reset, moveNext.
     it.reset(1);
-    Expect.equals(null, it.rawIndex);
-    Expect.equals(null, it.current);
+    Expect.equals(-1, it.rawIndex);
+    Expect.equals(-1, it.current);
     it.moveNext();
     Expect.equals(1, it.rawIndex);
     Expect.equals(expectedRunes[1], it.current);
 
     // Reset, movePrevious.
     it.reset(1);
-    Expect.equals(null, it.rawIndex);
-    Expect.equals(null, it.current);
+    Expect.equals(-1, it.rawIndex);
+    Expect.equals(-1, it.current);
     it.movePrevious();
     Expect.equals(0, it.rawIndex);
     Expect.equals(expectedRunes[0], it.current);
diff --git a/tests/language/call/method_as_cast_test.dart b/tests/language/call/method_as_cast_test.dart
index f0718a3..48ae3b7 100644
--- a/tests/language/call/method_as_cast_test.dart
+++ b/tests/language/call/method_as_cast_test.dart
@@ -23,13 +23,13 @@
   // The presence of a `.call` method does not cause class `C` to become a
   // subtype of any function type.
   C c = new C();
-  Expect.throwsCastError(() => c as BToB); //# 01: ok
-  Expect.throwsCastError(() => c as NullToObject); //# 02: ok
-  Expect.throwsCastError(() => c as Function); //# 03: ok
+  Expect.throwsTypeError(() => c as BToB); //# 01: ok
+  Expect.throwsTypeError(() => c as NullToObject); //# 02: ok
+  Expect.throwsTypeError(() => c as Function); //# 03: ok
 
   // The same goes for class `D`: `implements Function` is ignored in Dart 2.
   D d = new D();
-  Expect.throwsCastError(() => d as BToB); //# 04: ok
-  Expect.throwsCastError(() => d as NullToObject); //# 05: ok
-  Expect.throwsCastError(() => d as Function); //# 06: ok
+  Expect.throwsTypeError(() => d as BToB); //# 04: ok
+  Expect.throwsTypeError(() => d as NullToObject); //# 05: ok
+  Expect.throwsTypeError(() => d as Function); //# 06: ok
 }
diff --git a/tests/language/nnbd/operator_type_test.dart b/tests/language/nnbd/operator_type_test.dart
index 9a17555..2885ffd 100644
--- a/tests/language/nnbd/operator_type_test.dart
+++ b/tests/language/nnbd/operator_type_test.dart
@@ -311,7 +311,7 @@
 
   nn ?? 1;
 
-  nn ??= 1;
+  nn ??= maybeNotNullable<NN>(1);
 
   nn?.toRadixString(16);
 
diff --git a/tests/language/nnbd/subtyping/type_casts_strong_test.dart b/tests/language/nnbd/subtyping/type_casts_strong_test.dart
index c38b217..7c8ac23 100644
--- a/tests/language/nnbd/subtyping/type_casts_strong_test.dart
+++ b/tests/language/nnbd/subtyping/type_casts_strong_test.dart
@@ -16,7 +16,7 @@
   ac.asT(new C());
   ac.asT(new D());
   ac.asT(null);
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     ac.asT(new Y());
   });
 
@@ -25,10 +25,10 @@
   abc.asT(new B<C>());
   abc.asT(new B<D>());
   abc.asT(null);
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     abc.asT(new B<dynamic>());
   });
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     abc.asT(new B<Y>());
   });
 
@@ -37,7 +37,7 @@
   ay.asT(new Y());
   ay.asT(new Z());
   ay.asT(null);
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     ay.asT(new C());
   });
 
@@ -46,7 +46,7 @@
   wc.asT(new C());
   wc.asT(new D());
   wc.asT(null);
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wc.asT(new Y());
   });
 
@@ -54,7 +54,7 @@
   wc.asNullableT(new C());
   wc.asNullableT(new D());
   wc.asNullableT(null);
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wc.asNullableT(new Y());
   });
 
@@ -63,10 +63,10 @@
   wby.asT(new B<C>());
   wby.asT(new B<D>());
   wby.asT(null);
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wby.asT(new B<dynamic>());
   });
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wby.asT(new B<Y>());
   });
 
@@ -74,10 +74,10 @@
   wby.asNullableT(new B<C>());
   wby.asNullableT(new B<D>());
   wby.asNullableT(null);
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wby.asNullableT(new B<dynamic>());
   });
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wby.asNullableT(new B<Y>());
   });
 
@@ -85,10 +85,10 @@
   final wy = new W<Y>();
   wy.asT(new Y());
   wy.asT(new Z());
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wy.asT(null);
   });
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wy.asT(new C());
   });
 
@@ -96,7 +96,7 @@
   wy.asNullableT(new Y());
   wy.asNullableT(new Z());
   wy.asNullableT(null);
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wy.asNullableT(new C());
   });
 
@@ -104,10 +104,10 @@
   ay.asBT(new B<Y>());
   ay.asBT(new B<Z>());
   ay.asBT(null);
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     ay.asBT(new B<dynamic>());
   });
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     ay.asBT(new B<C>());
   });
 
@@ -115,13 +115,13 @@
   wy.asXT(new X<Y>());
   wy.asXT(new X<Z>());
   wy.asXT(newXOfLegacyY());
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wy.asXT(null);
   });
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wy.asXT(new X<dynamic>());
   });
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wy.asXT(new X<Y?>());
   });
 
@@ -130,10 +130,10 @@
   wy.asNullableXT(new X<Z>());
   wy.asNullableXT(newXOfLegacyY());
   wy.asNullableXT(null);
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wy.asNullableXT(new X<dynamic>());
   });
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wy.asNullableXT(new X<Y?>());
   });
 
@@ -142,10 +142,10 @@
   wy.asXNullableT(new X<Z>());
   wy.asXNullableT(new X<Y?>());
   wy.asXNullableT(newXOfLegacyY());
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wy.asXNullableT(null);
   });
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wy.asXNullableT(new X<dynamic>());
   });
 
@@ -155,10 +155,10 @@
   wny.asXT(new X<Z>());
   wny.asXT(new X<Y?>());
   wny.asXT(newXOfLegacyY());
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wny.asXT(null);
   });
-  Expect.throwsCastError(() {
+  Expect.throwsTypeError(() {
     wny.asXT(new X<dynamic>());
   });
 }
diff --git a/tests/language/nnbd/syntax/late_modifier_error_test.dart b/tests/language/nnbd/syntax/late_modifier_error_test.dart
index 2e1e994..a21deb7 100644
--- a/tests/language/nnbd/syntax/late_modifier_error_test.dart
+++ b/tests/language/nnbd/syntax/late_modifier_error_test.dart
@@ -10,12 +10,12 @@
 int f1(
   late //# 02: compile-time error
   int x
-) {}
+) => throw 0;
 
 late //# 03: syntax error
 class C1 {
   late //# 04: syntax error
-  int m() {}
+  int m() => throw 0;
 }
 
 main() {
diff --git a/tests/language/nnbd/syntax/required_modifier_error_test.dart b/tests/language/nnbd/syntax/required_modifier_error_test.dart
index 6bf7395..3312580 100644
--- a/tests/language/nnbd/syntax/required_modifier_error_test.dart
+++ b/tests/language/nnbd/syntax/required_modifier_error_test.dart
@@ -10,7 +10,7 @@
 int f1(
   required //# 02: syntax error
   int x
-) {}
+) => throw 0;
 
 required //# 03: syntax error
 class C1 {
diff --git a/tests/language/nnbd/type_equality/function_type_equality_test.dart b/tests/language/nnbd/type_equality/function_type_equality_test.dart
index cbf5b0d..10fffac 100644
--- a/tests/language/nnbd/type_equality/function_type_equality_test.dart
+++ b/tests/language/nnbd/type_equality/function_type_equality_test.dart
@@ -15,20 +15,20 @@
 void positionalIntToVoid(int i) => null;
 void positionalNullableIntToVoid(int? i) => null;
 void positionalNullableIntToVoid2(int? i) => null;
-void optionalIntToVoid([int i]) => null;
-void optionalIntToVoid2([int i]) => null;
+void optionalIntToVoid([int i = 0]) => null;
+void optionalIntToVoid2([int i = 0]) => null;
 void optionalNullableIntToVoid([int? i]) => null;
 void optionalNullableIntToVoid2([int? i]) => null;
-void namedIntToVoid({int i}) => null;
-void namedIntToVoid2({int i}) => null;
+void namedIntToVoid({int i = 0}) => null;
+void namedIntToVoid2({int i = 0}) => null;
 void namedNullableIntToVoid({int? i}) => null;
 void namedNullableIntToVoid2({int? i}) => null;
 void requiredIntToVoid({required int i}) => null;
 void requiredIntToVoid2({required int i}) => null;
 void requiredNullableIntToVoid({required int? i}) => null;
 void requiredNullableIntToVoid2({required int? i}) => null;
-void gn(bool b, [int i]) => null;
-void hn(bool b, {int i}) => null;
+void gn(bool b, [int i = 0]) => null;
+void hn(bool b, {int i = 0}) => null;
 
 main() {
   // Same functions with different names.
diff --git a/tests/language/nnbd/type_equality/futureOr_normalization_legacy_lib.dart b/tests/language/nnbd/type_equality/futureOr_normalization_legacy_lib.dart
new file mode 100644
index 0000000..cbad332
--- /dev/null
+++ b/tests/language/nnbd/type_equality/futureOr_normalization_legacy_lib.dart
@@ -0,0 +1,14 @@
+// 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.
+
+// Opt out of Null Safety:
+// @dart = 2.6
+
+import 'futureOr_normalization_null_safe_lib.dart' as nullSafe;
+
+Type extractType<T>() => T;
+Type nonNullableFutureOrOfLegacyObject() =>
+    nullSafe.nonNullableFutureOrOf<Object>();
+
+final object = extractType<Object>();
diff --git a/tests/language/nnbd/type_equality/futureOr_normalization_legacy_test.dart b/tests/language/nnbd/type_equality/futureOr_normalization_legacy_test.dart
new file mode 100644
index 0000000..c0570d4
--- /dev/null
+++ b/tests/language/nnbd/type_equality/futureOr_normalization_legacy_test.dart
@@ -0,0 +1,38 @@
+// 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.
+
+// Opt out of Null Safety:
+// @dart = 2.6
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+import 'futureOr_normalization_null_safe_lib.dart' as nullSafe;
+
+Type extractType<T>() => T;
+Type extractFutureOrType<T>() => _<FutureOr<T>>().runtimeType;
+Type embedFutureOrType<T>() => nullSafe.Embed<FutureOr<T>>().runtimeType;
+
+/// A class that should be ignored but it used embed the type signatures
+/// actually being tested.
+class _<T> {}
+
+main() {
+  // FutureOr types are normalized when they appear explicitly in the source.
+  Expect.identical(dynamic, extractType<FutureOr>());
+  Expect.identical(dynamic, extractType<FutureOr<dynamic>>());
+  Expect.identical(extractType<Object>(), extractType<FutureOr<Object>>());
+  Expect.identical(extractType<void>(), extractType<FutureOr<void>>());
+  Expect.identical(nullSafe.embeddedNullableFutureOfNull,
+      extractType<nullSafe.Embed<FutureOr<Null>>>());
+
+  // FutureOr types are normalized when they are created at runtime.
+  Expect.identical(extractType<_<dynamic>>(), extractFutureOrType());
+  Expect.identical(extractType<_<dynamic>>(), extractFutureOrType<dynamic>());
+  Expect.identical(extractType<_<Object>>(), extractFutureOrType<Object>());
+  Expect.identical(extractType<_<void>>(), extractFutureOrType<void>());
+  Expect.identical(
+      nullSafe.embeddedNullableFutureOfNull, embedFutureOrType<Null>());
+}
diff --git a/tests/language/nnbd/type_equality/futureOr_normalization_null_safe_lib.dart b/tests/language/nnbd/type_equality/futureOr_normalization_null_safe_lib.dart
new file mode 100644
index 0000000..c3391da
--- /dev/null
+++ b/tests/language/nnbd/type_equality/futureOr_normalization_null_safe_lib.dart
@@ -0,0 +1,14 @@
+// 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';
+
+/// A class that should be ignored but it used embed the type signatures
+/// actually being tested.
+class Embed<T> {}
+
+Type extractType<T>() => T;
+Type nonNullableFutureOrOf<T>() => extractType<FutureOr<T>>();
+
+final nullableFutureOfNull = extractType<Future<Null>?>();
+final embeddedNullableFutureOfNull = extractType<Embed<Future<Null>?>>();
diff --git a/tests/language/nnbd/type_equality/futureOr_normalization_test.dart b/tests/language/nnbd/type_equality/futureOr_normalization_test.dart
new file mode 100644
index 0000000..a9e61f5
--- /dev/null
+++ b/tests/language/nnbd/type_equality/futureOr_normalization_test.dart
@@ -0,0 +1,52 @@
+// 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';
+
+import 'package:expect/expect.dart';
+
+import 'futureOr_normalization_null_safe_lib.dart';
+import 'futureOr_normalization_legacy_lib.dart' as legacy;
+
+class A {}
+
+Type extractFutureOrType<T>() => Embed<FutureOr<T>>().runtimeType;
+Type embedNullableFutureOrType<T>() => Embed<FutureOr<T>?>().runtimeType;
+
+main() {
+  // FutureOr types are normalized when they appear explicitly in the source.
+  Expect.identical(dynamic, extractType<FutureOr>());
+  Expect.identical(dynamic, extractType<FutureOr<dynamic>>());
+  Expect.identical(Object, extractType<FutureOr<Object>>());
+  Expect.identical(extractType<Object?>(), extractType<FutureOr<Object>?>());
+  Expect.identical(extractType<Object?>(), extractType<FutureOr<Object?>>());
+  Expect.identical(extractType<void>(), extractType<FutureOr<void>>());
+  Expect.identical(
+      extractType<Future<Never>>(), extractType<FutureOr<Never>>());
+  Expect.identical(extractType<Future<Null>?>(), extractType<FutureOr<Null>>());
+  Expect.identical(
+      extractType<FutureOr<int?>>(), extractType<FutureOr<int?>?>());
+  Expect.identical(extractType<FutureOr<A?>>(), extractType<FutureOr<A?>?>());
+
+  // FutureOr types are normalized when they are composed at runtime.
+  Expect.identical(extractType<Embed<dynamic>>(), extractFutureOrType());
+  Expect.identical(
+      extractType<Embed<dynamic>>(), extractFutureOrType<dynamic>());
+  Expect.identical(extractType<Embed<Object>>(), extractFutureOrType<Object>());
+  Expect.identical(
+      extractType<Embed<Object?>>(), embedNullableFutureOrType<Object>());
+  Expect.identical(
+      extractType<Embed<Object?>>(), extractFutureOrType<Object?>());
+  Expect.identical(extractType<Embed<void>>(), extractFutureOrType<void>());
+  Expect.identical(
+      extractType<Embed<Future<Never>>>(), extractFutureOrType<Never>());
+  Expect.identical(
+      extractType<Embed<Future<Null>?>>(), extractFutureOrType<Null>());
+  Expect.identical(
+      extractType<Embed<FutureOr<int?>>>(), embedNullableFutureOrType<int?>());
+  Expect.identical(
+      extractType<Embed<FutureOr<A?>>>(), embedNullableFutureOrType<A?>());
+
+  // Object* == FutureOr<Object*>
+  Expect.identical(legacy.object, legacy.nonNullableFutureOrOfLegacyObject());
+}
diff --git a/tests/language/nnbd/type_equality/generic_function_type_equality_legacy_lib.dart b/tests/language/nnbd/type_equality/generic_function_type_equality_legacy_lib.dart
index d19128f..b354836 100644
--- a/tests/language/nnbd/type_equality/generic_function_type_equality_legacy_lib.dart
+++ b/tests/language/nnbd/type_equality/generic_function_type_equality_legacy_lib.dart
@@ -10,14 +10,14 @@
 void fn<X>() => null;
 R voidToR<R>() => null as R;
 void positionalRToVoid<R>(R i) => null;
-void optionalRToVoid<R>([R i]) => null;
-void namedRToVoid<R>({R i}) => null;
-void hn<T, S>(T b, [S i]) => null;
-void kn<T, S>(T b, {S i}) => null;
+void optionalRToVoid<R>([List<R> i]) => null;
+void namedRToVoid<R>({List<R> i}) => null;
+void hn<T, S>(T b, [List<S> i]) => null;
+void kn<T, S>(T b, {List<S> i}) => null;
 
 void positionalTToVoidWithBound<T extends B>(T i) => null;
-void optionalTToVoidWithBound<T extends B>([T i]) => null;
-void namedTToVoidWithBound<T extends B>({T i}) => null;
+void optionalTToVoidWithBound<T extends B>([List<T> i]) => null;
+void namedTToVoidWithBound<T extends B>({List<T> i}) => null;
 
 class A<T extends B> {
   void fn(T i) => null;
diff --git a/tests/language/nnbd/type_equality/generic_function_type_equality_test.dart b/tests/language/nnbd/type_equality/generic_function_type_equality_test.dart
index b830ba3..bd18b9a 100644
--- a/tests/language/nnbd/type_equality/generic_function_type_equality_test.dart
+++ b/tests/language/nnbd/type_equality/generic_function_type_equality_test.dart
@@ -14,12 +14,12 @@
 void positionalSToVoid<S>(S i) => null;
 void positionalNullableTToVoid<T>(T? i) => null;
 void positionalNullableSToVoid<S>(S? i) => null;
-void optionalTToVoid<T>([T i]) => null;
-void optionalSToVoid<S>([S i]) => null;
+void optionalTToVoid<T>([List<T> i = const <Never>[]]) => null;
+void optionalSToVoid<S>([List<S> i = const <Never>[]]) => null;
 void optionalNullableTToVoid<T>([T? i]) => null;
 void optionalNullableSToVoid<S>([S? i]) => null;
-void namedTToVoid<T>({T i}) => null;
-void namedSToVoid<S>({S i}) => null;
+void namedTToVoid<T>({List<T> i = const <Never>[]}) => null;
+void namedSToVoid<S>({List<S> i = const <Never>[]}) => null;
 void namedNullableTToVoid<T>({T? i}) => null;
 void namedNullableSToVoid<S>({S? i}) => null;
 void requiredTToVoid<T>({required T i}) => null;
@@ -28,8 +28,9 @@
 void requiredNullableSToVoid<S>({required S? i}) => null;
 
 void positionalTToVoidWithBound<T extends B>(T i) => null;
-void optionalTToVoidWithBound<T extends B>([T i]) => null;
-void namedTToVoidWithBound<T extends B>({T i}) => null;
+void optionalTToVoidWithBound<T extends B>([List<T> i = const <Never>[]]) =>
+    null;
+void namedTToVoidWithBound<T extends B>({List<T> i = const <Never>[]}) => null;
 
 class A<T extends B> {
   void fn(T i) => null;
@@ -38,7 +39,7 @@
 main() {
   // Same functions with different names.
   Expect.equals(fn.runtimeType, fn2.runtimeType);
-  Expect.equals(voidToT.runtimeType, voidToT.runtimeType);
+  Expect.equals(voidToT.runtimeType, voidToS.runtimeType);
   Expect.equals(positionalTToVoid.runtimeType, positionalSToVoid.runtimeType);
   Expect.equals(positionalNullableTToVoid.runtimeType,
       positionalNullableSToVoid.runtimeType);
diff --git a/tests/language_2/call/method_as_cast_test.dart b/tests/language_2/call/method_as_cast_test.dart
index f0718a3..48ae3b7 100644
--- a/tests/language_2/call/method_as_cast_test.dart
+++ b/tests/language_2/call/method_as_cast_test.dart
@@ -23,13 +23,13 @@
   // The presence of a `.call` method does not cause class `C` to become a
   // subtype of any function type.
   C c = new C();
-  Expect.throwsCastError(() => c as BToB); //# 01: ok
-  Expect.throwsCastError(() => c as NullToObject); //# 02: ok
-  Expect.throwsCastError(() => c as Function); //# 03: ok
+  Expect.throwsTypeError(() => c as BToB); //# 01: ok
+  Expect.throwsTypeError(() => c as NullToObject); //# 02: ok
+  Expect.throwsTypeError(() => c as Function); //# 03: ok
 
   // The same goes for class `D`: `implements Function` is ignored in Dart 2.
   D d = new D();
-  Expect.throwsCastError(() => d as BToB); //# 04: ok
-  Expect.throwsCastError(() => d as NullToObject); //# 05: ok
-  Expect.throwsCastError(() => d as Function); //# 06: ok
+  Expect.throwsTypeError(() => d as BToB); //# 04: ok
+  Expect.throwsTypeError(() => d as NullToObject); //# 05: ok
+  Expect.throwsTypeError(() => d as Function); //# 06: ok
 }
diff --git a/tests/language_2/deferred/type_dependency_lib1.dart b/tests/language_2/deferred/type_dependency_lib1.dart
index d9a3663..491ecc6 100644
--- a/tests/language_2/deferred/type_dependency_lib1.dart
+++ b/tests/language_2/deferred/type_dependency_lib1.dart
@@ -13,7 +13,7 @@
 bool fooAs(x) {
   try {
     return (x as A).p;
-  } on CastError catch (e) {
+  } on TypeError {
     return false;
   }
 }
@@ -22,7 +22,7 @@
   try {
     A y = x;
     return y is! String;
-  } on TypeError catch (e) {
+  } on TypeError {
     return false;
   }
 }
diff --git a/tests/language_2/enum/enum_test.dart b/tests/language_2/enum/enum_test.dart
index d3480ca..4e1303d 100644
--- a/tests/language_2/enum/enum_test.dart
+++ b/tests/language_2/enum/enum_test.dart
@@ -37,7 +37,7 @@
   Expect.isFalse(obj is _IsNot, '$obj is _IsNot');
   // test cast
   t = obj as T;
-  Expect.throwsCastError(() => obj as _IsNot, '$obj as _IsNot');
+  Expect.throwsTypeError(() => obj as _IsNot, '$obj as _IsNot');
 }
 
 main() {
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_6_error_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_6_error_test.dart
index de842c8..258feaa 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_6_error_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_6_error_test.dart
@@ -119,6 +119,6 @@
   var a = new AGlobal();
   a.instanceTest();
 
-  Expect.throwsCastError(() => 3.castToShadowedTypeParam<String>());
-  Expect.throwsCastError(() => 3.castToShadowedTypeList<String>());
+  Expect.throwsTypeError(() => 3.castToShadowedTypeParam<String>());
+  Expect.throwsTypeError(() => 3.castToShadowedTypeList<String>());
 }
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_6_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_6_test.dart
index 929b306..f8dd416 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_6_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_6_test.dart
@@ -97,5 +97,5 @@
   var a = new AGlobal();
   a.instanceTest();
 
-  Expect.throwsCastError(() => 3.castToShadowedTypeParam<String>());
+  Expect.throwsTypeError(() => 3.castToShadowedTypeParam<String>());
 }
diff --git a/tests/language_2/generic/function_bounds_test.dart b/tests/language_2/generic/function_bounds_test.dart
index c48483b..ad7f17d 100644
--- a/tests/language_2/generic/function_bounds_test.dart
+++ b/tests/language_2/generic/function_bounds_test.dart
@@ -68,29 +68,29 @@
   Expect.equals((d as F<num>)(40), 42);
 
   // Check that casting to a generic function with more specific bounds fails
-  Expect.throwsCastError(
+  Expect.throwsTypeError(
       () => (f as G<int>), "Generic functions are invariant");
-  Expect.throwsCastError(
+  Expect.throwsTypeError(
       () => (d as G<int>), "Generic functions are invariant");
-  Expect.throwsCastError(
+  Expect.throwsTypeError(
       () => (f as G<double>), "Generic functions are invariant");
-  Expect.throwsCastError(
+  Expect.throwsTypeError(
       () => (d as G<double>), "Generic functions are invariant");
-  Expect.throwsCastError(
+  Expect.throwsTypeError(
       () => (f as G<Null>), "Generic functions are invariant");
-  Expect.throwsCastError(
+  Expect.throwsTypeError(
       () => (d as G<Null>), "Generic functions are invariant");
 
   // Check that casting to a generic function with a more general bound fails
-  Expect.throwsCastError(
+  Expect.throwsTypeError(
       () => (f as G<Object>), "Generic functions are invariant");
-  Expect.throwsCastError(
+  Expect.throwsTypeError(
       () => (d as G<Object>), "Generic functions are invariant");
 
   // Check that casting to a generic function with an unrelated bound fails
-  Expect.throwsCastError(
+  Expect.throwsTypeError(
       () => (f as G<String>), "Generic functions are invariant");
-  Expect.throwsCastError(
+  Expect.throwsTypeError(
       () => (d as G<String>), "Generic functions are invariant");
 }
 
diff --git a/tests/language_2/generic_methods/type_expression_test.dart b/tests/language_2/generic_methods/type_expression_test.dart
index 80d4376..e809704 100644
--- a/tests/language_2/generic_methods/type_expression_test.dart
+++ b/tests/language_2/generic_methods/type_expression_test.dart
@@ -45,9 +45,9 @@
   Expect.isFalse(f4<int>(<int>[42]));
   Expect.isTrue(f4<String>(<int>[42])); // `is! List<dynamic>` is true.
   Expect.equals(f5<String>(s), s); // `s as String == s`
-  Expect.throwsCastError(() => f5<int>(s)); // `s as int == s`
+  Expect.throwsTypeError(() => f5<int>(s)); // `s as int == s`
   Expect.equals(f6<String>(ss), ss);
-  Expect.throwsCastError(() => f6<int>(ss)); // `as List<int>` fails.
+  Expect.throwsTypeError(() => f6<int>(ss)); // `as List<int>` fails.
   Expect.equals(f7<int>(), int);
 
   // Returns `List<int>`.
diff --git a/tests/language_2/malbounded/type_cast_runtime_test.dart b/tests/language_2/malbounded/type_cast_runtime_test.dart
index 31e8b55..fd75b12 100644
--- a/tests/language_2/malbounded/type_cast_runtime_test.dart
+++ b/tests/language_2/malbounded/type_cast_runtime_test.dart
@@ -17,10 +17,10 @@
 
 main() {
   var m = new Malbounded1();
-  Expect.throwsCastError(() => m as Super<int>);
+  Expect.throwsTypeError(() => m as Super<int>);
   var s = new Super<int>();
-  Expect.throwsCastError(() => s as Malbounded1);
-  Expect.throwsCastError(() => s as Malbounded2);
+  Expect.throwsTypeError(() => s as Malbounded1);
+  Expect.throwsTypeError(() => s as Malbounded2);
   s as Super
 
       ;
diff --git a/tests/language_2/malbounded/type_cast_test.dart b/tests/language_2/malbounded/type_cast_test.dart
index 4ebe0c7..2c56e68 100644
--- a/tests/language_2/malbounded/type_cast_test.dart
+++ b/tests/language_2/malbounded/type_cast_test.dart
@@ -22,10 +22,10 @@
 
 main() {
   var m = new Malbounded1();
-  Expect.throwsCastError(() => m as Super<int>);
+  Expect.throwsTypeError(() => m as Super<int>);
   var s = new Super<int>();
-  Expect.throwsCastError(() => s as Malbounded1);
-  Expect.throwsCastError(() => s as Malbounded2);
+  Expect.throwsTypeError(() => s as Malbounded1);
+  Expect.throwsTypeError(() => s as Malbounded2);
   s as Super
   //^
   // [cfe] Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'Super'.
diff --git a/tests/language_2/null/null_test.dart b/tests/language_2/null/null_test.dart
index 10e37fa..19f85f0 100644
--- a/tests/language_2/null/null_test.dart
+++ b/tests/language_2/null/null_test.dart
@@ -143,7 +143,7 @@
   Expect.equals(null, null as Null);
   Expect.equals(null, null as Object);
   Expect.equals(null, null as int);
-  Expect.throwsCastError(() => 42 as Null);
+  Expect.throwsTypeError(() => 42 as Null);
   Expect.equals(null, new Generic<Null>().cast(null));
   Expect.equals(null, new Generic<Object>().cast(null));
   Expect.equals(null, new Generic<int>().cast(null));
diff --git a/tests/language_2/regress/regress10747_test.dart b/tests/language_2/regress/regress10747_test.dart
index 2fc2b65..46fb8bd 100644
--- a/tests/language_2/regress/regress10747_test.dart
+++ b/tests/language_2/regress/regress10747_test.dart
@@ -15,9 +15,9 @@
 
 main() {
   Expect.equals(42, new A<int>(42).asTypeVariable());
-  Expect.throwsCastError(() => new A<String>(42).asTypeVariable());
+  Expect.throwsTypeError(() => new A<String>(42).asTypeVariable());
 
   var b = new B<int>();
   Expect.equals(b, new A<int>(b).asBOfT());
-  Expect.throwsCastError(() => new A<String>(b).asBOfT());
+  Expect.throwsTypeError(() => new A<String>(b).asBOfT());
 }
diff --git a/tests/language_2/type/check_test.dart b/tests/language_2/type/check_test.dart
index 820c0dd..20539a1 100644
--- a/tests/language_2/type/check_test.dart
+++ b/tests/language_2/type/check_test.dart
@@ -15,5 +15,5 @@
   var a = [new A(), new B()];
   var b = a[0];
   b = b as A;
-  Expect.throwsCastError(() => b as B);
+  Expect.throwsTypeError(() => b as B);
 }
diff --git a/tests/language_2/type/error_test.dart b/tests/language_2/type/error_test.dart
index fc62c23..4797b37 100644
--- a/tests/language_2/type/error_test.dart
+++ b/tests/language_2/type/error_test.dart
@@ -4,193 +4,42 @@
 
 import "package:expect/expect.dart";
 
-// Test that various type errors doesn't invoke user-defined code
-// during error reporting.
+// Test that various type errors produced by explicit casts don't invoke
+// user-defined code during error reporting.
 
-class MyClass {}
-
-class IntTypeError {
+class NoToString {
   toString() {
-    int value = wrap(this);
-    return super.toString();
-  }
-}
-
-class StringTypeError {
-  toString() {
-    String value = wrap(this);
-    return super.toString();
-  }
-}
-
-class DoubleTypeError {
-  toString() {
-    double value = wrap(this);
-    return super.toString();
-  }
-}
-
-class NumTypeError {
-  toString() {
-    num value = wrap(this);
-    return super.toString();
-  }
-}
-
-class BoolTypeError {
-  toString() {
-    bool value = wrap(this);
-    return super.toString();
-  }
-}
-
-class FunctionTypeError {
-  toString() {
-    Function value = wrap(this);
-    return super.toString();
-  }
-}
-
-class MyClassTypeError {
-  toString() {
-    MyClass value = wrap(this);
-    return super.toString();
-  }
-}
-
-class ListTypeError {
-  toString() {
-    List value = wrap(this);
-    return super.toString();
-  }
-}
-
-class IntCastError {
-  toString() {
-    wrap(this) as int;
-    return super.toString();
-  }
-}
-
-class StringCastError {
-  toString() {
-    wrap(this) as String;
-    return super.toString();
-  }
-}
-
-class DoubleCastError {
-  toString() {
-    wrap(this) as double;
-    return super.toString();
-  }
-}
-
-class NumCastError {
-  toString() {
-    wrap(this) as num;
-    return super.toString();
-  }
-}
-
-class BoolCastError {
-  toString() {
-    wrap(this) as bool;
-    return super.toString();
-  }
-}
-
-class FunctionCastError {
-  toString() {
-    wrap(this) as Function;
-    return super.toString();
-  }
-}
-
-class MyClassCastError {
-  toString() {
-    wrap(this) as MyClass;
-    return super.toString();
-  }
-}
-
-class ListCastError {
-  toString() {
-    wrap(this) as List;
-    return super.toString();
+    Expect.fail("should not be called");
+    return "";
   }
 }
 
 /// Defeat optimizations of type checks.
-wrap(e) {
+dynamic wrap(e) {
   if (new DateTime.now().year == 1980) return null;
   return e;
 }
 
-checkTypeError(o) {
-  try {
-    print(o);
-  } on TypeError catch (e) {
-    print(e); // This might provoke an error.
-    if (assertionsEnabled) return; // Expected type error.
-    rethrow; // Rethrow unexpected type error.
-  }
-  if (assertionsEnabled) {
-    throw 'expected TypeError';
-  }
-}
-
-checkAssert(o) {
-  try {
-    assert(o);
-  } on TypeError catch (e) {
-    print(e); // This might provoke an error.
-    if (!assertionsEnabled) rethrow; // Unexpected error.
-  }
-}
-
-checkCastError(o) {
-  try {
-    print(o);
-  } on TypeError catch (e) {
-    print('unexpected type error: ${Error.safeToString(e)}');
-    rethrow; // Unexpected type error.
-  } on CastError catch (e) {
-    print(e); // This might provoke an error.
-    return; // Expected a cast error.
-  }
-  throw 'expected CastError';
-}
-
 bool assertionsEnabled = false;
 
-main() {
+void main() {
   assert(assertionsEnabled = true);
 
-  checkTypeError(new IntTypeError());
-  checkTypeError(new StringTypeError());
-  checkTypeError(new DoubleTypeError());
-  checkTypeError(new NumTypeError());
-  checkTypeError(new BoolTypeError());
-  checkTypeError(new FunctionTypeError());
-  checkTypeError(new MyClassTypeError());
-  checkTypeError(new ListTypeError());
+  dynamic noToString = NoToString();
 
-  checkAssert(new IntTypeError());
-  checkAssert(new StringTypeError());
-  checkAssert(new DoubleTypeError());
-  checkAssert(new NumTypeError());
-  checkAssert(new BoolTypeError());
-  checkAssert(new FunctionTypeError());
-  checkAssert(new MyClassTypeError());
-  checkAssert(new ListTypeError());
+  Expect.throws<TypeError>(() {
+    wrap(noToString) as int; // Explicit cast should throw
+  }, (e) {
+    e.toString(); // Should not throw.
+    return true;
+  });
 
-  checkCastError(new IntCastError());
-  checkCastError(new StringCastError());
-  checkCastError(new DoubleCastError());
-  checkCastError(new NumCastError());
-  checkCastError(new BoolCastError());
-  checkCastError(new FunctionCastError());
-  checkCastError(new MyClassCastError());
-  checkCastError(new ListCastError());
+  if (assertionsEnabled) {
+    Expect.throws<AssertionError>(() {
+      assert(wrap(false), noToString); // Assertion should throw
+    }, (e) {
+      e.toString(); // Should not throw.
+      return true;
+    });
+  }
 }
diff --git a/tests/language_2/type/implicit_error_test.dart b/tests/language_2/type/implicit_error_test.dart
new file mode 100644
index 0000000..1c42842
--- /dev/null
+++ b/tests/language_2/type/implicit_error_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test that various type errors produced by implicit casts don't invoke
+// user-defined code during error reporting.
+
+class NoToString {
+  toString() {
+    Expect.fail("should not be called");
+    return "";
+  }
+}
+
+/// Defeat optimizations of type checks.
+dynamic wrap(e) {
+  if (new DateTime.now().year == 1980) return null;
+  return e;
+}
+
+bool assertionsEnabled = false;
+
+void main() {
+  assert(assertionsEnabled = true);
+
+  dynamic noToString = NoToString();
+
+  Expect.throws<TypeError>(() {
+    int x = wrap(noToString); // Implicit cast should throw
+    return x;
+  }, (e) {
+    e.toString(); // Should not throw.
+    return true;
+  });
+
+  if (assertionsEnabled) {
+    Expect.throws<TypeError>(() {
+      assert(wrap(noToString)); // Implicit cast should throw
+    }, (e) {
+      e.toString(); // Should not throw.
+      return true;
+    });
+  }
+}
diff --git a/tests/language_2/vm/type_cast_vm_test.dart b/tests/language_2/vm/type_cast_vm_test.dart
index 07580db..5a83874 100644
--- a/tests/language_2/vm/type_cast_vm_test.dart
+++ b/tests/language_2/vm/type_cast_vm_test.dart
@@ -20,10 +20,10 @@
   static test() {
     int result = 0;
     try {
-      var i = "hello" as int; // Throws a CastError
+      var i = "hello" as int; // Throws a TypeError
     } catch (error) {
       result = 1;
-      Expect.isTrue(error is CastError);
+      Expect.type<TypeError>(error);
       var msg = error.toString();
       Expect.isTrue(msg.contains("int")); // dstType
       Expect.isTrue(msg.contains("String")); // srcType
@@ -57,10 +57,10 @@
     }
 
     try {
-      int i = f("hello" as int); // Throws a CastError
+      int i = f("hello" as int); // Throws a TypeError
     } catch (error) {
       result = 1;
-      Expect.isTrue(error is CastError);
+      Expect.type<TypeError>(error);
       var msg = error.toString();
       Expect.isTrue(msg.contains("int")); // dstType
       Expect.isTrue(msg.contains("String")); // srcType
@@ -72,14 +72,14 @@
   static testReturn() {
     int result = 0;
     int f(String s) {
-      return s as int; // Throws a CastError
+      return s as int; // Throws a TypeError
     }
 
     try {
       int i = f("hello");
     } catch (error) {
       result = 1;
-      Expect.isTrue(error is CastError);
+      Expect.type<TypeError>(error);
       var msg = error.toString();
       Expect.isTrue(msg.contains("int")); // dstType
       Expect.isTrue(msg.contains("String")); // srcType
@@ -94,7 +94,7 @@
     int result = 0;
     Expect.equals(5, (field as String).length);
     try {
-      field as int; // Throws a CastError
+      field as int; // Throws a TypeError
     } catch (error) {
       result = 1;
       var msg = error.toString();
diff --git a/tests/lib/async/catch_errors.dart b/tests/lib/async/catch_errors.dart
index b170b70..c684cf9 100644
--- a/tests/lib/async/catch_errors.dart
+++ b/tests/lib/async/catch_errors.dart
@@ -19,7 +19,7 @@
 }
 
 runZonedScheduleMicrotask(body(),
-    {void onScheduleMicrotask(void callback()), Function onError}) {
+    {void onScheduleMicrotask(void callback()), Function? onError}) {
   if (onScheduleMicrotask == null) {
     return runZoned(body, onError: onError);
   }
diff --git a/tests/lib/async/event_helper.dart b/tests/lib/async/event_helper.dart
index d7ff0f4..671e724 100644
--- a/tests/lib/async/event_helper.dart
+++ b/tests/lib/async/event_helper.dart
@@ -86,7 +86,7 @@
     events.add(new DataEvent(value));
   }
 
-  void addError(error, [StackTrace stackTrace]) {
+  void addError(error, [StackTrace? stackTrace]) {
     if (trace) print("Events#$hashCode: addError($error)");
     events.add(new ErrorEvent(error));
   }
@@ -100,7 +100,7 @@
   /**
    * Error shorthand, for writing events manually.
    */
-  void error(var value, [StackTrace stackTrace]) {
+  void error(var value, [StackTrace? stackTrace]) {
     addError(value, stackTrace);
   }
 
@@ -130,7 +130,7 @@
    * Should only be used when there is a subscription. That is, after a
    * call to [subscribeTo].
    */
-  void pause([Future resumeSignal]) {
+  void pause([Future? resumeSignal]) {
     throw new StateError("Not capturing events.");
   }
 
@@ -160,14 +160,14 @@
         onError: addError, onDone: close, cancelOnError: cancelOnError);
   }
 
-  void addError(error, [stackTrace]) {
+  void addError(error, [StackTrace? stackTrace]) {
     super.addError(error, stackTrace);
     if (cancelOnError) {
       onDoneSignal.complete();
     }
   }
 
-  void pause([Future resumeSignal]) {
+  void pause([Future? resumeSignal]) {
     if (trace) print("Events#$hashCode: pause");
     subscription.pause(resumeSignal);
   }
diff --git a/tests/lib/async/future_foreach_test.dart b/tests/lib/async/future_foreach_test.dart
index 7416b94..904ae80 100644
--- a/tests/lib/async/future_foreach_test.dart
+++ b/tests/lib/async/future_foreach_test.dart
@@ -63,9 +63,9 @@
       Expect.isTrue(n >= 0);
       switch (delay) {
         case 1:
-          return new Future<String>(() {});
+          return new Future(() {});
         case 2:
-          return new Future<String>.microtask(() {});
+          return new Future.microtask(() {});
       }
     }).then((_) {
       Expect.fail("Did not throw");
diff --git a/tests/lib/async/futures_test.dart b/tests/lib/async/futures_test.dart
index 537b65c..6dd4311 100644
--- a/tests/lib/async/futures_test.dart
+++ b/tests/lib/async/futures_test.dart
@@ -15,7 +15,7 @@
 
 Future testCompleteAfterWait() {
   final futures = new List<Future>();
-  final c = new Completer<Object>();
+  final c = new Completer<Object?>();
   futures.add(c.future);
   Future future = Future.wait(futures);
   c.complete(null);
diff --git a/tests/lib/async/stream_subscription_as_future_test.dart b/tests/lib/async/stream_subscription_as_future_test.dart
index 5be5c91..d12c0ac 100644
--- a/tests/lib/async/stream_subscription_as_future_test.dart
+++ b/tests/lib/async/stream_subscription_as_future_test.dart
@@ -71,7 +71,7 @@
     var subscription = stream.listen((x) {
       output.add(x);
     });
-    subscription.asFuture(output).catchError(expectAsync((error) {
+    subscription.asFuture<List?>(output).catchError(expectAsync((error) {
       Expect.equals(error, "foo");
     }));
   });
@@ -85,7 +85,7 @@
     var subscription = stream.listen((x) {
       output.add(x);
     });
-    subscription.asFuture(output).catchError(expectAsync((error) {
+    subscription.asFuture<List?>(output).catchError(expectAsync((error) {
       Expect.equals(error, "foo");
     }));
   });
@@ -103,7 +103,7 @@
       output.add(x);
     });
     bool catchErrorHasRun = false;
-    subscription.asFuture(output).catchError(expectAsync((error) {
+    subscription.asFuture<List?>(output).catchError(expectAsync((error) {
       Expect.equals(error, "foo");
       catchErrorHasRun = true;
     }));
@@ -127,7 +127,7 @@
         output.add(x);
       });
       bool catchErrorHasRun = false;
-      subscription.asFuture(output).catchError(expectAsync((error) {
+      subscription.asFuture<List?>(output).catchError(expectAsync((error) {
         Expect.equals(error, "foo");
         catchErrorHasRun = true;
       }));
@@ -139,4 +139,4 @@
       Expect.equals(499, e);
     }));
   });
-}
+}
\ No newline at end of file
diff --git a/tests/lib/mirrors/basic_types_in_dart_core_test.dart b/tests/lib/mirrors/basic_types_in_dart_core_test.dart
index 50e9203..748faf8 100644
--- a/tests/lib/mirrors/basic_types_in_dart_core_test.dart
+++ b/tests/lib/mirrors/basic_types_in_dart_core_test.dart
@@ -10,7 +10,7 @@
 main() {
   LibraryMirror dartcore = currentMirrorSystem().findLibrary(#dart.core);
   ClassMirror cm;
-  TypeMirror tm;
+  TypeMirror? tm;
 
   cm = dartcore.declarations[#int] as ClassMirror;
   Expect.equals(reflectClass(int), cm);
@@ -44,9 +44,9 @@
   Expect.equals(reflectClass(Object), cm);
   Expect.equals(#Object, cm.simpleName);
 
-  tm = dartcore.declarations[#dynamic] as TypeMirror;
+  tm = dartcore.declarations[#dynamic] as TypeMirror?;
   Expect.isNull(tm);
 
-  tm = dartcore.declarations[const Symbol('void')] as TypeMirror;
+  tm = dartcore.declarations[const Symbol('void')] as TypeMirror?;
   Expect.isNull(tm);
 }
diff --git a/tests/lib/typed_data/typed_data_list_test.dart b/tests/lib/typed_data/typed_data_list_test.dart
index 890f274..edeb362 100644
--- a/tests/lib/typed_data/typed_data_list_test.dart
+++ b/tests/lib/typed_data/typed_data_list_test.dart
@@ -155,7 +155,7 @@
 
   var copy = list.toList();
   // Make sure we are allowed to call range-functions if they are 0..0.
-  list.fillRange(0, 0);
+  list.fillRange(0, 0, toElementType(0));
   Expect.listEquals([], list.getRange(0, 0).toList());
 
   final minusOne = toElementType(-1);
diff --git a/tests/lib_2/html/canvasrendering/draw_image_video_element_test.dart b/tests/lib_2/html/canvasrendering/draw_image_video_element_test.dart
index 5fad4d2..c6aa721 100644
--- a/tests/lib_2/html/canvasrendering/draw_image_video_element_test.dart
+++ b/tests/lib_2/html/canvasrendering/draw_image_video_element_test.dart
@@ -4,189 +4,209 @@
 
 library canvas_rendering_context_2d_test;
 
+import 'dart:async';
 import 'dart:html';
 import 'dart:math';
 
 import 'canvas_rendering_util.dart';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_helper.dart';
+
+// These videos and base64 strings are the same video, representing 2
+// frames of 8x8 red pixels.
+// The videos were created with:
+//   convert -size 8x8 xc:red blank1.jpg
+//   convert -size 8x8 xc:red blank2.jpg
+//   avconv -f image2  -i "blank%d.jpg" -c:v libx264 small.mp4
+//   avconv -i small.mp4 small.webm
+//   python -m base64 -e small.mp4
+//   python -m base64 -e small.webm
+var mp4VideoUrl = '/root_dart/tests/lib_2/html/small.mp4';
+var webmVideoUrl = '/root_dart/tests/lib_2/html/small.webm';
+var mp4VideoDataUrl =
+    'data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAA'
+    'AIZnJlZQAAAsdtZGF0AAACmwYF//+X3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlID'
+    'EyMCByMjE1MSBhM2Y0NDA3IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZW'
+    'Z0IDIwMDMtMjAxMSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG'
+    '9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweD'
+    'ExMSBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj'
+    '0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MC'
+    'BkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aH'
+    'JlYWRzPTE4IHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZW'
+    'Q9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl'
+    '9weXJhbWlkPTAgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MCBvcG'
+    'VuX2dvcD0xIHdlaWdodHA9MiBrZXlpbnQ9MjUwIGtleWludF9taW49MjUgc2NlbmVjdX'
+    'Q9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MCByYz1jcmYgbWJ0cmVlPT'
+    'EgY3JmPTUxLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IGlwX3'
+    'JhdGlvPTEuMjUgYXE9MToxLjAwAIAAAAARZYiEB//3aoK5/tP9+8yeuIEAAAAHQZoi2P'
+    '/wgAAAAzxtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAAUAABAAABAAAAAAAAAA'
+    'AAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAA'
+    'AAAAAAAAAAAAAAAAAAAAACAAAAGGlvZHMAAAAAEICAgAcAT/////7/AAACUHRyYWsAAA'
+    'BcdGtoZAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAQAAAA'
+    'AAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAACAAAAAgAAAAAACRlZHRzAAAAHG'
+    'Vsc3QAAAAAAAAAAQAAAFAAAAABAAEAAAAAAchtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAA'
+    'AAAAAZAAAAAlXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSG'
+    'FuZGxlcgAAAAFzbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZg'
+    'AAAAAAAAABAAAADHVybCAAAAABAAABM3N0YmwAAACXc3RzZAAAAAAAAAABAAAAh2F2Yz'
+    'EAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAACAAIAEgAAABIAAAAAAAAAAEAAAAAAAAAAA'
+    'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAxYXZjQwFNQAr/4QAYZ01ACuiPyy'
+    '4C2QAAAwABAAADADIPEiUSAQAGaOvAZSyAAAAAGHN0dHMAAAAAAAAAAQAAAAIAAAABAA'
+    'AAFHN0c3MAAAAAAAAAAQAAAAEAAAAYY3R0cwAAAAAAAAABAAAAAgAAAAEAAAAcc3RzYw'
+    'AAAAAAAAABAAAAAQAAAAEAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAK0AAAACwAAAB'
+    'hzdGNvAAAAAAAAAAIAAAAwAAAC5AAAAGB1ZHRhAAAAWG1ldGEAAAAAAAAAIWhkbHIAAA'
+    'AAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAK2lsc3QAAAAjqXRvbwAAABtkYXRhAAAAAQ'
+    'AAAABMYXZmNTMuMjEuMQ==';
+var webmVideoDataUrl =
+    'data:video/webm;base64,GkXfowEAAAAAAAAfQoaBAUL3gQFC8oEEQvOBCEKChHdlY'
+    'm1Ch4ECQoWBAhhTgGcBAAAAAAAB/hFNm3RALE27i1OrhBVJqWZTrIHfTbuMU6uEFlSua'
+    '1OsggEsTbuMU6uEHFO7a1OsggHk7AEAAAAAAACkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
+    'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
+    'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
+    'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmAQAAAAAAA'
+    'EEq17GDD0JATYCLTGF2ZjUzLjIxLjFXQYtMYXZmNTMuMjEuMXOkkJatuHwTJ7cvFLSzB'
+    'Smxbp5EiYhAVAAAAAAAABZUrmsBAAAAAAAAR64BAAAAAAAAPteBAXPFgQGcgQAitZyDd'
+    'W5khoVWX1ZQOIOBASPjg4QCYloA4AEAAAAAAAASsIEIuoEIVLCBCFS6gQhUsoEDH0O2d'
+    'QEAAAAAAABZ54EAo72BAACA8AIAnQEqCAAIAABHCIWFiIWEiAICAnWqA/gD+gINTRgA/'
+    'v0hRf/kb+PnRv/I4//8WE8DijI//FRAo5WBACgAsQEAARAQABgAGFgv9AAIAAAcU7trA'
+    'QAAAAAAAA67jLOBALeH94EB8YIBfw==';
+
+Future testWithThreeParams() async {
+  setupFunc();
+
+  var playFuture = video.onCanPlay.first;
+  video.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+  if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+    video.src = webmVideoUrl;
+  } else if (video.canPlayType(
+          'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
+      '') {
+    video.src = mp4VideoUrl;
+  } else {
+    window.console.log('Video is not supported on this system.');
+  }
+
+  await playFuture;
+  context.drawImage(video, 50, 50);
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(54, 54);
+  expectPixelFilled(57, 57);
+  expectPixelUnfilled(58, 58);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(70, 70);
+  tearDownFunc();
+}
+
+Future testWithFiveParams() async {
+  setupFunc();
+
+  var playFuture = video.onCanPlay.first;
+  video.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+
+  if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+    video.src = webmVideoUrl;
+  } else if (video.canPlayType(
+          'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
+      '') {
+    video.src = mp4VideoUrl;
+  } else {
+    // TODO(amouravski): Better fallback?
+    window.console.log('Video is not supported on this system.');
+  }
+
+  await playFuture;
+  context.drawImageToRect(video, new Rectangle(50, 50, 20, 20));
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelFilled(60, 60);
+  expectPixelFilled(69, 69);
+  expectPixelUnfilled(70, 70);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(80, 80);
+  tearDownFunc();
+}
+
+Future testWithNineParams() async {
+  setupFunc();
+
+  var playFuture = video.onCanPlay.first;
+  video.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+
+  if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+    video.src = webmVideoUrl;
+  } else if (video.canPlayType(
+          'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
+      '') {
+    video.src = mp4VideoUrl;
+  } else {
+    // TODO(amouravski): Better fallback?
+    window.console.log('Video is not supported on this system.');
+  }
+
+  await playFuture;
+  context.drawImageToRect(video, new Rectangle(50, 50, 20, 20),
+      sourceRect: new Rectangle(2, 2, 6, 6));
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelFilled(60, 60);
+  expectPixelFilled(69, 69);
+  expectPixelUnfilled(70, 70);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(80, 80);
+  tearDownFunc();
+}
+
+Future testDataUrlWithNineParams() async {
+  setupFunc();
+
+  video = new VideoElement();
+  canvas = new CanvasElement();
+
+  var playFuture = video.onCanPlay.first;
+  video.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+
+  if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
+    video.src = webmVideoDataUrl;
+  } else if (video.canPlayType(
+          'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
+      '') {
+    video.src = mp4VideoDataUrl;
+  } else {
+    // TODO(amouravski): Better fallback?
+    window.console.log('Video is not supported on this system.');
+  }
+
+  await playFuture;
+  context.drawImageToRect(video, new Rectangle(50, 50, 20, 20),
+      sourceRect: new Rectangle(2, 2, 6, 6));
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelFilled(60, 60);
+  expectPixelFilled(69, 69);
+  expectPixelUnfilled(70, 70);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(80, 80);
+  tearDownFunc();
+}
 
 main() {
-  // These videos and base64 strings are the same video, representing 2
-  // frames of 8x8 red pixels.
-  // The videos were created with:
-  //   convert -size 8x8 xc:red blank1.jpg
-  //   convert -size 8x8 xc:red blank2.jpg
-  //   avconv -f image2  -i "blank%d.jpg" -c:v libx264 small.mp4
-  //   avconv -i small.mp4 small.webm
-  //   python -m base64 -e small.mp4
-  //   python -m base64 -e small.webm
-  var mp4VideoUrl = '/root_dart/tests/lib_2/html/small.mp4';
-  var webmVideoUrl = '/root_dart/tests/lib_2/html/small.webm';
-  var mp4VideoDataUrl =
-      'data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAA'
-      'AIZnJlZQAAAsdtZGF0AAACmwYF//+X3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlID'
-      'EyMCByMjE1MSBhM2Y0NDA3IC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZW'
-      'Z0IDIwMDMtMjAxMSAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG'
-      '9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweD'
-      'ExMSBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj'
-      '0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MC'
-      'BkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aH'
-      'JlYWRzPTE4IHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZW'
-      'Q9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl'
-      '9weXJhbWlkPTAgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MCBvcG'
-      'VuX2dvcD0xIHdlaWdodHA9MiBrZXlpbnQ9MjUwIGtleWludF9taW49MjUgc2NlbmVjdX'
-      'Q9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MCByYz1jcmYgbWJ0cmVlPT'
-      'EgY3JmPTUxLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IGlwX3'
-      'JhdGlvPTEuMjUgYXE9MToxLjAwAIAAAAARZYiEB//3aoK5/tP9+8yeuIEAAAAHQZoi2P'
-      '/wgAAAAzxtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAAUAABAAABAAAAAAAAAA'
-      'AAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAA'
-      'AAAAAAAAAAAAAAAAAAAAACAAAAGGlvZHMAAAAAEICAgAcAT/////7/AAACUHRyYWsAAA'
-      'BcdGtoZAAAAA8AAAAAAAAAAAAAAAEAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAQAAAA'
-      'AAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAACAAAAAgAAAAAACRlZHRzAAAAHG'
-      'Vsc3QAAAAAAAAAAQAAAFAAAAABAAEAAAAAAchtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAA'
-      'AAAAAZAAAAAlXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSG'
-      'FuZGxlcgAAAAFzbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZg'
-      'AAAAAAAAABAAAADHVybCAAAAABAAABM3N0YmwAAACXc3RzZAAAAAAAAAABAAAAh2F2Yz'
-      'EAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAACAAIAEgAAABIAAAAAAAAAAEAAAAAAAAAAA'
-      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAxYXZjQwFNQAr/4QAYZ01ACuiPyy'
-      '4C2QAAAwABAAADADIPEiUSAQAGaOvAZSyAAAAAGHN0dHMAAAAAAAAAAQAAAAIAAAABAA'
-      'AAFHN0c3MAAAAAAAAAAQAAAAEAAAAYY3R0cwAAAAAAAAABAAAAAgAAAAEAAAAcc3RzYw'
-      'AAAAAAAAABAAAAAQAAAAEAAAABAAAAHHN0c3oAAAAAAAAAAAAAAAIAAAK0AAAACwAAAB'
-      'hzdGNvAAAAAAAAAAIAAAAwAAAC5AAAAGB1ZHRhAAAAWG1ldGEAAAAAAAAAIWhkbHIAAA'
-      'AAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAK2lsc3QAAAAjqXRvbwAAABtkYXRhAAAAAQ'
-      'AAAABMYXZmNTMuMjEuMQ==';
-  var webmVideoDataUrl =
-      'data:video/webm;base64,GkXfowEAAAAAAAAfQoaBAUL3gQFC8oEEQvOBCEKChHdlY'
-      'm1Ch4ECQoWBAhhTgGcBAAAAAAAB/hFNm3RALE27i1OrhBVJqWZTrIHfTbuMU6uEFlSua'
-      '1OsggEsTbuMU6uEHFO7a1OsggHk7AEAAAAAAACkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
-      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
-      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
-      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmAQAAAAAAA'
-      'EEq17GDD0JATYCLTGF2ZjUzLjIxLjFXQYtMYXZmNTMuMjEuMXOkkJatuHwTJ7cvFLSzB'
-      'Smxbp5EiYhAVAAAAAAAABZUrmsBAAAAAAAAR64BAAAAAAAAPteBAXPFgQGcgQAitZyDd'
-      'W5khoVWX1ZQOIOBASPjg4QCYloA4AEAAAAAAAASsIEIuoEIVLCBCFS6gQhUsoEDH0O2d'
-      'QEAAAAAAABZ54EAo72BAACA8AIAnQEqCAAIAABHCIWFiIWEiAICAnWqA/gD+gINTRgA/'
-      'v0hRf/kb+PnRv/I4//8WE8DijI//FRAo5WBACgAsQEAARAQABgAGFgv9AAIAAAcU7trA'
-      'QAAAAAAAA67jLOBALeH94EB8YIBfw==';
-
-  setUp(setupFunc);
-  tearDown(tearDownFunc);
-
-  test('with 3 params', () {
-    video.onCanPlay.listen(expectAsync((_) {
-      context.drawImage(video, 50, 50);
-
-      expectPixelFilled(50, 50);
-      expectPixelFilled(54, 54);
-      expectPixelFilled(57, 57);
-      expectPixelUnfilled(58, 58);
-      expectPixelUnfilled(0, 0);
-      expectPixelUnfilled(70, 70);
-    }));
-
-    video.onError.listen((_) {
-      fail('URL failed to load.');
-    });
-
-    if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
-      video.src = webmVideoUrl;
-    } else if (video.canPlayType(
-            'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
-        '') {
-      video.src = mp4VideoUrl;
-    } else {
-      window.console.log('Video is not supported on this system.');
-    }
-  });
-
-  test('with 5 params', () {
-    video.onCanPlay.listen(expectAsync((_) {
-      context.drawImageToRect(video, new Rectangle(50, 50, 20, 20));
-
-      expectPixelFilled(50, 50);
-      expectPixelFilled(55, 55);
-      expectPixelFilled(59, 59);
-      expectPixelFilled(60, 60);
-      expectPixelFilled(69, 69);
-      expectPixelUnfilled(70, 70);
-      expectPixelUnfilled(0, 0);
-      expectPixelUnfilled(80, 80);
-    }));
-    video.onError.listen((_) {
-      fail('URL failed to load.');
-    });
-
-    if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
-      video.src = webmVideoUrl;
-    } else if (video.canPlayType(
-            'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
-        '') {
-      video.src = mp4VideoUrl;
-    } else {
-      // TODO(amouravski): Better fallback?
-      window.console.log('Video is not supported on this system.');
-    }
-  });
-
-  test('with 9 params', () {
-    video.onCanPlay.listen(expectAsync((_) {
-      context.drawImageToRect(video, new Rectangle(50, 50, 20, 20),
-          sourceRect: new Rectangle(2, 2, 6, 6));
-
-      expectPixelFilled(50, 50);
-      expectPixelFilled(55, 55);
-      expectPixelFilled(59, 59);
-      expectPixelFilled(60, 60);
-      expectPixelFilled(69, 69);
-      expectPixelUnfilled(70, 70);
-      expectPixelUnfilled(0, 0);
-      expectPixelUnfilled(80, 80);
-    }));
-    video.onError.listen((_) {
-      fail('URL failed to load.');
-    });
-
-    if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
-      video.src = webmVideoUrl;
-    } else if (video.canPlayType(
-            'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
-        '') {
-      video.src = mp4VideoUrl;
-    } else {
-      // TODO(amouravski): Better fallback?
-      window.console.log('Video is not supported on this system.');
-    }
-  });
-
-  test('dataurl with 9 params', () {
-    video = new VideoElement();
-    canvas = new CanvasElement();
-    video.onCanPlay.listen(expectAsync((_) {
-      context.drawImageToRect(video, new Rectangle(50, 50, 20, 20),
-          sourceRect: new Rectangle(2, 2, 6, 6));
-
-      expectPixelFilled(50, 50);
-      expectPixelFilled(55, 55);
-      expectPixelFilled(59, 59);
-      expectPixelFilled(60, 60);
-      expectPixelFilled(69, 69);
-      expectPixelUnfilled(70, 70);
-      expectPixelUnfilled(0, 0);
-      expectPixelUnfilled(80, 80);
-    }));
-    video.onError.listen((_) {
-      fail('URL failed to load.');
-    });
-
-    if (video.canPlayType('video/webm; codecs="vp8.0, vorbis"', '') != '') {
-      video.src = webmVideoDataUrl;
-    } else if (video.canPlayType(
-            'video/mp4; codecs="avc1.4D401E, mp4a.40.2"', null) !=
-        '') {
-      video.src = mp4VideoDataUrl;
-    } else {
-      // TODO(amouravski): Better fallback?
-      window.console.log('Video is not supported on this system.');
-    }
+  asyncTest(() async {
+    await testWithThreeParams();
+    await testWithFiveParams();
+    await testWithNineParams();
+    await testDataUrlWithNineParams();
   });
 }
diff --git a/tests/lib_2/html/canvasrendering/image_element_test.dart b/tests/lib_2/html/canvasrendering/image_element_test.dart
index 1eac2b9..a1d8040 100644
--- a/tests/lib_2/html/canvasrendering/image_element_test.dart
+++ b/tests/lib_2/html/canvasrendering/image_element_test.dart
@@ -4,91 +4,105 @@
 
 library canvas_rendering_context_2d_test;
 
+import 'dart:async';
 import 'dart:html';
 import 'dart:math';
 
 import 'canvas_rendering_util.dart';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_helper.dart';
+
+Future testWithThreeParams() async {
+  setupFunc();
+  // Draw an image to the canvas from an image element.
+  var dataUrl = otherCanvas.toDataUrl('image/gif');
+  var img = new ImageElement();
+
+  var loadedFuture = img.onLoad.first;
+  img.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+  img.src = dataUrl;
+
+  await loadedFuture;
+  context.drawImage(img, 50, 50);
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelUnfilled(60, 60);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(70, 70);
+  tearDownFunc();
+}
+
+Future testWithFiveParams() async {
+  setupFunc();
+  // Draw an image to the canvas from an image element and scale it.
+  var dataUrl = otherCanvas.toDataUrl('image/gif');
+  var img = new ImageElement();
+
+  var loadedFuture = img.onLoad.first;
+  img.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+  img.src = dataUrl;
+
+  await loadedFuture;
+  context.drawImageToRect(img, new Rectangle(50, 50, 20, 20));
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelFilled(60, 60);
+  expectPixelFilled(69, 69);
+  expectPixelUnfilled(70, 70);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(80, 80);
+  tearDownFunc();
+}
+
+Future testWithNineParams() async {
+  setupFunc();
+  // Draw an image to the canvas from an image element and scale it.
+  otherContext.fillStyle = "blue";
+  otherContext.fillRect(5, 5, 5, 5);
+  var dataUrl = otherCanvas.toDataUrl('image/gif');
+  var img = new ImageElement();
+
+  var loadedFuture = img.onLoad.first;
+  img.onError.listen((_) {
+    throw ('URL failed to load.');
+  });
+  img.src = dataUrl;
+
+  await loadedFuture;
+  // This will take a 6x6 square from the first canvas from position 2,2
+  // and then scale it to a 20x20 square and place it to the second
+  // canvas at 50,50.
+  context.drawImageToRect(img, new Rectangle(50, 50, 20, 20),
+      sourceRect: new Rectangle(2, 2, 6, 6));
+
+  checkPixel(readPixel(50, 50), [255, 0, 0, 255]);
+  checkPixel(readPixel(55, 55), [255, 0, 0, 255]);
+  checkPixel(readPixel(60, 50), [255, 0, 0, 255]);
+  checkPixel(readPixel(65, 65), [0, 0, 255, 255]);
+  checkPixel(readPixel(69, 69), [0, 0, 255, 255]);
+
+  expectPixelFilled(50, 50);
+  expectPixelFilled(55, 55);
+  expectPixelFilled(59, 59);
+  expectPixelFilled(60, 60);
+  expectPixelFilled(69, 69);
+  expectPixelUnfilled(70, 70);
+  expectPixelUnfilled(0, 0);
+  expectPixelUnfilled(80, 80);
+  tearDownFunc();
+}
 
 main() {
-  setUp(setupFunc);
-  tearDown(tearDownFunc);
-  // Draw an image to the canvas from an image element.
-  test('with 3 params', () {
-    var dataUrl = otherCanvas.toDataUrl('image/gif');
-    var img = new ImageElement();
-
-    img.onLoad.listen(expectAsync((_) {
-      context.drawImage(img, 50, 50);
-
-      expectPixelFilled(50, 50);
-      expectPixelFilled(55, 55);
-      expectPixelFilled(59, 59);
-      expectPixelUnfilled(60, 60);
-      expectPixelUnfilled(0, 0);
-      expectPixelUnfilled(70, 70);
-    }));
-    img.onError.listen((_) {
-      fail('URL failed to load.');
-    });
-    img.src = dataUrl;
-  });
-
-  // Draw an image to the canvas from an image element and scale it.
-  test('with 5 params', () {
-    var dataUrl = otherCanvas.toDataUrl('image/gif');
-    var img = new ImageElement();
-
-    img.onLoad.listen(expectAsync((_) {
-      context.drawImageToRect(img, new Rectangle(50, 50, 20, 20));
-
-      expectPixelFilled(50, 50);
-      expectPixelFilled(55, 55);
-      expectPixelFilled(59, 59);
-      expectPixelFilled(60, 60);
-      expectPixelFilled(69, 69);
-      expectPixelUnfilled(70, 70);
-      expectPixelUnfilled(0, 0);
-      expectPixelUnfilled(80, 80);
-    }));
-    img.onError.listen((_) {
-      fail('URL failed to load.');
-    });
-    img.src = dataUrl;
-  });
-
-  // Draw an image to the canvas from an image element and scale it.
-  test('with 9 params', () {
-    otherContext.fillStyle = "blue";
-    otherContext.fillRect(5, 5, 5, 5);
-    var dataUrl = otherCanvas.toDataUrl('image/gif');
-    var img = new ImageElement();
-
-    img.onLoad.listen(expectAsync((_) {
-      // This will take a 6x6 square from the first canvas from position 2,2
-      // and then scale it to a 20x20 square and place it to the second
-      // canvas at 50,50.
-      context.drawImageToRect(img, new Rectangle(50, 50, 20, 20),
-          sourceRect: new Rectangle(2, 2, 6, 6));
-
-      checkPixel(readPixel(50, 50), [255, 0, 0, 255]);
-      checkPixel(readPixel(55, 55), [255, 0, 0, 255]);
-      checkPixel(readPixel(60, 50), [255, 0, 0, 255]);
-      checkPixel(readPixel(65, 65), [0, 0, 255, 255]);
-      checkPixel(readPixel(69, 69), [0, 0, 255, 255]);
-
-      expectPixelFilled(50, 50);
-      expectPixelFilled(55, 55);
-      expectPixelFilled(59, 59);
-      expectPixelFilled(60, 60);
-      expectPixelFilled(69, 69);
-      expectPixelUnfilled(70, 70);
-      expectPixelUnfilled(0, 0);
-      expectPixelUnfilled(80, 80);
-    }));
-    img.onError.listen((_) {
-      fail('URL failed to load.');
-    });
-    img.src = dataUrl;
+  asyncTest(() async {
+    await testWithThreeParams();
+    await testWithFiveParams();
+    await testWithNineParams();
   });
 }
diff --git a/tools/VERSION b/tools/VERSION
index 94e07ba..e997a23 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
 MAJOR 2
 MINOR 8
 PATCH 0
-PRERELEASE 14
+PRERELEASE 15
 PRERELEASE_PATCH 0
 ABI_VERSION 29
 OLDEST_SUPPORTED_ABI_VERSION 29