Version 2.9.0-5.0.dev

Merge commit '8c96812bec49947e2e70c788568fac9e36d33814' into dev
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 9a6403f..35fc3b9 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-03-11T09:16:09.767708",
+  "generated": "2020-04-21T17:36:03.446742",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -66,19 +66,18 @@
       "name": "args",
       "rootUri": "../third_party/pkg/args",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.3"
     },
     {
       "name": "async",
       "rootUri": "../third_party/pkg/async",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.2"
     },
     {
       "name": "async_helper",
       "rootUri": "../pkg/async_helper",
-      "packageUri": "lib/",
-      "languageVersion": "2.7"
+      "packageUri": "lib/"
     },
     {
       "name": "bazel_worker",
@@ -117,12 +116,6 @@
       "languageVersion": "2.0"
     },
     {
-      "name": "code_transformers",
-      "rootUri": "../third_party/pkg/code_transformers",
-      "packageUri": "lib/",
-      "languageVersion": "1.0"
-    },
-    {
       "name": "collection",
       "rootUri": "../third_party/pkg/collection",
       "packageUri": "lib/",
@@ -180,7 +173,7 @@
       "name": "dart_style",
       "rootUri": "../third_party/pkg_tested/dart_style",
       "packageUri": "lib/",
-      "languageVersion": "2.3"
+      "languageVersion": "2.7"
     },
     {
       "name": "dartdev",
@@ -192,7 +185,7 @@
       "name": "dartdoc",
       "rootUri": "../third_party/pkg/dartdoc",
       "packageUri": "lib/",
-      "languageVersion": "2.6"
+      "languageVersion": "2.7"
     },
     {
       "name": "dartfix",
@@ -204,7 +197,7 @@
       "name": "dds",
       "rootUri": "../pkg/dds",
       "packageUri": "lib/",
-      "languageVersion": "2.3"
+      "languageVersion": "2.6"
     },
     {
       "name": "dev_compiler",
@@ -221,8 +214,7 @@
     {
       "name": "expect",
       "rootUri": "../pkg/expect",
-      "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "packageUri": "lib/"
     },
     {
       "name": "ffi",
@@ -274,12 +266,6 @@
       "languageVersion": "2.7"
     },
     {
-      "name": "func",
-      "rootUri": "../third_party/pkg/func",
-      "packageUri": "lib/",
-      "languageVersion": "1.9"
-    },
-    {
       "name": "gardening",
       "rootUri": "../tools/gardening",
       "packageUri": "lib/",
@@ -334,16 +320,10 @@
       "languageVersion": "2.0"
     },
     {
-      "name": "initialize",
-      "rootUri": "../third_party/pkg/initialize",
-      "packageUri": "lib/",
-      "languageVersion": "1.9"
-    },
-    {
       "name": "intl",
       "rootUri": "../third_party/pkg/intl",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.5"
     },
     {
       "name": "js",
@@ -379,7 +359,7 @@
       "name": "linter",
       "rootUri": "../third_party/pkg/linter",
       "packageUri": "lib/",
-      "languageVersion": "2.2"
+      "languageVersion": "2.6"
     },
     {
       "name": "logging",
@@ -406,12 +386,6 @@
       "languageVersion": "1.12"
     },
     {
-      "name": "metatest",
-      "rootUri": "../third_party/pkg/metatest",
-      "packageUri": "lib/",
-      "languageVersion": "1.8"
-    },
-    {
       "name": "mime",
       "rootUri": "../third_party/pkg/mime",
       "packageUri": "lib/",
@@ -454,12 +428,6 @@
       "languageVersion": "2.0"
     },
     {
-      "name": "observable",
-      "rootUri": "../third_party/pkg/observable",
-      "packageUri": "lib/",
-      "languageVersion": "1.19"
-    },
-    {
       "name": "observatory",
       "rootUri": "../runtime/observatory",
       "packageUri": "lib/",
@@ -471,12 +439,6 @@
       "languageVersion": "2.7"
     },
     {
-      "name": "observe",
-      "rootUri": "../third_party/pkg/observe",
-      "packageUri": "lib/",
-      "languageVersion": "1.9"
-    },
-    {
       "name": "package_config",
       "rootUri": "../third_party/pkg_tested/package_config",
       "packageUri": "lib/",
@@ -495,30 +457,12 @@
       "languageVersion": "2.1"
     },
     {
-      "name": "platform",
-      "rootUri": "../third_party/pkg/platform",
-      "packageUri": "lib/",
-      "languageVersion": "1.24"
-    },
-    {
-      "name": "plugin",
-      "rootUri": "../third_party/pkg/plugin",
-      "packageUri": "lib/",
-      "languageVersion": "1.0"
-    },
-    {
       "name": "pool",
       "rootUri": "../third_party/pkg/pool",
       "packageUri": "lib/",
       "languageVersion": "2.0"
     },
     {
-      "name": "process",
-      "rootUri": "../third_party/pkg/process",
-      "packageUri": "lib/",
-      "languageVersion": "2.0"
-    },
-    {
       "name": "protobuf",
       "rootUri": "../third_party/pkg/protobuf/protobuf",
       "packageUri": "lib/",
@@ -534,7 +478,7 @@
       "name": "pub_semver",
       "rootUri": "../third_party/pkg/pub_semver",
       "packageUri": "lib/",
-      "languageVersion": "1.0"
+      "languageVersion": "2.0"
     },
     {
       "name": "quiver",
@@ -549,12 +493,6 @@
       "languageVersion": "2.0"
     },
     {
-      "name": "scheduled_test",
-      "rootUri": "../third_party/pkg/scheduled_test",
-      "packageUri": "lib/",
-      "languageVersion": "1.22"
-    },
-    {
       "name": "sdk_library_metadata",
       "rootUri": "../sdk/lib/_internal/sdk_library_metadata",
       "packageUri": "lib/",
@@ -570,13 +508,13 @@
       "name": "shelf_packages_handler",
       "rootUri": "../third_party/pkg/shelf_packages_handler",
       "packageUri": "lib/",
-      "languageVersion": "1.22"
+      "languageVersion": "2.0"
     },
     {
       "name": "shelf_proxy",
       "rootUri": "../third_party/pkg/shelf_proxy",
       "packageUri": "lib/",
-      "languageVersion": "2.3"
+      "languageVersion": "2.0"
     },
     {
       "name": "shelf_static",
@@ -597,16 +535,10 @@
       "languageVersion": "2.3"
     },
     {
-      "name": "smoke",
-      "rootUri": "../third_party/pkg/smoke",
-      "packageUri": "lib/",
-      "languageVersion": "1.12"
-    },
-    {
       "name": "source_map_stack_trace",
       "rootUri": "../third_party/pkg/source_map_stack_trace",
       "packageUri": "lib/",
-      "languageVersion": "1.8"
+      "languageVersion": "2.7"
     },
     {
       "name": "source_maps",
@@ -672,19 +604,19 @@
       "name": "test",
       "rootUri": "../third_party/pkg/test/pkgs/test",
       "packageUri": "lib/",
-      "languageVersion": "2.2"
+      "languageVersion": "2.7"
     },
     {
       "name": "test_api",
       "rootUri": "../third_party/pkg/test/pkgs/test_api",
       "packageUri": "lib/",
-      "languageVersion": "2.1"
+      "languageVersion": "2.7"
     },
     {
       "name": "test_core",
       "rootUri": "../third_party/pkg/test/pkgs/test_core",
       "packageUri": "lib/",
-      "languageVersion": "2.1"
+      "languageVersion": "2.7"
     },
     {
       "name": "test_descriptor",
@@ -723,12 +655,6 @@
       "languageVersion": "2.6"
     },
     {
-      "name": "tuple",
-      "rootUri": "../third_party/pkg/tuple",
-      "packageUri": "lib/",
-      "languageVersion": "1.6"
-    },
-    {
       "name": "typed_data",
       "rootUri": "../third_party/pkg/typed_data",
       "packageUri": "lib/",
@@ -741,12 +667,6 @@
       "languageVersion": "2.0"
     },
     {
-      "name": "utf",
-      "rootUri": "../third_party/pkg/utf",
-      "packageUri": "lib/",
-      "languageVersion": "2.0"
-    },
-    {
       "name": "vm",
       "rootUri": "../pkg/vm",
       "packageUri": "lib/",
@@ -762,7 +682,7 @@
       "name": "watcher",
       "rootUri": "../third_party/pkg/watcher",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.2"
     },
     {
       "name": "web_components",
@@ -783,4 +703,4 @@
       "languageVersion": "2.0"
     }
   ]
-}
+}
\ No newline at end of file
diff --git a/DEPS b/DEPS
index 13150cf..c9b6ebe 100644
--- a/DEPS
+++ b/DEPS
@@ -90,7 +90,7 @@
   "ffi_tag": "ea88d71b043ee14b268c3aedff14e9eb32e20959",
   "fixnum_tag": "eb3748663dc979271ff6a3d014fbe522543b1d91",
   "glob_tag": "e9f4e6b7ae8abe5071461cf8f47191bb19cf7ef6",
-  "html_tag" : "0.14.0+1",
+  "html_tag": "083a36cd801a4b787ba156b7c6e4c8b2e2daed4a",
   "http_io_rev": "2fa188caf7937e313026557713f7feffedd4978b",
   "http_multi_server_rev" : "ea269f79321d659208402088f3297e8920a88ee6",
   "http_parser_tag" : "3.1.3",
@@ -109,13 +109,13 @@
   "matcher_tag": "af4fe7daf8e94a46981e4f072872be550a6969e9",
   "mime_tag": "179b5e6a88f4b63f36dc1b8fcbc1e83e5e0cd3a7",
   "mockito_tag": "d39ac507483b9891165e422ec98d9fb480037c8b",
-  "mustache_tag" : "5e81b12215566dbe2473b2afd01a8a8aedd56ad9",
-  "oauth2_tag": "1.2.1",
+  "mustache_tag": "664737ecad027e6b96d0d1e627257efa0e46fcb1",
+  "oauth2_tag": "1.6.0",
   "package_config_tag": "v1.9.2",
   "path_tag": "1.7.0",
   "pedantic_tag": "v1.9.0",
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
-  "pool_tag": "1.3.6",
+  "pool_tag": "86fbb2cde9bbc66c8d159909d2f65a5981ea5b50",
   "protobuf_rev": "3746c8fd3f2b0147623a8e3db89c3ff4330de760",
   "pub_rev": "3606265962da4248d34d352aa3d170aae4496a90",
   "pub_semver_tag": "v1.4.4",
@@ -130,7 +130,7 @@
   "shelf_web_socket_tag": "0.2.2+3",
   "source_map_stack_trace_tag": "2.0.0",
   "source_maps-0.9.4_rev": "38524",
-  "source_maps_tag": "8af7cc1a1c3a193c1fba5993ce22a546a319c40e",
+  "source_maps_tag": "87b4fd9027378bbd51b02e9d7df794eee8a82b7a",
   "source_span_tag": "1.7.0",
   "stack_trace_tag": "1.9.3",
   "stagehand_tag": "v3.3.7",
@@ -138,7 +138,7 @@
   "string_scanner_tag": "1.0.3",
   "test_descriptor_tag": "1.1.1",
   "test_process_tag": "1.0.3",
-  "term_glyph_tag": "1.0.1",
+  "term_glyph_tag": "b3da31e9684a99cfe5f192b89914492018b44da7",
   "test_reflective_loader_tag": "0.1.9",
   "test_tag": "test_core-v0.3.2",
   "tflite_native_rev": "3c777c40608a2a9f1427bfe0028ab48e7116b4c1",
@@ -146,9 +146,9 @@
   "usage_tag": "3.4.0",
   "watcher_rev": "fc3c9aae5d31d707b3013b42634dde8d8a1161b4",
   "web_components_rev": "8f57dac273412a7172c8ade6f361b407e2e4ed02",
-  "web_socket_channel_tag": "1.1.0",
+  "web_socket_channel_tag": "490061ef0e22d3c8460ad2802f9948219365ad6b",
   "WebCore_rev": "fb11e887f77919450e497344da570d780e078bc8",
-  "yaml_tag": "2.2.0",
+  "yaml_tag": "62e9f6b3a933b1f76dd3007d1a5ce0be8e429b2d",
   "zlib_rev": "c44fb7248079cc3d5563b14b3f758aee60d6b415",
   "crashpad_rev": "bf327d8ceb6a669607b0dbab5a83a275d03f99ed",
   "minichromium_rev": "8d641e30a8b12088649606b912c2bc4947419ccc",
diff --git a/benchmarks/RuntimeType/dart/RuntimeType.dart b/benchmarks/RuntimeType/dart/RuntimeType.dart
new file mode 100644
index 0000000..fe21b30
--- /dev/null
+++ b/benchmarks/RuntimeType/dart/RuntimeType.dart
@@ -0,0 +1,176 @@
+// 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.
+//
+// Benchmark for runtimeType patterns as used in Flutter.
+
+// ignore_for_file: prefer_const_constructors
+// ignore_for_file: avoid_function_literals_in_foreach_calls
+
+import 'dart:typed_data';
+
+import 'package:benchmark_harness/benchmark_harness.dart';
+
+abstract class Key {
+  const factory Key(String value) = ValueKey<String>;
+  const Key.empty();
+}
+
+abstract class LocalKey extends Key {
+  const LocalKey() : super.empty();
+}
+
+class ValueKey<T> extends LocalKey {
+  const ValueKey(this.value);
+  final T value;
+  @override
+  bool operator ==(Object other) {
+    if (other.runtimeType != runtimeType) return false;
+    return other is ValueKey<T> && other.value == value;
+  }
+
+  @override
+  int get hashCode => value.hashCode;
+}
+
+abstract class Widget {
+  const Widget({this.key});
+  final Key key;
+
+  @pragma('dart2js:noInline')
+  static bool canUpdate(Widget oldWidget, Widget newWidget) {
+    return oldWidget.runtimeType == newWidget.runtimeType &&
+        oldWidget.key == newWidget.key;
+  }
+}
+
+class AWidget extends Widget {
+  const AWidget({Key key}) : super(key: key);
+}
+
+class BWidget extends Widget {
+  const BWidget({Key key}) : super(key: key);
+}
+
+class CWidget extends Widget {
+  const CWidget({Key key}) : super(key: key);
+}
+
+class DWidget extends Widget {
+  const DWidget({Key key}) : super(key: key);
+}
+
+class EWidget extends Widget {
+  const EWidget({Key key}) : super(key: key);
+}
+
+class FWidget extends Widget {
+  const FWidget({Key key}) : super(key: key);
+}
+
+class WWidget<W extends Widget> extends Widget {
+  final W /*?*/ ref;
+  const WWidget({this.ref, Key key}) : super(key: key);
+}
+
+class WidgetCanUpdateBenchmark extends BenchmarkBase {
+  WidgetCanUpdateBenchmark() : super('RuntimeType.Widget.canUpdate.byType');
+
+  // All widgets have different types.
+  static List<Widget> _widgets() => [
+        AWidget(),
+        BWidget(),
+        CWidget(),
+        DWidget(),
+        EWidget(),
+        FWidget(),
+        WWidget<AWidget>(),
+        WWidget<BWidget>(ref: const BWidget()),
+        WWidget<CWidget>(ref: CWidget()),
+        const WWidget<DWidget>(ref: DWidget()),
+      ];
+  // Bulk up list to reduce loop overheads.
+  final List<Widget> widgets = _widgets() + _widgets() + _widgets();
+
+  @override
+  void exercise() => run();
+
+  @override
+  void run() {
+    for (var w1 in widgets) {
+      for (var w2 in widgets) {
+        if (Widget.canUpdate(w1, w2) != Widget.canUpdate(w2, w1)) {
+          throw 'Hmm $w1 $w2';
+        }
+      }
+    }
+  }
+
+  // Normalize by number of calls to [Widgets.canUpdate].
+  @override
+  double measure() => super.measure() / (widgets.length * widgets.length * 2);
+}
+
+class ValueKeyEqualBenchmark extends BenchmarkBase {
+  ValueKeyEqualBenchmark() : super('RuntimeType.Widget.canUpdate.byKey');
+
+  // All widgets the same class but distinguished on keys.
+  static List<Widget> _widgets() => [
+        AWidget(),
+        AWidget(key: ValueKey(1)),
+        AWidget(key: ValueKey(1)),
+        AWidget(key: ValueKey(2)),
+        AWidget(key: ValueKey(2)),
+        AWidget(key: ValueKey(3)),
+        AWidget(key: ValueKey('one')),
+        AWidget(key: ValueKey('two')),
+        AWidget(key: ValueKey('three')),
+        AWidget(key: ValueKey(Duration(seconds: 5))),
+      ];
+  // Bulk up list to reduce loop overheads.
+  final List<Widget> widgets = _widgets() + _widgets() + _widgets();
+
+  @override
+  void exercise() => run();
+
+  @override
+  void run() {
+    for (var w1 in widgets) {
+      for (var w2 in widgets) {
+        if (Widget.canUpdate(w1, w2) != Widget.canUpdate(w2, w1)) {
+          throw 'Hmm $w1 $w2';
+        }
+      }
+    }
+  }
+
+  // Normalize by number of calls to [Widgets.canUpdate].
+  @override
+  double measure() => super.measure() / (widgets.length * widgets.length * 2);
+}
+
+void pollute() {
+  // Various bits of code to make environment less unrealistic.
+  void check(dynamic a, dynamic b) {
+    if (a.runtimeType != b.runtimeType) throw 'mismatch $a $b';
+  }
+
+  check(Uint8List(1), Uint8List(2)); // dart2js needs native interceptors.
+  check(Int16List(1), Int16List(2));
+  check([], []);
+  check(<bool>{}, <bool>{});
+}
+
+void main() {
+  pollute();
+
+  final benchmarks = [
+    WidgetCanUpdateBenchmark(),
+    ValueKeyEqualBenchmark(),
+  ];
+
+  // Warm up all benchmarks before running any.
+  benchmarks.forEach((bm) => bm.run());
+
+  benchmarks.forEach((bm) => bm.report());
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/factory_type_test_helper.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/factory_type_test_helper.dart
index cc28dc3..1980d46 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/factory_type_test_helper.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/factory_type_test_helper.dart
@@ -6,6 +6,7 @@
   Type futureNone(Type type);
   Type futureOrNone(Type type);
 
+  Type get dynamicType;
   Type get intNone;
   Type get intQuestion;
   Type get intStar;
@@ -19,6 +20,11 @@
   Type get stringQuestion;
   Type get stringStar;
   Type get nullNone;
+  Type get voidType;
+
+  void test_dynamic() {
+    check(dynamicType, intNone, 'dynamic');
+  }
 
   void test_futureOr() {
     check(futureOrNone(intNone), intNone, 'Future<int>');
@@ -95,6 +101,10 @@
     check(intStar, stringStar, 'int');
   }
 
+  void test_void() {
+    check(voidType, intNone, 'void');
+  }
+
   Type factor(Type T, Type S);
 
   void expect(Type T, Type S, String actualResult, String expectedResult);
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 fbacec0..b274629 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
@@ -1376,26 +1376,65 @@
     if (info.writeCaptured) {
       return new ExpressionInfo<Variable, Type>(this, this, this);
     }
+
     Type previousType = info.promotedTypes?.last;
     previousType ??= typeOperations.variableType(variable);
-    Type type = typeOperations.promoteToNonNull(previousType);
-    if (typeOperations.isSameType(type, previousType)) {
+
+    Type newType = typeOperations.promoteToNonNull(previousType);
+    if (typeOperations.isSameType(newType, previousType)) {
       return new ExpressionInfo<Variable, Type>(this, this, this);
     }
-    assert(typeOperations.isSubtypeOf(type, previousType));
-    return _finishTypeTest(typeOperations, variable, info, type);
+    assert(typeOperations.isSubtypeOf(newType, previousType));
+
+    FlowModel<Variable, Type> modelIfSuccessful =
+        _finishTypeTest(typeOperations, variable, info, null, newType);
+
+    FlowModel<Variable, Type> modelIfFailed = this;
+
+    return new ExpressionInfo<Variable, Type>(
+        this, modelIfSuccessful, modelIfFailed);
   }
 
-  /// Returns an [ExpressionInfo] indicating the result of checking whether the
-  /// given [variable] satisfies the given [type], e.g. as a consequence of an
-  /// `is` expression as the condition of an `if` statement.
+  /// Returns an [ExpressionInfo] indicating the result of casting the given
+  /// [variable] to the given [type], as a consequence of an `as` expression.
   ///
   /// Note that the state is only changed if [type] is a subtype of the
   /// variable's previous (possibly promoted) type.
   ///
   /// TODO(paulberry): if the type is non-nullable, should this method mark the
   /// variable as definitely assigned?  Does it matter?
-  ExpressionInfo<Variable, Type> tryPromote(
+  FlowModel<Variable, Type> tryPromoteForTypeCast(
+      TypeOperations<Variable, Type> typeOperations,
+      Variable variable,
+      Type type) {
+    VariableModel<Type> info = infoFor(variable);
+    if (info.writeCaptured) {
+      return this;
+    }
+
+    Type previousType = info.promotedTypes?.last;
+    previousType ??= typeOperations.variableType(variable);
+
+    Type newType = typeOperations.tryPromoteToType(type, previousType);
+    if (newType == null || typeOperations.isSameType(newType, previousType)) {
+      return this;
+    }
+
+    assert(typeOperations.isSubtypeOf(newType, previousType),
+        "Expected $newType to be a subtype of $previousType.");
+    return _finishTypeTest(typeOperations, variable, info, type, newType);
+  }
+
+  /// Returns an [ExpressionInfo] indicating the result of checking whether the
+  /// given [variable] satisfies the given [type], e.g. as a consequence of an
+  /// `is` expression as the condition of an `if` statement.
+  ///
+  /// Note that the "ifTrue" state is only changed if [type] is a subtype of
+  /// the variable's previous (possibly promoted) type.
+  ///
+  /// TODO(paulberry): if the type is non-nullable, should this method mark the
+  /// variable as definitely assigned?  Does it matter?
+  ExpressionInfo<Variable, Type> tryPromoteForTypeCheck(
       TypeOperations<Variable, Type> typeOperations,
       Variable variable,
       Type type) {
@@ -1403,16 +1442,29 @@
     if (info.writeCaptured) {
       return new ExpressionInfo<Variable, Type>(this, this, this);
     }
+
     Type previousType = info.promotedTypes?.last;
     previousType ??= typeOperations.variableType(variable);
 
-    Type newType = typeOperations.tryPromoteToType(type, previousType);
-    if (newType == null || typeOperations.isSameType(newType, previousType)) {
-      return new ExpressionInfo<Variable, Type>(this, this, this);
+    FlowModel<Variable, Type> modelIfSuccessful = this;
+    Type typeIfSuccess = typeOperations.tryPromoteToType(type, previousType);
+    if (typeIfSuccess != null &&
+        !typeOperations.isSameType(typeIfSuccess, previousType)) {
+      assert(typeOperations.isSubtypeOf(typeIfSuccess, previousType),
+          "Expected $typeIfSuccess to be a subtype of $previousType.");
+      modelIfSuccessful =
+          _finishTypeTest(typeOperations, variable, info, type, typeIfSuccess);
     }
-    assert(typeOperations.isSubtypeOf(newType, previousType),
-        "Expected $newType to be a subtype of $previousType.");
-    return _finishTypeTest(typeOperations, variable, info, newType);
+
+    Type factoredType = typeOperations.factor(previousType, type);
+    Type typeIfFailed = typeOperations.isSameType(factoredType, previousType)
+        ? null
+        : factoredType;
+    FlowModel<Variable, Type> modelIfFailed =
+        _finishTypeTest(typeOperations, variable, info, type, typeIfFailed);
+
+    return new ExpressionInfo<Variable, Type>(
+        this, modelIfSuccessful, modelIfFailed);
   }
 
   /// Updates the state to indicate that an assignment was made to the given
@@ -1431,38 +1483,43 @@
     return _updateVariableInfo(variable, newInfoForVar);
   }
 
-  /// Common algorithm for [tryMarkNonNullable] and [tryPromote].  Builds an
-  /// [ExpressionInfo] object describing the effect of trying to promote
-  /// [variable] to [testedType], under the following preconditions:
+  /// Common algorithm for [tryMarkNonNullable], [tryPromoteForTypeCast],
+  /// and [tryPromoteForTypeCheck].  Builds a [FlowModel] object describing the
+  /// effect of updating the [variable] by adding the [testedType] to the
+  /// list of tested types (if not `null`, and not there already), adding the
+  /// [promotedType] to the chain of promoted types.
+  ///
+  /// Preconditions:
   /// - [info] should be the result of calling `infoFor(variable)`
-  /// - [testedType] should be a subtype of the currently-promoted type (i.e.
+  /// - [promotedType] should be a subtype of the currently-promoted type (i.e.
   ///   no redundant or side-promotions)
   /// - The variable should not be write-captured.
-  ExpressionInfo<Variable, Type> _finishTypeTest(
-      TypeOperations<Variable, Type> typeOperations,
-      Variable variable,
-      VariableModel<Type> info,
-      Type testedType) {
-    List<Type> newPromotedTypes =
-        VariableModel._addToPromotedTypes(info.promotedTypes, testedType);
-    List<Type> newTested = VariableModel._addTypeToUniqueList(
-        info.tested, testedType, typeOperations);
-    FlowModel<Variable, Type> modelIfFailed = identical(newTested, info.tested)
+  FlowModel<Variable, Type> _finishTypeTest(
+    TypeOperations<Variable, Type> typeOperations,
+    Variable variable,
+    VariableModel<Type> info,
+    Type testedType,
+    Type promotedType,
+  ) {
+    List<Type> newTested = info.tested;
+    if (testedType != null) {
+      newTested = VariableModel._addTypeToUniqueList(
+          info.tested, testedType, typeOperations);
+    }
+
+    List<Type> newPromotedTypes = info.promotedTypes;
+    if (promotedType != null) {
+      newPromotedTypes =
+          VariableModel._addToPromotedTypes(info.promotedTypes, promotedType);
+    }
+
+    return identical(newTested, info.tested) &&
+            identical(newPromotedTypes, info.promotedTypes)
         ? this
         : _updateVariableInfo(
             variable,
-            new VariableModel<Type>(info.promotedTypes, newTested,
-                info.assigned, info.unassigned, info.writeCaptured));
-    FlowModel<Variable, Type> modelIfSuccessful =
-        identical(newPromotedTypes, info.promotedTypes) &&
-                identical(newTested, info.tested)
-            ? this
-            : _updateVariableInfo(
-                variable,
-                new VariableModel<Type>(newPromotedTypes, newTested,
-                    info.assigned, info.unassigned, info.writeCaptured));
-    return new ExpressionInfo<Variable, Type>(
-        this, modelIfSuccessful, modelIfFailed);
+            new VariableModel<Type>(newPromotedTypes, newTested, info.assigned,
+                info.unassigned, info.writeCaptured));
   }
 
   /// Returns a new [FlowModel] where the information for [variable] is replaced
@@ -1579,6 +1636,10 @@
 
 /// Operations on types, abstracted from concrete type interfaces.
 abstract class TypeOperations<Variable, Type> {
+  /// Returns the "remainder" of [from] when [what] has been removed from
+  /// consideration by an instance check.
+  Type factor(Type from, Type what);
+
   /// Returns `true` if [type1] and [type2] are the same type.
   bool isSameType(Type type1, Type type2);
 
@@ -2160,7 +2221,7 @@
     } else {
       return;
     }
-    _current = _current.tryPromote(typeOperations, variable, type).ifTrue;
+    _current = _current.tryPromoteForTypeCast(typeOperations, variable, type);
   }
 
   @override
@@ -2468,7 +2529,7 @@
       return;
     }
     ExpressionInfo<Variable, Type> expressionInfo =
-        _current.tryPromote(typeOperations, variable, type);
+        _current.tryPromoteForTypeCheck(typeOperations, variable, type);
     _storeExpressionInfo(isExpression,
         isNot ? ExpressionInfo.invert(expressionInfo) : expressionInfo);
   }
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 ae5b0e2..4c34d93 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -2908,29 +2908,33 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
+        String string,
         String
-            string)> templateExperimentNotEnabled = const Template<
-        Message Function(String string)>(
+            string2)> templateExperimentNotEnabled = const Template<
+        Message Function(String string, String string2)>(
     messageTemplate:
-        r"""This requires the '#string' experiment to be enabled.""",
+        r"""This requires the '#string' language feature to be enabled.""",
     tipTemplate:
-        r"""Try enabling this experiment by adding it to the command line when compiling and running.""",
+        r"""Try updating your pubspec.yaml to set the minimum SDK constraint to #string2 or higher, and running 'pub get'.""",
     withArguments: _withArgumentsExperimentNotEnabled);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)> codeExperimentNotEnabled =
-    const Code<Message Function(String string)>(
+const Code<Message Function(String string, String string2)>
+    codeExperimentNotEnabled =
+    const Code<Message Function(String string, String string2)>(
         "ExperimentNotEnabled", templateExperimentNotEnabled,
         index: 48);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExperimentNotEnabled(String string) {
+Message _withArgumentsExperimentNotEnabled(String string, String string2) {
   if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
   return new Message(codeExperimentNotEnabled,
-      message: """This requires the '${string}' experiment to be enabled.""",
+      message:
+          """This requires the '${string}' language feature to be enabled.""",
       tip:
-          """Try enabling this experiment by adding it to the command line when compiling and running.""",
-      arguments: {'string': string});
+          """Try updating your pubspec.yaml to set the minimum SDK constraint to ${string2} or higher, and running 'pub get'.""",
+      arguments: {'string': string, 'string2': string2});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
index 45ed3dbd0..0877766 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
@@ -1213,7 +1213,7 @@
   void reportVarianceModifierNotEnabled(Token variance) {
     if (variance != null) {
       handleRecoverableError(
-          templateExperimentNotEnabled.withArguments('variance'),
+          templateExperimentNotEnabled.withArguments('variance', '2.9'),
           variance,
           variance);
     }
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 b3ad6f5..13ab757 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -2482,7 +2482,7 @@
         reportRecoverableError(
             beforeType.next,
             codes.templateExperimentNotEnabled
-                .withArguments('extension-methods'));
+                .withArguments('extension-methods', '2.6'));
         token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
       } else {
         token = ensureSemicolon(token);
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 8676e22..16800f0 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
@@ -789,10 +789,14 @@
       });
     });
 
-    void _checkIs(String declaredType, String tryPromoteType,
-        String expectedPromotedType) {
+    void _checkIs(
+      String declaredType,
+      String tryPromoteType,
+      String expectedPromotedTypeThen,
+      String expectedPromotedTypeElse,
+    ) {
       var h = _Harness();
-      var x = h.addVar('x', 'int?');
+      var x = h.addVar('x', declaredType);
       h.run((flow) {
         h.declare(x, initialized: true);
         var read = _Expression();
@@ -800,27 +804,31 @@
         var expr = _Expression();
         flow.isExpression_end(expr, read, false, _Type(tryPromoteType));
         flow.ifStatement_thenBegin(expr);
-        if (expectedPromotedType == null) {
+        if (expectedPromotedTypeThen == null) {
           expect(flow.promotedType(x), isNull);
         } else {
-          expect(flow.promotedType(x).type, expectedPromotedType);
+          expect(flow.promotedType(x).type, expectedPromotedTypeThen);
         }
         flow.ifStatement_elseBegin();
-        expect(flow.promotedType(x), isNull);
+        if (expectedPromotedTypeElse == null) {
+          expect(flow.promotedType(x), isNull);
+        } else {
+          expect(flow.promotedType(x).type, expectedPromotedTypeElse);
+        }
         flow.ifStatement_end(true);
       });
     }
 
     test('isExpression_end promotes to a subtype', () {
-      _checkIs('int?', 'int', 'int');
+      _checkIs('int?', 'int', 'int', 'Never?');
     });
 
     test('isExpression_end does not promote to a supertype', () {
-      _checkIs('int', 'int?', null);
+      _checkIs('int', 'int?', null, 'Never');
     });
 
     test('isExpression_end does not promote to an unrelated type', () {
-      _checkIs('int', 'String', null);
+      _checkIs('int', 'String', null, null);
     });
 
     test('isExpression_end() does not promote write-captured vars', () {
@@ -1748,32 +1756,32 @@
       });
     });
 
-    group('promote', () {
+    group('tryPromoteForTypeCheck', () {
       test('unpromoted -> unchanged (same)', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true);
-        var s2 = s1.tryPromote(h, intVar, _Type('int')).ifTrue;
+        var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('int')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> unchanged (supertype)', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true);
-        var s2 = s1.tryPromote(h, intVar, _Type('Object')).ifTrue;
+        var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('Object')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> unchanged (unrelated)', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true);
-        var s2 = s1.tryPromote(h, intVar, _Type('String')).ifTrue;
+        var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('String')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> subtype', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true);
-        var s2 = s1.tryPromote(h, intQVar, _Type('int')).ifTrue;
+        var s2 = s1.tryPromoteForTypeCheck(h, intQVar, _Type('int')).ifTrue;
         expect(s2.reachable, true);
         expect(s2.variableInfo, {
           intQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int'])
@@ -1783,36 +1791,38 @@
       test('promoted -> unchanged (same)', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .tryPromote(h, objectQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
-        var s2 = s1.tryPromote(h, objectQVar, _Type('int')).ifTrue;
+        var s2 = s1.tryPromoteForTypeCheck(h, objectQVar, _Type('int')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('promoted -> unchanged (supertype)', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .tryPromote(h, objectQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
-        var s2 = s1.tryPromote(h, objectQVar, _Type('Object')).ifTrue;
+        var s2 =
+            s1.tryPromoteForTypeCheck(h, objectQVar, _Type('Object')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('promoted -> unchanged (unrelated)', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .tryPromote(h, objectQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
-        var s2 = s1.tryPromote(h, objectQVar, _Type('String')).ifTrue;
+        var s2 =
+            s1.tryPromoteForTypeCheck(h, objectQVar, _Type('String')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('promoted -> subtype', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .tryPromote(h, objectQVar, _Type('int?'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
             .ifTrue;
-        var s2 = s1.tryPromote(h, objectQVar, _Type('int')).ifTrue;
+        var s2 = s1.tryPromoteForTypeCheck(h, objectQVar, _Type('int')).ifTrue;
         expect(s2.reachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -1857,7 +1867,7 @@
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
             .declare(objectQVar, true)
-            .tryPromote(h, objectQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         expect(s1.variableInfo, contains(objectQVar));
         var s2 = s1.write(objectQVar, _Type('int?'), h);
@@ -1875,9 +1885,9 @@
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
             .declare(objectQVar, true)
-            .tryPromote(h, objectQVar, _Type('num?'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
-            .tryPromote(h, objectQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         expect(s1.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -1901,11 +1911,11 @@
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
             .declare(objectQVar, true)
-            .tryPromote(h, objectQVar, _Type('num?'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
-            .tryPromote(h, objectQVar, _Type('num'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('num'))
             .ifTrue
-            .tryPromote(h, objectQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         expect(s1.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -1929,9 +1939,9 @@
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
             .declare(objectQVar, true)
-            .tryPromote(h, objectQVar, _Type('num?'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
-            .tryPromote(h, objectQVar, _Type('num'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('num'))
             .ifTrue;
         expect(s1.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -1949,9 +1959,9 @@
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
             .declare(objectQVar, true)
-            .tryPromote(h, objectQVar, _Type('num?'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
-            .tryPromote(h, objectQVar, _Type('num'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('num'))
             .ifTrue;
         expect(s1.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -2006,7 +2016,7 @@
           var h = _Harness();
           var s1 = FlowModel<_Var, _Type>(true)
               .declare(objectQVar, true)
-              .tryPromote(h, objectQVar, _Type('int?'))
+              .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
               .ifTrue;
           expect(s1.variableInfo, {
             objectQVar: _matchVariableModel(
@@ -2027,18 +2037,18 @@
           var h = _Harness();
           var s1 = FlowModel<_Var, _Type>(true)
               .declare(objectQVar, true)
-              .tryPromote(h, objectQVar, _Type('int?'))
+              .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
               .ifFalse;
           expect(s1.variableInfo, {
             objectQVar: _matchVariableModel(
-              chain: null,
+              chain: ['Object'],
               ofInterest: ['int?'],
             ),
           });
           var s2 = s1.write(objectQVar, _Type('int'), h);
           expect(s2.variableInfo, {
             objectQVar: _matchVariableModel(
-              chain: ['int'],
+              chain: ['Object', 'int'],
               ofInterest: ['int?'],
             ),
           });
@@ -2049,14 +2059,20 @@
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
             .declare(objectQVar, true)
-            .tryPromote(h, objectQVar, _Type('num?'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifFalse;
         expect(s1.variableInfo, {
-          objectQVar: _matchVariableModel(chain: null, ofInterest: ['num?'])
+          objectQVar: _matchVariableModel(
+            chain: ['Object'],
+            ofInterest: ['num?'],
+          ),
         });
         var s2 = s1.write(objectQVar, _Type('num?'), h);
         expect(s2.variableInfo, {
-          objectQVar: _matchVariableModel(chain: ['num?'], ofInterest: ['num?'])
+          objectQVar: _matchVariableModel(
+            chain: ['num?'],
+            ofInterest: ['num?'],
+          ),
         });
       });
 
@@ -2064,18 +2080,22 @@
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
             .declare(objectQVar, true)
-            .tryPromote(h, objectQVar, _Type('num?'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
-            .tryPromote(h, objectQVar, _Type('int?'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
             .ifFalse;
         expect(s1.variableInfo, {
-          objectQVar:
-              _matchVariableModel(chain: ['num?'], ofInterest: ['num?', 'int?'])
+          objectQVar: _matchVariableModel(
+            chain: ['num?', 'num'],
+            ofInterest: ['num?', 'int?'],
+          ),
         });
         var s2 = s1.write(objectQVar, _Type('int?'), h);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
-              chain: ['num?', 'int?'], ofInterest: ['num?', 'int?'])
+            chain: ['num?', 'int?'],
+            ofInterest: ['num?', 'int?'],
+          ),
         });
       });
 
@@ -2095,6 +2115,7 @@
             h.addSubtype(_Type('A'), _Type('Object'), true);
             h.addSubtype(_Type('A'), _Type('Object?'), true);
             h.addSubtype(_Type('A'), _Type('A?'), true);
+            h.addSubtype(_Type('A'), _Type('B'), false);
             h.addSubtype(_Type('A'), _Type('B?'), false);
             h.addSubtype(_Type('A?'), _Type('Object'), false);
             h.addSubtype(_Type('A?'), _Type('Object?'), true);
@@ -2114,6 +2135,12 @@
             h.addSubtype(_Type('C'), _Type('A?'), true);
             h.addSubtype(_Type('C'), _Type('B'), true);
             h.addSubtype(_Type('C'), _Type('B?'), true);
+
+            h.addFactor(_Type('Object'), _Type('A?'), _Type('Object'));
+            h.addFactor(_Type('Object'), _Type('B?'), _Type('Object'));
+            h.addFactor(_Type('Object?'), _Type('A'), _Type('Object?'));
+            h.addFactor(_Type('Object?'), _Type('A?'), _Type('Object'));
+            h.addFactor(_Type('Object?'), _Type('B?'), _Type('Object'));
           });
 
           test('; first', () {
@@ -2121,13 +2148,13 @@
 
             var s1 = FlowModel<_Var, _Type>(true)
                 .declare(x, true)
-                .tryPromote(h, x, _Type('B?'))
+                .tryPromoteForTypeCheck(h, x, _Type('B?'))
                 .ifFalse
-                .tryPromote(h, x, _Type('A?'))
+                .tryPromoteForTypeCheck(h, x, _Type('A?'))
                 .ifFalse;
             expect(s1.variableInfo, {
               x: _matchVariableModel(
-                chain: null,
+                chain: ['Object'],
                 ofInterest: ['A?', 'B?'],
               ),
             });
@@ -2135,7 +2162,7 @@
             var s2 = s1.write(x, _Type('C'), h);
             expect(s2.variableInfo, {
               x: _matchVariableModel(
-                chain: ['B'],
+                chain: ['Object', 'B'],
                 ofInterest: ['A?', 'B?'],
               ),
             });
@@ -2146,13 +2173,13 @@
 
             var s1 = FlowModel<_Var, _Type>(true)
                 .declare(x, true)
-                .tryPromote(h, x, _Type('A?'))
+                .tryPromoteForTypeCheck(h, x, _Type('A?'))
                 .ifFalse
-                .tryPromote(h, x, _Type('B?'))
+                .tryPromoteForTypeCheck(h, x, _Type('B?'))
                 .ifFalse;
             expect(s1.variableInfo, {
               x: _matchVariableModel(
-                chain: null,
+                chain: ['Object'],
                 ofInterest: ['A?', 'B?'],
               ),
             });
@@ -2160,7 +2187,7 @@
             var s2 = s1.write(x, _Type('C'), h);
             expect(s2.variableInfo, {
               x: _matchVariableModel(
-                chain: ['B'],
+                chain: ['Object', 'B'],
                 ofInterest: ['A?', 'B?'],
               ),
             });
@@ -2171,13 +2198,13 @@
 
             var s1 = FlowModel<_Var, _Type>(true)
                 .declare(x, true)
-                .tryPromote(h, x, _Type('A'))
+                .tryPromoteForTypeCheck(h, x, _Type('A'))
                 .ifFalse
-                .tryPromote(h, x, _Type('A?'))
+                .tryPromoteForTypeCheck(h, x, _Type('A?'))
                 .ifFalse;
             expect(s1.variableInfo, {
               x: _matchVariableModel(
-                chain: null,
+                chain: ['Object'],
                 ofInterest: ['A', 'A?'],
               ),
             });
@@ -2185,7 +2212,7 @@
             var s2 = s1.write(x, _Type('B'), h);
             expect(s2.variableInfo, {
               x: _matchVariableModel(
-                chain: ['A'],
+                chain: ['Object', 'A'],
                 ofInterest: ['A', 'A?'],
               ),
             });
@@ -2197,13 +2224,13 @@
             var h = _Harness();
             var s1 = FlowModel<_Var, _Type>(true)
                 .declare(objectQVar, true)
-                .tryPromote(h, objectQVar, _Type('num?'))
+                .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
                 .ifFalse
-                .tryPromote(h, objectQVar, _Type('num*'))
+                .tryPromoteForTypeCheck(h, objectQVar, _Type('num*'))
                 .ifFalse;
             expect(s1.variableInfo, {
               objectQVar: _matchVariableModel(
-                chain: null,
+                chain: ['Object'],
                 ofInterest: ['num?', 'num*'],
               ),
             });
@@ -2218,13 +2245,13 @@
           var h = _Harness();
           var s1 = FlowModel<_Var, _Type>(true)
               .declare(objectQVar, true)
-              .tryPromote(h, objectQVar, _Type('num?'))
+              .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
               .ifFalse
-              .tryPromote(h, objectQVar, _Type('num*'))
+              .tryPromoteForTypeCheck(h, objectQVar, _Type('num*'))
               .ifFalse;
           expect(s1.variableInfo, {
             objectQVar: _matchVariableModel(
-              chain: null,
+              chain: ['Object'],
               ofInterest: ['num?', 'num*'],
             ),
           });
@@ -2273,13 +2300,13 @@
         var s2 = s1.tryMarkNonNullable(h, intQVar).ifTrue;
         expect(s2.reachable, true);
         expect(s2.infoFor(intQVar),
-            _matchVariableModel(chain: ['int'], ofInterest: ['int']));
+            _matchVariableModel(chain: ['int'], ofInterest: []));
       });
 
       test('promoted -> unchanged', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .tryPromote(h, objectQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
         expect(s2, same(s1));
@@ -2288,13 +2315,13 @@
       test('promoted -> re-promoted', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .tryPromote(h, objectQVar, _Type('int?'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
             .ifTrue;
         var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
         expect(s2.reachable, true);
         expect(s2.variableInfo, {
-          objectQVar: _matchVariableModel(
-              chain: ['int?', 'int'], ofInterest: ['int?', 'int'])
+          objectQVar:
+              _matchVariableModel(chain: ['int?', 'int'], ofInterest: ['int?'])
         });
       });
     });
@@ -2412,7 +2439,7 @@
       test('unchanged', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .tryPromote(h, objectQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.removePromotedAll([intQVar], []);
         expect(s2, same(s1));
@@ -2421,9 +2448,9 @@
       test('written', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .tryPromote(h, objectQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue
-            .tryPromote(h, intQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, intQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.removePromotedAll([intQVar], []);
         expect(s2.reachable, true);
@@ -2436,9 +2463,9 @@
       test('write captured', () {
         var h = _Harness();
         var s1 = FlowModel<_Var, _Type>(true)
-            .tryPromote(h, objectQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue
-            .tryPromote(h, intQVar, _Type('int'))
+            .tryPromoteForTypeCheck(h, intQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.removePromotedAll([], [intQVar]);
         expect(s2.reachable, true);
@@ -2522,10 +2549,10 @@
           var s0 = FlowModel<_Var, _Type>(true).declare(x, true);
           var s1 = thisType == null
               ? s0
-              : s0.tryPromote(h, x, _Type(thisType)).ifTrue;
+              : s0.tryPromoteForTypeCheck(h, x, _Type(thisType)).ifTrue;
           var s2 = otherType == null
               ? s0
-              : s0.tryPromote(h, x, _Type(otherType)).ifTrue;
+              : s0.tryPromoteForTypeCheck(h, x, _Type(otherType)).ifTrue;
           var result = s1.restrict(h, s2, unsafe ? [x].toSet() : Set());
           if (expectedChain == null) {
             expect(result.variableInfo, contains(x));
@@ -2573,18 +2600,20 @@
           var x = _Var('x', _Type('Object?'));
           var initialModel = FlowModel<_Var, _Type>(true).declare(x, true);
           for (var t in before) {
-            initialModel = initialModel.tryPromote(h, x, _Type(t)).ifTrue;
+            initialModel =
+                initialModel.tryPromoteForTypeCheck(h, x, _Type(t)).ifTrue;
           }
           _checkChain(initialModel.infoFor(x).promotedTypes, before);
           var tryModel = initialModel;
           for (var t in inTry) {
-            tryModel = tryModel.tryPromote(h, x, _Type(t)).ifTrue;
+            tryModel = tryModel.tryPromoteForTypeCheck(h, x, _Type(t)).ifTrue;
           }
           var expectedTryChain = before.toList()..addAll(inTry);
           _checkChain(tryModel.infoFor(x).promotedTypes, expectedTryChain);
           var finallyModel = initialModel;
           for (var t in inFinally) {
-            finallyModel = finallyModel.tryPromote(h, x, _Type(t)).ifTrue;
+            finallyModel =
+                finallyModel.tryPromoteForTypeCheck(h, x, _Type(t)).ifTrue;
           }
           var expectedFinallyChain = before.toList()..addAll(inFinally);
           _checkChain(
@@ -3090,6 +3119,7 @@
     'int <: num': true,
     'int <: num?': true,
     'int <: num*': true,
+    'int <: Never?': false,
     'int <: Object': true,
     'int <: Object?': true,
     'int <: String': false,
@@ -3121,6 +3151,12 @@
     'List <: int': false,
     'List <: Iterable': true,
     'List <: Object': true,
+    'Never <: int': true,
+    'Never <: int?': true,
+    'Never? <: int': false,
+    'Never? <: int?': true,
+    'Never? <: num?': true,
+    'Never? <: Object?': true,
     'Object <: int': false,
     'Object <: int?': false,
     'Object <: List': false,
@@ -3132,11 +3168,46 @@
     'Object? <: int?': false,
     'String <: int': false,
     'String <: int?': false,
+    'String <: num?': false,
     'String <: Object?': true,
   };
 
+  static final Map<String, _Type> _coreFactors = {
+    'Object? - int': _Type('Object?'),
+    'Object? - int?': _Type('Object'),
+    'Object? - num?': _Type('Object'),
+    'Object? - Object?': _Type('Never?'),
+    'Object? - String': _Type('Object?'),
+    'Object - int': _Type('Object'),
+    'int - Object': _Type('Never'),
+    'int - String': _Type('int'),
+    'int - int': _Type('Never'),
+    'int - int?': _Type('Never'),
+    'int? - int': _Type('Never?'),
+    'int? - int?': _Type('Never'),
+    'int? - String': _Type('int?'),
+    'num - int': _Type('num'),
+    'num? - num': _Type('Never?'),
+    'num? - int': _Type('num?'),
+    'num? - int?': _Type('num'),
+    'num? - Object': _Type('Never?'),
+    'num? - String': _Type('num?'),
+    'Object - int?': _Type('Object'),
+    'Object - num': _Type('Object'),
+    'Object - num?': _Type('Object'),
+    'Object - num*': _Type('Object'),
+    'Object - Iterable': _Type('Object'),
+    'Object? - Object': _Type('Never?'),
+    'Object? - Iterable': _Type('Object?'),
+    'Object? - num': _Type('Object?'),
+    'Iterable - List': _Type('Iterable'),
+    'num* - Object': _Type('Never'),
+  };
+
   final Map<String, bool> _subtypes = Map.of(_coreSubtypes);
 
+  final Map<String, _Type> _factorResults = Map.of(_coreFactors);
+
   FlowAnalysis<_Node, _Statement, _Expression, _Var, _Type> _flow;
 
   final _assignedVariables = AssignedVariables<_Node, _Var>();
@@ -3151,6 +3222,11 @@
         return expr;
       };
 
+  void addFactor(_Type from, _Type what, _Type result) {
+    var query = '$from - $what';
+    _factorResults[query] = result;
+  }
+
   void addSubtype(_Type leftType, _Type rightType, bool isSubtype) {
     var query = '$leftType <: $rightType';
     _subtypes[query] = isSubtype;
@@ -3212,6 +3288,12 @@
     };
   }
 
+  @override
+  _Type factor(_Type from, _Type what) {
+    var query = '$from - $what';
+    return _factorResults[query] ?? fail('Unknown factor query: $query');
+  }
+
   /// Invokes flow analysis of a nested function.
   void function(_Node node, void body()) {
     _flow.functionExpression_begin(node);
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart
index b71d9fb..9b8e497 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart
@@ -19,3 +19,13 @@
 
 int conditional_in_expression_function_body(Object o) =>
     o is int ? /*int*/ o : 0;
+
+void conditional_factor_Null(int? x) {
+  x is Null ? /*Null*/ x : /*int*/ x;
+  x;
+}
+
+void conditional_factor_nullable(num? x) {
+  x is int? ? /*int?*/ x : /*num*/ x;
+  x;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/if.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/if.dart
index e150823..de0fa50 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/if.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/if.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:async';
+
 class A {}
 
 class B extends A {}
@@ -63,6 +65,60 @@
   v;
 }
 
+isType_factor_Null(int? v) {
+  if (v is Null) {
+    /*Null*/ v;
+  } else {
+    /*int*/ v;
+  }
+  v;
+}
+
+isType_factor_nullable(num? v) {
+  if (v is int?) {
+    /*int?*/ v;
+  } else {
+    /*num*/ v;
+  }
+  v;
+}
+
+isType_factor_declaredType(int? v) {
+  if (v is int?) {
+    v;
+  } else {
+    /*Never*/ v;
+  }
+  v;
+}
+
+isType_factor_supertype(int? v) {
+  if (v is num?) {
+    v;
+  } else {
+    /*Never*/ v;
+  }
+  v;
+}
+
+isType_factor_futureOr_future(FutureOr<int> v) {
+  if (v is Future<int>) {
+    /*Future<int>*/ v;
+  } else {
+    /*int*/ v;
+  }
+  v;
+}
+
+isType_factor_futureOr_type(FutureOr<int> v) {
+  if (v is int) {
+    /*int*/ v;
+  } else {
+    /*Future<int>*/ v;
+  }
+  v;
+}
+
 isType_thenNonBoolean(Object x) {
   if ((x is String) != 3) {
     x;
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_in.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_in.dart
index ce65245..0ee78c7 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_in.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_in.dart
@@ -56,57 +56,49 @@
 
 /*class: F1:A,C,F1,Object*/
 class F1 extends A implements C {
-  /*cfe|cfe:builder.member: F1.method:void Function(void, {void named})*/
-  /*analyzer.member: F1.method:Object? Function(Object?, {Object? named})*/
+  /*member: F1.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: F2:A,C,F2,Object*/
 class F2 extends C implements A {
-  /*cfe|cfe:builder.member: F2.method:void Function(void, {void named})*/
-  /*analyzer.member: F2.method:Object? Function(Object?, {Object? named})*/
+  /*member: F2.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: F3:A,C,F3,Object*/
 class F3 implements A, C {
-  /*cfe|cfe:builder.member: F3.method:void Function(void, {void named})*/
-  /*analyzer.member: F3.method:Object? Function(Object?, {Object? named})*/
+  /*member: F3.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: F4:A,C,F4,Object*/
 class F4 implements C, A {
-  /*cfe|cfe:builder.member: F4.method:void Function(void, {void named})*/
-  /*analyzer.member: F4.method:Object? Function(Object?, {Object? named})*/
+  /*member: F4.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: G1:A,B,C,G1,Object*/
 class G1 extends B implements C {
-  /*cfe|cfe:builder.member: G1.method:void Function(void, {void named})*/
-  /*analyzer.member: G1.method:Object? Function(Object?, {Object? named})*/
+  /*member: G1.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: G2:A,B,C,G2,Object*/
 class G2 extends C implements B {
-  /*cfe|cfe:builder.member: G2.method:void Function(void, {void named})*/
-  /*analyzer.member: G2.method:Object? Function(Object?, {Object? named})*/
+  /*member: G2.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: G3:A,B,C,G3,Object*/
 class G3 implements B, C {
-  /*cfe|cfe:builder.member: G3.method:void Function(void, {void named})*/
-  /*analyzer.member: G3.method:Object? Function(Object?, {Object? named})*/
+  /*member: G3.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
 /*class: G4:A,B,C,G4,Object*/
 class G4 implements C, B {
-  /*cfe|cfe:builder.member: G4.method:void Function(void, {void named})*/
-  /*analyzer.member: G4.method:Object? Function(Object?, {Object? named})*/
+  /*member: G4.method:Object? Function(Object?, {Object? named})*/
   method(o, {named}) {}
 }
 
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481.dart
index a388a8d..5b56249 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481.dart
@@ -19,8 +19,7 @@
 /*class: B1:A<Object?>,A_Object,A_dynamic,B1,Object*/
 class B1 extends A_Object implements A_dynamic {}
 
-/*cfe|cfe:builder.class: B2:A<void>,A_Object,A_void,B2,Object*/
-/*analyzer.class: B2:A<Object?>,A_Object,A_void,B2,Object*/
+/*class: B2:A<Object?>,A_Object,A_void,B2,Object*/
 class B2 extends A_Object implements A_void {}
 
 main() {}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481/main.dart
index a84f5d1..6468993 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481/main.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40481/main.dart
@@ -15,8 +15,7 @@
 /*class: B1:A<Object?>,A_Object,A_dynamic,B1,Object*/
 class B1 extends A_Object implements A_dynamic {}
 
-/*cfe|cfe:builder.class: B2:A<void>,A_Object,A_void,B2,Object*/
-/*analyzer.class: B2:A<Object?>,A_Object,A_void,B2,Object*/
+/*class: B2:A<Object?>,A_Object,A_void,B2,Object*/
 class B2 extends A_Object implements A_void {}
 
 main() {}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_direct.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_direct.dart
new file mode 100644
index 0000000..bb1b4ab
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_direct.dart
@@ -0,0 +1,47 @@
+// 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.
+
+/*library: nnbd=true*/
+
+/*class: A:A<T>,Object*/
+class A<T> {
+  /*member: A.member:T Function()*/
+  T member() => throw "Unreachable";
+}
+
+/*class: B:A<T>,B<T>,Object*/
+/*member: B.member:T Function()*/
+class B<T> extends A<T> {}
+
+/*class: D0:A<Object?>,B<Object?>,D0,Object*/
+/*member: D0.member:Object? Function()*/
+class D0 extends A<dynamic> implements B<Object?> {}
+
+/*class: D1:A<Object?>,B<dynamic>,D1,Object*/
+/*member: D1.member:Object? Function()*/
+class D1 extends A<Object?> implements B<dynamic> {}
+
+/*class: D2:A<Object?>,B<Object?>,D2,Object*/
+/*member: D2.member:Object? Function()*/
+class D2 extends A<void> implements B<Object?> {}
+
+/*class: D3:A<Object?>,B<void>,D3,Object*/
+/*member: D3.member:Object? Function()*/
+class D3 extends A<Object?> implements B<void> {}
+
+/*class: D4:A<Object?>,B<dynamic>,D4,Object*/
+/*member: D4.member:Object? Function()*/
+class D4 extends A<void> implements B<dynamic> {}
+
+/*class: D5:A<Object?>,B<void>,D5,Object*/
+/*member: D5.member:Object? Function()*/
+class D5 extends A<dynamic> implements B<void> {}
+
+/*class: D6:A<void>,B<void>,D6,Object*/
+/*member: D6.member:void Function()*/
+class D6 extends A<void> implements B<void> {}
+
+/*class: D7:A<dynamic>,B<dynamic>,D7,Object*/
+/*member: D7.member:dynamic Function()*/
+class D7 extends A<dynamic> implements B<dynamic> {}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_mixin.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_mixin.dart
new file mode 100644
index 0000000..597a802
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_mixin.dart
@@ -0,0 +1,49 @@
+// 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.
+
+/*library: nnbd=true*/
+
+/*class: A:A<T>,Object*/
+abstract class A<T> {
+  /*member: A.member:T Function()*/
+  T member();
+}
+
+/*cfe|cfe:builder.class: B:B<T>,Object*/
+/*cfe|cfe:builder.member: B.member:T Function()*/
+mixin B<T> {
+  T member();
+}
+
+/*class: D0:A<dynamic>,B<Object?>,D0,Object*/
+/*member: D0.member:Object? Function()*/
+abstract class D0 extends A<dynamic> with B<Object?> {}
+
+/*class: D1:A<Object?>,B<dynamic>,D1,Object*/
+/*member: D1.member:dynamic Function()*/
+abstract class D1 extends A<Object?> with B<dynamic> {}
+
+/*class: D2:A<void>,B<Object?>,D2,Object*/
+/*member: D2.member:Object? Function()*/
+abstract class D2 extends A<void> with B<Object?> {}
+
+/*class: D3:A<Object?>,B<void>,D3,Object*/
+/*member: D3.member:void Function()*/
+abstract class D3 extends A<Object?> with B<void> {}
+
+/*class: D4:A<void>,B<dynamic>,D4,Object*/
+/*member: D4.member:dynamic Function()*/
+abstract class D4 extends A<void> with B<dynamic> {}
+
+/*class: D5:A<dynamic>,B<void>,D5,Object*/
+/*member: D5.member:void Function()*/
+abstract class D5 extends A<dynamic> with B<void> {}
+
+/*class: D6:A<void>,B<void>,D6,Object*/
+/*member: D6.member:void Function()*/
+abstract class D6 extends A<void> with B<void> {}
+
+/*class: D7:A<dynamic>,B<dynamic>,D7,Object*/
+/*member: D7.member:dynamic Function()*/
+abstract class D7 extends A<dynamic> with B<dynamic> {}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_opt_in.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_opt_in.dart
index bd4dc1f..3845f87 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_opt_in.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_opt_in.dart
@@ -32,8 +32,7 @@
 
 /*class: E1:A,B,C,D,E1,Object*/
 abstract class E1 implements A, B, C, D {
-  /*cfe|cfe:builder.member: E1.method:void Function(void)*/
-  /*analyzer.member: E1.method:Object? Function(Object?)*/
+  /*member: E1.method:Object? Function(Object?)*/
 }
 
 /*class: E2:A,B,E2,Object*/
@@ -43,14 +42,12 @@
 
 /*class: E3:B,C,E3,Object*/
 abstract class E3 implements B, C {
-  /*cfe|cfe:builder.member: E3.method:void Function(void)*/
-  /*analyzer.member: E3.method:Object? Function(Object?)*/
+  /*member: E3.method:Object? Function(Object?)*/
 }
 
 /*class: E4:A,C,E4,Object*/
 abstract class E4 implements A, C {
-  /*cfe|cfe:builder.member: E4.method:void Function(void)*/
-  /*analyzer.member: E4.method:Object? Function(Object?)*/
+  /*member: E4.method:Object? Function(Object?)*/
 }
 
 /*class: E5:A,D,E5,Object*/
@@ -71,24 +68,20 @@
 
 /*class: G1:A,C,F,G1,Object*/
 abstract class G1 implements A, C, F {
-  /*cfe|cfe:builder.member: G1.method:void Function(void)*/
-  /*analyzer.member: G1.method:Object? Function(Object?)*/
+  /*member: G1.method:Object? Function(Object?)*/
 }
 
 /*class: G2:A,C,F,G2,Object*/
 abstract class G2 implements A, F, C {
-  /*cfe|cfe:builder.member: G2.method:void Function(void)*/
-  /*analyzer.member: G2.method:Object? Function(Object?)*/
+  /*member: G2.method:Object? Function(Object?)*/
 }
 
 /*class: G3:A,C,F,G3,Object*/
 abstract class G3 implements C, A, F {
-  /*cfe|cfe:builder.member: G3.method:void Function(void)*/
-  /*analyzer.member: G3.method:Object? Function(Object?)*/
+  /*member: G3.method:Object? Function(Object?)*/
 }
 
 /*class: G4:A,C,F,G4,Object*/
 abstract class G4 implements C, F, A {
-  /*cfe|cfe:builder.member: G4.method:void Function(void)*/
-  /*analyzer.member: G4.method:Object? Function(Object?)*/
+  /*member: G4.method:Object? Function(Object?)*/
 }
diff --git a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
index 89432f8..1f83281 100644
--- a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
@@ -47,6 +47,9 @@
   /// which all included paths share.
   final String includedRoot;
 
+  /// Indicates whether the web preview of migration results should be launched.
+  final bool enablePreview;
+
   /// The HTTP server that serves the preview tool.
   HttpPreviewServer _server;
 
@@ -70,7 +73,9 @@
   Future<void> Function([List<String>]) rerunFunction;
 
   NonNullableFix(this.listener,
-      {List<String> included = const [], this.preferredPort})
+      {List<String> included = const [],
+      this.preferredPort,
+      this.enablePreview = true})
       : includedRoot =
             _getIncludedRoot(included, listener.server.resourceProvider) {
     reset();
@@ -96,7 +101,7 @@
         migration, includedRoot, listener, instrumentationListener);
     await state.refresh();
 
-    if (_server == null) {
+    if (enablePreview && _server == null) {
       _server = HttpPreviewServer(state, rerun, preferredPort);
       _server.serveHttp();
       port = await _server.boundPort;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart
index db8e83f..b559a08 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart
@@ -26,12 +26,35 @@
     if (directive is NamespaceDirective) {
       var library = directive.uriElement as LibraryElement;
       if (library != null) {
+        var existingNames = _getCombinatorNames(directive);
         for (var element in library.exportNamespace.definedNames.values) {
-          builder.suggestElement(element,
-              kind: CompletionSuggestionKind.IDENTIFIER);
+          if (!existingNames.contains(element.name)) {
+            builder.suggestElement(element,
+                kind: CompletionSuggestionKind.IDENTIFIER);
+          }
         }
       }
     }
     return const <CompletionSuggestion>[];
   }
+
+  List<String> _getCombinatorNames(NamespaceDirective directive) {
+    var combinatorNameList = <String>[];
+    for (var combinator in directive.combinators) {
+      if (combinator is ShowCombinator) {
+        for (var simpleId in combinator.shownNames) {
+          if (!simpleId.isSynthetic) {
+            combinatorNameList.add(simpleId.name);
+          }
+        }
+      } else if (combinator is HideCombinator) {
+        for (var simpleId in combinator.hiddenNames) {
+          if (!simpleId.isSynthetic) {
+            combinatorNameList.add(simpleId.name);
+          }
+        }
+      }
+    }
+    return combinatorNameList;
+  }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
index d7c061b..bcc6898 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
@@ -8,8 +8,6 @@
     show CompletionSuggestion, CompletionSuggestionKind;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:analysis_server/src/services/completion/dart/utilities.dart';
-import 'package:analysis_server/src/utilities/flutter.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -80,11 +78,10 @@
         }
       } else {
         if (opType.includeVoidReturnSuggestions) {
-          var suggestion = memberBuilder.addSuggestionForMethod(
+          memberBuilder.addSuggestionForMethod(
               method: method,
               inheritanceDistance: inheritanceDistance,
               kind: kind);
-          _updateFlutterSuggestions(request, method, suggestion);
         }
       }
     }
@@ -128,35 +125,4 @@
     }
     return null;
   }
-
-  void _updateFlutterSuggestions(DartCompletionRequest request, Element element,
-      CompletionSuggestion suggestion) {
-    if (suggestion == null) {
-      return;
-    }
-    if (element is MethodElement &&
-        element.name == 'setState' &&
-        Flutter.of(request.result).isExactState(element.enclosingElement)) {
-      // Find the line indentation.
-      var indent = getRequestLineIndent(request);
-
-      // Let the user know that we are going to insert a complete statement.
-      suggestion.displayText = 'setState(() {});';
-
-      // Build the completion and the selection offset.
-      var buffer = StringBuffer();
-      buffer.writeln('setState(() {');
-      buffer.write('$indent  ');
-      suggestion.selectionOffset = buffer.length;
-      buffer.writeln();
-      buffer.write('$indent});');
-      suggestion.completion = buffer.toString();
-
-      // There are no arguments to fill.
-      suggestion.parameterNames = null;
-      suggestion.parameterTypes = null;
-      suggestion.requiredParameterCount = null;
-      suggestion.hasNamedParameters = null;
-    }
-  }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 43ae5ba..e7e5e69 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -13,6 +13,7 @@
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
+import 'package:analysis_server/src/utilities/flutter.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
@@ -293,94 +294,25 @@
   }
 
   /// Add a suggestion for the given [method].
-  CompletionSuggestion addSuggestionForMethod(
+  void addSuggestionForMethod(
       {@required MethodElement method,
       String containingMethodName,
       CompletionSuggestionKind kind,
       @required double inheritanceDistance}) {
-    int oldRelevance() {
-      if (method.hasDeprecated) {
-        return DART_RELEVANCE_LOW;
-      } else if (method.name == containingMethodName) {
-        // Boost the relevance of a super expression calling a method of the
-        // same name as the containing method.
-        return DART_RELEVANCE_HIGH;
-      }
-      var identifier = method.displayName;
-      if (identifier != null && identifier.startsWith(r'$')) {
-        // Decrease relevance of suggestions starting with $
-        // https://github.com/dart-lang/sdk/issues/27303
-        return DART_RELEVANCE_LOW;
-      }
-      return DART_RELEVANCE_DEFAULT;
+    if (method.isAccessibleIn(request.libraryElement) &&
+        _shouldAddSuggestion(method)) {
+      builder.suggestMethod(method,
+          containingMethodName: containingMethodName,
+          kind: kind,
+          inheritanceDistance: inheritanceDistance);
     }
-
-    if (!method.isAccessibleIn(request.libraryElement)) {
-      // Don't suggest private members from imported libraries.
-      return null;
-    }
-    int relevance;
-    if (request.useNewRelevance) {
-      var featureComputer = request.featureComputer;
-      var contextType = featureComputer.contextTypeFeature(
-          request.contextType, method.returnType);
-      var hasDeprecated = featureComputer.hasDeprecatedFeature(method);
-      var startsWithDollar =
-          featureComputer.startsWithDollarFeature(method.name);
-      var superMatches = featureComputer.superMatchesFeature(
-          containingMethodName, method.name);
-      relevance = _computeRelevance(
-          contextType: contextType,
-          hasDeprecated: hasDeprecated,
-          inheritanceDistance: inheritanceDistance,
-          startsWithDollar: startsWithDollar,
-          superMatches: superMatches);
-    } else {
-      relevance = oldRelevance();
-    }
-    return _addSuggestion(method, relevance, kind: kind);
   }
 
   /// Add a suggestion for the given [element] with the given [relevance],
   /// provided that it is not shadowed by a previously added suggestion.
   CompletionSuggestion _addSuggestion(Element element, int relevance,
       {CompletionSuggestionKind kind}) {
-    var identifier = element.displayName;
-
-    var alreadyGenerated = _completionTypesGenerated.putIfAbsent(
-        identifier, () => _COMPLETION_TYPE_NONE);
-    if (element is MethodElement) {
-      // Anything shadows a method.
-      if (alreadyGenerated != _COMPLETION_TYPE_NONE) {
-        return null;
-      }
-      _completionTypesGenerated[identifier] =
-          _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET;
-    } else if (element is PropertyAccessorElement) {
-      if (element.isGetter) {
-        // Getters, fields, and methods shadow a getter.
-        if ((alreadyGenerated & _COMPLETION_TYPE_GETTER) != 0) {
-          return null;
-        }
-        _completionTypesGenerated[identifier] |= _COMPLETION_TYPE_GETTER;
-      } else {
-        // Setters, fields, and methods shadow a setter.
-        if ((alreadyGenerated & _COMPLETION_TYPE_SETTER) != 0) {
-          return null;
-        }
-        _completionTypesGenerated[identifier] |= _COMPLETION_TYPE_SETTER;
-      }
-    } else if (element is FieldElement) {
-      // Fields and methods shadow a field.  A getter/setter pair shadows a
-      // field, but a getter or setter by itself doesn't.
-      if (alreadyGenerated == _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET) {
-        return null;
-      }
-      _completionTypesGenerated[identifier] =
-          _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET;
-    } else {
-      // Unexpected element type; skip it.
-      assert(false);
+    if (!_shouldAddSuggestion(element)) {
       return null;
     }
     var suggestion =
@@ -422,6 +354,49 @@
     ]);
     return toRelevance(score, Relevance.member);
   }
+
+  /// Return `true` if a suggestion for the given [element] should be created.
+  bool _shouldAddSuggestion(Element element) {
+    var identifier = element.displayName;
+
+    var alreadyGenerated = _completionTypesGenerated.putIfAbsent(
+        identifier, () => _COMPLETION_TYPE_NONE);
+    if (element is MethodElement) {
+      // Anything shadows a method.
+      if (alreadyGenerated != _COMPLETION_TYPE_NONE) {
+        return false;
+      }
+      _completionTypesGenerated[identifier] =
+          _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET;
+    } else if (element is PropertyAccessorElement) {
+      if (element.isGetter) {
+        // Getters, fields, and methods shadow a getter.
+        if ((alreadyGenerated & _COMPLETION_TYPE_GETTER) != 0) {
+          return false;
+        }
+        _completionTypesGenerated[identifier] |= _COMPLETION_TYPE_GETTER;
+      } else {
+        // Setters, fields, and methods shadow a setter.
+        if ((alreadyGenerated & _COMPLETION_TYPE_SETTER) != 0) {
+          return false;
+        }
+        _completionTypesGenerated[identifier] |= _COMPLETION_TYPE_SETTER;
+      }
+    } else if (element is FieldElement) {
+      // Fields and methods shadow a field.  A getter/setter pair shadows a
+      // field, but a getter or setter by itself doesn't.
+      if (alreadyGenerated == _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET) {
+        return false;
+      }
+      _completionTypesGenerated[identifier] =
+          _COMPLETION_TYPE_FIELD_OR_METHOD_OR_GETSET;
+    } else {
+      // Unexpected element type; skip it.
+      assert(false);
+      return false;
+    }
+    return true;
+  }
 }
 
 /// An object used to build a list of suggestions in response to a single
@@ -442,10 +417,18 @@
   /// `false`.
   DartType _cachedContextType;
 
+  /// The cached instance of the flutter utilities, or `null` if it hasn't been
+  /// created yet.
+  Flutter _flutter;
+
   /// Initialize a newly created suggestion builder to build suggestions for the
   /// given [request].
   SuggestionBuilder(this.request);
 
+  /// Return an object that can answer questions about Flutter code based on the
+  /// flavor of Flutter being used.
+  Flutter get flutter => _flutter ??= Flutter.of(request.result);
+
   DartType get _contextType {
     if (!_hasContextType) {
       _hasContextType = true;
@@ -608,6 +591,82 @@
     suggestions.add(createSuggestion(request, function, relevance: relevance));
   }
 
+  void suggestMethod(MethodElement method,
+      {String containingMethodName,
+      CompletionSuggestionKind kind,
+      @required double inheritanceDistance}) {
+    // TODO(brianwilkerson) Refactor callers so that we're passing in the type
+    //  of the target (assuming we don't already have that type available via
+    //  the [request]) and compute the [inheritanceDistance] in this method.
+    int oldRelevance() {
+      if (method.hasDeprecated) {
+        return DART_RELEVANCE_LOW;
+      } else if (method.name == containingMethodName) {
+        // Boost the relevance of a super expression calling a method of the
+        // same name as the containing method.
+        return DART_RELEVANCE_HIGH;
+      }
+      var identifier = method.displayName;
+      if (identifier != null && identifier.startsWith(r'$')) {
+        // Decrease relevance of suggestions starting with $
+        // https://github.com/dart-lang/sdk/issues/27303
+        return DART_RELEVANCE_LOW;
+      }
+      return DART_RELEVANCE_DEFAULT;
+    }
+
+    int relevance;
+    if (request.useNewRelevance) {
+      var featureComputer = request.featureComputer;
+      var contextType = featureComputer.contextTypeFeature(
+          request.contextType, method.returnType);
+      var hasDeprecated = featureComputer.hasDeprecatedFeature(method);
+      var startsWithDollar =
+          featureComputer.startsWithDollarFeature(method.name);
+      var superMatches = featureComputer.superMatchesFeature(
+          containingMethodName, method.name);
+      relevance = _computeMemberRelevance(
+          contextType: contextType,
+          hasDeprecated: hasDeprecated,
+          inheritanceDistance: inheritanceDistance,
+          startsWithDollar: startsWithDollar,
+          superMatches: superMatches);
+    } else {
+      relevance = oldRelevance();
+    }
+
+    var suggestion =
+        createSuggestion(request, method, kind: kind, relevance: relevance);
+    if (suggestion != null) {
+      if (method.name == 'setState' &&
+          flutter.isExactState(method.enclosingElement)) {
+        // TODO(brianwilkerson) Make this more efficient by creating the correct
+        //  suggestion in the first place.
+        // Find the line indentation.
+        var indent = getRequestLineIndent(request);
+
+        // Let the user know that we are going to insert a complete statement.
+        suggestion.displayText = 'setState(() {});';
+
+        // Build the completion and the selection offset.
+        var buffer = StringBuffer();
+        buffer.writeln('setState(() {');
+        buffer.write('$indent  ');
+        suggestion.selectionOffset = buffer.length;
+        buffer.writeln();
+        buffer.write('$indent});');
+        suggestion.completion = buffer.toString();
+
+        // There are no arguments to fill.
+        suggestion.parameterNames = null;
+        suggestion.parameterTypes = null;
+        suggestion.requiredParameterCount = null;
+        suggestion.hasNamedParameters = null;
+      }
+      suggestions.add(suggestion);
+    }
+  }
+
   /// Add a suggestion for the top-level [function].
   void suggestTopLevelFunction(FunctionElement function,
       {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION}) {
@@ -657,6 +716,38 @@
         createSuggestion(request, variable, kind: kind, relevance: relevance));
   }
 
+  /// Compute a relevance value from the given feature scores:
+  /// - [contextType] is higher if the type of the element matches the context
+  ///   type,
+  /// - [hasDeprecated] is higher if the element is not deprecated,
+  /// - [inheritanceDistance] is higher if the element is defined closer to the
+  ///   target type,
+  /// - [startsWithDollar] is higher if the element's name doe _not_ start with
+  ///   a dollar sign, and
+  /// - [superMatches] is higher if the element is being invoked through `super`
+  ///   and the element's name matches the name of the enclosing method.
+  int _computeMemberRelevance(
+      {@required double contextType,
+      @required double hasDeprecated,
+      @required double inheritanceDistance,
+      @required double startsWithDollar,
+      @required double superMatches}) {
+    var score = weightedAverage([
+      contextType,
+      hasDeprecated,
+      inheritanceDistance,
+      startsWithDollar,
+      superMatches
+    ], [
+      1.0,
+      0.5,
+      1.0,
+      0.5,
+      1.0
+    ]);
+    return toRelevance(score, Relevance.member);
+  }
+
   /// Return the relevance score for a top-level [element].
   int _computeTopLevelRelevance(Element element,
       {int defaultRelevance = 800, DartType elementType}) {
diff --git a/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
index 04a362b..ec3822e 100644
--- a/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
@@ -74,6 +74,12 @@
     assertNotSuggested('Object');
   }
 
+  Future<void> test_Combinator_hide_duplicate() async {
+    addTestSource('import "dart:math" hide PI, ^;');
+    await computeSuggestions();
+    assertNotSuggested('PI');
+  }
+
   Future<void> test_Combinator_show() async {
     // SimpleIdentifier  HideCombinator  ImportDirective
     addSource('/home/test/lib/ab.dart', '''
@@ -123,6 +129,12 @@
     assertNotSuggested('Object');
   }
 
+  Future<void> test_Combinator_show_duplicate() async {
+    addTestSource('import "dart:math" show PI, ^;');
+    await computeSuggestions();
+    assertNotSuggested('PI');
+  }
+
   Future<void> test_Combinator_show_export_withShow() async {
     addSource('/home/test/lib/a.dart', r'''
 class A {}
diff --git a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
index 799104d..b043bd3 100644
--- a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
@@ -1924,7 +1924,7 @@
     assertNoSuggestions();
   }
 
-  Future<void> test_extendsClause() async {
+  Future<void> test_ExtendsClause() async {
     newFile('/home/test/lib/a.dart', content: 'class A {}');
     addTestSource('''
 import 'a.dart';
@@ -1935,6 +1935,41 @@
     assertSuggestClass('A');
   }
 
+  Future<void> test_ExtensionDeclaration_extendedType() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    addTestSource('''
+import 'a.dart';
+
+extension E on ^
+''');
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertNotSuggested('E');
+  }
+
+  Future<void> test_ExtensionDeclaration_extendedType2() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    addTestSource('''
+import 'a.dart';
+
+extension E on ^ {}
+''');
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertNotSuggested('E');
+  }
+
+  Future<void> test_ExtensionDeclaration_member() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    addTestSource('''
+import 'a.dart';
+
+extension E on A { ^ }
+''');
+    await computeSuggestions();
+    assertSuggestClass('A');
+  }
+
   Future<void> test_FieldDeclaration_name_typed() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // FieldDeclaration
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index 4ddc388..c9bb123 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -2513,7 +2513,7 @@
     assertNoSuggestions();
   }
 
-  Future<void> test_extendsClause() async {
+  Future<void> test_ExtendsClause() async {
     addTestSource('''
 class A {}
 mixin M {}
@@ -2524,6 +2524,35 @@
     assertNotSuggested('M');
   }
 
+  Future<void> test_ExtensionDeclaration_extendedType() async {
+    addTestSource('''
+class A {}
+extension E on ^
+''');
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertNotSuggested('E');
+  }
+
+  Future<void> test_ExtensionDeclaration_extendedType2() async {
+    addTestSource('''
+class A {}
+extension E on ^ {}
+''');
+    await computeSuggestions();
+    assertSuggestClass('A');
+    assertNotSuggested('E');
+  }
+
+  Future<void> test_ExtensionDeclaration_member() async {
+    addTestSource('''
+class A {}
+extension E on A { ^ }
+''');
+    await computeSuggestions();
+    assertSuggestClass('A');
+  }
+
   Future<void> test_FieldDeclaration_name_typed() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // FieldDeclaration
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 85aeefe..ad33ec7 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -246,9 +246,9 @@
 
 const ParserErrorCode _EXPERIMENT_NOT_ENABLED = ParserErrorCode(
     'EXPERIMENT_NOT_ENABLED',
-    r"This requires the '#string' experiment to be enabled.",
+    r"This requires the '#string' language feature to be enabled.",
     correction:
-        "Try enabling this experiment by adding it to the command line when compiling and running.");
+        "Try updating your pubspec.yaml to set the minimum SDK constraint to #string2 or higher, and running 'pub get'.");
 
 const ParserErrorCode _EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE = ParserErrorCode(
     'EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE',
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 c85c898..19c607e 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -351,6 +351,11 @@
   TypeSystemTypeOperations(this.typeSystem);
 
   @override
+  DartType factor(DartType from, DartType what) {
+    return typeSystem.factor(from, what);
+  }
+
+  @override
   bool isSameType(covariant TypeImpl type1, covariant TypeImpl type2) {
     return type1 == type2;
   }
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 770dd99..efc8d42 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -62,6 +62,7 @@
         TypeParameterImpl;
 import 'package:analyzer/src/fasta/error_converter.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:pub_semver/pub_semver.dart';
 
 const _invalidCollectionElement = _InvalidCollectionElement._();
 
@@ -603,11 +604,15 @@
       reportErrorIfSuper(right);
       push(ast.binaryExpression(left, operatorToken, right));
       if (!enableTripleShift && operatorToken.type == TokenType.GT_GT_GT) {
+        var feature = ExperimentalFeatures.triple_shift;
         handleRecoverableError(
-            templateExperimentNotEnabled
-                .withArguments(EnableString.triple_shift),
-            operatorToken,
-            operatorToken);
+          templateExperimentNotEnabled.withArguments(
+            feature.enableString,
+            _versionAsString(ExperimentStatus.currentVersion),
+          ),
+          operatorToken,
+          operatorToken,
+        );
       }
     }
   }
@@ -2292,10 +2297,15 @@
     }
     push(ast.assignmentExpression(lhs, token, rhs));
     if (!enableTripleShift && token.type == TokenType.GT_GT_GT_EQ) {
+      var feature = ExperimentalFeatures.triple_shift;
       handleRecoverableError(
-          templateExperimentNotEnabled.withArguments(EnableString.triple_shift),
-          token,
-          token);
+        templateExperimentNotEnabled.withArguments(
+          feature.enableString,
+          _versionAsString(ExperimentStatus.currentVersion),
+        ),
+        token,
+        token,
+      );
     }
   }
 
@@ -3328,11 +3338,15 @@
       push(ast.spreadElement(
           spreadOperator: spreadToken, expression: expression));
     } else {
+      var feature = Feature.spread_collections;
       handleRecoverableError(
-          templateExperimentNotEnabled
-              .withArguments(EnableString.spread_collections),
-          spreadToken,
-          spreadToken);
+        templateExperimentNotEnabled.withArguments(
+          feature.enableString,
+          _versionAsString(feature.firstSupportedVersion),
+        ),
+        spreadToken,
+        spreadToken,
+      );
       push(_invalidCollectionElement);
     }
   }
@@ -3547,11 +3561,15 @@
         body: entry as CollectionElement,
       ));
     } else {
+      var feature = Feature.control_flow_collections;
       handleRecoverableError(
-          templateExperimentNotEnabled
-              .withArguments(EnableString.control_flow_collections),
-          forToken,
-          forToken);
+        templateExperimentNotEnabled.withArguments(
+          feature.enableString,
+          _versionAsString(feature.firstSupportedVersion),
+        ),
+        forToken,
+        forToken,
+      );
       push(_invalidCollectionElement);
     }
   }
@@ -3576,11 +3594,15 @@
         elseElement: elseElement,
       ));
     } else {
+      var feature = ExperimentalFeatures.control_flow_collections;
       handleRecoverableError(
-          templateExperimentNotEnabled
-              .withArguments(EnableString.control_flow_collections),
-          ifToken,
-          ifToken);
+        templateExperimentNotEnabled.withArguments(
+          feature.enableString,
+          _versionAsString(feature.firstSupportedVersion),
+        ),
+        ifToken,
+        ifToken,
+      );
       push(_invalidCollectionElement);
     }
   }
@@ -3588,10 +3610,15 @@
   void reportErrorIfNullableType(Token questionMark) {
     if (questionMark != null) {
       assert(optional('?', questionMark));
+      var feature = ExperimentalFeatures.non_nullable;
       handleRecoverableError(
-          templateExperimentNotEnabled.withArguments('non-nullable'),
-          questionMark,
-          questionMark);
+        templateExperimentNotEnabled.withArguments(
+          feature.enableString,
+          _versionAsString(ExperimentStatus.currentVersion),
+        ),
+        questionMark,
+        questionMark,
+      );
     }
   }
 
@@ -3605,16 +3632,28 @@
 
   void reportNonNullableModifierError(Token modifierToken) {
     if (modifierToken != null) {
+      var feature = ExperimentalFeatures.non_nullable;
       handleRecoverableError(
-          templateExperimentNotEnabled.withArguments('non-nullable'),
-          modifierToken,
-          modifierToken);
+        templateExperimentNotEnabled.withArguments(
+          feature.enableString,
+          _versionAsString(ExperimentStatus.currentVersion),
+        ),
+        modifierToken,
+        modifierToken,
+      );
     }
   }
 
   void reportNonNullAssertExpressionNotEnabled(Token bang) {
+    var feature = ExperimentalFeatures.non_nullable;
     handleRecoverableError(
-        templateExperimentNotEnabled.withArguments('non-nullable'), bang, bang);
+      templateExperimentNotEnabled.withArguments(
+        feature.enableString,
+        _versionAsString(ExperimentStatus.currentVersion),
+      ),
+      bang,
+      bang,
+    );
   }
 
   Comment _findComment(List<Annotation> metadata, Token tokenAfterMetadata) {
@@ -3686,6 +3725,10 @@
       return ParameterKind.REQUIRED;
     }
   }
+
+  static String _versionAsString(Version version) {
+    return '${version.major}.${version.minor}.${version.patch}';
+  }
 }
 
 class _ConstructorNameWithInvalidTypeArgs {
diff --git a/pkg/analyzer/test/src/dart/element/factor_type_test.dart b/pkg/analyzer/test/src/dart/element/factor_type_test.dart
index 94a865c..f3ad7cc 100644
--- a/pkg/analyzer/test/src/dart/element/factor_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/factor_type_test.dart
@@ -33,12 +33,13 @@
     );
   }
 
-  void setUp() {
-    var analysisContext = TestAnalysisContext(
-      featureSet: testFeatureSet,
-    );
-    typeProvider = analysisContext.typeProviderNonNullableByDefault;
-    typeSystem = analysisContext.typeSystemNonNullableByDefault;
+  @override
+  DartType get voidType => typeProvider.voidType;
+
+  @override
+  void expect(
+      DartType T, DartType S, String actualResult, String expectedResult) {
+    test.expect(actualResult, expectedResult);
   }
 
   @override
@@ -46,10 +47,12 @@
     return typeSystem.factor(T, S);
   }
 
-  @override
-  void expect(
-      DartType T, DartType S, String actualResult, String expectedResult) {
-    test.expect(actualResult, expectedResult);
+  void setUp() {
+    var analysisContext = TestAnalysisContext(
+      featureSet: testFeatureSet,
+    );
+    typeProvider = analysisContext.typeProviderNonNullableByDefault;
+    typeSystem = analysisContext.typeSystemNonNullableByDefault;
   }
 
   @override
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
index 144b1a3..7e92f7d 100644
--- a/pkg/analyzer/tool/summary/mini_ast.dart
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -11,6 +11,8 @@
 import 'package:_fe_analyzer_shared/src/parser/parser.dart';
 import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart';
 import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:pub_semver/pub_semver.dart';
 
 /// "Mini AST" representation of a declaration which can accept annotations.
 class AnnotatedNode {
@@ -615,16 +617,32 @@
   void reportErrorIfNullableType(Token questionMark) {
     if (questionMark != null) {
       assert(optional('?', questionMark));
+      var feature = ExperimentalFeatures.non_nullable;
       handleRecoverableError(
-          templateExperimentNotEnabled.withArguments('non-nullable'),
-          questionMark,
-          questionMark);
+        templateExperimentNotEnabled.withArguments(
+          feature.enableString,
+          _versionAsString(ExperimentStatus.currentVersion),
+        ),
+        questionMark,
+        questionMark,
+      );
     }
   }
 
   void reportNonNullAssertExpressionNotEnabled(Token bang) {
+    var feature = ExperimentalFeatures.non_nullable;
     handleRecoverableError(
-        templateExperimentNotEnabled.withArguments('non-nullable'), bang, bang);
+      templateExperimentNotEnabled.withArguments(
+        feature.enableString,
+        _versionAsString(ExperimentStatus.currentVersion),
+      ),
+      bang,
+      bang,
+    );
+  }
+
+  static String _versionAsString(Version version) {
+    return '${version.major}.${version.minor}.${version.patch}';
   }
 }
 
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index cf57798..295f5cf 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -1,6 +1,8 @@
 name: analyzer_cli
 description: Command line interface for the Dart Analyzer.
 publish_to: none
+environment:
+  sdk: "^2.7.0"
 dependencies:
   analyzer: ^0.37.0
   args: '>=0.13.0 <2.0.0'
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index adbccee..d138827 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -634,6 +634,7 @@
   void visitExtensionDeclaration(ExtensionDeclaration node) {
     if (identical(entity, node.extendedType)) {
       optype.completionLocation = 'ExtensionDeclaration_extendedType';
+      optype.includeTypeNameSuggestions = true;
     } else if (node.members.contains(entity) ||
         identical(entity, node.rightBracket)) {
       // Make suggestions in the body of the extension declaration
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 07ba9b9..c9f6489 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
@@ -1070,6 +1070,14 @@
         completionLocation: 'ExtensionDeclaration_member', typeNames: true);
   }
 
+  Future<void> test_extensionDeclaration_extendedType() async {
+    // SimpleIdentifier  MethodDeclaration  ExtensionDeclaration
+    addTestSource('extension E on ^ {}');
+    await assertOpType(
+        completionLocation: 'ExtensionDeclaration_extendedType',
+        typeNames: true);
+  }
+
   Future<void> test_extensionOverride_argumentList() async {
     // ExtensionDeclaration  CompilationUnit
     addTestSource('''
diff --git a/pkg/async_helper/lib/async_helper.dart b/pkg/async_helper/lib/async_helper.dart
index d5bcc08..1f3acb1 100644
--- a/pkg/async_helper/lib/async_helper.dart
+++ b/pkg/async_helper/lib/async_helper.dart
@@ -107,7 +107,10 @@
     [bool check(T error) = _pass, String reason = ""]) {
   var type = "";
   if (T != dynamic && T != Object) type = "<$T>";
-  var header = "asyncExpectThrows$type(${reason ?? ''}):";
+  // Handle null being passed in from legacy code while also avoiding producing
+  // an unnecessary null check warning here.
+  if ((reason as dynamic) == null) reason = "";
+  var header = "asyncExpectThrows$type(${reason}):";
 
   // TODO(rnystrom): It might useful to validate that T is not bound to
   // ExpectException since that won't work.
@@ -124,7 +127,7 @@
   }
 
   asyncStart();
-  result.then((_) {
+  result.then<Null>((_) {
     throw ExpectException("$header Did not throw.");
   }).catchError((error, stack) {
     // A test failure doesn't count as throwing.
diff --git a/pkg/async_helper/lib/async_minitest.dart b/pkg/async_helper/lib/async_minitest.dart
index 57a05eb..fa5d319 100644
--- a/pkg/async_helper/lib/async_minitest.dart
+++ b/pkg/async_helper/lib/async_minitest.dart
@@ -310,9 +310,7 @@
 bool _initializedTestNameCallback = false;
 
 /// The current combined name of the nesting [group] or [test].
-// TODO(rnystrom): Type this "String?" when this library does not need to be
-// NNBD agnostic.
-dynamic _currentName = null;
+String _currentName = "";
 
 String _pushName(String newName) {
   // Look up the current test name from the zone created for the test.
@@ -322,7 +320,7 @@
   }
 
   var oldName = _currentName;
-  if (oldName == null) {
+  if (oldName == "") {
     _currentName = newName;
   } else {
     _currentName = "$oldName $newName";
diff --git a/pkg/async_helper/pubspec.yaml b/pkg/async_helper/pubspec.yaml
index df92b53..9497752 100644
--- a/pkg/async_helper/pubspec.yaml
+++ b/pkg/async_helper/pubspec.yaml
@@ -7,6 +7,5 @@
  language tests.
  Third parties are discouraged from using this, and should use
  the facilities provided in package:test.
-
 dependencies:
   expect: any
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 9916400..874bf6b 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -859,14 +859,17 @@
     if (mask != null) return mask;
     // TODO(sigmund): ensure that this is only called once per node.
     DartType staticType = _getStaticType(receiver);
-    // TODO(sigmund): this needs to be adjusted when we enable non-nullable
-    // types to handle legacy and nullable wrappers.
+    bool includeNull =
+        _dartTypes.useLegacySubtyping || staticType is NullableType;
+    staticType = staticType.withoutNullability;
     if (staticType is InterfaceType) {
       ClassEntity cls = staticType.element;
       if (receiver is ir.ThisExpression && !_closedWorld.isUsedAsMixin(cls)) {
         mask = _closedWorld.abstractValueDomain.createNonNullSubclass(cls);
-      } else {
+      } else if (includeNull) {
         mask = _closedWorld.abstractValueDomain.createNullableSubtype(cls);
+      } else {
+        mask = _closedWorld.abstractValueDomain.createNonNullSubtype(cls);
       }
       data.setReceiverTypeMask(node, mask);
       return mask;
@@ -1706,7 +1709,7 @@
     if (exception != null) {
       TypeInformation mask;
       DartType type = node.guard != null
-          ? _elementMap.getDartType(node.guard)
+          ? _elementMap.getDartType(node.guard).withoutNullability
           : _dartTypes.dynamicType();
       if (type is InterfaceType) {
         InterfaceType interfaceType = type;
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 75ec907..b1eda7b 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -742,6 +742,8 @@
     assert(
         node.promotedType == null ||
             promotedType == typeEnvironment.nullType ||
+            promotedType is ir.InterfaceType &&
+                promotedType.classNode == typeEnvironment.futureOrClass ||
             typeEnvironment.isSubtypeOf(promotedType, node.promotedType,
                 ir.SubtypeCheckMode.ignoringNullabilities),
         "Unexpected promotion of ${node.variable} in ${node.parent}. "
diff --git a/pkg/dart2native/pubspec.yaml b/pkg/dart2native/pubspec.yaml
index feca449..c89834f 100644
--- a/pkg/dart2native/pubspec.yaml
+++ b/pkg/dart2native/pubspec.yaml
@@ -1,6 +1,9 @@
 name: dart2native
 publish_to: none
 
+environment:
+  sdk: "^2.7.0"
+
 # Add the bin/dart2native.dart script to the scripts pub installs.
 executables:
   dart2native:
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index 3a3e9c4..5c6cd31 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -26,6 +26,7 @@
     // command pub with no commands or flags.
     final command = sdk.dart;
     final args = [
+      '--disable-dart-dev',
       '--help',
       if (verbose) '--verbose',
     ];
@@ -52,7 +53,8 @@
 
     // Starting in ProcessStartMode.inheritStdio mode means the child process
     // can detect support for ansi chars.
-    final process = await Process.start(sdk.dart, args,
+    final process = await Process.start(
+        sdk.dart, ['--disable-dart-dev', ...args],
         mode: ProcessStartMode.inheritStdio);
     return process.exitCode;
   }
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index 0e993bc..4a177ab 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -490,7 +490,7 @@
    *
    * If the objects are iterables or maps, recurses into them.
    */
-  static void deepEquals(Object expected, Object actual) {
+  static void deepEquals(dynamic expected, dynamic actual) {
     // Early exit check for equality.
     if (expected == actual) return;
 
@@ -560,8 +560,10 @@
     // TODO(vsm): Make check and reason nullable or change call sites.
     // Existing tests pass null to set a reason and/or pass them through
     // via helpers.
-    check ??= _defaultCheck;
-    reason ??= "";
+    // TODO(rnystrom): Using the strange form below instead of "??=" to avoid
+    // warnings of unnecessary null checks when analyzed as NNBD code.
+    if ((check as dynamic) == null) check = _defaultCheck;
+    if ((reason as dynamic) == null) reason = "";
     String msg = reason.isEmpty ? "" : "($reason)";
     if (f is! Function()) {
       // Only throws from executing the function body should count as throwing.
@@ -570,7 +572,7 @@
     }
     try {
       f();
-    } on Object catch (e, s) {
+    } catch (e, s) {
       // A test failure doesn't count as throwing.
       if (e is ExpectException) rethrow;
       if (e is T && check(e as dynamic)) return;
diff --git a/pkg/expect/lib/minitest.dart b/pkg/expect/lib/minitest.dart
index 350b6aa..0021ada 100644
--- a/pkg/expect/lib/minitest.dart
+++ b/pkg/expect/lib/minitest.dart
@@ -26,7 +26,7 @@
 import 'package:expect/expect.dart';
 
 typedef dynamic _Action();
-typedef void _ExpectationFunction(Object actual);
+typedef void _ExpectationFunction(dynamic actual);
 
 final List<_Group> _groups = [new _Group()];
 
@@ -124,7 +124,7 @@
   _groups.last.tearDownFunction = body;
 }
 
-void expect(Object actual, Object expected, {String reason = ""}) {
+void expect(dynamic actual, dynamic expected, {String reason = ""}) {
   // TODO(rnystrom): Do something useful with reason.
   if (expected is! _Expectation) {
     expected = equals(expected);
@@ -138,19 +138,19 @@
   Expect.fail(message);
 }
 
-Object equals(Object value) => new _Expectation((actual) {
+Object equals(dynamic value) => new _Expectation((actual) {
       Expect.deepEquals(value, actual);
     });
 
-Object notEquals(Object value) => new _Expectation((actual) {
+Object notEquals(dynamic value) => new _Expectation((actual) {
       Expect.notEquals(value, actual);
     });
 
-Object unorderedEquals(Object value) => new _Expectation((actual) {
+Object unorderedEquals(dynamic value) => new _Expectation((actual) {
       Expect.setEquals(value as Iterable, actual as Iterable);
     });
 
-Object predicate(bool fn(Object value), [String description = ""]) =>
+Object predicate(bool fn(dynamic value), [String description = ""]) =>
     new _Expectation((actual) {
       Expect.isTrue(fn(actual), description);
     });
@@ -169,7 +169,7 @@
       }
     });
 
-Object same(Object value) => new _Expectation((actual) {
+Object same(dynamic value) => new _Expectation((actual) {
       Expect.identical(value, actual);
     });
 
diff --git a/pkg/expect/pubspec.yaml b/pkg/expect/pubspec.yaml
index 5e6beb6..595d26c 100644
--- a/pkg/expect/pubspec.yaml
+++ b/pkg/expect/pubspec.yaml
@@ -6,8 +6,5 @@
  Third parties are discouraged from using this, and should use
  the expect() function in the unit test library instead for
  test assertions.
-environment:
-  sdk: ">=2.0.0 <3.0.0"
-
 dependencies:
   meta: any
diff --git a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
index 597ce2a..734b8b4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
@@ -346,8 +346,15 @@
         parameterIndex < interfaceTypeParameters.length;
         parameterIndex++) {
       TypeParameter typeParameter = interfaceTypeParameters[parameterIndex];
-      bool isGenericCovariantImpl = typeParameter.isGenericCovariantImpl ||
-          needsCheck(typeParameter.bound);
+      DartType parameterBound =
+          substitution.substituteType(typeParameter.bound);
+      DartType bound = initialType(_combinedMemberIndex, parameterBound);
+      DartType parameterDefaultType =
+          substitution.substituteType(typeParameter.defaultType);
+      DartType defaultType =
+          initialType(_combinedMemberIndex, parameterDefaultType);
+      bool isGenericCovariantImpl =
+          typeParameter.isGenericCovariantImpl || needsCheck(parameterBound);
       TypeParameter superTypeParameter = typeParameter;
       for (int candidateIndex = 0;
           candidateIndex < _candidates.length;
@@ -374,6 +381,14 @@
               true;
         }
       }
+      if (bound != null && bound != parameterBound) {
+        createStubIfNeeded(forMemberSignature: true);
+        stub.function.typeParameters[parameterIndex].bound = bound;
+      }
+      if (defaultType != null && defaultType != parameterDefaultType) {
+        createStubIfNeeded(forMemberSignature: true);
+        stub.function.typeParameters[parameterIndex].defaultType = defaultType;
+      }
     }
     DartType returnType =
         substitution.substituteType(getReturnType(interfaceMember));
@@ -486,6 +501,8 @@
       for (int i = 0; i < typeParameters.length; i++) {
         typeParameters[i].bound =
             substitution.substituteType(targetTypeParameters[i].bound);
+        typeParameters[i].defaultType =
+            substitution.substituteType(targetTypeParameters[i].defaultType);
       }
     }
     List<VariableDeclaration> positionalParameters =
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 34c3490..cc122ab 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -2810,7 +2810,8 @@
   ExpressionInferenceResult visitSuperIndexSet(
       SuperIndexSet node, DartType typeContext) {
     ObjectAccessTarget indexSetTarget = node.setter != null
-        ? new ObjectAccessTarget.interfaceMember(node.setter)
+        ? new ObjectAccessTarget.interfaceMember(node.setter,
+            isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
 
     DartType indexType =
@@ -3107,7 +3108,8 @@
   ExpressionInferenceResult visitIfNullSuperIndexSet(
       IfNullSuperIndexSet node, DartType typeContext) {
     ObjectAccessTarget readTarget = node.getter != null
-        ? new ObjectAccessTarget.interfaceMember(node.getter)
+        ? new ObjectAccessTarget.interfaceMember(node.getter,
+            isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
 
     DartType readType = inferrer.getReturnType(readTarget, inferrer.thisType);
@@ -3121,7 +3123,8 @@
         .member;
 
     ObjectAccessTarget writeTarget = node.setter != null
-        ? new ObjectAccessTarget.interfaceMember(node.setter)
+        ? new ObjectAccessTarget.interfaceMember(node.setter,
+            isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
 
     DartType writeIndexType =
@@ -3416,11 +3419,9 @@
       {bool isNot}) {
     assert(isNot != null);
     inferrer.flowAnalysis.equalityOp_rightBegin(left);
-    ObjectAccessTarget objectEqualsTarget =
-        inferrer.getObjectMemberIfNullableReceiver(leftType, equalsName);
-    ObjectAccessTarget equalsTarget = objectEqualsTarget ??
-        inferrer.findInterfaceMember(leftType, equalsName, fileOffset,
-            includeExtensionMethods: true);
+    ObjectAccessTarget equalsTarget = inferrer.findInterfaceMember(
+        leftType, equalsName, fileOffset,
+        includeExtensionMethods: true);
 
     bool typeNeeded = !inferrer.isTopLevel;
     ExpressionInferenceResult rightResult = inferrer.inferExpression(
@@ -3515,6 +3516,7 @@
             extensionAccessCandidates: binaryTarget.candidates);
         break;
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         assert(binaryTarget.extensionMethodKind != ProcedureKind.Setter);
         binary = new StaticInvocation(
             binaryTarget.member,
@@ -3526,9 +3528,11 @@
           ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
       case ObjectAccessTargetKind.invalid:
       case ObjectAccessTargetKind.unresolved:
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
       case ObjectAccessTargetKind.never:
         if (binaryTarget.isInstanceMember &&
@@ -3568,19 +3572,15 @@
         }
         break;
     }
-    if (!inferrer.isTopLevel && inferrer.isNonNullableByDefault) {
-      if (leftType is! InvalidType &&
-          leftType is! DynamicType &&
-          isPotentiallyNullable(leftType, inferrer.coreTypes.futureOrClass)) {
-        return new ExpressionInferenceResult(
-            binaryType,
-            inferrer.helper.wrapInProblem(
-                binary,
-                templateNullableOperatorCallError.withArguments(
-                    binaryName.name, leftType, inferrer.isNonNullableByDefault),
-                binary.fileOffset,
-                binaryName.name.length));
-      }
+    if (!inferrer.isTopLevel && binaryTarget.isNullable) {
+      return new ExpressionInferenceResult(
+          binaryType,
+          inferrer.helper.wrapInProblem(
+              binary,
+              templateNullableOperatorCallError.withArguments(
+                  binaryName.name, leftType, inferrer.isNonNullableByDefault),
+              binary.fileOffset,
+              binaryName.name.length));
     }
     return new ExpressionInferenceResult(binaryType, binary);
   }
@@ -3614,6 +3614,7 @@
             extensionAccessCandidates: unaryTarget.candidates);
         break;
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         assert(unaryTarget.extensionMethodKind != ProcedureKind.Setter);
         unary = new StaticInvocation(
             unaryTarget.member,
@@ -3624,9 +3625,11 @@
           ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
       case ObjectAccessTargetKind.invalid:
       case ObjectAccessTargetKind.unresolved:
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
       case ObjectAccessTargetKind.never:
         if (unaryTarget.isInstanceMember &&
@@ -3662,22 +3665,17 @@
         }
         break;
     }
-    if (!inferrer.isTopLevel && inferrer.isNonNullableByDefault) {
-      if (expressionType is! InvalidType &&
-          expressionType is! DynamicType &&
-          isPotentiallyNullable(
-              expressionType, inferrer.coreTypes.futureOrClass)) {
-        // TODO(johnniwinther): Special case 'unary-' in messages. It should
-        // probably be referred to as "Unary operator '-' ...".
-        return new ExpressionInferenceResult(
-            unaryType,
-            inferrer.helper.wrapInProblem(
-                unary,
-                templateNullableOperatorCallError.withArguments(unaryName.name,
-                    expressionType, inferrer.isNonNullableByDefault),
-                unary.fileOffset,
-                unaryName == unaryMinusName ? 1 : unaryName.name.length));
-      }
+    if (!inferrer.isTopLevel && unaryTarget.isNullable) {
+      // TODO(johnniwinther): Special case 'unary-' in messages. It should
+      // probably be referred to as "Unary operator '-' ...".
+      return new ExpressionInferenceResult(
+          unaryType,
+          inferrer.helper.wrapInProblem(
+              unary,
+              templateNullableOperatorCallError.withArguments(unaryName.name,
+                  expressionType, inferrer.isNonNullableByDefault),
+              unary.fileOffset,
+              unaryName == unaryMinusName ? 1 : unaryName.name.length));
     }
     return new ExpressionInferenceResult(unaryType, unary);
   }
@@ -3708,6 +3706,7 @@
             extensionAccessCandidates: readTarget.candidates);
         break;
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         read = new StaticInvocation(
             readTarget.member,
             new Arguments(<Expression>[
@@ -3718,9 +3717,11 @@
           ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
       case ObjectAccessTargetKind.invalid:
       case ObjectAccessTargetKind.unresolved:
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
       case ObjectAccessTargetKind.never:
         read = new MethodInvocation(
@@ -3748,22 +3749,15 @@
         }
         break;
     }
-    if (!inferrer.isTopLevel && inferrer.isNonNullableByDefault) {
-      if (receiverType is! DynamicType &&
-          receiverType is! InvalidType &&
-          isPotentiallyNullable(
-              receiverType, inferrer.coreTypes.futureOrClass)) {
-        return new ExpressionInferenceResult(
-            readType,
-            inferrer.helper.wrapInProblem(
-                read,
-                templateNullableOperatorCallError.withArguments(
-                    indexGetName.name,
-                    receiverType,
-                    inferrer.isNonNullableByDefault),
-                read.fileOffset,
-                noLength));
-      }
+    if (!inferrer.isTopLevel && readTarget.isNullable) {
+      return new ExpressionInferenceResult(
+          readType,
+          inferrer.helper.wrapInProblem(
+              read,
+              templateNullableOperatorCallError.withArguments(indexGetName.name,
+                  receiverType, inferrer.isNonNullableByDefault),
+              read.fileOffset,
+              noLength));
     }
     return new ExpressionInferenceResult(readType, read);
   }
@@ -3796,6 +3790,7 @@
             extensionAccessCandidates: writeTarget.candidates);
         break;
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         assert(writeTarget.extensionMethodKind != ProcedureKind.Setter);
         write = new StaticInvocation(
             writeTarget.member,
@@ -3805,9 +3800,11 @@
           ..fileOffset = fileOffset;
         break;
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
       case ObjectAccessTargetKind.invalid:
       case ObjectAccessTargetKind.unresolved:
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
       case ObjectAccessTargetKind.never:
         write = new MethodInvocation(
@@ -3818,18 +3815,13 @@
           ..fileOffset = fileOffset;
         break;
     }
-    if (!inferrer.isTopLevel && inferrer.isNonNullableByDefault) {
-      if (receiverType is! InvalidType &&
-          receiverType is! DynamicType &&
-          isPotentiallyNullable(
-              receiverType, inferrer.coreTypes.futureOrClass)) {
-        return inferrer.helper.wrapInProblem(
-            write,
-            templateNullableOperatorCallError.withArguments(indexSetName.name,
-                receiverType, inferrer.isNonNullableByDefault),
-            write.fileOffset,
-            noLength);
-      }
+    if (!inferrer.isTopLevel && writeTarget.isNullable) {
+      return inferrer.helper.wrapInProblem(
+          write,
+          templateNullableOperatorCallError.withArguments(
+              indexSetName.name, receiverType, inferrer.isNonNullableByDefault),
+          write.fileOffset,
+          noLength);
     }
     return write;
   }
@@ -3851,16 +3843,14 @@
       {bool isThisReceiver}) {
     assert(isThisReceiver != null);
 
-    ObjectAccessTarget objectReadTarget =
-        inferrer.getObjectMemberIfNullableReceiver(receiverType, propertyName);
-
-    ObjectAccessTarget readTarget = objectReadTarget ??
-        inferrer.findInterfaceMember(receiverType, propertyName, fileOffset,
-            includeExtensionMethods: true);
+    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
+        receiverType, propertyName, fileOffset,
+        includeExtensionMethods: true);
 
     DartType readType = inferrer.getGetterType(readTarget, receiverType);
 
     Expression read;
+    ExpressionInferenceResult readResult;
     switch (readTarget.kind) {
       case ObjectAccessTargetKind.missing:
         read = inferrer.createMissingPropertyGet(
@@ -3872,6 +3862,7 @@
             extensionAccessCandidates: readTarget.candidates);
         break;
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         switch (readTarget.extensionMethodKind) {
           case ProcedureKind.Getter:
             read = new StaticInvocation(
@@ -3890,7 +3881,9 @@
                 ], types: readTarget.inferredExtensionTypeArguments)
                   ..fileOffset = fileOffset)
               ..fileOffset = fileOffset;
-            return inferrer.instantiateTearOff(readType, typeContext, read);
+            readResult =
+                inferrer.instantiateTearOff(readType, typeContext, read);
+            break;
           case ProcedureKind.Setter:
           case ProcedureKind.Factory:
           case ProcedureKind.Operator:
@@ -3899,9 +3892,11 @@
         }
         break;
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
       case ObjectAccessTargetKind.invalid:
       case ObjectAccessTargetKind.unresolved:
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
       case ObjectAccessTargetKind.never:
         if (readTarget.isInstanceMember &&
@@ -3945,30 +3940,20 @@
         }
         Member member = readTarget.member;
         if (member is Procedure && member.kind == ProcedureKind.Method) {
-          return inferrer.instantiateTearOff(readType, typeContext, read);
+          readResult = inferrer.instantiateTearOff(readType, typeContext, read);
         }
         break;
     }
-    if (!inferrer.isTopLevel && inferrer.isNonNullableByDefault) {
-      if (receiverType is! DynamicType &&
-          receiverType is! InvalidType &&
-          isPotentiallyNullable(
-              receiverType, inferrer.coreTypes.futureOrClass) &&
-          !inferrer.matchesObjectMemberCall(
-              propertyName, const [], const [], const [])) {
-        return new ExpressionInferenceResult(
-            readType,
-            inferrer.helper.wrapInProblem(
-                read,
-                templateNullablePropertyAccessError.withArguments(
-                    propertyName.name,
-                    receiverType,
-                    inferrer.isNonNullableByDefault),
-                read.fileOffset,
-                propertyName.name.length));
-      }
+    readResult ??= new ExpressionInferenceResult(readType, read);
+    if (!inferrer.isTopLevel && readTarget.isNullable) {
+      readResult = inferrer.wrapExpressionInferenceResultInProblem(
+          readResult,
+          templateNullablePropertyAccessError.withArguments(
+              propertyName.name, receiverType, inferrer.isNonNullableByDefault),
+          read.fileOffset,
+          propertyName.name.length);
     }
-    return new ExpressionInferenceResult(readType, read);
+    return readResult;
   }
 
   /// Creates a property set operation of [writeTarget] on [receiver] using
@@ -4008,6 +3993,7 @@
             extensionAccessCandidates: writeTarget.candidates);
         break;
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         if (forEffect) {
           write = new StaticInvocation(
               writeTarget.member,
@@ -4032,9 +4018,11 @@
         }
         break;
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
       case ObjectAccessTargetKind.invalid:
       case ObjectAccessTargetKind.unresolved:
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
       case ObjectAccessTargetKind.never:
         write =
@@ -4042,17 +4030,13 @@
               ..fileOffset = fileOffset;
         break;
     }
-    if (!inferrer.isTopLevel && inferrer.isNonNullableByDefault) {
-      if (receiverType is! DynamicType &&
-          isPotentiallyNullable(
-              receiverType, inferrer.coreTypes.futureOrClass)) {
-        return inferrer.helper.wrapInProblem(
-            write,
-            templateNullablePropertyAccessError.withArguments(propertyName.name,
-                receiverType, inferrer.isNonNullableByDefault),
-            write.fileOffset,
-            propertyName.name.length);
-      }
+    if (!inferrer.isTopLevel && writeTarget.isNullable) {
+      return inferrer.helper.wrapInProblem(
+          write,
+          templateNullablePropertyAccessError.withArguments(
+              propertyName.name, receiverType, inferrer.isNonNullableByDefault),
+          write.fileOffset,
+          propertyName.name.length);
     }
 
     return write;
@@ -4348,7 +4332,8 @@
   ExpressionInferenceResult visitCompoundSuperIndexSet(
       CompoundSuperIndexSet node, DartType typeContext) {
     ObjectAccessTarget readTarget = node.getter != null
-        ? new ObjectAccessTarget.interfaceMember(node.getter)
+        ? new ObjectAccessTarget.interfaceMember(node.getter,
+            isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
 
     DartType readType = inferrer.getReturnType(readTarget, inferrer.thisType);
@@ -4400,7 +4385,8 @@
     DartType binaryType = binaryResult.inferredType;
 
     ObjectAccessTarget writeTarget = node.setter != null
-        ? new ObjectAccessTarget.interfaceMember(node.setter)
+        ? new ObjectAccessTarget.interfaceMember(node.setter,
+            isPotentiallyNullable: false)
         : const ObjectAccessTarget.missing();
 
     DartType writeIndexType =
@@ -5102,7 +5088,8 @@
         node,
         typeContext,
         node.interfaceTarget != null
-            ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget)
+            ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget,
+                isPotentiallyNullable: false)
             : const ObjectAccessTarget.unresolved());
   }
 
@@ -5120,7 +5107,8 @@
         node,
         typeContext,
         node.interfaceTarget != null
-            ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget)
+            ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget,
+                isPotentiallyNullable: false)
             : const ObjectAccessTarget.unresolved());
   }
 
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
index 5e3b43a..26baf64 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
@@ -81,8 +81,10 @@
         addProblem(messageNonNullableOptOut, token.charOffset, token.charCount);
       }
     } else {
-      addProblem(templateExperimentNotEnabled.withArguments('non-nullable'),
-          token.offset, noLength);
+      addProblem(
+          templateExperimentNotEnabled.withArguments('non-nullable', '2.9'),
+          token.offset,
+          noLength);
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/factor_type.dart b/pkg/front_end/lib/src/fasta/type_inference/factor_type.dart
index 26ea347..6f93a2b 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/factor_type.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/factor_type.dart
@@ -18,6 +18,9 @@
   // * Else if T is R? then factor(R, S)?
   if (T.nullability == Nullability.nullable) {
     DartType R = T.withNullability(Nullability.nonNullable);
+    if (identical(R, T)) {
+      return T;
+    }
     DartType factor_RS = factorType(typeEnvironment, R, S);
     if (typeEnvironment.isSubtypeOf(
         typeEnvironment.nullType, S, SubtypeCheckMode.withNullabilities)) {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index b33a2df..018b077 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -40,6 +40,8 @@
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
+import 'factor_type.dart';
+
 import 'type_inferrer.dart';
 
 import 'type_schema_environment.dart' show TypeSchemaEnvironment;
@@ -253,6 +255,11 @@
 
   TypeOperationsCfe(this.typeEnvironment);
 
+  @override
+  DartType factor(DartType from, DartType what) {
+    return factorType(typeEnvironment, from, what);
+  }
+
   // TODO(dmitryas): Consider checking for mutual subtypes instead of ==.
   @override
   bool isSameType(DartType type1, DartType type2) => type1 == type2;
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 d2628dd..3d30680 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
@@ -1014,6 +1014,153 @@
     return inferredTypes;
   }
 
+  /// Returns the extension member access by the given [name] for a receiver
+  /// with the static [receiverType].
+  ///
+  /// If none is found, [defaultTarget] is returned.
+  ///
+  /// If multiple are found, none more specific, an
+  /// [AmbiguousExtensionAccessTarget] is returned. This access kind results in
+  /// a compile-time error, but is used to provide a better message than just
+  /// reporting that the receiver does not have a member by the given name.
+  ///
+  /// If [isPotentiallyNullableAccess] is `true`, the returned extension member
+  /// is flagged as a nullable extension member access. This access kind results
+  /// in a compile-time error, but is used to provide a better message than just
+  /// reporting that the receiver does not have a member by the given name.
+  ObjectAccessTarget _findExtensionMember(
+      DartType receiverType, Class classNode, Name name, int fileOffset,
+      {bool setter: false,
+      ObjectAccessTarget defaultTarget,
+      bool isPotentiallyNullableAccess: false}) {
+    Name otherName = name;
+    bool otherIsSetter;
+    if (name == indexGetName) {
+      // [] must be checked against []=.
+      otherName = indexSetName;
+      otherIsSetter = false;
+    } else if (name == indexSetName) {
+      // []= must be checked against [].
+      otherName = indexGetName;
+      otherIsSetter = false;
+    } else {
+      otherName = name;
+      otherIsSetter = !setter;
+    }
+
+    Member otherMember =
+        _getInterfaceMember(classNode, otherName, otherIsSetter, fileOffset);
+    if (otherMember != null) {
+      // If we're looking for `foo` and `foo=` can be found or vice-versa then
+      // extension methods should not be found.
+      return defaultTarget;
+    }
+
+    ExtensionAccessCandidate bestSoFar;
+    List<ExtensionAccessCandidate> noneMoreSpecific = [];
+    library.forEachExtensionInScope((ExtensionBuilder extensionBuilder) {
+      MemberBuilder thisBuilder =
+          extensionBuilder.lookupLocalMemberByName(name, setter: setter);
+      MemberBuilder otherBuilder = extensionBuilder
+          .lookupLocalMemberByName(otherName, setter: otherIsSetter);
+      if ((thisBuilder != null && !thisBuilder.isStatic) ||
+          (otherBuilder != null && !otherBuilder.isStatic)) {
+        DartType onType;
+        DartType onTypeInstantiateToBounds;
+        List<DartType> inferredTypeArguments;
+        if (extensionBuilder.extension.typeParameters.isEmpty) {
+          onTypeInstantiateToBounds =
+              onType = extensionBuilder.extension.onType;
+          inferredTypeArguments = const <DartType>[];
+        } else {
+          List<TypeParameter> typeParameters =
+              extensionBuilder.extension.typeParameters;
+          inferredTypeArguments = inferExtensionTypeArguments(
+              extensionBuilder.extension, receiverType);
+          Substitution inferredSubstitution =
+              Substitution.fromPairs(typeParameters, inferredTypeArguments);
+
+          for (int index = 0; index < typeParameters.length; index++) {
+            TypeParameter typeParameter = typeParameters[index];
+            DartType typeArgument = inferredTypeArguments[index];
+            DartType bound =
+                inferredSubstitution.substituteType(typeParameter.bound);
+            if (!typeSchemaEnvironment.isSubtypeOf(
+                typeArgument, bound, SubtypeCheckMode.withNullabilities)) {
+              return;
+            }
+          }
+          onType = inferredSubstitution
+              .substituteType(extensionBuilder.extension.onType);
+          List<DartType> instantiateToBoundTypeArguments = calculateBounds(
+              typeParameters, coreTypes.objectClass, library.library);
+          Substitution instantiateToBoundsSubstitution = Substitution.fromPairs(
+              typeParameters, instantiateToBoundTypeArguments);
+          onTypeInstantiateToBounds = instantiateToBoundsSubstitution
+              .substituteType(extensionBuilder.extension.onType);
+        }
+
+        if (typeSchemaEnvironment.isSubtypeOf(
+            receiverType, onType, SubtypeCheckMode.withNullabilities)) {
+          ExtensionAccessCandidate candidate = new ExtensionAccessCandidate(
+              thisBuilder ?? otherBuilder,
+              onType,
+              onTypeInstantiateToBounds,
+              thisBuilder != null &&
+                      !thisBuilder.isField &&
+                      !thisBuilder.isStatic
+                  ? new ObjectAccessTarget.extensionMember(
+                      setter
+                          ? thisBuilder.writeTarget
+                          : thisBuilder.invokeTarget,
+                      thisBuilder.readTarget,
+                      thisBuilder.kind,
+                      inferredTypeArguments,
+                      isPotentiallyNullable: isPotentiallyNullableAccess)
+                  : const ObjectAccessTarget.missing(),
+              isPlatform: extensionBuilder.library.importUri.scheme == 'dart');
+          if (noneMoreSpecific.isNotEmpty) {
+            bool isMostSpecific = true;
+            for (ExtensionAccessCandidate other in noneMoreSpecific) {
+              bool isMoreSpecific =
+                  candidate.isMoreSpecificThan(typeSchemaEnvironment, other);
+              if (isMoreSpecific != true) {
+                isMostSpecific = false;
+                break;
+              }
+            }
+            if (isMostSpecific) {
+              bestSoFar = candidate;
+              noneMoreSpecific.clear();
+            } else {
+              noneMoreSpecific.add(candidate);
+            }
+          } else if (bestSoFar == null) {
+            bestSoFar = candidate;
+          } else {
+            bool isMoreSpecific =
+                candidate.isMoreSpecificThan(typeSchemaEnvironment, bestSoFar);
+            if (isMoreSpecific == true) {
+              bestSoFar = candidate;
+            } else if (isMoreSpecific == null) {
+              noneMoreSpecific.add(bestSoFar);
+              noneMoreSpecific.add(candidate);
+              bestSoFar = null;
+            }
+          }
+        }
+      }
+    });
+    if (bestSoFar != null) {
+      return bestSoFar.target;
+    } else {
+      if (noneMoreSpecific.isNotEmpty) {
+        return new AmbiguousExtensionAccessTarget(noneMoreSpecific);
+      }
+    }
+    return defaultTarget;
+  }
+
   /// Finds a member of [receiverType] called [name], and if it is found,
   /// reports it through instrumentation using [fileOffset].
   ///
@@ -1032,12 +1179,41 @@
       bool includeExtensionMethods: false}) {
     assert(receiverType != null && isKnown(receiverType));
 
-    receiverType = resolveTypeParameter(receiverType);
+    DartType receiverBound = resolveTypeParameter(receiverType);
 
-    if (receiverType is FunctionType && name == callName) {
-      return const ObjectAccessTarget.callFunction();
-    } else if (receiverType is NeverType) {
-      switch (receiverType.nullability) {
+    bool isReceiverTypePotentiallyNullable = isNonNullableByDefault &&
+        isPotentiallyNullable(receiverType, coreTypes.futureOrClass) &&
+        // Calls to `==` are always on a non-null receiver.
+        name != equalsName;
+
+    Class classNode = receiverBound is InterfaceType
+        ? receiverBound.classNode
+        : coreTypes.objectClass;
+
+    if (isReceiverTypePotentiallyNullable) {
+      Member member =
+          _getInterfaceMember(coreTypes.objectClass, name, setter, fileOffset);
+      if (member != null) {
+        return new ObjectAccessTarget.interfaceMember(member,
+            // Null implements all Object members so this is not considered a
+            // potentially nullable access.
+            isPotentiallyNullable: false);
+      }
+      if (includeExtensionMethods) {
+        ObjectAccessTarget target =
+            _findExtensionMember(receiverBound, classNode, name, fileOffset);
+        if (target != null) {
+          return target;
+        }
+      }
+    }
+
+    if (receiverBound is FunctionType && name == callName) {
+      return isReceiverTypePotentiallyNullable
+          ? const ObjectAccessTarget.nullableCallFunction()
+          : const ObjectAccessTarget.callFunction();
+    } else if (receiverBound is NeverType) {
+      switch (receiverBound.nullability) {
         case Nullability.nonNullable:
           return const ObjectAccessTarget.never();
         case Nullability.nullable:
@@ -1047,332 +1223,65 @@
         case Nullability.undetermined:
           return internalProblem(
               templateInternalProblemUnsupportedNullability.withArguments(
-                  "${receiverType.nullability}",
-                  receiverType,
+                  "${receiverBound.nullability}",
+                  receiverBound,
                   isNonNullableByDefault),
               fileOffset,
               library.fileUri);
       }
     }
-    Class classNode = receiverType is InterfaceType
-        ? receiverType.classNode
-        : coreTypes.objectClass;
+
+    ObjectAccessTarget target;
     Member interfaceMember =
         _getInterfaceMember(classNode, name, setter, fileOffset);
-    ObjectAccessTarget target;
     if (interfaceMember != null) {
-      target = new ObjectAccessTarget.interfaceMember(interfaceMember);
-    } else if (receiverType is DynamicType) {
+      target = new ObjectAccessTarget.interfaceMember(interfaceMember,
+          isPotentiallyNullable: isReceiverTypePotentiallyNullable);
+    } else if (receiverBound is DynamicType) {
       target = const ObjectAccessTarget.dynamic();
-    } else if (receiverType is InvalidType) {
+    } else if (receiverBound is InvalidType) {
       target = const ObjectAccessTarget.invalid();
-    } else if (receiverType is InterfaceType &&
-        receiverType.classNode == coreTypes.functionClass &&
+    } else if (receiverBound is InterfaceType &&
+        receiverBound.classNode == coreTypes.functionClass &&
         name == callName) {
-      target = const ObjectAccessTarget.callFunction();
+      target = isReceiverTypePotentiallyNullable
+          ? const ObjectAccessTarget.nullableCallFunction()
+          : const ObjectAccessTarget.callFunction();
     } else {
       target = const ObjectAccessTarget.missing();
     }
     if (instrumented &&
-        receiverType != const DynamicType() &&
+        receiverBound != const DynamicType() &&
         target.isInstanceMember) {
       instrumentation?.record(uriForInstrumentation, fileOffset, 'target',
           new InstrumentationValueForMember(target.member));
     }
 
     if (target.isUnresolved &&
-        receiverType is! DynamicType &&
+        receiverBound is! DynamicType &&
         includeExtensionMethods) {
-      Name otherName = name;
-      bool otherIsSetter;
-      if (name == indexGetName) {
-        // [] must be checked against []=.
-        otherName = indexSetName;
-        otherIsSetter = false;
-      } else if (name == indexSetName) {
-        // []= must be checked against [].
-        otherName = indexGetName;
-        otherIsSetter = false;
+      if (isReceiverTypePotentiallyNullable) {
+        // When the receiver type is potentially nullable we would have found
+        // the extension member above, if available. Therefore we know that we
+        // are in an erroneous case and instead look up the extension member on
+        // the non-nullable receiver bound but flag the found target as a
+        // nullable extension member access. This is done to provide the better
+        // error message that the extension member exists but that the access is
+        // invalid.
+        target = _findExtensionMember(
+            computeNonNullable(receiverBound), classNode, name, fileOffset,
+            setter: setter,
+            defaultTarget: target,
+            isPotentiallyNullableAccess: true);
       } else {
-        otherName = name;
-        otherIsSetter = !setter;
-      }
-
-      Member otherMember =
-          _getInterfaceMember(classNode, otherName, otherIsSetter, fileOffset);
-      if (otherMember != null) {
-        // If we're looking for `foo` and `foo=` can be found or vice-versa then
-        // extension methods should not be found.
-        return target;
-      }
-
-      ExtensionAccessCandidate bestSoFar;
-      List<ExtensionAccessCandidate> noneMoreSpecific = [];
-      library.forEachExtensionInScope((ExtensionBuilder extensionBuilder) {
-        MemberBuilder thisBuilder =
-            extensionBuilder.lookupLocalMemberByName(name, setter: setter);
-        MemberBuilder otherBuilder = extensionBuilder
-            .lookupLocalMemberByName(otherName, setter: otherIsSetter);
-        if ((thisBuilder != null && !thisBuilder.isStatic) ||
-            (otherBuilder != null && !otherBuilder.isStatic)) {
-          DartType onType;
-          DartType onTypeInstantiateToBounds;
-          List<DartType> inferredTypeArguments;
-          if (extensionBuilder.extension.typeParameters.isEmpty) {
-            onTypeInstantiateToBounds =
-                onType = extensionBuilder.extension.onType;
-            inferredTypeArguments = const <DartType>[];
-          } else {
-            List<TypeParameter> typeParameters =
-                extensionBuilder.extension.typeParameters;
-            inferredTypeArguments = inferExtensionTypeArguments(
-                extensionBuilder.extension, receiverType);
-            Substitution inferredSubstitution =
-                Substitution.fromPairs(typeParameters, inferredTypeArguments);
-
-            for (int index = 0; index < typeParameters.length; index++) {
-              TypeParameter typeParameter = typeParameters[index];
-              DartType typeArgument = inferredTypeArguments[index];
-              DartType bound =
-                  inferredSubstitution.substituteType(typeParameter.bound);
-              if (!typeSchemaEnvironment.isSubtypeOf(
-                  typeArgument, bound, SubtypeCheckMode.withNullabilities)) {
-                return;
-              }
-            }
-            onType = inferredSubstitution
-                .substituteType(extensionBuilder.extension.onType);
-            List<DartType> instantiateToBoundTypeArguments = calculateBounds(
-                typeParameters, coreTypes.objectClass, library.library);
-            Substitution instantiateToBoundsSubstitution =
-                Substitution.fromPairs(
-                    typeParameters, instantiateToBoundTypeArguments);
-            onTypeInstantiateToBounds = instantiateToBoundsSubstitution
-                .substituteType(extensionBuilder.extension.onType);
-          }
-
-          if (typeSchemaEnvironment.isSubtypeOf(
-              receiverType, onType, SubtypeCheckMode.ignoringNullabilities)) {
-            ExtensionAccessCandidate candidate = new ExtensionAccessCandidate(
-                thisBuilder ?? otherBuilder,
-                onType,
-                onTypeInstantiateToBounds,
-                thisBuilder != null &&
-                        !thisBuilder.isField &&
-                        !thisBuilder.isStatic
-                    ? new ObjectAccessTarget.extensionMember(
-                        setter
-                            ? thisBuilder.writeTarget
-                            : thisBuilder.invokeTarget,
-                        thisBuilder.readTarget,
-                        thisBuilder.kind,
-                        inferredTypeArguments)
-                    : const ObjectAccessTarget.missing(),
-                isPlatform:
-                    extensionBuilder.library.importUri.scheme == 'dart');
-            if (noneMoreSpecific.isNotEmpty) {
-              bool isMostSpecific = true;
-              for (ExtensionAccessCandidate other in noneMoreSpecific) {
-                bool isMoreSpecific =
-                    candidate.isMoreSpecificThan(typeSchemaEnvironment, other);
-                if (isMoreSpecific != true) {
-                  isMostSpecific = false;
-                  break;
-                }
-              }
-              if (isMostSpecific) {
-                bestSoFar = candidate;
-                noneMoreSpecific.clear();
-              } else {
-                noneMoreSpecific.add(candidate);
-              }
-            } else if (bestSoFar == null) {
-              bestSoFar = candidate;
-            } else {
-              bool isMoreSpecific = candidate.isMoreSpecificThan(
-                  typeSchemaEnvironment, bestSoFar);
-              if (isMoreSpecific == true) {
-                bestSoFar = candidate;
-              } else if (isMoreSpecific == null) {
-                noneMoreSpecific.add(bestSoFar);
-                noneMoreSpecific.add(candidate);
-                bestSoFar = null;
-              }
-            }
-          }
-        }
-      });
-      if (bestSoFar != null) {
-        target = bestSoFar.target;
-      } else {
-        if (noneMoreSpecific.isNotEmpty) {
-          target = new AmbiguousExtensionAccessTarget(noneMoreSpecific);
-        }
+        target = _findExtensionMember(
+            receiverBound, classNode, name, fileOffset,
+            setter: setter, defaultTarget: target);
       }
     }
     return target;
   }
 
-  /// Returns the Object member by given [name] if [receiverType] is potentially
-  /// nullable.
-  ///
-  /// This method is used to infer nullable calls to Object member against the
-  /// Object member signature and not the overridden signature.
-  ///
-  /// If the member is procedure that isn't applicable with the provided
-  /// [arguments], `null` is returned. This is a special casing that ensures
-  /// that calls that wouldn't match the Object member regardless of typing
-  /// will be reported as nullable access of the overridden member instead of
-  /// inapplicable access to the Object member.
-  ObjectAccessTarget getObjectMemberIfNullableReceiver(
-      DartType receiverType, Name name,
-      [Arguments arguments]) {
-    if (isNonNullableByDefault &&
-        receiverType is! DynamicType &&
-        receiverType is! InvalidType &&
-        isPotentiallyNullable(receiverType, coreTypes.futureOrClass)) {
-      ObjectAccessTarget target = findInterfaceMember(
-          coreTypes.objectNonNullableRawType, name, -1,
-          instrumented: false);
-      if (target.isUnresolved) {
-        // No member found.
-        return null;
-      }
-      Member member = target.member;
-      if (arguments != null &&
-          member is Procedure &&
-          member.kind == ProcedureKind.Method) {
-        // A method is called.
-        FunctionNode function = member.function;
-        if (arguments.positional.length >
-            function.positionalParameters.length) {
-          // The call is not going to match the Object member so we report
-          // a problem on the nullable access instead.
-          return null;
-        }
-        if (arguments.named.isNotEmpty && function.namedParameters.isEmpty) {
-          // The call is not going to match the Object member so we report
-          // a problem on the nullable access instead.
-          return null;
-        }
-      }
-      return target;
-    }
-    return null;
-  }
-
-  /// True if [Object]'s member called [name] can be called with the arguments.
-  ///
-  /// Checks for the arity and the types of the arguments and tells if an
-  /// invocation of a method [name] on the receiver with static type [Object]
-  /// doesn't lead to a compile-time error.
-  bool matchesObjectMemberCall(
-      Name name,
-      List<DartType> typeArguments,
-      List<DartType> positionalArgumentTypes,
-      List<NamedType> namedArgumentTypes) {
-    ObjectAccessTarget target = findInterfaceMember(
-        coreTypes.objectNonNullableRawType, name, -1,
-        instrumented: false);
-    if (target.isUnresolved) return false;
-    return matchesMemberCall(target.member, typeArguments ?? const [],
-        positionalArgumentTypes ?? const [], namedArgumentTypes ?? const []);
-  }
-
-  /// True if [member] can be called with the arguments.
-  ///
-  /// Checks for the arity and the types of the arguments and tells if an
-  /// invocation of [member] doesn't lead to a compile-time error.
-  bool matchesMemberCall(
-      Member member,
-      List<DartType> typeArguments,
-      List<DartType> positionalArgumentTypes,
-      List<NamedType> namedArgumentTypes) {
-    FunctionNode function = member.function;
-    List<TypeParameter> typeParameters = function.typeParameters;
-    List<VariableDeclaration> positionalParameters =
-        function.positionalParameters;
-    List<VariableDeclaration> namedParameters = function.namedParameters;
-    if (typeParameters.length != typeArguments.length ||
-        positionalParameters.length < positionalArgumentTypes.length ||
-        namedParameters.length < namedArgumentTypes.length) {
-      // The number of arguments isn't compatible.
-      return false;
-    }
-
-    // Assume that both named parameters and named arguments are sorted
-    // lexicographically.
-    assert(namedParameters.isEmpty ||
-        namedParameters.skip(1).fold(
-                namedParameters[0],
-                (p, n) =>
-                    p != null && p.name.compareTo(n.name) <= 0 ? n : null) !=
-            null);
-    assert(namedArgumentTypes.isEmpty ||
-        namedArgumentTypes.skip(1).fold(
-                namedArgumentTypes[0],
-                (p, n) =>
-                    p != null && p.name.compareTo(n.name) <= 0 ? n : null) !=
-            null);
-
-    Substitution substitution = typeParameters.isEmpty
-        ? Substitution.empty
-        : Substitution.fromPairs(typeParameters, typeArguments);
-
-    {
-      int parameterIndex = 0;
-      int argumentIndex = 0;
-      while (parameterIndex < namedParameters.length &&
-          argumentIndex < namedArgumentTypes.length) {
-        VariableDeclaration parameter = namedParameters[parameterIndex];
-        NamedType argument = namedArgumentTypes[argumentIndex];
-        int compareResult = parameter.name.compareTo(argument.name);
-        if (compareResult == 0) {
-          if (!isAssignable(
-              substitution.substituteType(parameter.type), argument.type)) {
-            // Types aren't compatible.
-            return false;
-          }
-          ++parameterIndex;
-          ++argumentIndex;
-        } else if (compareResult < 0) {
-          if (parameter.isRequired) {
-            // A required parameter is skipped.
-            return false;
-          }
-          ++parameterIndex;
-        } else {
-          assert(compareResult > 0);
-          // Extra argument.
-          return false;
-        }
-      }
-    }
-    for (int i = 0; i < positionalArgumentTypes.length; ++i) {
-      VariableDeclaration parameter = positionalParameters[i];
-      DartType argument = positionalArgumentTypes[i];
-      if (!isAssignable(
-          substitution.substituteType(parameter.type), argument)) {
-        // Types aren't compatible.
-        return false;
-      }
-    }
-    for (int i = 0; i < typeArguments.length; ++i) {
-      TypeParameter parameter = typeParameters[i];
-      DartType argument = typeArguments[i];
-      if (!typeSchemaEnvironment.isSubtypeOf(
-          argument,
-          substitution.substituteType(parameter.bound),
-          library.isNonNullableByDefault
-              ? SubtypeCheckMode.withNullabilities
-              : SubtypeCheckMode.ignoringNullabilities)) {
-        // The type argument doesn't conform to the bound.
-        return false;
-      }
-    }
-    return true;
-  }
-
   /// If target is missing on a non-dynamic receiver, an error is reported
   /// using [errorTemplate] and an invalid expression is returned.
   Expression reportMissingInterfaceMember(
@@ -1413,6 +1322,7 @@
   DartType getGetterType(ObjectAccessTarget target, DartType receiverType) {
     switch (target.kind) {
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
         return receiverType;
       case ObjectAccessTargetKind.invalid:
         return const InvalidType();
@@ -1424,8 +1334,10 @@
       case ObjectAccessTargetKind.never:
         return const NeverType(Nullability.nonNullable);
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
         return getGetterTypeForMemberTarget(target.member, receiverType);
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         switch (target.extensionMethodKind) {
           case ProcedureKind.Method:
           case ProcedureKind.Operator:
@@ -1520,6 +1432,7 @@
       ObjectAccessTarget target, DartType receiverType) {
     switch (target.kind) {
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
         return _getFunctionType(receiverType);
       case ObjectAccessTargetKind.unresolved:
       case ObjectAccessTargetKind.dynamic:
@@ -1529,9 +1442,11 @@
       case ObjectAccessTargetKind.ambiguous:
         return unknownFunction;
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
         return _getFunctionType(
             getGetterTypeForMemberTarget(target.member, receiverType));
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         switch (target.extensionMethodKind) {
           case ProcedureKind.Method:
           case ProcedureKind.Operator:
@@ -1567,11 +1482,13 @@
   DartType getReturnType(ObjectAccessTarget target, DartType receiverType) {
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
         FunctionType functionType = _getFunctionType(
             getGetterTypeForMemberTarget(target.member, receiverType));
         return functionType.returnType;
         break;
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         switch (target.extensionMethodKind) {
           case ProcedureKind.Operator:
             FunctionType functionType =
@@ -1593,6 +1510,7 @@
       case ObjectAccessTargetKind.invalid:
         return const InvalidType();
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.unresolved:
       case ObjectAccessTargetKind.dynamic:
       case ObjectAccessTargetKind.missing:
@@ -1606,6 +1524,7 @@
       ObjectAccessTarget target, DartType receiverType, int index) {
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
         FunctionType functionType = _getFunctionType(
             getGetterTypeForMemberTarget(target.member, receiverType));
         if (functionType.positionalParameters.length > index) {
@@ -1613,6 +1532,7 @@
         }
         break;
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         FunctionType functionType =
             target.member.function.computeFunctionType(library.nonNullable);
         if (functionType.positionalParameters.length > index + 1) {
@@ -1629,6 +1549,7 @@
       case ObjectAccessTargetKind.invalid:
         return const InvalidType();
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.unresolved:
       case ObjectAccessTargetKind.dynamic:
       case ObjectAccessTargetKind.never:
@@ -1661,6 +1582,7 @@
   DartType getIndexKeyType(ObjectAccessTarget target, DartType receiverType) {
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
         FunctionType functionType = _getFunctionType(
             getGetterTypeForMemberTarget(target.member, receiverType));
         if (functionType.positionalParameters.length >= 1) {
@@ -1668,6 +1590,7 @@
         }
         break;
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         switch (target.extensionMethodKind) {
           case ProcedureKind.Operator:
             FunctionType functionType =
@@ -1690,6 +1613,7 @@
       case ObjectAccessTargetKind.invalid:
         return const InvalidType();
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.unresolved:
       case ObjectAccessTargetKind.dynamic:
       case ObjectAccessTargetKind.never:
@@ -1719,6 +1643,7 @@
       ObjectAccessTarget target, DartType receiverType) {
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
         FunctionType functionType = _getFunctionType(
             getGetterTypeForMemberTarget(target.member, receiverType));
         if (functionType.positionalParameters.length >= 2) {
@@ -1726,6 +1651,7 @@
         }
         break;
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         switch (target.extensionMethodKind) {
           case ProcedureKind.Operator:
             FunctionType functionType =
@@ -1748,6 +1674,7 @@
       case ObjectAccessTargetKind.invalid:
         return const InvalidType();
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.unresolved:
       case ObjectAccessTargetKind.dynamic:
       case ObjectAccessTargetKind.never:
@@ -1812,6 +1739,7 @@
       case ObjectAccessTargetKind.invalid:
         return const InvalidType();
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
         Member interfaceMember = target.member;
         Class memberClass = interfaceMember.enclosingClass;
         DartType setterType;
@@ -1840,6 +1768,7 @@
         }
         return setterType;
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         switch (target.extensionMethodKind) {
           case ProcedureKind.Setter:
             FunctionType functionType =
@@ -1861,6 +1790,7 @@
         // TODO(johnniwinther): Compute the right setter type.
         return const DynamicType();
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
         break;
     }
     throw unhandled(target.runtimeType.toString(), 'getSetterType', null, null);
@@ -1946,6 +1876,19 @@
         variable, variable.fileOffset, equalsMember, this);
   }
 
+  ExpressionInferenceResult wrapExpressionInferenceResultInProblem(
+      ExpressionInferenceResult result,
+      Message message,
+      int fileOffset,
+      int length,
+      {List<LocatedMessage> context}) {
+    return createNullAwareExpressionInferenceResult(
+        result.inferredType,
+        helper.wrapInProblem(
+            result.nullAwareAction, message, fileOffset, length),
+        result.nullAwareGuards);
+  }
+
   ExpressionInferenceResult createNullAwareExpressionInferenceResult(
       DartType inferredType,
       Expression expression,
@@ -2440,32 +2383,6 @@
         "Inferred return type $inferredType contains free variables."
         "Inferred function type: $calleeType.");
 
-    if (!isTopLevel && isNonNullableByDefault) {
-      if (receiverType != null &&
-          receiverType is! DynamicType &&
-          isPotentiallyNullable(receiverType, coreTypes.futureOrClass) &&
-          !matchesObjectMemberCall(targetName, inferredTypes,
-              positionalArgumentTypes, namedArgumentTypes)) {
-        if (isImplicitCall) {
-          return new WrapInProblemInferenceResult(
-              inferredType,
-              templateNullableExpressionCallError.withArguments(
-                  receiverType, isNonNullableByDefault),
-              offset,
-              noLength,
-              helper);
-        } else {
-          return new WrapInProblemInferenceResult(
-              inferredType,
-              templateNullableMethodCallError.withArguments(
-                  targetName.name, receiverType, isNonNullableByDefault),
-              offset,
-              targetName.name.length,
-              helper);
-        }
-      }
-    }
-
     return new SuccessfulInferenceResult(inferredType);
   }
 
@@ -2563,12 +2480,15 @@
       VariableDeclarationImpl formal = formals[i];
       if (formal.isImplicitlyTyped) {
         DartType inferredType;
-        if (formalTypesFromContext[i] == coreTypes.nullType) {
-          inferredType = coreTypes.objectRawType(library.nullable);
-        } else if (formalTypesFromContext[i] != null) {
-          inferredType = greatestClosure(
-              substitution.substituteType(formalTypesFromContext[i]),
-              bottomType);
+        if (formalTypesFromContext[i] != null) {
+          if (coreTypes.isBottom(formalTypesFromContext[i]) ||
+              coreTypes.isNull(formalTypesFromContext[i])) {
+            inferredType = coreTypes.objectRawType(library.nullable);
+          } else {
+            inferredType = greatestClosure(
+                substitution.substituteType(formalTypesFromContext[i]),
+                bottomType);
+          }
         } else {
           inferredType = const DynamicType();
         }
@@ -2680,7 +2600,7 @@
 
   StaticInvocation transformExtensionMethodInvocation(int fileOffset,
       ObjectAccessTarget target, Expression receiver, Arguments arguments) {
-    assert(target.isExtensionMember);
+    assert(target.isExtensionMember || target.isNullableExtensionMember);
     Procedure procedure = target.member;
     return engine.forest.createStaticInvocation(
         fileOffset,
@@ -2788,19 +2708,36 @@
       List<VariableDeclaration> hoistedExpressions,
       {bool isImplicitCall}) {
     assert(isImplicitCall != null);
-    assert(target.isExtensionMember);
+    assert(target.isExtensionMember || target.isNullableExtensionMember);
     DartType calleeType = getGetterType(target, receiverType);
     FunctionType functionType = getFunctionType(target, receiverType);
 
     if (target.extensionMethodKind == ProcedureKind.Getter) {
       StaticInvocation staticInvocation = transformExtensionMethodInvocation(
           fileOffset, target, receiver, new Arguments.empty());
-      return inferMethodInvocation(fileOffset, nullAwareGuards,
-          staticInvocation, calleeType, callName, arguments, typeContext,
+      ExpressionInferenceResult result = inferMethodInvocation(
+          fileOffset,
+          nullAwareGuards,
+          staticInvocation,
+          calleeType,
+          callName,
+          arguments,
+          typeContext,
           hoistedExpressions: hoistedExpressions,
           isExpressionInvocation: false,
           isImplicitCall: true,
           implicitInvocationPropertyName: name);
+
+      if (!isTopLevel && target.isNullable) {
+        result = wrapExpressionInferenceResultInProblem(
+            result,
+            templateNullableExpressionCallError.withArguments(
+                receiverType, isNonNullableByDefault),
+            fileOffset,
+            noLength);
+      }
+
+      return result;
     } else {
       StaticInvocation staticInvocation = transformExtensionMethodInvocation(
           fileOffset, target, receiver, arguments);
@@ -2814,8 +2751,27 @@
         library.checkBoundsInStaticInvocation(staticInvocation,
             typeSchemaEnvironment, helper.uri, getTypeArgumentsInfo(arguments));
       }
-      return createNullAwareExpressionInferenceResult(result.inferredType,
-          result.applyResult(staticInvocation), nullAwareGuards);
+
+      Expression replacement = result.applyResult(staticInvocation);
+      if (!isTopLevel && target.isNullable) {
+        if (isImplicitCall) {
+          replacement = helper.wrapInProblem(
+              replacement,
+              templateNullableExpressionCallError.withArguments(
+                  receiverType, isNonNullableByDefault),
+              fileOffset,
+              noLength);
+        } else {
+          replacement = helper.wrapInProblem(
+              replacement,
+              templateNullableMethodCallError.withArguments(
+                  name.name, receiverType, isNonNullableByDefault),
+              fileOffset,
+              name.name.length);
+        }
+      }
+      return createNullAwareExpressionInferenceResult(
+          result.inferredType, replacement, nullAwareGuards);
     }
   }
 
@@ -2830,19 +2786,36 @@
       List<VariableDeclaration> hoistedExpressions,
       {bool isImplicitCall}) {
     assert(isImplicitCall != null);
-    assert(target.isCallFunction);
+    assert(target.isCallFunction || target.isNullableCallFunction);
     FunctionType functionType = getFunctionType(target, receiverType);
     InvocationInferenceResult result = inferInvocation(
         typeContext, fileOffset, functionType, arguments, callName,
         hoistedExpressions: hoistedExpressions,
         receiverType: receiverType,
         isImplicitCall: isImplicitCall);
+    Expression replacement = result.applyResult(
+        new MethodInvocation(receiver, callName, arguments)
+          ..fileOffset = fileOffset);
+    if (!isTopLevel && target.isNullableCallFunction) {
+      if (isImplicitCall) {
+        replacement = helper.wrapInProblem(
+            replacement,
+            templateNullableExpressionCallError.withArguments(
+                receiverType, isNonNullableByDefault),
+            fileOffset,
+            noLength);
+      } else {
+        replacement = helper.wrapInProblem(
+            replacement,
+            templateNullableMethodCallError.withArguments(
+                callName.name, receiverType, isNonNullableByDefault),
+            fileOffset,
+            callName.name.length);
+      }
+    }
     // TODO(johnniwinther): Check that type arguments against the bounds.
     return createNullAwareExpressionInferenceResult(
-        result.inferredType,
-        result.applyResult(new MethodInvocation(receiver, callName, arguments)
-          ..fileOffset = fileOffset),
-        nullAwareGuards);
+        result.inferredType, replacement, nullAwareGuards);
   }
 
   ExpressionInferenceResult _inferInstanceMethodInvocation(
@@ -2856,7 +2829,7 @@
       List<VariableDeclaration> hoistedExpressions,
       {bool isImplicitCall}) {
     assert(isImplicitCall != null);
-    assert(target.isInstanceMember);
+    assert(target.isInstanceMember || target.isNullableInstanceMember);
     Procedure method = target.member;
     assert(method.kind == ProcedureKind.Method,
         "Unexpected instance method $method");
@@ -2924,8 +2897,27 @@
         new MethodInvocation(receiver, methodName, arguments, method)
           ..fileOffset = fileOffset;
 
+    replacement = result.applyResult(replacement);
+    if (!isTopLevel && target.isNullable) {
+      if (isImplicitCall) {
+        replacement = helper.wrapInProblem(
+            replacement,
+            templateNullableExpressionCallError.withArguments(
+                receiverType, isNonNullableByDefault),
+            fileOffset,
+            noLength);
+      } else {
+        replacement = helper.wrapInProblem(
+            replacement,
+            templateNullableMethodCallError.withArguments(
+                methodName.name, receiverType, isNonNullableByDefault),
+            fileOffset,
+            methodName.name.length);
+      }
+    }
+
     return createNullAwareExpressionInferenceResult(
-        result.inferredType, result.applyResult(replacement), nullAwareGuards);
+        result.inferredType, replacement, nullAwareGuards);
   }
 
   ExpressionInferenceResult _inferInstanceGetterInvocation(
@@ -2939,7 +2931,7 @@
       List<VariableDeclaration> hoistedExpressions,
       {bool isExpressionInvocation}) {
     assert(isExpressionInvocation != null);
-    assert(target.isInstanceMember);
+    assert(target.isInstanceMember || target.isNullableInstanceMember);
     Procedure getter = target.member;
     assert(getter.kind == ProcedureKind.Getter);
 
@@ -3015,6 +3007,16 @@
           noLength);
       return new ExpressionInferenceResult(const DynamicType(), error);
     }
+
+    if (!isTopLevel && target.isNullable) {
+      invocationResult = wrapExpressionInferenceResultInProblem(
+          invocationResult,
+          templateNullableExpressionCallError.withArguments(
+              receiverType, isNonNullableByDefault),
+          fileOffset,
+          noLength);
+    }
+
     if (!library.loader.target.backendTarget.supportsExplicitGetterCalls) {
       // TODO(johnniwinther): Remove this when dart2js/ddc supports explicit
       //  getter calls.
@@ -3074,7 +3076,7 @@
       List<VariableDeclaration> hoistedExpressions,
       {bool isExpressionInvocation}) {
     assert(isExpressionInvocation != null);
-    assert(target.isInstanceMember);
+    assert(target.isInstanceMember || target.isNullableInstanceMember);
     Field field = target.member;
 
     DartType calleeType = getGetterType(target, receiverType);
@@ -3130,6 +3132,16 @@
           noLength);
       return new ExpressionInferenceResult(const DynamicType(), error);
     }
+
+    if (!isTopLevel && target.isNullable) {
+      invocationResult = wrapExpressionInferenceResultInProblem(
+          invocationResult,
+          templateNullableExpressionCallError.withArguments(
+              receiverType, isNonNullableByDefault),
+          fileOffset,
+          noLength);
+    }
+
     if (!library.loader.target.backendTarget.supportsExplicitGetterCalls) {
       // TODO(johnniwinther): Remove this when dart2js/ddc supports explicit
       //  getter calls.
@@ -3170,14 +3182,12 @@
     assert(isExpressionInvocation != null);
     assert(isImplicitCall != null);
 
-    ObjectAccessTarget objectReadTarget =
-        getObjectMemberIfNullableReceiver(receiverType, name, arguments);
-
-    ObjectAccessTarget target = objectReadTarget ??
-        findInterfaceMember(receiverType, name, fileOffset,
-            instrumented: true, includeExtensionMethods: true);
+    ObjectAccessTarget target = findInterfaceMember(
+        receiverType, name, fileOffset,
+        instrumented: true, includeExtensionMethods: true);
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
         Member member = target.member;
         if (member is Procedure) {
           if (member.kind == ProcedureKind.Getter) {
@@ -3217,10 +3227,12 @@
         }
         break;
       case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.nullableCallFunction:
         return _inferFunctionInvocation(fileOffset, nullAwareGuards, receiver,
             receiverType, target, arguments, typeContext, hoistedExpressions,
             isImplicitCall: isImplicitCall);
       case ObjectAccessTargetKind.extensionMember:
+      case ObjectAccessTargetKind.nullableExtensionMember:
         return _inferExtensionInvocation(
             fileOffset,
             nullAwareGuards,
@@ -3308,7 +3320,7 @@
 
   bool isOverloadedArithmeticOperatorAndType(
       ObjectAccessTarget target, DartType receiverType) {
-    return target.isInstanceMember &&
+    return (target.isInstanceMember || target.isNullableInstanceMember) &&
         target.member is Procedure &&
         typeSchemaEnvironment.isOverloadedArithmeticOperatorAndType(
             target.member, receiverType);
@@ -4193,14 +4205,48 @@
 }
 
 enum ObjectAccessTargetKind {
+  /// A valid access to a statically known instance member. The access is
+  /// either non-nullable or potentially nullable on a `Object` member.
   instanceMember,
+
+  /// A potentially nullable access to a statically known instance member. This
+  /// is an erroneous case and a compile-time error is reported.
+  nullableInstanceMember,
+
+  /// A (non-nullable) access to the `.call` method of a function. This is used
+  /// for access on `Function` and on function types.
   callFunction,
+
+  /// A potentially nullable access to the `.call` method of a function. This is
+  /// an erroneous case and a compile-time error is reported.
+  nullableCallFunction,
+
+  /// A valid access to an extension member.
   extensionMember,
+
+  /// A potentially nullable access to an extension member on an extension of
+  /// a non-nullable type. This is an erroneous case and a compile-time error is
+  /// reported.
+  nullableExtensionMember,
+
+  /// An access on a receiver of type `dynamic`.
   dynamic,
+
+  /// An access on a receiver of type `Never`.
   never,
+
+  /// An access on a receiver of an invalid type. This case is the result of
+  /// a previously report error and no error is report this case.
   invalid,
+
+  /// An access to a statically unknown instance member. This is an erroneous
+  /// case and a compile-time error is reported.
   missing,
+
+  /// An access to multiple extension members, none of which are most specific.
+  /// This is an erroneous case and a compile-time error is reported.
   ambiguous,
+
   // TODO(johnniwinther): Remove this.
   unresolved,
 }
@@ -4214,10 +4260,15 @@
   const ObjectAccessTarget.internal(this.kind, this.member);
 
   /// Creates an access to the instance [member].
-  factory ObjectAccessTarget.interfaceMember(Member member) {
+  factory ObjectAccessTarget.interfaceMember(Member member,
+      {bool isPotentiallyNullable}) {
     assert(member != null);
+    assert(isPotentiallyNullable != null);
     return new ObjectAccessTarget.internal(
-        ObjectAccessTargetKind.instanceMember, member);
+        isPotentiallyNullable
+            ? ObjectAccessTargetKind.nullableInstanceMember
+            : ObjectAccessTargetKind.instanceMember,
+        member);
   }
 
   /// Creates an access to the extension [member].
@@ -4225,13 +4276,19 @@
       Member member,
       Member tearoffTarget,
       ProcedureKind kind,
-      List<DartType> inferredTypeArguments) = ExtensionAccessTarget;
+      List<DartType> inferredTypeArguments,
+      {bool isPotentiallyNullable}) = ExtensionAccessTarget;
 
   /// Creates an access to a 'call' method on a function, i.e. a function
   /// invocation.
   const ObjectAccessTarget.callFunction()
       : this.internal(ObjectAccessTargetKind.callFunction, null);
 
+  /// Creates an access to a 'call' method on a potentially nullable function,
+  /// i.e. a function invocation.
+  const ObjectAccessTarget.nullableCallFunction()
+      : this.internal(ObjectAccessTargetKind.nullableCallFunction, null);
+
   /// Creates an access with no known target.
   const ObjectAccessTarget.unresolved()
       : this.internal(ObjectAccessTargetKind.unresolved, null);
@@ -4265,6 +4322,11 @@
   /// Returns `true` if this is an access to the 'call' method on a function.
   bool get isCallFunction => kind == ObjectAccessTargetKind.callFunction;
 
+  /// Returns `true` if this is an access to the 'call' method on a potentially
+  /// nullable function.
+  bool get isNullableCallFunction =>
+      kind == ObjectAccessTargetKind.nullableCallFunction;
+
   /// Returns `true` if this is an access without a known target.
   bool get isUnresolved =>
       kind == ObjectAccessTargetKind.unresolved ||
@@ -4285,6 +4347,23 @@
   /// occurs when an implicit extension access is ambiguous.
   bool get isAmbiguous => kind == ObjectAccessTargetKind.ambiguous;
 
+  /// Returns `true` if this is an access to an instance member on a potentially
+  /// nullable receiver.
+  bool get isNullableInstanceMember =>
+      kind == ObjectAccessTargetKind.nullableInstanceMember;
+
+  /// Returns `true` if this is an access to an instance member on a potentially
+  /// nullable receiver.
+  bool get isNullableExtensionMember =>
+      kind == ObjectAccessTargetKind.nullableExtensionMember;
+
+  /// Returns `true` if this is an access to an instance member on a potentially
+  /// nullable receiver.
+  bool get isNullable =>
+      isNullableInstanceMember ||
+      isNullableCallFunction ||
+      isNullableExtensionMember;
+
   /// Returns the candidates for an ambiguous extension access.
   List<ExtensionAccessCandidate> get candidates =>
       throw new UnsupportedError('ObjectAccessTarget.candidates');
@@ -4322,8 +4401,13 @@
   final List<DartType> inferredExtensionTypeArguments;
 
   ExtensionAccessTarget(Member member, this.tearoffTarget,
-      this.extensionMethodKind, this.inferredExtensionTypeArguments)
-      : super.internal(ObjectAccessTargetKind.extensionMember, member);
+      this.extensionMethodKind, this.inferredExtensionTypeArguments,
+      {bool isPotentiallyNullable: false})
+      : super.internal(
+            isPotentiallyNullable
+                ? ObjectAccessTargetKind.nullableExtensionMember
+                : ObjectAccessTargetKind.extensionMember,
+            member);
 
   @override
   String toString() =>
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 81c2a65..bf8b9c1 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -236,8 +236,8 @@
 
 ExperimentNotEnabled:
   index: 48
-  template: "This requires the '#string' experiment to be enabled."
-  tip: "Try enabling this experiment by adding it to the command line when compiling and running."
+  template: "This requires the '#string' language feature to be enabled."
+  tip: "Try updating your pubspec.yaml to set the minimum SDK constraint to #string2 or higher, and running 'pub get'."
   analyzerCode: ParserErrorCode.EXPERIMENT_NOT_ENABLED
 
 EmptyNamedParameterList:
diff --git a/pkg/front_end/test/fasta/type_inference/factor_type_test.dart b/pkg/front_end/test/fasta/type_inference/factor_type_test.dart
index 184c9f1..c56155d 100644
--- a/pkg/front_end/test/fasta/type_inference/factor_type_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/factor_type_test.dart
@@ -23,9 +23,11 @@
   CoreTypes get coreTypes => typeEnvironment.coreTypes;
 
   void run() {
+    test_dynamic();
     test_futureOr();
     test_object();
     test_subtype();
+    test_void();
   }
 
   @override
@@ -49,6 +51,9 @@
       coreTypes.futureOrClass, Nullability.nonNullable, [type]);
 
   @override
+  DartType get dynamicType => const DynamicType();
+
+  @override
   DartType get intNone => coreTypes.intNonNullableRawType;
 
   @override
@@ -88,6 +93,9 @@
   DartType get stringStar => coreTypes.stringLegacyRawType;
 
   @override
+  DartType get voidType => const VoidType();
+
+  @override
   String typeString(DartType type) =>
       typeToText(type, TypeRepresentation.analyzerNonNullableByDefault);
 }
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 88dcde6..5d57d7835 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -369,6 +369,7 @@
 f
 faced
 factor
+factored
 fangorn
 fasta
 favoring
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 2327236..885f530 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -1170,6 +1170,7 @@
 fixes
 fixing
 flag
+flagged
 flags
 flat
 flatten
diff --git a/pkg/front_end/test/spell_checking_list_messages.txt b/pkg/front_end/test/spell_checking_list_messages.txt
index 1dbcdac..1e01dae 100644
--- a/pkg/front_end/test/spell_checking_list_messages.txt
+++ b/pkg/front_end/test/spell_checking_list_messages.txt
@@ -46,6 +46,7 @@
 opts
 part(s)
 patch(es)
+pubspec.yaml
 re
 sdksummary
 stacktrace
diff --git a/pkg/front_end/testcases/general/vm_type_ops.dart.outline.expect b/pkg/front_end/testcases/general/vm_type_ops.dart.outline.expect
index 3950bfe..441c807 100644
--- a/pkg/front_end/testcases/general/vm_type_ops.dart.outline.expect
+++ b/pkg/front_end/testcases/general/vm_type_ops.dart.outline.expect
@@ -48,7 +48,7 @@
     ;
   method foo8<generic-covariant-impl Q extends self::H::T* = self::H::T*>(self::H::foo8::Q* a, covariant core::int* b, generic-covariant-impl self::H::T* c) → void
     ;
-  forwarding-stub method foo7<generic-covariant-impl Q extends self::H::T*>(self::H::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::H::T* c) → void
+  forwarding-stub method foo7<generic-covariant-impl Q extends self::H::T* = self::H::T*>(self::H::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::H::T* c) → void
     return super.{self::G::foo7}<self::H::foo7::Q*>(a, b, c);
 }
 static field core::List<core::Iterable<dynamic>*>* globalVar;
diff --git a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.expect b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.expect
index ced2c81..1418ee2 100644
--- a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.expect
+++ b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.expect
@@ -68,7 +68,7 @@
     : super self::G::•()
     ;
   method foo8<generic-covariant-impl Q extends self::H::T* = self::H::T*>(self::H::foo8::Q* a, covariant core::int* b, generic-covariant-impl self::H::T* c) → void {}
-  forwarding-stub method foo7<generic-covariant-impl Q extends self::H::T*>(self::H::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::H::T* c) → void
+  forwarding-stub method foo7<generic-covariant-impl Q extends self::H::T* = self::H::T*>(self::H::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::H::T* c) → void
     return super.{self::G::foo7}<self::H::foo7::Q*>(a, b, c);
 }
 static field core::List<core::Iterable<dynamic>*>* globalVar;
diff --git a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect
index ced2c81..1418ee2 100644
--- a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect
@@ -68,7 +68,7 @@
     : super self::G::•()
     ;
   method foo8<generic-covariant-impl Q extends self::H::T* = self::H::T*>(self::H::foo8::Q* a, covariant core::int* b, generic-covariant-impl self::H::T* c) → void {}
-  forwarding-stub method foo7<generic-covariant-impl Q extends self::H::T*>(self::H::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::H::T* c) → void
+  forwarding-stub method foo7<generic-covariant-impl Q extends self::H::T* = self::H::T*>(self::H::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::H::T* c) → void
     return super.{self::G::foo7}<self::H::foo7::Q*>(a, b, c);
 }
 static field core::List<core::Iterable<dynamic>*>* globalVar;
diff --git a/pkg/front_end/testcases/nnbd/covariant_equals.dart b/pkg/front_end/testcases/nnbd/covariant_equals.dart
index bcb77b7..b69bb3e 100644
--- a/pkg/front_end/testcases/nnbd/covariant_equals.dart
+++ b/pkg/front_end/testcases/nnbd/covariant_equals.dart
@@ -69,43 +69,46 @@
 
   a == a; // ok
   a == b; // ok
-  a == c_dynamic; // ok
-  a == c_int; // ok
-  a == c_string; // ok
-  a == d; // ok
+  // TODO(johnniwinther): Awaiting spec update about `==`. Before NNBD these
+  // would cause an error but with the current (insufficient) specification for
+  // `==` it is ok.
+  a == c_dynamic; // ok or error ?
+  a == c_int; // ok or error ?
+  a == c_string; // ok or error ?
+  a == d; // ok or error ?
 
   b == a; // ok
   b == b; // ok
-  b == c_dynamic; // ok
-  b == c_int; // ok
-  b == c_string; // ok
-  b == d; // ok
+  b == c_dynamic; // ok or error ?
+  b == c_int; // ok or error ?
+  b == c_string; // ok or error ?
+  b == d; // ok or error ?
 
-  c_dynamic == a; // ok
-  c_dynamic == b; // ok
+  c_dynamic == a; // ok or error ?
+  c_dynamic == b; // ok or error ?
   c_dynamic == c_dynamic; // ok
   c_dynamic == c_int; // ok
   c_dynamic == c_string; // ok
   c_dynamic == d; // ok
 
-  c_int == a; // ok
-  c_int == b; // ok
-  c_int == c_dynamic; // ok
+  c_int == a; // ok or error ?
+  c_int == b; // ok or error ?
+  c_int == c_dynamic; // ok or error ?
   c_int == c_int; // ok
-  c_int == c_string; // ok
+  c_int == c_string; // ok or error ?
   c_int == d; // ok}
 
-  c_string == a; // ok
-  c_string == b; // ok
-  c_string == c_dynamic; // ok
-  c_string == c_int; // ok
+  c_string == a; // ok or error ?
+  c_string == b; // ok or error ?
+  c_string == c_dynamic; // ok or error ?
+  c_string == c_int; // ok or error ?
   c_string == c_string; // ok
-  c_string == d; // ok
+  c_string == d; // ok or error ?
 
-  d == a; // ok
-  d == b; // ok
-  d == c_dynamic; // ok
+  d == a; // ok or error ?
+  d == b; // ok or error ?
+  d == c_dynamic; // ok or error ?
   d == c_int; // ok
-  d == c_string; // ok
+  d == c_string; // ok or error ?
   d == d; // ok
 }
diff --git a/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.expect b/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.expect
index 93ef34b..6c746cd 100644
--- a/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.expect
@@ -134,6 +134,138 @@
 //   d == c_string; // error
 //        ^
 //
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:75:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:76:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_int; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:77:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_string; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:78:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == d; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:82:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:83:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_int; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:84:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_string; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:85:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == d; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:87:16: Error: The argument type 'A?' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == a; // ok or error ?
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:88:16: Error: The argument type 'B?' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == b; // ok or error ?
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:94:12: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == a; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:95:12: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == b; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:96:12: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_dynamic; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:98:12: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_string; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:101:15: Error: The argument type 'A?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == a; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:102:15: Error: The argument type 'B?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == b; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:103:15: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_dynamic; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:104:15: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_int; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:106:15: Error: The argument type 'D?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == d; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:108:8: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == a; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:109:8: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == b; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:110:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:112:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_string; // ok or error ?
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -289,40 +421,126 @@
   d.{self::C::==}(d);
 }
 static method testNullable(self::A? a, self::B? b, self::C<dynamic>? c_dynamic, self::C<core::int>? c_int, self::C<core::String>? c_string, self::D? d) → dynamic {
-  a.{core::Object::==}(a);
-  a.{core::Object::==}(b);
-  a.{core::Object::==}(c_dynamic);
-  a.{core::Object::==}(c_int);
-  a.{core::Object::==}(c_string);
-  a.{core::Object::==}(d);
-  b.{core::Object::==}(a);
-  b.{core::Object::==}(b);
-  b.{core::Object::==}(c_dynamic);
-  b.{core::Object::==}(c_int);
-  b.{core::Object::==}(c_string);
-  b.{core::Object::==}(d);
-  c_dynamic.{core::Object::==}(a);
-  c_dynamic.{core::Object::==}(b);
-  c_dynamic.{core::Object::==}(c_dynamic);
-  c_dynamic.{core::Object::==}(c_int);
-  c_dynamic.{core::Object::==}(c_string);
-  c_dynamic.{core::Object::==}(d);
-  c_int.{core::Object::==}(a);
-  c_int.{core::Object::==}(b);
-  c_int.{core::Object::==}(c_dynamic);
-  c_int.{core::Object::==}(c_int);
-  c_int.{core::Object::==}(c_string);
-  c_int.{core::Object::==}(d);
-  c_string.{core::Object::==}(a);
-  c_string.{core::Object::==}(b);
-  c_string.{core::Object::==}(c_dynamic);
-  c_string.{core::Object::==}(c_int);
-  c_string.{core::Object::==}(c_string);
-  c_string.{core::Object::==}(d);
-  d.{core::Object::==}(a);
-  d.{core::Object::==}(b);
-  d.{core::Object::==}(c_dynamic);
-  d.{core::Object::==}(c_int);
-  d.{core::Object::==}(c_string);
-  d.{core::Object::==}(d);
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:75:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:76:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_int; // ok or error ?
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:77:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:78:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == d; // ok or error ?
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:82:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:83:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_int; // ok or error ?
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:84:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t31 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:85:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == d; // ok or error ?
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:87:16: Error: The argument type 'A?' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == a; // ok or error ?
+               ^" in a as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:88:16: Error: The argument type 'B?' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == b; // ok or error ?
+               ^" in b as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:94:12: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == a; // ok or error ?
+           ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:95:12: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == b; // ok or error ?
+           ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:96:12: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_dynamic; // ok or error ?
+           ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:98:12: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_string; // ok or error ?
+           ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:101:15: Error: The argument type 'A?' can't be assigned to the parameter type 'C<String>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == a; // ok or error ?
+              ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t39 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:102:15: Error: The argument type 'B?' can't be assigned to the parameter type 'C<String>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == b; // ok or error ?
+              ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t40 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:103:15: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_dynamic; // ok or error ?
+              ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:104:15: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_int; // ok or error ?
+              ^" in c_int as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:106:15: Error: The argument type 'D?' can't be assigned to the parameter type 'C<String>?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == d; // ok or error ?
+              ^" in d as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  d.{self::C::==}(let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:108:8: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == a; // ok or error ?
+       ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:109:8: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == b; // ok or error ?
+       ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t45 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:110:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t46 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:112:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(d);
 }
diff --git a/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.transformed.expect
index 93ef34b..6c746cd 100644
--- a/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/covariant_equals.dart.strong.transformed.expect
@@ -134,6 +134,138 @@
 //   d == c_string; // error
 //        ^
 //
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:75:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:76:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_int; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:77:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_string; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:78:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == d; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:82:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:83:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_int; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:84:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_string; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:85:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == d; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:87:16: Error: The argument type 'A?' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == a; // ok or error ?
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:88:16: Error: The argument type 'B?' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == b; // ok or error ?
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:94:12: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == a; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:95:12: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == b; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:96:12: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_dynamic; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:98:12: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_string; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:101:15: Error: The argument type 'A?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == a; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:102:15: Error: The argument type 'B?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == b; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:103:15: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_dynamic; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:104:15: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_int; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:106:15: Error: The argument type 'D?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == d; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:108:8: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == a; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:109:8: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == b; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:110:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:112:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_string; // ok or error ?
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -289,40 +421,126 @@
   d.{self::C::==}(d);
 }
 static method testNullable(self::A? a, self::B? b, self::C<dynamic>? c_dynamic, self::C<core::int>? c_int, self::C<core::String>? c_string, self::D? d) → dynamic {
-  a.{core::Object::==}(a);
-  a.{core::Object::==}(b);
-  a.{core::Object::==}(c_dynamic);
-  a.{core::Object::==}(c_int);
-  a.{core::Object::==}(c_string);
-  a.{core::Object::==}(d);
-  b.{core::Object::==}(a);
-  b.{core::Object::==}(b);
-  b.{core::Object::==}(c_dynamic);
-  b.{core::Object::==}(c_int);
-  b.{core::Object::==}(c_string);
-  b.{core::Object::==}(d);
-  c_dynamic.{core::Object::==}(a);
-  c_dynamic.{core::Object::==}(b);
-  c_dynamic.{core::Object::==}(c_dynamic);
-  c_dynamic.{core::Object::==}(c_int);
-  c_dynamic.{core::Object::==}(c_string);
-  c_dynamic.{core::Object::==}(d);
-  c_int.{core::Object::==}(a);
-  c_int.{core::Object::==}(b);
-  c_int.{core::Object::==}(c_dynamic);
-  c_int.{core::Object::==}(c_int);
-  c_int.{core::Object::==}(c_string);
-  c_int.{core::Object::==}(d);
-  c_string.{core::Object::==}(a);
-  c_string.{core::Object::==}(b);
-  c_string.{core::Object::==}(c_dynamic);
-  c_string.{core::Object::==}(c_int);
-  c_string.{core::Object::==}(c_string);
-  c_string.{core::Object::==}(d);
-  d.{core::Object::==}(a);
-  d.{core::Object::==}(b);
-  d.{core::Object::==}(c_dynamic);
-  d.{core::Object::==}(c_int);
-  d.{core::Object::==}(c_string);
-  d.{core::Object::==}(d);
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:75:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:76:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_int; // ok or error ?
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:77:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:78:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == d; // ok or error ?
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:82:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:83:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_int; // ok or error ?
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:84:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t31 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:85:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == d; // ok or error ?
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:87:16: Error: The argument type 'A?' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == a; // ok or error ?
+               ^" in a as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:88:16: Error: The argument type 'B?' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == b; // ok or error ?
+               ^" in b as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:94:12: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == a; // ok or error ?
+           ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:95:12: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == b; // ok or error ?
+           ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:96:12: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_dynamic; // ok or error ?
+           ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:98:12: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_string; // ok or error ?
+           ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:101:15: Error: The argument type 'A?' can't be assigned to the parameter type 'C<String>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == a; // ok or error ?
+              ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t39 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:102:15: Error: The argument type 'B?' can't be assigned to the parameter type 'C<String>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == b; // ok or error ?
+              ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t40 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:103:15: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_dynamic; // ok or error ?
+              ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:104:15: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_int; // ok or error ?
+              ^" in c_int as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:106:15: Error: The argument type 'D?' can't be assigned to the parameter type 'C<String>?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == d; // ok or error ?
+              ^" in d as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  d.{self::C::==}(let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:108:8: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == a; // ok or error ?
+       ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:109:8: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == b; // ok or error ?
+       ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t45 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:110:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t46 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:112:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(d);
 }
diff --git a/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.expect b/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.expect
index 93ef34b..6c746cd 100644
--- a/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.expect
@@ -134,6 +134,138 @@
 //   d == c_string; // error
 //        ^
 //
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:75:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:76:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_int; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:77:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_string; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:78:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == d; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:82:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:83:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_int; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:84:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_string; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:85:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == d; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:87:16: Error: The argument type 'A?' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == a; // ok or error ?
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:88:16: Error: The argument type 'B?' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == b; // ok or error ?
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:94:12: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == a; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:95:12: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == b; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:96:12: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_dynamic; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:98:12: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_string; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:101:15: Error: The argument type 'A?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == a; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:102:15: Error: The argument type 'B?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == b; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:103:15: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_dynamic; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:104:15: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_int; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:106:15: Error: The argument type 'D?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == d; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:108:8: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == a; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:109:8: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == b; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:110:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:112:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_string; // ok or error ?
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -289,40 +421,126 @@
   d.{self::C::==}(d);
 }
 static method testNullable(self::A? a, self::B? b, self::C<dynamic>? c_dynamic, self::C<core::int>? c_int, self::C<core::String>? c_string, self::D? d) → dynamic {
-  a.{core::Object::==}(a);
-  a.{core::Object::==}(b);
-  a.{core::Object::==}(c_dynamic);
-  a.{core::Object::==}(c_int);
-  a.{core::Object::==}(c_string);
-  a.{core::Object::==}(d);
-  b.{core::Object::==}(a);
-  b.{core::Object::==}(b);
-  b.{core::Object::==}(c_dynamic);
-  b.{core::Object::==}(c_int);
-  b.{core::Object::==}(c_string);
-  b.{core::Object::==}(d);
-  c_dynamic.{core::Object::==}(a);
-  c_dynamic.{core::Object::==}(b);
-  c_dynamic.{core::Object::==}(c_dynamic);
-  c_dynamic.{core::Object::==}(c_int);
-  c_dynamic.{core::Object::==}(c_string);
-  c_dynamic.{core::Object::==}(d);
-  c_int.{core::Object::==}(a);
-  c_int.{core::Object::==}(b);
-  c_int.{core::Object::==}(c_dynamic);
-  c_int.{core::Object::==}(c_int);
-  c_int.{core::Object::==}(c_string);
-  c_int.{core::Object::==}(d);
-  c_string.{core::Object::==}(a);
-  c_string.{core::Object::==}(b);
-  c_string.{core::Object::==}(c_dynamic);
-  c_string.{core::Object::==}(c_int);
-  c_string.{core::Object::==}(c_string);
-  c_string.{core::Object::==}(d);
-  d.{core::Object::==}(a);
-  d.{core::Object::==}(b);
-  d.{core::Object::==}(c_dynamic);
-  d.{core::Object::==}(c_int);
-  d.{core::Object::==}(c_string);
-  d.{core::Object::==}(d);
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:75:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:76:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_int; // ok or error ?
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:77:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:78:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == d; // ok or error ?
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:82:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:83:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_int; // ok or error ?
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:84:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t31 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:85:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == d; // ok or error ?
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:87:16: Error: The argument type 'A?' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == a; // ok or error ?
+               ^" in a as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:88:16: Error: The argument type 'B?' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == b; // ok or error ?
+               ^" in b as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:94:12: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == a; // ok or error ?
+           ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:95:12: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == b; // ok or error ?
+           ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:96:12: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_dynamic; // ok or error ?
+           ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:98:12: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_string; // ok or error ?
+           ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:101:15: Error: The argument type 'A?' can't be assigned to the parameter type 'C<String>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == a; // ok or error ?
+              ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t39 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:102:15: Error: The argument type 'B?' can't be assigned to the parameter type 'C<String>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == b; // ok or error ?
+              ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t40 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:103:15: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_dynamic; // ok or error ?
+              ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:104:15: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_int; // ok or error ?
+              ^" in c_int as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:106:15: Error: The argument type 'D?' can't be assigned to the parameter type 'C<String>?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == d; // ok or error ?
+              ^" in d as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  d.{self::C::==}(let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:108:8: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == a; // ok or error ?
+       ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:109:8: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == b; // ok or error ?
+       ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t45 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:110:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t46 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:112:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(d);
 }
diff --git a/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.transformed.expect
index 93ef34b..6c746cd 100644
--- a/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/covariant_equals.dart.weak.transformed.expect
@@ -134,6 +134,138 @@
 //   d == c_string; // error
 //        ^
 //
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:75:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:76:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_int; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:77:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == c_string; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:78:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   a == d; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:82:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:83:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_int; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:84:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == c_string; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:85:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   b == d; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:87:16: Error: The argument type 'A?' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == a; // ok or error ?
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:88:16: Error: The argument type 'B?' can't be assigned to the parameter type 'C<dynamic>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_dynamic == b; // ok or error ?
+//                ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:94:12: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == a; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:95:12: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == b; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:96:12: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_dynamic; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:98:12: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_int == c_string; // ok or error ?
+//            ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:101:15: Error: The argument type 'A?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == a; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:102:15: Error: The argument type 'B?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == b; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:103:15: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_dynamic; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:104:15: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == c_int; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:106:15: Error: The argument type 'D?' can't be assigned to the parameter type 'C<String>?'.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   c_string == d; // ok or error ?
+//               ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:108:8: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == a; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:109:8: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == b; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:110:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_dynamic; // ok or error ?
+//        ^
+//
+// pkg/front_end/testcases/nnbd/covariant_equals.dart:112:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+//   d == c_string; // ok or error ?
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -289,40 +421,126 @@
   d.{self::C::==}(d);
 }
 static method testNullable(self::A? a, self::B? b, self::C<dynamic>? c_dynamic, self::C<core::int>? c_int, self::C<core::String>? c_string, self::D? d) → dynamic {
-  a.{core::Object::==}(a);
-  a.{core::Object::==}(b);
-  a.{core::Object::==}(c_dynamic);
-  a.{core::Object::==}(c_int);
-  a.{core::Object::==}(c_string);
-  a.{core::Object::==}(d);
-  b.{core::Object::==}(a);
-  b.{core::Object::==}(b);
-  b.{core::Object::==}(c_dynamic);
-  b.{core::Object::==}(c_int);
-  b.{core::Object::==}(c_string);
-  b.{core::Object::==}(d);
-  c_dynamic.{core::Object::==}(a);
-  c_dynamic.{core::Object::==}(b);
-  c_dynamic.{core::Object::==}(c_dynamic);
-  c_dynamic.{core::Object::==}(c_int);
-  c_dynamic.{core::Object::==}(c_string);
-  c_dynamic.{core::Object::==}(d);
-  c_int.{core::Object::==}(a);
-  c_int.{core::Object::==}(b);
-  c_int.{core::Object::==}(c_dynamic);
-  c_int.{core::Object::==}(c_int);
-  c_int.{core::Object::==}(c_string);
-  c_int.{core::Object::==}(d);
-  c_string.{core::Object::==}(a);
-  c_string.{core::Object::==}(b);
-  c_string.{core::Object::==}(c_dynamic);
-  c_string.{core::Object::==}(c_int);
-  c_string.{core::Object::==}(c_string);
-  c_string.{core::Object::==}(d);
-  d.{core::Object::==}(a);
-  d.{core::Object::==}(b);
-  d.{core::Object::==}(c_dynamic);
-  d.{core::Object::==}(c_int);
-  d.{core::Object::==}(c_string);
-  d.{core::Object::==}(d);
+  a.{self::A::==}(a);
+  a.{self::A::==}(b);
+  a.{self::A::==}(let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:75:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:76:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_int; // ok or error ?
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:77:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  a.{self::A::==}(let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:78:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  a == d; // ok or error ?
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(a);
+  b.{self::B::==}(b);
+  b.{self::B::==}(let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:82:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:83:8: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_int; // ok or error ?
+       ^" in c_int as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:84:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'A?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::A?);
+  b.{self::B::==}(let final<BottomType> #t31 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:85:8: Error: The argument type 'D?' can't be assigned to the parameter type 'A?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  b == d; // ok or error ?
+       ^" in d as{TypeError,ForNonNullableByDefault} self::A?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:87:16: Error: The argument type 'A?' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == a; // ok or error ?
+               ^" in a as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:88:16: Error: The argument type 'B?' can't be assigned to the parameter type 'C<dynamic>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_dynamic == b; // ok or error ?
+               ^" in b as{TypeError,ForNonNullableByDefault} self::C<dynamic>?);
+  c_dynamic.{self::C::==}(c_dynamic);
+  c_dynamic.{self::C::==}(c_int);
+  c_dynamic.{self::C::==}(c_string);
+  c_dynamic.{self::C::==}(d);
+  c_int.{self::C::==}(let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:94:12: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == a; // ok or error ?
+           ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:95:12: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == b; // ok or error ?
+           ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:96:12: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_dynamic; // ok or error ?
+           ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(c_int);
+  c_int.{self::C::==}(let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:98:12: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_int == c_string; // ok or error ?
+           ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  c_int.{self::C::==}(d);
+  c_string.{self::C::==}(let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:101:15: Error: The argument type 'A?' can't be assigned to the parameter type 'C<String>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == a; // ok or error ?
+              ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t39 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:102:15: Error: The argument type 'B?' can't be assigned to the parameter type 'C<String>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == b; // ok or error ?
+              ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t40 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:103:15: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_dynamic; // ok or error ?
+              ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:104:15: Error: The argument type 'C<int>?' can't be assigned to the parameter type 'C<String>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == c_int; // ok or error ?
+              ^" in c_int as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  c_string.{self::C::==}(c_string);
+  c_string.{self::C::==}(let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:106:15: Error: The argument type 'D?' can't be assigned to the parameter type 'C<String>?'.
+ - 'D' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  c_string == d; // ok or error ?
+              ^" in d as{TypeError,ForNonNullableByDefault} self::C<core::String>?);
+  d.{self::C::==}(let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:108:8: Error: The argument type 'A?' can't be assigned to the parameter type 'C<int>?'.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == a; // ok or error ?
+       ^" in a as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:109:8: Error: The argument type 'B?' can't be assigned to the parameter type 'C<int>?'.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == b; // ok or error ?
+       ^" in b as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(let final<BottomType> #t45 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:110:8: Error: The argument type 'C<dynamic>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_dynamic; // ok or error ?
+       ^" in c_dynamic as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(c_int);
+  d.{self::C::==}(let final<BottomType> #t46 = invalid-expression "pkg/front_end/testcases/nnbd/covariant_equals.dart:112:8: Error: The argument type 'C<String>?' can't be assigned to the parameter type 'C<int>?'.
+ - 'C' is from 'pkg/front_end/testcases/nnbd/covariant_equals.dart'.
+  d == c_string; // ok or error ?
+       ^" in c_string as{TypeError,ForNonNullableByDefault} self::C<core::int>?);
+  d.{self::C::==}(d);
 }
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart b/pkg/front_end/testcases/nnbd/generic_override.dart
index f898600..8a3f194 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'generic_override_lib.dart';
+
 abstract class Class1 {
   void method1a<T>();
   void method1b<T>();
@@ -42,4 +44,24 @@
   void method5c<T extends Class1>(); // error
 }
 
+abstract class Class3 extends LegacyClass1 {
+  void method1a<T>();
+  void method1b<T extends Object?>();
+  void method1c<T extends dynamic>();
+  void method2a<T>();
+  void method2b<T extends Object?>();
+  void method2c<T extends dynamic>();
+  void method3a<T>();
+  void method3b<T extends Object?>();
+  void method3c<T extends dynamic>();
+
+  void method4a<T extends Object>();
+  void method4b<T extends Object?>();
+  void method4c<T extends Object>();
+
+  void method5a<T extends Class1>();
+  void method5b<T extends Class1?>();
+  void method5c<T extends Class1>();
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect
index 7af22c0..1364f7a 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect
@@ -2,40 +2,43 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:39:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
 //  - 'Object' is from 'dart:core'.
 //   void method4b<T extends Object?>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
+// pkg/front_end/testcases/nnbd/generic_override.dart:19:8: Context: This is the overridden method ('method4b').
 //   void method4b<T extends Object>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:38:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:40:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
 //  - 'Object' is from 'dart:core'.
 //   void method4c<T extends Object>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:18:8: Context: This is the overridden method ('method4c').
+// pkg/front_end/testcases/nnbd/generic_override.dart:20:8: Context: This is the overridden method ('method4c').
 //   void method4c<T extends Object?>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:41:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:43:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5b<T extends Class1?>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:21:8: Context: This is the overridden method ('method5b').
+// pkg/front_end/testcases/nnbd/generic_override.dart:23:8: Context: This is the overridden method ('method5b').
 //   void method5b<T extends Class1>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:44:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5c<T extends Class1>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
+// pkg/front_end/testcases/nnbd/generic_override.dart:24:8: Context: This is the overridden method ('method5c').
 //   void method5c<T extends Class1?>();
 //        ^
 //
 import self as self;
 import "dart:core" as core;
+import "generic_override_lib.dart" as gen;
+
+import "org-dartlang-testcase:///generic_override_lib.dart";
 
 abstract class Class1 extends core::Object {
   synthetic constructor •() → self::Class1
@@ -75,5 +78,88 @@
   abstract method method5b<T extends self::Class1? = self::Class1?>() → void;
   abstract method method5c<T extends self::Class1 = self::Class1>() → void;
 }
+abstract class Class3 extends gen::LegacyClass1 {
+  synthetic constructor •() → self::Class3
+    ;
+  abstract method method1a<T extends core::Object? = dynamic>() → void;
+  abstract method method1b<T extends core::Object? = core::Object?>() → void;
+  abstract method method1c<T extends dynamic = dynamic>() → void;
+  abstract method method2a<T extends core::Object? = dynamic>() → void;
+  abstract method method2b<T extends core::Object? = core::Object?>() → void;
+  abstract method method2c<T extends dynamic = dynamic>() → void;
+  abstract method method3a<T extends core::Object? = dynamic>() → void;
+  abstract method method3b<T extends core::Object? = core::Object?>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object = core::Object>() → void;
+  abstract method method4b<T extends core::Object? = core::Object?>() → void;
+  abstract method method4c<T extends core::Object = core::Object>() → void;
+  abstract method method5a<T extends self::Class1 = self::Class1>() → void;
+  abstract method method5b<T extends self::Class1? = self::Class1?>() → void;
+  abstract method method5c<T extends self::Class1 = self::Class1>() → void;
+}
+static method main() → dynamic
+  ;
+
+library;
+import self as gen;
+import "dart:core" as core;
+import "generic_override.dart" as self;
+
+import "org-dartlang-testcase:///generic_override.dart";
+
+abstract class LegacyClass1 extends core::Object {
+  synthetic constructor •() → gen::LegacyClass1*
+    ;
+  abstract method method1a<T extends core::Object* = dynamic>() → void;
+  abstract method method1b<T extends core::Object* = dynamic>() → void;
+  abstract method method1c<T extends core::Object* = dynamic>() → void;
+  abstract method method2a<T extends core::Object* = core::Object*>() → void;
+  abstract method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract method method2c<T extends core::Object* = core::Object*>() → void;
+  abstract method method3a<T extends dynamic = dynamic>() → void;
+  abstract method method3b<T extends dynamic = dynamic>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
+abstract class LegacyClass2 extends self::Class1 {
+  synthetic constructor •() → gen::LegacyClass2*
+    ;
+  abstract method method1a<T extends core::Object* = dynamic>() → void;
+  abstract method method1b<T extends core::Object* = core::Object*>() → void;
+  abstract method method1c<T extends dynamic = dynamic>() → void;
+  abstract method method2a<T extends core::Object* = dynamic>() → void;
+  abstract method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract method method2c<T extends dynamic = dynamic>() → void;
+  abstract method method3a<T extends core::Object* = dynamic>() → void;
+  abstract method method3b<T extends core::Object* = core::Object*>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
+abstract class LegacyClass3 extends self::Class1 {
+  synthetic constructor •() → gen::LegacyClass3*
+    ;
+  abstract member-signature method method1a<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method1b<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method1c<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method2a<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method2c<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract member-signature method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract member-signature method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect
index f9ca321..419cad0 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect
@@ -2,40 +2,43 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:39:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
 //  - 'Object' is from 'dart:core'.
 //   void method4b<T extends Object?>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
+// pkg/front_end/testcases/nnbd/generic_override.dart:19:8: Context: This is the overridden method ('method4b').
 //   void method4b<T extends Object>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:38:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:40:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
 //  - 'Object' is from 'dart:core'.
 //   void method4c<T extends Object>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:18:8: Context: This is the overridden method ('method4c').
+// pkg/front_end/testcases/nnbd/generic_override.dart:20:8: Context: This is the overridden method ('method4c').
 //   void method4c<T extends Object?>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:41:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:43:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5b<T extends Class1?>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:21:8: Context: This is the overridden method ('method5b').
+// pkg/front_end/testcases/nnbd/generic_override.dart:23:8: Context: This is the overridden method ('method5b').
 //   void method5b<T extends Class1>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:44:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5c<T extends Class1>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
+// pkg/front_end/testcases/nnbd/generic_override.dart:24:8: Context: This is the overridden method ('method5c').
 //   void method5c<T extends Class1?>();
 //        ^
 //
 import self as self;
 import "dart:core" as core;
+import "generic_override_lib.dart" as gen;
+
+import "org-dartlang-testcase:///generic_override_lib.dart";
 
 abstract class Class1 extends core::Object {
   synthetic constructor •() → self::Class1
@@ -77,4 +80,90 @@
   abstract method method5b<T extends self::Class1? = self::Class1?>() → void;
   abstract method method5c<T extends self::Class1 = self::Class1>() → void;
 }
+abstract class Class3 extends gen::LegacyClass1 {
+  synthetic constructor •() → self::Class3
+    : super gen::LegacyClass1::•()
+    ;
+  abstract method method1a<T extends core::Object? = dynamic>() → void;
+  abstract method method1b<T extends core::Object? = core::Object?>() → void;
+  abstract method method1c<T extends dynamic = dynamic>() → void;
+  abstract method method2a<T extends core::Object? = dynamic>() → void;
+  abstract method method2b<T extends core::Object? = core::Object?>() → void;
+  abstract method method2c<T extends dynamic = dynamic>() → void;
+  abstract method method3a<T extends core::Object? = dynamic>() → void;
+  abstract method method3b<T extends core::Object? = core::Object?>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object = core::Object>() → void;
+  abstract method method4b<T extends core::Object? = core::Object?>() → void;
+  abstract method method4c<T extends core::Object = core::Object>() → void;
+  abstract method method5a<T extends self::Class1 = self::Class1>() → void;
+  abstract method method5b<T extends self::Class1? = self::Class1?>() → void;
+  abstract method method5c<T extends self::Class1 = self::Class1>() → void;
+}
+static method main() → dynamic {}
+
+library;
+import self as gen;
+import "dart:core" as core;
+import "generic_override.dart" as self;
+
+import "org-dartlang-testcase:///generic_override.dart";
+
+abstract class LegacyClass1 extends core::Object {
+  synthetic constructor •() → gen::LegacyClass1*
+    : super core::Object::•()
+    ;
+  abstract method method1a<T extends core::Object* = dynamic>() → void;
+  abstract method method1b<T extends core::Object* = dynamic>() → void;
+  abstract method method1c<T extends core::Object* = dynamic>() → void;
+  abstract method method2a<T extends core::Object* = core::Object*>() → void;
+  abstract method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract method method2c<T extends core::Object* = core::Object*>() → void;
+  abstract method method3a<T extends dynamic = dynamic>() → void;
+  abstract method method3b<T extends dynamic = dynamic>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
+abstract class LegacyClass2 extends self::Class1 {
+  synthetic constructor •() → gen::LegacyClass2*
+    : super self::Class1::•()
+    ;
+  abstract method method1a<T extends core::Object* = dynamic>() → void;
+  abstract method method1b<T extends core::Object* = core::Object*>() → void;
+  abstract method method1c<T extends dynamic = dynamic>() → void;
+  abstract method method2a<T extends core::Object* = dynamic>() → void;
+  abstract method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract method method2c<T extends dynamic = dynamic>() → void;
+  abstract method method3a<T extends core::Object* = dynamic>() → void;
+  abstract method method3b<T extends core::Object* = core::Object*>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
+abstract class LegacyClass3 extends self::Class1 {
+  synthetic constructor •() → gen::LegacyClass3*
+    : super self::Class1::•()
+    ;
+  abstract member-signature method method1a<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method1b<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method1c<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method2a<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method2c<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract member-signature method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract member-signature method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect
index f9ca321..419cad0 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect
@@ -2,40 +2,43 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:39:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
 //  - 'Object' is from 'dart:core'.
 //   void method4b<T extends Object?>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
+// pkg/front_end/testcases/nnbd/generic_override.dart:19:8: Context: This is the overridden method ('method4b').
 //   void method4b<T extends Object>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:38:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:40:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
 //  - 'Object' is from 'dart:core'.
 //   void method4c<T extends Object>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:18:8: Context: This is the overridden method ('method4c').
+// pkg/front_end/testcases/nnbd/generic_override.dart:20:8: Context: This is the overridden method ('method4c').
 //   void method4c<T extends Object?>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:41:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:43:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5b<T extends Class1?>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:21:8: Context: This is the overridden method ('method5b').
+// pkg/front_end/testcases/nnbd/generic_override.dart:23:8: Context: This is the overridden method ('method5b').
 //   void method5b<T extends Class1>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:44:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5c<T extends Class1>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
+// pkg/front_end/testcases/nnbd/generic_override.dart:24:8: Context: This is the overridden method ('method5c').
 //   void method5c<T extends Class1?>();
 //        ^
 //
 import self as self;
 import "dart:core" as core;
+import "generic_override_lib.dart" as gen;
+
+import "org-dartlang-testcase:///generic_override_lib.dart";
 
 abstract class Class1 extends core::Object {
   synthetic constructor •() → self::Class1
@@ -77,4 +80,90 @@
   abstract method method5b<T extends self::Class1? = self::Class1?>() → void;
   abstract method method5c<T extends self::Class1 = self::Class1>() → void;
 }
+abstract class Class3 extends gen::LegacyClass1 {
+  synthetic constructor •() → self::Class3
+    : super gen::LegacyClass1::•()
+    ;
+  abstract method method1a<T extends core::Object? = dynamic>() → void;
+  abstract method method1b<T extends core::Object? = core::Object?>() → void;
+  abstract method method1c<T extends dynamic = dynamic>() → void;
+  abstract method method2a<T extends core::Object? = dynamic>() → void;
+  abstract method method2b<T extends core::Object? = core::Object?>() → void;
+  abstract method method2c<T extends dynamic = dynamic>() → void;
+  abstract method method3a<T extends core::Object? = dynamic>() → void;
+  abstract method method3b<T extends core::Object? = core::Object?>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object = core::Object>() → void;
+  abstract method method4b<T extends core::Object? = core::Object?>() → void;
+  abstract method method4c<T extends core::Object = core::Object>() → void;
+  abstract method method5a<T extends self::Class1 = self::Class1>() → void;
+  abstract method method5b<T extends self::Class1? = self::Class1?>() → void;
+  abstract method method5c<T extends self::Class1 = self::Class1>() → void;
+}
+static method main() → dynamic {}
+
+library;
+import self as gen;
+import "dart:core" as core;
+import "generic_override.dart" as self;
+
+import "org-dartlang-testcase:///generic_override.dart";
+
+abstract class LegacyClass1 extends core::Object {
+  synthetic constructor •() → gen::LegacyClass1*
+    : super core::Object::•()
+    ;
+  abstract method method1a<T extends core::Object* = dynamic>() → void;
+  abstract method method1b<T extends core::Object* = dynamic>() → void;
+  abstract method method1c<T extends core::Object* = dynamic>() → void;
+  abstract method method2a<T extends core::Object* = core::Object*>() → void;
+  abstract method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract method method2c<T extends core::Object* = core::Object*>() → void;
+  abstract method method3a<T extends dynamic = dynamic>() → void;
+  abstract method method3b<T extends dynamic = dynamic>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
+abstract class LegacyClass2 extends self::Class1 {
+  synthetic constructor •() → gen::LegacyClass2*
+    : super self::Class1::•()
+    ;
+  abstract method method1a<T extends core::Object* = dynamic>() → void;
+  abstract method method1b<T extends core::Object* = core::Object*>() → void;
+  abstract method method1c<T extends dynamic = dynamic>() → void;
+  abstract method method2a<T extends core::Object* = dynamic>() → void;
+  abstract method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract method method2c<T extends dynamic = dynamic>() → void;
+  abstract method method3a<T extends core::Object* = dynamic>() → void;
+  abstract method method3b<T extends core::Object* = core::Object*>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
+abstract class LegacyClass3 extends self::Class1 {
+  synthetic constructor •() → gen::LegacyClass3*
+    : super self::Class1::•()
+    ;
+  abstract member-signature method method1a<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method1b<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method1c<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method2a<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method2c<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract member-signature method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract member-signature method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect
index f9ca321..419cad0 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect
@@ -2,40 +2,43 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:39:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
 //  - 'Object' is from 'dart:core'.
 //   void method4b<T extends Object?>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
+// pkg/front_end/testcases/nnbd/generic_override.dart:19:8: Context: This is the overridden method ('method4b').
 //   void method4b<T extends Object>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:38:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:40:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
 //  - 'Object' is from 'dart:core'.
 //   void method4c<T extends Object>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:18:8: Context: This is the overridden method ('method4c').
+// pkg/front_end/testcases/nnbd/generic_override.dart:20:8: Context: This is the overridden method ('method4c').
 //   void method4c<T extends Object?>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:41:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:43:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5b<T extends Class1?>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:21:8: Context: This is the overridden method ('method5b').
+// pkg/front_end/testcases/nnbd/generic_override.dart:23:8: Context: This is the overridden method ('method5b').
 //   void method5b<T extends Class1>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:44:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5c<T extends Class1>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
+// pkg/front_end/testcases/nnbd/generic_override.dart:24:8: Context: This is the overridden method ('method5c').
 //   void method5c<T extends Class1?>();
 //        ^
 //
 import self as self;
 import "dart:core" as core;
+import "generic_override_lib.dart" as gen;
+
+import "org-dartlang-testcase:///generic_override_lib.dart";
 
 abstract class Class1 extends core::Object {
   synthetic constructor •() → self::Class1
@@ -77,4 +80,90 @@
   abstract method method5b<T extends self::Class1? = self::Class1?>() → void;
   abstract method method5c<T extends self::Class1 = self::Class1>() → void;
 }
+abstract class Class3 extends gen::LegacyClass1 {
+  synthetic constructor •() → self::Class3
+    : super gen::LegacyClass1::•()
+    ;
+  abstract method method1a<T extends core::Object? = dynamic>() → void;
+  abstract method method1b<T extends core::Object? = core::Object?>() → void;
+  abstract method method1c<T extends dynamic = dynamic>() → void;
+  abstract method method2a<T extends core::Object? = dynamic>() → void;
+  abstract method method2b<T extends core::Object? = core::Object?>() → void;
+  abstract method method2c<T extends dynamic = dynamic>() → void;
+  abstract method method3a<T extends core::Object? = dynamic>() → void;
+  abstract method method3b<T extends core::Object? = core::Object?>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object = core::Object>() → void;
+  abstract method method4b<T extends core::Object? = core::Object?>() → void;
+  abstract method method4c<T extends core::Object = core::Object>() → void;
+  abstract method method5a<T extends self::Class1 = self::Class1>() → void;
+  abstract method method5b<T extends self::Class1? = self::Class1?>() → void;
+  abstract method method5c<T extends self::Class1 = self::Class1>() → void;
+}
+static method main() → dynamic {}
+
+library;
+import self as gen;
+import "dart:core" as core;
+import "generic_override.dart" as self;
+
+import "org-dartlang-testcase:///generic_override.dart";
+
+abstract class LegacyClass1 extends core::Object {
+  synthetic constructor •() → gen::LegacyClass1*
+    : super core::Object::•()
+    ;
+  abstract method method1a<T extends core::Object* = dynamic>() → void;
+  abstract method method1b<T extends core::Object* = dynamic>() → void;
+  abstract method method1c<T extends core::Object* = dynamic>() → void;
+  abstract method method2a<T extends core::Object* = core::Object*>() → void;
+  abstract method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract method method2c<T extends core::Object* = core::Object*>() → void;
+  abstract method method3a<T extends dynamic = dynamic>() → void;
+  abstract method method3b<T extends dynamic = dynamic>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
+abstract class LegacyClass2 extends self::Class1 {
+  synthetic constructor •() → gen::LegacyClass2*
+    : super self::Class1::•()
+    ;
+  abstract method method1a<T extends core::Object* = dynamic>() → void;
+  abstract method method1b<T extends core::Object* = core::Object*>() → void;
+  abstract method method1c<T extends dynamic = dynamic>() → void;
+  abstract method method2a<T extends core::Object* = dynamic>() → void;
+  abstract method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract method method2c<T extends dynamic = dynamic>() → void;
+  abstract method method3a<T extends core::Object* = dynamic>() → void;
+  abstract method method3b<T extends core::Object* = core::Object*>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
+abstract class LegacyClass3 extends self::Class1 {
+  synthetic constructor •() → gen::LegacyClass3*
+    : super self::Class1::•()
+    ;
+  abstract member-signature method method1a<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method1b<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method1c<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method2a<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method2c<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract member-signature method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract member-signature method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect
index f9ca321..419cad0 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect
@@ -2,40 +2,43 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:39:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
 //  - 'Object' is from 'dart:core'.
 //   void method4b<T extends Object?>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
+// pkg/front_end/testcases/nnbd/generic_override.dart:19:8: Context: This is the overridden method ('method4b').
 //   void method4b<T extends Object>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:38:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:40:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
 //  - 'Object' is from 'dart:core'.
 //   void method4c<T extends Object>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:18:8: Context: This is the overridden method ('method4c').
+// pkg/front_end/testcases/nnbd/generic_override.dart:20:8: Context: This is the overridden method ('method4c').
 //   void method4c<T extends Object?>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:41:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:43:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5b<T extends Class1?>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:21:8: Context: This is the overridden method ('method5b').
+// pkg/front_end/testcases/nnbd/generic_override.dart:23:8: Context: This is the overridden method ('method5b').
 //   void method5b<T extends Class1>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
+// pkg/front_end/testcases/nnbd/generic_override.dart:44:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5c<T extends Class1>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
+// pkg/front_end/testcases/nnbd/generic_override.dart:24:8: Context: This is the overridden method ('method5c').
 //   void method5c<T extends Class1?>();
 //        ^
 //
 import self as self;
 import "dart:core" as core;
+import "generic_override_lib.dart" as gen;
+
+import "org-dartlang-testcase:///generic_override_lib.dart";
 
 abstract class Class1 extends core::Object {
   synthetic constructor •() → self::Class1
@@ -77,4 +80,90 @@
   abstract method method5b<T extends self::Class1? = self::Class1?>() → void;
   abstract method method5c<T extends self::Class1 = self::Class1>() → void;
 }
+abstract class Class3 extends gen::LegacyClass1 {
+  synthetic constructor •() → self::Class3
+    : super gen::LegacyClass1::•()
+    ;
+  abstract method method1a<T extends core::Object? = dynamic>() → void;
+  abstract method method1b<T extends core::Object? = core::Object?>() → void;
+  abstract method method1c<T extends dynamic = dynamic>() → void;
+  abstract method method2a<T extends core::Object? = dynamic>() → void;
+  abstract method method2b<T extends core::Object? = core::Object?>() → void;
+  abstract method method2c<T extends dynamic = dynamic>() → void;
+  abstract method method3a<T extends core::Object? = dynamic>() → void;
+  abstract method method3b<T extends core::Object? = core::Object?>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object = core::Object>() → void;
+  abstract method method4b<T extends core::Object? = core::Object?>() → void;
+  abstract method method4c<T extends core::Object = core::Object>() → void;
+  abstract method method5a<T extends self::Class1 = self::Class1>() → void;
+  abstract method method5b<T extends self::Class1? = self::Class1?>() → void;
+  abstract method method5c<T extends self::Class1 = self::Class1>() → void;
+}
+static method main() → dynamic {}
+
+library;
+import self as gen;
+import "dart:core" as core;
+import "generic_override.dart" as self;
+
+import "org-dartlang-testcase:///generic_override.dart";
+
+abstract class LegacyClass1 extends core::Object {
+  synthetic constructor •() → gen::LegacyClass1*
+    : super core::Object::•()
+    ;
+  abstract method method1a<T extends core::Object* = dynamic>() → void;
+  abstract method method1b<T extends core::Object* = dynamic>() → void;
+  abstract method method1c<T extends core::Object* = dynamic>() → void;
+  abstract method method2a<T extends core::Object* = core::Object*>() → void;
+  abstract method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract method method2c<T extends core::Object* = core::Object*>() → void;
+  abstract method method3a<T extends dynamic = dynamic>() → void;
+  abstract method method3b<T extends dynamic = dynamic>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
+abstract class LegacyClass2 extends self::Class1 {
+  synthetic constructor •() → gen::LegacyClass2*
+    : super self::Class1::•()
+    ;
+  abstract method method1a<T extends core::Object* = dynamic>() → void;
+  abstract method method1b<T extends core::Object* = core::Object*>() → void;
+  abstract method method1c<T extends dynamic = dynamic>() → void;
+  abstract method method2a<T extends core::Object* = dynamic>() → void;
+  abstract method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract method method2c<T extends dynamic = dynamic>() → void;
+  abstract method method3a<T extends core::Object* = dynamic>() → void;
+  abstract method method3b<T extends core::Object* = core::Object*>() → void;
+  abstract method method3c<T extends dynamic = dynamic>() → void;
+  abstract method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
+abstract class LegacyClass3 extends self::Class1 {
+  synthetic constructor •() → gen::LegacyClass3*
+    : super self::Class1::•()
+    ;
+  abstract member-signature method method1a<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method1b<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method1c<T extends core::Object* = dynamic>() → void;
+  abstract member-signature method method2a<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method2b<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method2c<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4a<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4b<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method4c<T extends core::Object* = core::Object*>() → void;
+  abstract member-signature method method5a<T extends self::Class1* = self::Class1*>() → void;
+  abstract member-signature method method5b<T extends self::Class1* = self::Class1*>() → void;
+  abstract member-signature method method5c<T extends self::Class1* = self::Class1*>() → void;
+}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/generic_override_lib.dart b/pkg/front_end/testcases/nnbd/generic_override_lib.dart
new file mode 100644
index 0000000..8a2640df
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/generic_override_lib.dart
@@ -0,0 +1,51 @@
+// 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.6
+
+import 'generic_override.dart';
+
+abstract class LegacyClass1 {
+  void method1a<T>();
+  void method1b<T>();
+  void method1c<T>();
+  void method2a<T extends Object>();
+  void method2b<T extends Object>();
+  void method2c<T extends Object>();
+  void method3a<T extends dynamic>();
+  void method3b<T extends dynamic>();
+  void method3c<T extends dynamic>();
+
+  void method4a<T extends Object>();
+  void method4b<T extends Object>();
+  void method4c<T extends Object>();
+
+  void method5a<T extends Class1>();
+  void method5b<T extends Class1>();
+  void method5c<T extends Class1>();
+}
+
+abstract class LegacyClass2 extends Class1 {
+  void method1a<T>();
+  void method1b<T extends Object>();
+  void method1c<T extends dynamic>();
+  void method2a<T>();
+  void method2b<T extends Object>();
+  void method2c<T extends dynamic>();
+  void method3a<T>();
+  void method3b<T extends Object>();
+  void method3c<T extends dynamic>();
+
+  void method4a<T extends Object>();
+  void method4b<T extends Object>();
+  void method4c<T extends Object>();
+
+  void method5a<T extends Class1>();
+  void method5b<T extends Class1>();
+  void method5c<T extends Class1>();
+}
+
+abstract class LegacyClass3 extends Class1 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/infer_method_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/infer_method_types.dart.outline.expect
index 5f8c4b8..f0f39bc4 100644
--- a/pkg/front_end/testcases/nnbd/infer_method_types.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/infer_method_types.dart.outline.expect
@@ -40,7 +40,7 @@
 abstract class H extends core::Object implements self::D, self::E, self::F, self::C {
   synthetic constructor •() → self::H
     ;
-  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → core::Object?;
 }
 abstract class I extends core::Object implements self::D {
   synthetic constructor •() → self::I
@@ -50,17 +50,17 @@
 abstract class J extends core::Object implements self::H {
   synthetic constructor •() → self::J
     ;
-  abstract method m(covariant core::num a) → void;
+  abstract method m(covariant core::num a) → core::Object?;
 }
 abstract class K extends core::Object implements self::I, self::E, self::G {
   synthetic constructor •() → self::K
     ;
-  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → core::Object?;
 }
 abstract class L extends core::Object implements self::K {
   synthetic constructor •() → self::L
     ;
-  abstract method m(covariant core::num a) → void;
+  abstract method m(covariant core::num a) → core::Object?;
 }
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.expect
index cc03fc1..85e72a0 100644
--- a/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.expect
@@ -48,7 +48,7 @@
   synthetic constructor •() → self::H
     : super core::Object::•()
     ;
-  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → core::Object?;
 }
 abstract class I extends core::Object implements self::D {
   synthetic constructor •() → self::I
@@ -60,18 +60,18 @@
   synthetic constructor •() → self::J
     : super core::Object::•()
     ;
-  abstract method m(covariant core::num a) → void;
+  abstract method m(covariant core::num a) → core::Object?;
 }
 abstract class K extends core::Object implements self::I, self::E, self::G {
   synthetic constructor •() → self::K
     : super core::Object::•()
     ;
-  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → core::Object?;
 }
 abstract class L extends core::Object implements self::K {
   synthetic constructor •() → self::L
     : super core::Object::•()
     ;
-  abstract method m(covariant core::num a) → void;
+  abstract method m(covariant core::num a) → core::Object?;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.transformed.expect
index cc03fc1..85e72a0 100644
--- a/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.transformed.expect
@@ -48,7 +48,7 @@
   synthetic constructor •() → self::H
     : super core::Object::•()
     ;
-  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → core::Object?;
 }
 abstract class I extends core::Object implements self::D {
   synthetic constructor •() → self::I
@@ -60,18 +60,18 @@
   synthetic constructor •() → self::J
     : super core::Object::•()
     ;
-  abstract method m(covariant core::num a) → void;
+  abstract method m(covariant core::num a) → core::Object?;
 }
 abstract class K extends core::Object implements self::I, self::E, self::G {
   synthetic constructor •() → self::K
     : super core::Object::•()
     ;
-  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → core::Object?;
 }
 abstract class L extends core::Object implements self::K {
   synthetic constructor •() → self::L
     : super core::Object::•()
     ;
-  abstract method m(covariant core::num a) → void;
+  abstract method m(covariant core::num a) → core::Object?;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.expect b/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.expect
index cc03fc1..85e72a0 100644
--- a/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.expect
@@ -48,7 +48,7 @@
   synthetic constructor •() → self::H
     : super core::Object::•()
     ;
-  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → core::Object?;
 }
 abstract class I extends core::Object implements self::D {
   synthetic constructor •() → self::I
@@ -60,18 +60,18 @@
   synthetic constructor •() → self::J
     : super core::Object::•()
     ;
-  abstract method m(covariant core::num a) → void;
+  abstract method m(covariant core::num a) → core::Object?;
 }
 abstract class K extends core::Object implements self::I, self::E, self::G {
   synthetic constructor •() → self::K
     : super core::Object::•()
     ;
-  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → core::Object?;
 }
 abstract class L extends core::Object implements self::K {
   synthetic constructor •() → self::L
     : super core::Object::•()
     ;
-  abstract method m(covariant core::num a) → void;
+  abstract method m(covariant core::num a) → core::Object?;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.transformed.expect
index cc03fc1..85e72a0 100644
--- a/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.transformed.expect
@@ -48,7 +48,7 @@
   synthetic constructor •() → self::H
     : super core::Object::•()
     ;
-  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → core::Object?;
 }
 abstract class I extends core::Object implements self::D {
   synthetic constructor •() → self::I
@@ -60,18 +60,18 @@
   synthetic constructor •() → self::J
     : super core::Object::•()
     ;
-  abstract method m(covariant core::num a) → void;
+  abstract method m(covariant core::num a) → core::Object?;
 }
 abstract class K extends core::Object implements self::I, self::E, self::G {
   synthetic constructor •() → self::K
     : super core::Object::•()
     ;
-  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → core::Object?;
 }
 abstract class L extends core::Object implements self::K {
   synthetic constructor •() → self::L
     : super core::Object::•()
     ;
-  abstract method m(covariant core::num a) → void;
+  abstract method m(covariant core::num a) → core::Object?;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue41349.dart b/pkg/front_end/testcases/nnbd/issue41349.dart
new file mode 100644
index 0000000..0ded2f1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41349.dart
@@ -0,0 +1,41 @@
+// 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 A {
+  foo() => 23;
+}
+
+extension B on A? {
+  foo() => 42;
+  bar() => 87;
+}
+
+extension C on A {
+  bar() => 123;
+}
+
+extension D on int Function()? {
+  int call() => 76;
+}
+
+main() {
+  testA(new A());
+  testFunction(() => 53);
+}
+
+testA(A? a) {
+  expect(23, a?.foo()); // A.foo instead of B.foo.
+  expect(42, a.foo()); // B.foo instead of nullable access to A.foo.
+  expect(123, a?.bar()); // C.bar instead of B.bar.
+  expect(87, a.bar()); // B.bar instead of nullable access to C.bar.
+}
+
+testFunction(int Function()? f) {
+  expect(53, f?.call()); // Function.call instead of D.call.
+  expect(76, f.call()); // D.call instead of nullable access to Function.call.
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41349.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue41349.dart.outline.expect
new file mode 100644
index 0000000..15071a6e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41349.dart.outline.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  method foo() → dynamic
+    ;
+}
+extension B on self::A? {
+  method foo = self::B|foo;
+  tearoff foo = self::B|get#foo;
+  method bar = self::B|bar;
+  tearoff bar = self::B|get#bar;
+}
+extension C on self::A {
+  method bar = self::C|bar;
+  tearoff bar = self::C|get#bar;
+}
+extension D on () →? core::int {
+  method call = self::D|call;
+  tearoff call = self::D|get#call;
+}
+static method B|foo(final self::A? #this) → dynamic
+  ;
+static method B|get#foo(final self::A? #this) → () → dynamic
+  return () → dynamic => self::B|foo(#this);
+static method B|bar(final self::A? #this) → dynamic
+  ;
+static method B|get#bar(final self::A? #this) → () → dynamic
+  return () → dynamic => self::B|bar(#this);
+static method C|bar(final self::A #this) → dynamic
+  ;
+static method C|get#bar(final self::A #this) → () → dynamic
+  return () → dynamic => self::C|bar(#this);
+static method D|call(final () →? core::int #this) → core::int
+  ;
+static method D|get#call(final () →? core::int #this) → () → core::int
+  return () → core::int => self::D|call(#this);
+static method main() → dynamic
+  ;
+static method testA(self::A? a) → dynamic
+  ;
+static method testFunction(() →? core::int f) → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue41349.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41349.dart.strong.expect
new file mode 100644
index 0000000..750eec3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41349.dart.strong.expect
@@ -0,0 +1,59 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo() → dynamic
+    return 23;
+}
+extension B on self::A? {
+  method foo = self::B|foo;
+  tearoff foo = self::B|get#foo;
+  method bar = self::B|bar;
+  tearoff bar = self::B|get#bar;
+}
+extension C on self::A {
+  method bar = self::C|bar;
+  tearoff bar = self::C|get#bar;
+}
+extension D on () →? core::int {
+  method call = self::D|call;
+  tearoff call = self::D|get#call;
+}
+static method B|foo(final self::A? #this) → dynamic
+  return 42;
+static method B|get#foo(final self::A? #this) → () → dynamic
+  return () → dynamic => self::B|foo(#this);
+static method B|bar(final self::A? #this) → dynamic
+  return 87;
+static method B|get#bar(final self::A? #this) → () → dynamic
+  return () → dynamic => self::B|bar(#this);
+static method C|bar(final self::A #this) → dynamic
+  return 123;
+static method C|get#bar(final self::A #this) → () → dynamic
+  return () → dynamic => self::C|bar(#this);
+static method D|call(final () →? core::int #this) → core::int
+  return 76;
+static method D|get#call(final () →? core::int #this) → () → core::int
+  return () → core::int => self::D|call(#this);
+static method main() → dynamic {
+  self::testA(new self::A::•());
+  self::testFunction(() → core::int => 53);
+}
+static method testA(self::A? a) → dynamic {
+  self::expect(23, let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{self::A}.{self::A::foo}());
+  self::expect(42, self::B|foo(a));
+  self::expect(123, let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{dynamic} null : self::C|bar(#t2{self::A}));
+  self::expect(87, self::B|bar(a));
+}
+static method testFunction(() →? core::int f) → dynamic {
+  self::expect(53, let final () →? core::int #t3 = f in #t3.{core::Object::==}(null) ?{core::int?} null : #t3{() → core::int}.call());
+  self::expect(76, self::D|call(f));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41349.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41349.dart.strong.transformed.expect
new file mode 100644
index 0000000..750eec3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41349.dart.strong.transformed.expect
@@ -0,0 +1,59 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo() → dynamic
+    return 23;
+}
+extension B on self::A? {
+  method foo = self::B|foo;
+  tearoff foo = self::B|get#foo;
+  method bar = self::B|bar;
+  tearoff bar = self::B|get#bar;
+}
+extension C on self::A {
+  method bar = self::C|bar;
+  tearoff bar = self::C|get#bar;
+}
+extension D on () →? core::int {
+  method call = self::D|call;
+  tearoff call = self::D|get#call;
+}
+static method B|foo(final self::A? #this) → dynamic
+  return 42;
+static method B|get#foo(final self::A? #this) → () → dynamic
+  return () → dynamic => self::B|foo(#this);
+static method B|bar(final self::A? #this) → dynamic
+  return 87;
+static method B|get#bar(final self::A? #this) → () → dynamic
+  return () → dynamic => self::B|bar(#this);
+static method C|bar(final self::A #this) → dynamic
+  return 123;
+static method C|get#bar(final self::A #this) → () → dynamic
+  return () → dynamic => self::C|bar(#this);
+static method D|call(final () →? core::int #this) → core::int
+  return 76;
+static method D|get#call(final () →? core::int #this) → () → core::int
+  return () → core::int => self::D|call(#this);
+static method main() → dynamic {
+  self::testA(new self::A::•());
+  self::testFunction(() → core::int => 53);
+}
+static method testA(self::A? a) → dynamic {
+  self::expect(23, let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{self::A}.{self::A::foo}());
+  self::expect(42, self::B|foo(a));
+  self::expect(123, let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{dynamic} null : self::C|bar(#t2{self::A}));
+  self::expect(87, self::B|bar(a));
+}
+static method testFunction(() →? core::int f) → dynamic {
+  self::expect(53, let final () →? core::int #t3 = f in #t3.{core::Object::==}(null) ?{core::int?} null : #t3{() → core::int}.call());
+  self::expect(76, self::D|call(f));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41349.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41349.dart.weak.expect
new file mode 100644
index 0000000..750eec3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41349.dart.weak.expect
@@ -0,0 +1,59 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo() → dynamic
+    return 23;
+}
+extension B on self::A? {
+  method foo = self::B|foo;
+  tearoff foo = self::B|get#foo;
+  method bar = self::B|bar;
+  tearoff bar = self::B|get#bar;
+}
+extension C on self::A {
+  method bar = self::C|bar;
+  tearoff bar = self::C|get#bar;
+}
+extension D on () →? core::int {
+  method call = self::D|call;
+  tearoff call = self::D|get#call;
+}
+static method B|foo(final self::A? #this) → dynamic
+  return 42;
+static method B|get#foo(final self::A? #this) → () → dynamic
+  return () → dynamic => self::B|foo(#this);
+static method B|bar(final self::A? #this) → dynamic
+  return 87;
+static method B|get#bar(final self::A? #this) → () → dynamic
+  return () → dynamic => self::B|bar(#this);
+static method C|bar(final self::A #this) → dynamic
+  return 123;
+static method C|get#bar(final self::A #this) → () → dynamic
+  return () → dynamic => self::C|bar(#this);
+static method D|call(final () →? core::int #this) → core::int
+  return 76;
+static method D|get#call(final () →? core::int #this) → () → core::int
+  return () → core::int => self::D|call(#this);
+static method main() → dynamic {
+  self::testA(new self::A::•());
+  self::testFunction(() → core::int => 53);
+}
+static method testA(self::A? a) → dynamic {
+  self::expect(23, let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{self::A}.{self::A::foo}());
+  self::expect(42, self::B|foo(a));
+  self::expect(123, let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{dynamic} null : self::C|bar(#t2{self::A}));
+  self::expect(87, self::B|bar(a));
+}
+static method testFunction(() →? core::int f) → dynamic {
+  self::expect(53, let final () →? core::int #t3 = f in #t3.{core::Object::==}(null) ?{core::int?} null : #t3{() → core::int}.call());
+  self::expect(76, self::D|call(f));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41349.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41349.dart.weak.transformed.expect
new file mode 100644
index 0000000..750eec3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41349.dart.weak.transformed.expect
@@ -0,0 +1,59 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo() → dynamic
+    return 23;
+}
+extension B on self::A? {
+  method foo = self::B|foo;
+  tearoff foo = self::B|get#foo;
+  method bar = self::B|bar;
+  tearoff bar = self::B|get#bar;
+}
+extension C on self::A {
+  method bar = self::C|bar;
+  tearoff bar = self::C|get#bar;
+}
+extension D on () →? core::int {
+  method call = self::D|call;
+  tearoff call = self::D|get#call;
+}
+static method B|foo(final self::A? #this) → dynamic
+  return 42;
+static method B|get#foo(final self::A? #this) → () → dynamic
+  return () → dynamic => self::B|foo(#this);
+static method B|bar(final self::A? #this) → dynamic
+  return 87;
+static method B|get#bar(final self::A? #this) → () → dynamic
+  return () → dynamic => self::B|bar(#this);
+static method C|bar(final self::A #this) → dynamic
+  return 123;
+static method C|get#bar(final self::A #this) → () → dynamic
+  return () → dynamic => self::C|bar(#this);
+static method D|call(final () →? core::int #this) → core::int
+  return 76;
+static method D|get#call(final () →? core::int #this) → () → core::int
+  return () → core::int => self::D|call(#this);
+static method main() → dynamic {
+  self::testA(new self::A::•());
+  self::testFunction(() → core::int => 53);
+}
+static method testA(self::A? a) → dynamic {
+  self::expect(23, let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{dynamic} null : #t1{self::A}.{self::A::foo}());
+  self::expect(42, self::B|foo(a));
+  self::expect(123, let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{dynamic} null : self::C|bar(#t2{self::A}));
+  self::expect(87, self::B|bar(a));
+}
+static method testFunction(() →? core::int f) → dynamic {
+  self::expect(53, let final () →? core::int #t3 = f in #t3.{core::Object::==}(null) ?{core::int?} null : #t3{() → core::int}.call());
+  self::expect(76, self::D|call(f));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41415.dart b/pkg/front_end/testcases/nnbd/issue41415.dart
new file mode 100644
index 0000000..60e3258
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41415.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2017, 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.
+
+// Requirements=nnbd-strong
+import "package:expect/expect.dart";
+
+main() {
+  // Pre-NNBD bottom type.
+  int Function(Null) f = (x) => 1; // Runtime type is int Function(Object?)
+  // NNBD bottom type.
+  int Function(Never) g = (x) => 1; // Runtime type is int Function(Object?)
+  // NNBD bottom type.
+
+  int Function(Never?) h = (x) => 1; // Runtime type is int Function(Object?)
+
+  int Function(String) i = (x) => 1; // Runtime type is int Function(String)
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41415.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue41415.dart.outline.expect
new file mode 100644
index 0000000..73b21aa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41415.dart.outline.expect
@@ -0,0 +1,7 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "package:expect/expect.dart";
+
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue41415.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41415.dart.strong.expect
new file mode 100644
index 0000000..7e85811
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41415.dart.strong.expect
@@ -0,0 +1,12 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static method main() → dynamic {
+  (core::Null?) → core::int f = (core::Object? x) → core::int => 1;
+  (Never) → core::int g = (core::Object? x) → core::int => 1;
+  (Never?) → core::int h = (core::Object? x) → core::int => 1;
+  (core::String) → core::int i = (core::String x) → core::int => 1;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41415.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41415.dart.strong.transformed.expect
new file mode 100644
index 0000000..7e85811
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41415.dart.strong.transformed.expect
@@ -0,0 +1,12 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static method main() → dynamic {
+  (core::Null?) → core::int f = (core::Object? x) → core::int => 1;
+  (Never) → core::int g = (core::Object? x) → core::int => 1;
+  (Never?) → core::int h = (core::Object? x) → core::int => 1;
+  (core::String) → core::int i = (core::String x) → core::int => 1;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41415.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41415.dart.weak.expect
new file mode 100644
index 0000000..7e85811
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41415.dart.weak.expect
@@ -0,0 +1,12 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static method main() → dynamic {
+  (core::Null?) → core::int f = (core::Object? x) → core::int => 1;
+  (Never) → core::int g = (core::Object? x) → core::int => 1;
+  (Never?) → core::int h = (core::Object? x) → core::int => 1;
+  (core::String) → core::int i = (core::String x) → core::int => 1;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41415.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41415.dart.weak.transformed.expect
new file mode 100644
index 0000000..7e85811
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41415.dart.weak.transformed.expect
@@ -0,0 +1,12 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+static method main() → dynamic {
+  (core::Null?) → core::int f = (core::Object? x) → core::int => 1;
+  (Never) → core::int g = (core::Object? x) → core::int => 1;
+  (Never?) → core::int h = (core::Object? x) → core::int => 1;
+  (core::String) → core::int i = (core::String x) → core::int => 1;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart b/pkg/front_end/testcases/nnbd/issue41495.dart
new file mode 100644
index 0000000..ceaf89a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart
@@ -0,0 +1,16 @@
+// 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 A {
+  int c1 = 1;
+  int test() => 2;
+}
+
+main() {}
+
+errors() {
+  A? a1 = new A();
+  a1.c1;
+  a1.test;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue41495.dart.outline.expect
new file mode 100644
index 0000000..20f3ce6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart.outline.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int c1;
+  synthetic constructor •() → self::A
+    ;
+  method test() → core::int
+    ;
+}
+static method main() → dynamic
+  ;
+static method errors() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect
new file mode 100644
index 0000000..ecc36781
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+// Try accessing using ?. instead.
+//   a1.c1;
+//      ^^
+//
+// pkg/front_end/testcases/nnbd/issue41495.dart:15:6: Error: Property 'test' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+// Try accessing using ?. instead.
+//   a1.test;
+//      ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int c1 = 1;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method test() → core::int
+    return 2;
+}
+static method main() → dynamic {}
+static method errors() → dynamic {
+  self::A? a1 = new self::A::•();
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+Try accessing using ?. instead.
+  a1.c1;
+     ^^" in a1.{self::A::c1};
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:15:6: Error: Property 'test' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+Try accessing using ?. instead.
+  a1.test;
+     ^^^^" in a1.{self::A::test};
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41495.dart.strong.transformed.expect
new file mode 100644
index 0000000..ecc36781
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart.strong.transformed.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+// Try accessing using ?. instead.
+//   a1.c1;
+//      ^^
+//
+// pkg/front_end/testcases/nnbd/issue41495.dart:15:6: Error: Property 'test' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+// Try accessing using ?. instead.
+//   a1.test;
+//      ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int c1 = 1;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method test() → core::int
+    return 2;
+}
+static method main() → dynamic {}
+static method errors() → dynamic {
+  self::A? a1 = new self::A::•();
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+Try accessing using ?. instead.
+  a1.c1;
+     ^^" in a1.{self::A::c1};
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:15:6: Error: Property 'test' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+Try accessing using ?. instead.
+  a1.test;
+     ^^^^" in a1.{self::A::test};
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect
new file mode 100644
index 0000000..ecc36781
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+// Try accessing using ?. instead.
+//   a1.c1;
+//      ^^
+//
+// pkg/front_end/testcases/nnbd/issue41495.dart:15:6: Error: Property 'test' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+// Try accessing using ?. instead.
+//   a1.test;
+//      ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int c1 = 1;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method test() → core::int
+    return 2;
+}
+static method main() → dynamic {}
+static method errors() → dynamic {
+  self::A? a1 = new self::A::•();
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+Try accessing using ?. instead.
+  a1.c1;
+     ^^" in a1.{self::A::c1};
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:15:6: Error: Property 'test' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+Try accessing using ?. instead.
+  a1.test;
+     ^^^^" in a1.{self::A::test};
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41495.dart.weak.transformed.expect
new file mode 100644
index 0000000..ecc36781
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart.weak.transformed.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+// Try accessing using ?. instead.
+//   a1.c1;
+//      ^^
+//
+// pkg/front_end/testcases/nnbd/issue41495.dart:15:6: Error: Property 'test' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+// Try accessing using ?. instead.
+//   a1.test;
+//      ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int c1 = 1;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method test() → core::int
+    return 2;
+}
+static method main() → dynamic {}
+static method errors() → dynamic {
+  self::A? a1 = new self::A::•();
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+Try accessing using ?. instead.
+  a1.c1;
+     ^^" in a1.{self::A::c1};
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:15:6: Error: Property 'test' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
+Try accessing using ?. instead.
+  a1.test;
+     ^^^^" in a1.{self::A::test};
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41567.dart b/pkg/front_end/testcases/nnbd/issue41567.dart
new file mode 100644
index 0000000..9df5590
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41567.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.
+
+import 'issue41567_lib.dart';
+
+class B extends A {}
+
+class in1 extends out_Object implements B {} // ok
+
+class in2 extends B implements out_Object {} // ok
+
+class in3 extends out_int implements B {} // error
+
+class in4 extends B implements out_int {} // error
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue41567.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue41567.dart.outline.expect
new file mode 100644
index 0000000..4214a62
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41567.dart.outline.expect
@@ -0,0 +1,58 @@
+//
+// Problems in component:
+//
+// pkg/front_end/testcases/nnbd/issue41567.dart:13:7: Error: 'in3' can't implement both 'A<int>' and 'A<dynamic>'
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41567_lib.dart'.
+// class in3 extends out_int implements B {} // error
+//       ^
+//
+// pkg/front_end/testcases/nnbd/issue41567.dart:15:7: Error: 'in4' can't implement both 'A<dynamic>' and 'A<int>'
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41567_lib.dart'.
+// class in4 extends B implements out_int {} // error
+//       ^
+//
+library /*isNonNullableByDefault*/;
+import self as self;
+import "issue41567_lib.dart" as iss;
+
+import "org-dartlang-testcase:///issue41567_lib.dart";
+
+class B extends iss::A<dynamic> {
+  synthetic constructor •() → self::B
+    ;
+}
+class in1 extends iss::out_Object implements self::B {
+  synthetic constructor •() → self::in1
+    ;
+}
+class in2 extends self::B implements iss::out_Object {
+  synthetic constructor •() → self::in2
+    ;
+}
+class in3 extends iss::out_int implements self::B {
+  synthetic constructor •() → self::in3
+    ;
+}
+class in4 extends self::B implements iss::out_int {
+  synthetic constructor •() → self::in4
+    ;
+}
+static method main() → dynamic
+  ;
+
+library;
+import self as iss;
+import "dart:core" as core;
+
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → iss::A<iss::A::T*>*
+    ;
+}
+class out_int extends iss::A<core::int*> {
+  synthetic constructor •() → iss::out_int*
+    ;
+}
+class out_Object extends iss::A<core::Object*> {
+  synthetic constructor •() → iss::out_Object*
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41567.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41567.dart.strong.expect
new file mode 100644
index 0000000..5ae9d25
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41567.dart.strong.expect
@@ -0,0 +1,65 @@
+//
+// Problems in component:
+//
+// pkg/front_end/testcases/nnbd/issue41567.dart:13:7: Error: 'in3' can't implement both 'A<int>' and 'A<dynamic>'
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41567_lib.dart'.
+// class in3 extends out_int implements B {} // error
+//       ^
+//
+// pkg/front_end/testcases/nnbd/issue41567.dart:15:7: Error: 'in4' can't implement both 'A<dynamic>' and 'A<int>'
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41567_lib.dart'.
+// class in4 extends B implements out_int {} // error
+//       ^
+//
+library /*isNonNullableByDefault*/;
+import self as self;
+import "issue41567_lib.dart" as iss;
+
+import "org-dartlang-testcase:///issue41567_lib.dart";
+
+class B extends iss::A<dynamic> {
+  synthetic constructor •() → self::B
+    : super iss::A::•()
+    ;
+}
+class in1 extends iss::out_Object implements self::B {
+  synthetic constructor •() → self::in1
+    : super iss::out_Object::•()
+    ;
+}
+class in2 extends self::B implements iss::out_Object {
+  synthetic constructor •() → self::in2
+    : super self::B::•()
+    ;
+}
+class in3 extends iss::out_int implements self::B {
+  synthetic constructor •() → self::in3
+    : super iss::out_int::•()
+    ;
+}
+class in4 extends self::B implements iss::out_int {
+  synthetic constructor •() → self::in4
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {}
+
+library;
+import self as iss;
+import "dart:core" as core;
+
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → iss::A<iss::A::T*>*
+    : super core::Object::•()
+    ;
+}
+class out_int extends iss::A<core::int*> {
+  synthetic constructor •() → iss::out_int*
+    : super iss::A::•()
+    ;
+}
+class out_Object extends iss::A<core::Object*> {
+  synthetic constructor •() → iss::out_Object*
+    : super iss::A::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41567.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41567.dart.weak.expect
new file mode 100644
index 0000000..5ae9d25
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41567.dart.weak.expect
@@ -0,0 +1,65 @@
+//
+// Problems in component:
+//
+// pkg/front_end/testcases/nnbd/issue41567.dart:13:7: Error: 'in3' can't implement both 'A<int>' and 'A<dynamic>'
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41567_lib.dart'.
+// class in3 extends out_int implements B {} // error
+//       ^
+//
+// pkg/front_end/testcases/nnbd/issue41567.dart:15:7: Error: 'in4' can't implement both 'A<dynamic>' and 'A<int>'
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41567_lib.dart'.
+// class in4 extends B implements out_int {} // error
+//       ^
+//
+library /*isNonNullableByDefault*/;
+import self as self;
+import "issue41567_lib.dart" as iss;
+
+import "org-dartlang-testcase:///issue41567_lib.dart";
+
+class B extends iss::A<dynamic> {
+  synthetic constructor •() → self::B
+    : super iss::A::•()
+    ;
+}
+class in1 extends iss::out_Object implements self::B {
+  synthetic constructor •() → self::in1
+    : super iss::out_Object::•()
+    ;
+}
+class in2 extends self::B implements iss::out_Object {
+  synthetic constructor •() → self::in2
+    : super self::B::•()
+    ;
+}
+class in3 extends iss::out_int implements self::B {
+  synthetic constructor •() → self::in3
+    : super iss::out_int::•()
+    ;
+}
+class in4 extends self::B implements iss::out_int {
+  synthetic constructor •() → self::in4
+    : super self::B::•()
+    ;
+}
+static method main() → dynamic {}
+
+library;
+import self as iss;
+import "dart:core" as core;
+
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → iss::A<iss::A::T*>*
+    : super core::Object::•()
+    ;
+}
+class out_int extends iss::A<core::int*> {
+  synthetic constructor •() → iss::out_int*
+    : super iss::A::•()
+    ;
+}
+class out_Object extends iss::A<core::Object*> {
+  synthetic constructor •() → iss::out_Object*
+    : super iss::A::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41567_lib.dart b/pkg/front_end/testcases/nnbd/issue41567_lib.dart
new file mode 100644
index 0000000..e45bcd9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41567_lib.dart
@@ -0,0 +1,11 @@
+// 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.6
+
+class A<T> {}
+
+class out_int extends A<int> {}
+
+class out_Object extends A<Object> {}
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.expect
index 5ef8175..40260d9 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.expect
@@ -32,21 +32,11 @@
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
-// Try accessing using ?. instead.
-//   y.bar; // Error.
-//     ^^^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
-// Try accessing using ?. instead.
-//   y.baz = 42; // Error.
-//     ^^^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing method, or defining a method named 'call'.
 //   y(); // Error.
@@ -57,37 +47,21 @@
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-//   y++; // Error.
-//    ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-//   y += 1; // Error.
-//     ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]' operator.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
-//   y[42]; // Error.
-//    ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]=' operator.
 //   y[42] = 42; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
-//   y[42] = 42; // Error.
-//    ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -117,17 +91,11 @@
 Try correcting the name to the name of an existing method, or defining a method named 'foo'.
   y.foo(); // Error.
     ^^^";
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
-Try accessing using ?. instead.
-  y.bar; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
   y.bar; // Error.
     ^^^";
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
-Try accessing using ?. instead.
-  y.baz = 42; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
   y.baz = 42; // Error.
     ^^^";
@@ -135,27 +103,19 @@
 Try correcting the name to the name of an existing method, or defining a method named 'call'.
   y(); // Error.
    ^";
-  y = (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-  y++; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
+  y = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y++; // Error.
-   ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  y = (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-  y += 1; // Error.
-    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
+   ^" as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
+  y = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y += 1; // Error.
-    ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
-  y[42]; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
+    ^" as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]' operator.
   y[42]; // Error.
    ^";
-  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
-  y[42] = 42; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]=' operator.
   y[42] = 42; // Error.
    ^";
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.transformed.expect
index 5ef8175..40260d9 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.strong.transformed.expect
@@ -32,21 +32,11 @@
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
-// Try accessing using ?. instead.
-//   y.bar; // Error.
-//     ^^^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
-// Try accessing using ?. instead.
-//   y.baz = 42; // Error.
-//     ^^^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing method, or defining a method named 'call'.
 //   y(); // Error.
@@ -57,37 +47,21 @@
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-//   y++; // Error.
-//    ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-//   y += 1; // Error.
-//     ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]' operator.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
-//   y[42]; // Error.
-//    ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]=' operator.
 //   y[42] = 42; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
-//   y[42] = 42; // Error.
-//    ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -117,17 +91,11 @@
 Try correcting the name to the name of an existing method, or defining a method named 'foo'.
   y.foo(); // Error.
     ^^^";
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
-Try accessing using ?. instead.
-  y.bar; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
   y.bar; // Error.
     ^^^";
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
-Try accessing using ?. instead.
-  y.baz = 42; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
   y.baz = 42; // Error.
     ^^^";
@@ -135,27 +103,19 @@
 Try correcting the name to the name of an existing method, or defining a method named 'call'.
   y(); // Error.
    ^";
-  y = (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-  y++; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
+  y = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y++; // Error.
-   ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  y = (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-  y += 1; // Error.
-    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
+   ^" as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
+  y = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y += 1; // Error.
-    ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
-  y[42]; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
+    ^" as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]' operator.
   y[42]; // Error.
    ^";
-  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
-  y[42] = 42; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]=' operator.
   y[42] = 42; // Error.
    ^";
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect
index 5ef8175..40260d9 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect
@@ -32,21 +32,11 @@
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
-// Try accessing using ?. instead.
-//   y.bar; // Error.
-//     ^^^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
-// Try accessing using ?. instead.
-//   y.baz = 42; // Error.
-//     ^^^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing method, or defining a method named 'call'.
 //   y(); // Error.
@@ -57,37 +47,21 @@
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-//   y++; // Error.
-//    ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-//   y += 1; // Error.
-//     ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]' operator.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
-//   y[42]; // Error.
-//    ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]=' operator.
 //   y[42] = 42; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
-//   y[42] = 42; // Error.
-//    ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -117,17 +91,11 @@
 Try correcting the name to the name of an existing method, or defining a method named 'foo'.
   y.foo(); // Error.
     ^^^";
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
-Try accessing using ?. instead.
-  y.bar; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
   y.bar; // Error.
     ^^^";
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
-Try accessing using ?. instead.
-  y.baz = 42; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
   y.baz = 42; // Error.
     ^^^";
@@ -135,27 +103,19 @@
 Try correcting the name to the name of an existing method, or defining a method named 'call'.
   y(); // Error.
    ^";
-  y = (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-  y++; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
+  y = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y++; // Error.
-   ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  y = (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-  y += 1; // Error.
-    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
+   ^" as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
+  y = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y += 1; // Error.
-    ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
-  y[42]; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
+    ^" as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]' operator.
   y[42]; // Error.
    ^";
-  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
-  y[42] = 42; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]=' operator.
   y[42] = 42; // Error.
    ^";
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.transformed.expect
index 5ef8175..40260d9 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.transformed.expect
@@ -32,21 +32,11 @@
 //   y.bar; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
-// Try accessing using ?. instead.
-//   y.bar; // Error.
-//     ^^^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
 //   y.baz = 42; // Error.
 //     ^^^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
-// Try accessing using ?. instead.
-//   y.baz = 42; // Error.
-//     ^^^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:33:4: Error: The method 'call' isn't defined for the class 'Never'.
 // Try correcting the name to the name of an existing method, or defining a method named 'call'.
 //   y(); // Error.
@@ -57,37 +47,21 @@
 //   y++; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-//   y++; // Error.
-//    ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '+' operator.
 //   y += 1; // Error.
 //     ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-//   y += 1; // Error.
-//     ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]' operator.
 //   y[42]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
-//   y[42]; // Error.
-//    ^
-//
 // pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 // Try correcting the operator to an existing operator, or defining a '[]=' operator.
 //   y[42] = 42; // Error.
 //    ^
 //
-// pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
-//   y[42] = 42; // Error.
-//    ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -117,17 +91,11 @@
 Try correcting the name to the name of an existing method, or defining a method named 'foo'.
   y.foo(); // Error.
     ^^^";
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: Property 'bar' cannot be accessed on 'Never' because it is potentially null.
-Try accessing using ?. instead.
-  y.bar; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:31:5: Error: The getter 'bar' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
   y.bar; // Error.
     ^^^";
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: Property 'baz' cannot be accessed on 'Never' because it is potentially null.
-Try accessing using ?. instead.
-  y.baz = 42; // Error.
-    ^^^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:32:5: Error: The setter 'baz' isn't defined for the class 'Never'.
 Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
   y.baz = 42; // Error.
     ^^^";
@@ -135,27 +103,19 @@
 Try correcting the name to the name of an existing method, or defining a method named 'call'.
   y(); // Error.
    ^";
-  y = (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-  y++; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
+  y = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:34:4: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y++; // Error.
-   ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  y = (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: Operator '+' cannot be called on 'Never' because it is potentially null.
-  y += 1; // Error.
-    ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
+   ^" as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
+  y = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:35:5: Error: The operator '+' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
   y += 1; // Error.
-    ^") as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
-  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: Operator '[]' cannot be called on 'Never' because it is potentially null.
-  y[42]; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
+    ^" as{TypeError,ForDynamic,ForNonNullableByDefault} Never?;
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:36:4: Error: The operator '[]' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]' operator.
   y[42]; // Error.
    ^";
-  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: Operator '[]=' cannot be called on 'Never' because it is potentially null.
-  y[42] = 42; // Error.
-   ^" in invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
+  invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:37:4: Error: The operator '[]=' isn't defined for the class 'Never'.
 Try correcting the operator to an existing operator, or defining a '[]=' operator.
   y[42] = 42; // Error.
    ^";
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart
index fa74007..8452c473 100644
--- a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart
@@ -6,6 +6,13 @@
 
 import 'nsm_from_opt_in_lib.dart';
 
+abstract class A2 implements A {
+  @override
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
 abstract class B2 extends A implements C2 {
   @override
   noSuchMethod(Invocation invocation) {
@@ -15,6 +22,9 @@
 
 abstract class C2 {
   int method(int i, {optional});
+  T genericMethod1<T>(T t);
+  T genericMethod2<T extends Object>(T t);
+  T genericMethod3<T extends Object>(T t);
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.outline.expect
index 00778a8..aff6f51 100644
--- a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.outline.expect
@@ -1,10 +1,21 @@
 library;
 import self as self;
-import "nsm_from_opt_in_lib.dart" as nsm;
 import "dart:core" as core;
+import "nsm_from_opt_in_lib.dart" as nsm;
 
 import "org-dartlang-testcase:///nsm_from_opt_in_lib.dart";
 
+abstract class A2 extends core::Object implements nsm::A {
+  synthetic constructor •() → self::A2*
+    ;
+  @core::override
+  method noSuchMethod(core::Invocation* invocation) → dynamic
+    ;
+  abstract member-signature method method(core::int* i) → core::int*;
+  abstract member-signature method genericMethod1<T extends core::Object* = dynamic>(self::A2::genericMethod1::T* t) → self::A2::genericMethod1::T*;
+  abstract member-signature method genericMethod2<T extends core::Object* = core::Object*>(self::A2::genericMethod2::T* t) → self::A2::genericMethod2::T*;
+  abstract member-signature method genericMethod3<T extends core::Object* = core::Object*>(self::A2::genericMethod3::T* t) → self::A2::genericMethod3::T*;
+}
 abstract class B2 extends nsm::A implements self::C2 {
   synthetic constructor •() → self::B2*
     ;
@@ -12,11 +23,17 @@
   method noSuchMethod(core::Invocation* invocation) → dynamic
     ;
   abstract forwarding-stub method method(core::int* i, {dynamic optional}) → core::int*;
+  abstract member-signature method genericMethod1<T extends core::Object* = dynamic>(self::B2::genericMethod1::T* t) → self::B2::genericMethod1::T*;
+  abstract member-signature method genericMethod2<T extends core::Object* = core::Object*>(self::B2::genericMethod2::T* t) → self::B2::genericMethod2::T*;
+  abstract member-signature method genericMethod3<T extends core::Object* = core::Object*>(self::B2::genericMethod3::T* t) → self::B2::genericMethod3::T*;
 }
 abstract class C2 extends core::Object {
   synthetic constructor •() → self::C2*
     ;
   abstract method method(core::int* i, {dynamic optional}) → core::int*;
+  abstract method genericMethod1<T extends core::Object* = dynamic>(self::C2::genericMethod1::T* t) → self::C2::genericMethod1::T*;
+  abstract method genericMethod2<T extends core::Object* = core::Object*>(self::C2::genericMethod2::T* t) → self::C2::genericMethod2::T*;
+  abstract method genericMethod3<T extends core::Object* = core::Object*>(self::C2::genericMethod3::T* t) → self::C2::genericMethod3::T*;
 }
 static method main() → dynamic
   ;
@@ -30,6 +47,12 @@
     ;
   method method(core::int? i) → core::int
     ;
+  method genericMethod1<T extends core::Object? = dynamic>(nsm::A::genericMethod1::T% t) → nsm::A::genericMethod1::T%
+    ;
+  method genericMethod2<T extends core::Object? = core::Object?>(nsm::A::genericMethod2::T% t) → nsm::A::genericMethod2::T%
+    ;
+  method genericMethod3<T extends core::Object = core::Object>(nsm::A::genericMethod3::T t) → nsm::A::genericMethod3::T
+    ;
 }
 abstract class B1 extends nsm::A implements nsm::C1 {
   synthetic constructor •() → nsm::B1
@@ -43,4 +66,7 @@
   synthetic constructor •() → nsm::C1
     ;
   abstract method method(core::int? i, {dynamic optional}) → core::int;
+  abstract method genericMethod1<T extends core::Object? = dynamic>(nsm::C1::genericMethod1::T% t) → nsm::C1::genericMethod1::T%;
+  abstract method genericMethod2<T extends core::Object? = core::Object?>(nsm::C1::genericMethod2::T% t) → nsm::C1::genericMethod2::T%;
+  abstract method genericMethod3<T extends core::Object = core::Object>(nsm::C1::genericMethod3::T t) → nsm::C1::genericMethod3::T;
 }
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.expect
index 10bcb6e..b04ccd6 100644
--- a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.expect
@@ -1,10 +1,23 @@
 library;
 import self as self;
-import "nsm_from_opt_in_lib.dart" as nsm;
 import "dart:core" as core;
+import "nsm_from_opt_in_lib.dart" as nsm;
 
 import "org-dartlang-testcase:///nsm_from_opt_in_lib.dart";
 
+abstract class A2 extends core::Object implements nsm::A {
+  synthetic constructor •() → self::A2*
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation* invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract member-signature method method(core::int* i) → core::int*;
+  abstract member-signature method genericMethod1<T extends core::Object* = dynamic>(self::A2::genericMethod1::T* t) → self::A2::genericMethod1::T*;
+  abstract member-signature method genericMethod2<T extends core::Object* = core::Object*>(self::A2::genericMethod2::T* t) → self::A2::genericMethod2::T*;
+  abstract member-signature method genericMethod3<T extends core::Object* = core::Object*>(self::A2::genericMethod3::T* t) → self::A2::genericMethod3::T*;
+}
 abstract class B2 extends nsm::A implements self::C2 {
   synthetic constructor •() → self::B2*
     : super nsm::A::•()
@@ -14,12 +27,18 @@
     return super.{core::Object::noSuchMethod}(invocation);
   }
   abstract forwarding-stub method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+  abstract member-signature method genericMethod1<T extends core::Object* = dynamic>(self::B2::genericMethod1::T* t) → self::B2::genericMethod1::T*;
+  abstract member-signature method genericMethod2<T extends core::Object* = core::Object*>(self::B2::genericMethod2::T* t) → self::B2::genericMethod2::T*;
+  abstract member-signature method genericMethod3<T extends core::Object* = core::Object*>(self::B2::genericMethod3::T* t) → self::B2::genericMethod3::T*;
 }
 abstract class C2 extends core::Object {
   synthetic constructor •() → self::C2*
     : super core::Object::•()
     ;
   abstract method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+  abstract method genericMethod1<T extends core::Object* = dynamic>(self::C2::genericMethod1::T* t) → self::C2::genericMethod1::T*;
+  abstract method genericMethod2<T extends core::Object* = core::Object*>(self::C2::genericMethod2::T* t) → self::C2::genericMethod2::T*;
+  abstract method genericMethod3<T extends core::Object* = core::Object*>(self::C2::genericMethod3::T* t) → self::C2::genericMethod3::T*;
 }
 static method main() → dynamic {}
 
@@ -33,6 +52,12 @@
     ;
   method method(core::int? i) → core::int
     return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+  method genericMethod1<T extends core::Object? = dynamic>(nsm::A::genericMethod1::T% t) → nsm::A::genericMethod1::T%
+    return t;
+  method genericMethod2<T extends core::Object? = core::Object?>(nsm::A::genericMethod2::T% t) → nsm::A::genericMethod2::T%
+    return t;
+  method genericMethod3<T extends core::Object = core::Object>(nsm::A::genericMethod3::T t) → nsm::A::genericMethod3::T
+    return t;
 }
 abstract class B1 extends nsm::A implements nsm::C1 {
   synthetic constructor •() → nsm::B1
@@ -49,6 +74,9 @@
     : super core::Object::•()
     ;
   abstract method method(core::int? i, {dynamic optional = #C2}) → core::int;
+  abstract method genericMethod1<T extends core::Object? = dynamic>(nsm::C1::genericMethod1::T% t) → nsm::C1::genericMethod1::T%;
+  abstract method genericMethod2<T extends core::Object? = core::Object?>(nsm::C1::genericMethod2::T% t) → nsm::C1::genericMethod2::T%;
+  abstract method genericMethod3<T extends core::Object = core::Object>(nsm::C1::genericMethod3::T t) → nsm::C1::genericMethod3::T;
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.transformed.expect
index 10bcb6e..b04ccd6 100644
--- a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.strong.transformed.expect
@@ -1,10 +1,23 @@
 library;
 import self as self;
-import "nsm_from_opt_in_lib.dart" as nsm;
 import "dart:core" as core;
+import "nsm_from_opt_in_lib.dart" as nsm;
 
 import "org-dartlang-testcase:///nsm_from_opt_in_lib.dart";
 
+abstract class A2 extends core::Object implements nsm::A {
+  synthetic constructor •() → self::A2*
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation* invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract member-signature method method(core::int* i) → core::int*;
+  abstract member-signature method genericMethod1<T extends core::Object* = dynamic>(self::A2::genericMethod1::T* t) → self::A2::genericMethod1::T*;
+  abstract member-signature method genericMethod2<T extends core::Object* = core::Object*>(self::A2::genericMethod2::T* t) → self::A2::genericMethod2::T*;
+  abstract member-signature method genericMethod3<T extends core::Object* = core::Object*>(self::A2::genericMethod3::T* t) → self::A2::genericMethod3::T*;
+}
 abstract class B2 extends nsm::A implements self::C2 {
   synthetic constructor •() → self::B2*
     : super nsm::A::•()
@@ -14,12 +27,18 @@
     return super.{core::Object::noSuchMethod}(invocation);
   }
   abstract forwarding-stub method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+  abstract member-signature method genericMethod1<T extends core::Object* = dynamic>(self::B2::genericMethod1::T* t) → self::B2::genericMethod1::T*;
+  abstract member-signature method genericMethod2<T extends core::Object* = core::Object*>(self::B2::genericMethod2::T* t) → self::B2::genericMethod2::T*;
+  abstract member-signature method genericMethod3<T extends core::Object* = core::Object*>(self::B2::genericMethod3::T* t) → self::B2::genericMethod3::T*;
 }
 abstract class C2 extends core::Object {
   synthetic constructor •() → self::C2*
     : super core::Object::•()
     ;
   abstract method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+  abstract method genericMethod1<T extends core::Object* = dynamic>(self::C2::genericMethod1::T* t) → self::C2::genericMethod1::T*;
+  abstract method genericMethod2<T extends core::Object* = core::Object*>(self::C2::genericMethod2::T* t) → self::C2::genericMethod2::T*;
+  abstract method genericMethod3<T extends core::Object* = core::Object*>(self::C2::genericMethod3::T* t) → self::C2::genericMethod3::T*;
 }
 static method main() → dynamic {}
 
@@ -33,6 +52,12 @@
     ;
   method method(core::int? i) → core::int
     return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+  method genericMethod1<T extends core::Object? = dynamic>(nsm::A::genericMethod1::T% t) → nsm::A::genericMethod1::T%
+    return t;
+  method genericMethod2<T extends core::Object? = core::Object?>(nsm::A::genericMethod2::T% t) → nsm::A::genericMethod2::T%
+    return t;
+  method genericMethod3<T extends core::Object = core::Object>(nsm::A::genericMethod3::T t) → nsm::A::genericMethod3::T
+    return t;
 }
 abstract class B1 extends nsm::A implements nsm::C1 {
   synthetic constructor •() → nsm::B1
@@ -49,6 +74,9 @@
     : super core::Object::•()
     ;
   abstract method method(core::int? i, {dynamic optional = #C2}) → core::int;
+  abstract method genericMethod1<T extends core::Object? = dynamic>(nsm::C1::genericMethod1::T% t) → nsm::C1::genericMethod1::T%;
+  abstract method genericMethod2<T extends core::Object? = core::Object?>(nsm::C1::genericMethod2::T% t) → nsm::C1::genericMethod2::T%;
+  abstract method genericMethod3<T extends core::Object = core::Object>(nsm::C1::genericMethod3::T t) → nsm::C1::genericMethod3::T;
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.expect
index 10bcb6e..b04ccd6 100644
--- a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.expect
@@ -1,10 +1,23 @@
 library;
 import self as self;
-import "nsm_from_opt_in_lib.dart" as nsm;
 import "dart:core" as core;
+import "nsm_from_opt_in_lib.dart" as nsm;
 
 import "org-dartlang-testcase:///nsm_from_opt_in_lib.dart";
 
+abstract class A2 extends core::Object implements nsm::A {
+  synthetic constructor •() → self::A2*
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation* invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract member-signature method method(core::int* i) → core::int*;
+  abstract member-signature method genericMethod1<T extends core::Object* = dynamic>(self::A2::genericMethod1::T* t) → self::A2::genericMethod1::T*;
+  abstract member-signature method genericMethod2<T extends core::Object* = core::Object*>(self::A2::genericMethod2::T* t) → self::A2::genericMethod2::T*;
+  abstract member-signature method genericMethod3<T extends core::Object* = core::Object*>(self::A2::genericMethod3::T* t) → self::A2::genericMethod3::T*;
+}
 abstract class B2 extends nsm::A implements self::C2 {
   synthetic constructor •() → self::B2*
     : super nsm::A::•()
@@ -14,12 +27,18 @@
     return super.{core::Object::noSuchMethod}(invocation);
   }
   abstract forwarding-stub method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+  abstract member-signature method genericMethod1<T extends core::Object* = dynamic>(self::B2::genericMethod1::T* t) → self::B2::genericMethod1::T*;
+  abstract member-signature method genericMethod2<T extends core::Object* = core::Object*>(self::B2::genericMethod2::T* t) → self::B2::genericMethod2::T*;
+  abstract member-signature method genericMethod3<T extends core::Object* = core::Object*>(self::B2::genericMethod3::T* t) → self::B2::genericMethod3::T*;
 }
 abstract class C2 extends core::Object {
   synthetic constructor •() → self::C2*
     : super core::Object::•()
     ;
   abstract method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+  abstract method genericMethod1<T extends core::Object* = dynamic>(self::C2::genericMethod1::T* t) → self::C2::genericMethod1::T*;
+  abstract method genericMethod2<T extends core::Object* = core::Object*>(self::C2::genericMethod2::T* t) → self::C2::genericMethod2::T*;
+  abstract method genericMethod3<T extends core::Object* = core::Object*>(self::C2::genericMethod3::T* t) → self::C2::genericMethod3::T*;
 }
 static method main() → dynamic {}
 
@@ -33,6 +52,12 @@
     ;
   method method(core::int? i) → core::int
     return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+  method genericMethod1<T extends core::Object? = dynamic>(nsm::A::genericMethod1::T% t) → nsm::A::genericMethod1::T%
+    return t;
+  method genericMethod2<T extends core::Object? = core::Object?>(nsm::A::genericMethod2::T% t) → nsm::A::genericMethod2::T%
+    return t;
+  method genericMethod3<T extends core::Object = core::Object>(nsm::A::genericMethod3::T t) → nsm::A::genericMethod3::T
+    return t;
 }
 abstract class B1 extends nsm::A implements nsm::C1 {
   synthetic constructor •() → nsm::B1
@@ -49,6 +74,9 @@
     : super core::Object::•()
     ;
   abstract method method(core::int? i, {dynamic optional = #C2}) → core::int;
+  abstract method genericMethod1<T extends core::Object? = dynamic>(nsm::C1::genericMethod1::T% t) → nsm::C1::genericMethod1::T%;
+  abstract method genericMethod2<T extends core::Object? = core::Object?>(nsm::C1::genericMethod2::T% t) → nsm::C1::genericMethod2::T%;
+  abstract method genericMethod3<T extends core::Object = core::Object>(nsm::C1::genericMethod3::T t) → nsm::C1::genericMethod3::T;
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.transformed.expect
index 10bcb6e..b04ccd6 100644
--- a/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in.dart.weak.transformed.expect
@@ -1,10 +1,23 @@
 library;
 import self as self;
-import "nsm_from_opt_in_lib.dart" as nsm;
 import "dart:core" as core;
+import "nsm_from_opt_in_lib.dart" as nsm;
 
 import "org-dartlang-testcase:///nsm_from_opt_in_lib.dart";
 
+abstract class A2 extends core::Object implements nsm::A {
+  synthetic constructor •() → self::A2*
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation* invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract member-signature method method(core::int* i) → core::int*;
+  abstract member-signature method genericMethod1<T extends core::Object* = dynamic>(self::A2::genericMethod1::T* t) → self::A2::genericMethod1::T*;
+  abstract member-signature method genericMethod2<T extends core::Object* = core::Object*>(self::A2::genericMethod2::T* t) → self::A2::genericMethod2::T*;
+  abstract member-signature method genericMethod3<T extends core::Object* = core::Object*>(self::A2::genericMethod3::T* t) → self::A2::genericMethod3::T*;
+}
 abstract class B2 extends nsm::A implements self::C2 {
   synthetic constructor •() → self::B2*
     : super nsm::A::•()
@@ -14,12 +27,18 @@
     return super.{core::Object::noSuchMethod}(invocation);
   }
   abstract forwarding-stub method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+  abstract member-signature method genericMethod1<T extends core::Object* = dynamic>(self::B2::genericMethod1::T* t) → self::B2::genericMethod1::T*;
+  abstract member-signature method genericMethod2<T extends core::Object* = core::Object*>(self::B2::genericMethod2::T* t) → self::B2::genericMethod2::T*;
+  abstract member-signature method genericMethod3<T extends core::Object* = core::Object*>(self::B2::genericMethod3::T* t) → self::B2::genericMethod3::T*;
 }
 abstract class C2 extends core::Object {
   synthetic constructor •() → self::C2*
     : super core::Object::•()
     ;
   abstract method method(core::int* i, {dynamic optional = #C2}) → core::int*;
+  abstract method genericMethod1<T extends core::Object* = dynamic>(self::C2::genericMethod1::T* t) → self::C2::genericMethod1::T*;
+  abstract method genericMethod2<T extends core::Object* = core::Object*>(self::C2::genericMethod2::T* t) → self::C2::genericMethod2::T*;
+  abstract method genericMethod3<T extends core::Object* = core::Object*>(self::C2::genericMethod3::T* t) → self::C2::genericMethod3::T*;
 }
 static method main() → dynamic {}
 
@@ -33,6 +52,12 @@
     ;
   method method(core::int? i) → core::int
     return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
+  method genericMethod1<T extends core::Object? = dynamic>(nsm::A::genericMethod1::T% t) → nsm::A::genericMethod1::T%
+    return t;
+  method genericMethod2<T extends core::Object? = core::Object?>(nsm::A::genericMethod2::T% t) → nsm::A::genericMethod2::T%
+    return t;
+  method genericMethod3<T extends core::Object = core::Object>(nsm::A::genericMethod3::T t) → nsm::A::genericMethod3::T
+    return t;
 }
 abstract class B1 extends nsm::A implements nsm::C1 {
   synthetic constructor •() → nsm::B1
@@ -49,6 +74,9 @@
     : super core::Object::•()
     ;
   abstract method method(core::int? i, {dynamic optional = #C2}) → core::int;
+  abstract method genericMethod1<T extends core::Object? = dynamic>(nsm::C1::genericMethod1::T% t) → nsm::C1::genericMethod1::T%;
+  abstract method genericMethod2<T extends core::Object? = core::Object?>(nsm::C1::genericMethod2::T% t) → nsm::C1::genericMethod2::T%;
+  abstract method genericMethod3<T extends core::Object = core::Object>(nsm::C1::genericMethod3::T t) → nsm::C1::genericMethod3::T;
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/nnbd/nsm_from_opt_in_lib.dart b/pkg/front_end/testcases/nnbd/nsm_from_opt_in_lib.dart
index 20d29b9..3b74079 100644
--- a/pkg/front_end/testcases/nnbd/nsm_from_opt_in_lib.dart
+++ b/pkg/front_end/testcases/nnbd/nsm_from_opt_in_lib.dart
@@ -4,6 +4,9 @@
 
 class A {
   int method(int? i) => i ?? 0;
+  T genericMethod1<T>(T t) => t;
+  T genericMethod2<T extends Object?>(T t) => t;
+  T genericMethod3<T extends Object>(T t) => t;
 }
 
 abstract class B1 extends A implements C1 {
@@ -15,4 +18,7 @@
 
 abstract class C1 {
   int method(int? i, {optional});
+  T genericMethod1<T>(T t);
+  T genericMethod2<T extends Object?>(T t);
+  T genericMethod3<T extends Object>(T t);
 }
diff --git a/pkg/front_end/testcases/nnbd/nullable_object_access.dart b/pkg/front_end/testcases/nnbd/nullable_object_access.dart
index bf88ca3..82729ce 100644
--- a/pkg/front_end/testcases/nnbd/nullable_object_access.dart
+++ b/pkg/front_end/testcases/nnbd/nullable_object_access.dart
@@ -50,7 +50,10 @@
   int noSuchMethod2 = c2.noSuchMethod(invocation); // ok
   var noSuchMethodVariable2 = c2.noSuchMethod(invocation);
 
-  c2 == ''; // ok
+  // TODO(johnniwinther): Awaiting spec update about `==`. Before NNBD this
+  // would cause an error but with the current (insufficient) specification for
+  // `==` it is ok (even though `c1 == ''` is an error).
+  c2 == ''; // ok or error?
   c2 == c1; // ok
 
   String Function({Object o}) toStringTearOff2 = c2.toString; // error
diff --git a/pkg/front_end/testcases/nnbd/nullable_object_access.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.strong.expect
index 81b9a41..ec3535f 100644
--- a/pkg/front_end/testcases/nnbd/nullable_object_access.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.strong.expect
@@ -29,16 +29,19 @@
 //       c2.noSuchMethod; // error
 //          ^
 //
-// pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   c2 == ''; // ok or error?
+//         ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
 //  - 'Object' is from 'dart:core'.
 //   String Function({Object o}) toStringTearOff2 = c2.toString; // error
 //                                                     ^
 //
-// pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
-//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
-// Try calling using ?. instead.
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:62:15: Error: No named parameter with the name 'o'.
 //   c2.toString(o: c1); // error
-//      ^^^^^^^^
+//               ^
 //
 import self as self;
 import "dart:core" as core;
@@ -104,18 +107,19 @@
   (core::Invocation) → dynamic noSuchMethodTearOffVariable2 = c2.{core::Object::noSuchMethod};
   core::int noSuchMethod2 = c2.{core::Object::noSuchMethod}(invocation) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
   dynamic noSuchMethodVariable2 = c2.{core::Object::noSuchMethod}(invocation);
-  c2.{core::Object::==}("");
-  c2.{core::Object::==}(c1);
-  ({o: core::Object}) → core::String toStringTearOff2 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+  c2.{self::Class::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  c2 == ''; // ok or error?
+        ^" in "" as{TypeError,ForNonNullableByDefault} self::Class?);
+  c2.{self::Class::==}(c1);
+  ({o: core::Object}) → core::String toStringTearOff2 = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
  - 'Object' is from 'dart:core'.
   String Function({Object o}) toStringTearOff2 = c2.toString; // error
                                                     ^" in c2.{core::Object::toString} as{TypeError,ForNonNullableByDefault} ({o: core::Object}) → core::String;
   () → core::String toStringTearOffVariable2 = c2.{core::Object::toString};
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
- - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
-Try calling using ?. instead.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:62:15: Error: No named parameter with the name 'o'.
   c2.toString(o: c1); // error
-     ^^^^^^^^" in c2.{self::Class::toString}(o: c1);
+              ^" in c2.{core::Object::toString}(o: c1);
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/nnbd/nullable_object_access.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.weak.expect
index 81b9a41..ec3535f 100644
--- a/pkg/front_end/testcases/nnbd/nullable_object_access.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_object_access.dart.weak.expect
@@ -29,16 +29,19 @@
 //       c2.noSuchMethod; // error
 //          ^
 //
-// pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+//   c2 == ''; // ok or error?
+//         ^
+//
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
 //  - 'Object' is from 'dart:core'.
 //   String Function({Object o}) toStringTearOff2 = c2.toString; // error
 //                                                     ^
 //
-// pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
-//  - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
-// Try calling using ?. instead.
+// pkg/front_end/testcases/nnbd/nullable_object_access.dart:62:15: Error: No named parameter with the name 'o'.
 //   c2.toString(o: c1); // error
-//      ^^^^^^^^
+//               ^
 //
 import self as self;
 import "dart:core" as core;
@@ -104,18 +107,19 @@
   (core::Invocation) → dynamic noSuchMethodTearOffVariable2 = c2.{core::Object::noSuchMethod};
   core::int noSuchMethod2 = c2.{core::Object::noSuchMethod}(invocation) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
   dynamic noSuchMethodVariable2 = c2.{core::Object::noSuchMethod}(invocation);
-  c2.{core::Object::==}("");
-  c2.{core::Object::==}(c1);
-  ({o: core::Object}) → core::String toStringTearOff2 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
+  c2.{self::Class::==}(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:56:9: Error: The argument type 'String' can't be assigned to the parameter type 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
+  c2 == ''; // ok or error?
+        ^" in "" as{TypeError,ForNonNullableByDefault} self::Class?);
+  c2.{self::Class::==}(c1);
+  ({o: core::Object}) → core::String toStringTearOff2 = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:53: Error: A value of type 'String Function()' can't be assigned to a variable of type 'String Function({Object o})'.
  - 'Object' is from 'dart:core'.
   String Function({Object o}) toStringTearOff2 = c2.toString; // error
                                                     ^" in c2.{core::Object::toString} as{TypeError,ForNonNullableByDefault} ({o: core::Object}) → core::String;
   () → core::String toStringTearOffVariable2 = c2.{core::Object::toString};
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:59:6: Error: Method 'toString' cannot be called on 'Class?' because it is potentially null.
- - 'Class' is from 'pkg/front_end/testcases/nnbd/nullable_object_access.dart'.
-Try calling using ?. instead.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_object_access.dart:62:15: Error: No named parameter with the name 'o'.
   c2.toString(o: c1); // error
-     ^^^^^^^^" in c2.{self::Class::toString}(o: c1);
+              ^" in c2.{core::Object::toString}(o: c1);
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect
index 380d689..b4de6e7 100644
--- a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect
@@ -36,11 +36,10 @@
 //   a();
 //    ^
 //
-// pkg/front_end/testcases/nnbd/nullable_receiver.dart:27:5: Error: Method 'toString' cannot be called on 'B?' because it is potentially null.
-//  - 'B' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
-// Try calling using ?. instead.
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:27:13: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
 //   b.toString(0);
-//     ^^^^^^^^
+//             ^
 //
 // pkg/front_end/testcases/nnbd/nullable_receiver.dart:29:17: Error: Can't tear off method 'call' from a potentially null value.
 //   Function f1 = a;
@@ -103,11 +102,10 @@
 Try calling using ?.call instead.
   a();
    ^" in a.{self::A::call}();
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:27:5: Error: Method 'toString' cannot be called on 'B?' because it is potentially null.
- - 'B' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
-Try calling using ?. instead.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:27:13: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
   b.toString(0);
-    ^^^^^^^^" in b.{self::B::toString}(0);
+            ^" in b.{core::Object::toString}(0);
   core::Function f1 = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:29:17: Error: Can't tear off method 'call' from a potentially null value.
   Function f1 = a;
                 ^" in a as{TypeError} core::Function;
@@ -119,7 +117,7 @@
                         ^" in a as{TypeError} () →? void;
 }
 static method ok<T extends core::Object? = core::Object?>(core::String? s, self::A? a, self::ok::T% t, self::B? b, core::Invocation i) → dynamic {
-  s.{core::Object::==}(s);
+  s.{core::String::==}(s);
   a.{core::Object::==}(a);
   t.{core::Object::==}(t);
   b.{core::Object::==}(b);
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect
index 380d689..b4de6e7 100644
--- a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect
@@ -36,11 +36,10 @@
 //   a();
 //    ^
 //
-// pkg/front_end/testcases/nnbd/nullable_receiver.dart:27:5: Error: Method 'toString' cannot be called on 'B?' because it is potentially null.
-//  - 'B' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
-// Try calling using ?. instead.
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:27:13: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
 //   b.toString(0);
-//     ^^^^^^^^
+//             ^
 //
 // pkg/front_end/testcases/nnbd/nullable_receiver.dart:29:17: Error: Can't tear off method 'call' from a potentially null value.
 //   Function f1 = a;
@@ -103,11 +102,10 @@
 Try calling using ?.call instead.
   a();
    ^" in a.{self::A::call}();
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:27:5: Error: Method 'toString' cannot be called on 'B?' because it is potentially null.
- - 'B' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
-Try calling using ?. instead.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:27:13: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
   b.toString(0);
-    ^^^^^^^^" in b.{self::B::toString}(0);
+            ^" in b.{core::Object::toString}(0);
   core::Function f1 = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:29:17: Error: Can't tear off method 'call' from a potentially null value.
   Function f1 = a;
                 ^" in a as{TypeError} core::Function;
@@ -119,7 +117,7 @@
                         ^" in a as{TypeError} () →? void;
 }
 static method ok<T extends core::Object? = core::Object?>(core::String? s, self::A? a, self::ok::T% t, self::B? b, core::Invocation i) → dynamic {
-  s.{core::Object::==}(s);
+  s.{core::String::==}(s);
   a.{core::Object::==}(a);
   t.{core::Object::==}(t);
   b.{core::Object::==}(b);
diff --git a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart
index a000d92..3fe3d5f 100644
--- a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart
+++ b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart
@@ -11,6 +11,19 @@
   void Function() get functionTypeGetter => () {};
 }
 
+extension Extension on Class {
+  int operator +(int value) => 0;
+  int operator -() => 0;
+  int operator [](int index) => 0;
+  void operator []=(int index, int value) {}
+  int call() => 0;
+  int get extensionProperty => 0;
+  void set extensionProperty(int value) {}
+  int extensionMethod() => 0;
+  Function get extensionFunctionGetter => () {};
+  void Function() get extensionFunctionTypeGetter => () {};
+}
+
 Function? get nullableFunction => () {};
 
 void Function()? get nullableFunctionType => () {};
@@ -42,6 +55,23 @@
 var topLevelFunctionGetter = nullableClass.functionGetter();
 var topLevelFunctionTypeGetter = nullableClass.functionTypeGetter();
 
+var topLevelExtensionBinary = nullableClass + 0;
+var topLevelExtensionUnary = -nullableClass;
+var topLevelExtensionIndexGet = nullableClass[0];
+var topLevelExtensionIndexSet = nullableClass[0] = 1;
+var topLevelExtensionIndexGetSet = nullableClass[0] += 1;
+var topLevelExtensionPropertyGet = nullableClass.extensionProperty;
+var topLevelExtensionPropertySet = nullableClass.extensionProperty = 1;
+var topLevelExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+var topLevelExtensionMethodInvocation = nullableClass.extensionMethod();
+var topLevelExtensionMethodTearOff = nullableClass.extensionMethod;
+var topLevelExtensionFunctionTypeImplicitCall = nullableClass();
+var topLevelExtensionFunctionTypeExplicitCall = nullableClass.call();
+var topLevelExtensionFunctionTypeTearOff = nullableClass.call;
+var topLevelExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+var topLevelExtensionFunctionTypeGetter =
+    nullableClass.extensionFunctionTypeGetter();
+
 test() {
   var localBinary = nullableInt + 0;
   var localUnary = -nullableInt;
@@ -63,6 +93,23 @@
   var localFunctionTypeField = nullableClass.functionTypeField();
   var localFunctionGetter = nullableClass.functionGetter();
   var localFunctionTypeGetter = nullableClass.functionTypeGetter();
+
+  var localExtensionBinary = nullableClass + 0;
+  var localExtensionUnary = -nullableClass;
+  var localExtensionIndexGet = nullableClass[0];
+  var localExtensionIndexSet = nullableClass[0] = 1;
+  var localExtensionIndexGetSet = nullableClass[0] += 1;
+  var localExtensionPropertyGet = nullableClass.extensionProperty;
+  var localExtensionPropertySet = nullableClass.extensionProperty = 1;
+  var localExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+  var localExtensionMethodInvocation = nullableClass.extensionMethod();
+  var localExtensionMethodTearOff = nullableClass.extensionMethod;
+  var localExtensionFunctionTypeImplicitCall = nullableClass();
+  var localExtensionFunctionTypeExplicitCall = nullableClass.call();
+  var localExtensionFunctionTypeTearOff = nullableClass.call;
+  var localExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+  var localExtensionFunctionTypeGetter =
+      nullableClass.extensionFunctionTypeGetter();
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.outline.expect b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.outline.expect
index e9455e1..7ba4b0f 100644
--- a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.outline.expect
@@ -15,6 +15,20 @@
   get functionTypeGetter() → () → void
     ;
 }
+extension Extension on self::Class {
+  operator + = self::Extension|+;
+  operator unary- = self::Extension|unary-;
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+  method call = self::Extension|call;
+  tearoff call = self::Extension|get#call;
+  get extensionProperty = self::Extension|get#extensionProperty;
+  method extensionMethod = self::Extension|extensionMethod;
+  tearoff extensionMethod = self::Extension|get#extensionMethod;
+  get extensionFunctionGetter = self::Extension|get#extensionFunctionGetter;
+  get extensionFunctionTypeGetter = self::Extension|get#extensionFunctionTypeGetter;
+  set extensionProperty = self::Extension|set#extensionProperty;
+}
 static field core::int? topLevelBinary;
 static field core::int topLevelUnary;
 static field dynamic topLevelIndexGet;
@@ -35,6 +49,45 @@
 static field void topLevelFunctionTypeField;
 static field dynamic topLevelFunctionGetter;
 static field void topLevelFunctionTypeGetter;
+static field core::int topLevelExtensionBinary;
+static field core::int topLevelExtensionUnary;
+static field core::int topLevelExtensionIndexGet;
+static field core::int topLevelExtensionIndexSet;
+static field core::int topLevelExtensionIndexGetSet;
+static field core::int topLevelExtensionPropertyGet;
+static field core::int topLevelExtensionPropertySet;
+static field core::int topLevelExtensionPropertyGetSet;
+static field core::int topLevelExtensionMethodInvocation;
+static field () → core::int topLevelExtensionMethodTearOff;
+static field core::int topLevelExtensionFunctionTypeImplicitCall;
+static field core::int topLevelExtensionFunctionTypeExplicitCall;
+static field () → core::int topLevelExtensionFunctionTypeTearOff;
+static field dynamic topLevelExtensionFunctionGetter;
+static field void topLevelExtensionFunctionTypeGetter;
+static method Extension|+(final self::Class #this, core::int value) → core::int
+  ;
+static method Extension|unary-(final self::Class #this) → core::int
+  ;
+static method Extension|[](final self::Class #this, core::int index) → core::int
+  ;
+static method Extension|[]=(final self::Class #this, core::int index, core::int value) → void
+  ;
+static method Extension|call(final self::Class #this) → core::int
+  ;
+static method Extension|get#call(final self::Class #this) → () → core::int
+  return () → core::int => self::Extension|call(#this);
+static method Extension|get#extensionProperty(final self::Class #this) → core::int
+  ;
+static method Extension|set#extensionProperty(final self::Class #this, core::int value) → void
+  ;
+static method Extension|extensionMethod(final self::Class #this) → core::int
+  ;
+static method Extension|get#extensionMethod(final self::Class #this) → () → core::int
+  return () → core::int => self::Extension|extensionMethod(#this);
+static method Extension|get#extensionFunctionGetter(final self::Class #this) → core::Function
+  ;
+static method Extension|get#extensionFunctionTypeGetter(final self::Class #this) → () → void
+  ;
 static get nullableFunction() → core::Function?
   ;
 static get nullableFunctionType() → () →? void
diff --git a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.strong.expect b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.strong.expect
index eeb102b..7c80c76 100644
--- a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.strong.expect
@@ -2,176 +2,416 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:24:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:37:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 // var topLevelBinary = nullableInt + 0;
 //                                  ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:25:21: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:38:21: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
 // var topLevelUnary = -nullableInt;
 //                     ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:26:35: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:39:35: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 // var topLevelIndexGet = nullableMap[0];
 //                                   ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:27:35: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:40:35: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 // var topLevelIndexSet = nullableMap[0] = 1;
 //                                   ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:28:38: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:41:38: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 // var topLevelIndexGetSet = nullableMap[0] += 1;
 //                                      ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:28:38: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:41:38: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 // var topLevelIndexGetSet = nullableMap[0] += 1;
 //                                      ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:29:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:42:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 // var topLevelPropertyGet = nullableClass.property;
 //                                         ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:30:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:43:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 // var topLevelPropertySet = nullableClass.property = 1;
 //                                         ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:31:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:44:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 // var topLevelPropertyGetSet = nullableClass.property += 1;
 //                                            ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:32:46: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:45:46: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try calling using ?. instead.
 // var topLevelMethodInvocation = nullableClass.method();
 //                                              ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:34:52: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:46:43: Error: Property 'method' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelMethodTearOff = nullableClass.method;
+//                                           ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:47:52: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try calling using ?.call instead.
 // var topLevelFunctionImplicitCall = nullableFunction();
 //                                                    ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:35:53: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:48:53: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try calling using ?. instead.
 // var topLevelFunctionExplicitCall = nullableFunction.call();
 //                                                     ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:36:48: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:49:48: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try accessing using ?. instead.
 // var topLevelFunctionTearOff = nullableFunction.call;
 //                                                ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:37:60: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:60: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
 // Try calling using ?.call instead.
 // var topLevelFunctionTypeImplicitCall = nullableFunctionType();
 //                                                            ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:38:61: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:51:61: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
 // Try calling using ?. instead.
 // var topLevelFunctionTypeExplicitCall = nullableFunctionType.call();
 //                                                             ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:39:56: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:52:56: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
 // Try accessing using ?. instead.
 // var topLevelFunctionTypeTearOff = nullableFunctionType.call;
 //                                                        ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:46:33: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:53:43: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelFunctionField = nullableClass.functionField();
+//                                           ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:54:47: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelFunctionTypeField = nullableClass.functionTypeField();
+//                                               ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:55:44: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelFunctionGetter = nullableClass.functionGetter();
+//                                            ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:56:48: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelFunctionTypeGetter = nullableClass.functionTypeGetter();
+//                                                ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:58:45: Error: Operator '+' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionBinary = nullableClass + 0;
+//                                             ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:59:30: Error: Operator 'unary-' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionUnary = -nullableClass;
+//                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:60:46: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionIndexGet = nullableClass[0];
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:61:46: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionIndexSet = nullableClass[0] = 1;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:62:49: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionIndexGetSet = nullableClass[0] += 1;
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:62:49: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionIndexGetSet = nullableClass[0] += 1;
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:63:50: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelExtensionPropertyGet = nullableClass.extensionProperty;
+//                                                  ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:64:50: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelExtensionPropertySet = nullableClass.extensionProperty = 1;
+//                                                  ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:65:53: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+//                                                     ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:66:55: Error: Method 'extensionMethod' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?. instead.
+// var topLevelExtensionMethodInvocation = nullableClass.extensionMethod();
+//                                                       ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:67:52: Error: Property 'extensionMethod' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelExtensionMethodTearOff = nullableClass.extensionMethod;
+//                                                    ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:68:62: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelExtensionFunctionTypeImplicitCall = nullableClass();
+//                                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:69:63: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?. instead.
+// var topLevelExtensionFunctionTypeExplicitCall = nullableClass.call();
+//                                                               ^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:70:58: Error: Property 'call' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelExtensionFunctionTypeTearOff = nullableClass.call;
+//                                                          ^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:71:53: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+//                                                     ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:73:19: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//     nullableClass.extensionFunctionTypeGetter();
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:76:33: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 //   var localBinary = nullableInt + 0;
 //                                 ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:47:20: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:77:20: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
 //   var localUnary = -nullableInt;
 //                    ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:48:34: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:78:34: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 //   var localIndexGet = nullableMap[0];
 //                                  ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:49:34: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:79:34: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 //   var localIndexSet = nullableMap[0] = 1;
 //                                  ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:37: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:80:37: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 //   var localIndexGetSet = nullableMap[0] += 1;
 //                                     ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:37: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:80:37: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 //   var localIndexGetSet = nullableMap[0] += 1;
 //                                     ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:51:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:81:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 //   var localPropertyGet = nullableClass.property;
 //                                        ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:52:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:82:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 //   var localPropertySet = nullableClass.property = 1;
 //                                        ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:53:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:83:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 //   var localPropertyGetSet = nullableClass.property += 1;
 //                                           ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:54:45: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:84:45: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try calling using ?. instead.
 //   var localMethodInvocation = nullableClass.method();
 //                                             ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:56:51: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:85:42: Error: Property 'method' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localMethodTearOff = nullableClass.method;
+//                                          ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:86:51: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try calling using ?.call instead.
 //   var localFunctionImplicitCall = nullableFunction();
 //                                                   ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:57:52: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:87:52: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try calling using ?. instead.
 //   var localFunctionExplicitCall = nullableFunction.call();
 //                                                    ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:58:47: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:88:47: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try accessing using ?. instead.
 //   var localFunctionTearOff = nullableFunction.call;
 //                                               ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:59:59: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:89:59: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
 // Try calling using ?.call instead.
 //   var localFunctionTypeImplicitCall = nullableFunctionType();
 //                                                           ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:60:60: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:90:60: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
 // Try calling using ?. instead.
 //   var localFunctionTypeExplicitCall = nullableFunctionType.call();
 //                                                            ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:61:55: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:91:55: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
 // Try accessing using ?. instead.
 //   var localFunctionTypeTearOff = nullableFunctionType.call;
 //                                                       ^^^^
 //
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:92:42: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localFunctionField = nullableClass.functionField();
+//                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:93:46: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localFunctionTypeField = nullableClass.functionTypeField();
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:94:43: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localFunctionGetter = nullableClass.functionGetter();
+//                                           ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:95:47: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localFunctionTypeGetter = nullableClass.functionTypeGetter();
+//                                               ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:97:44: Error: Operator '+' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionBinary = nullableClass + 0;
+//                                            ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:98:29: Error: Operator 'unary-' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionUnary = -nullableClass;
+//                             ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:99:45: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionIndexGet = nullableClass[0];
+//                                             ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:100:45: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionIndexSet = nullableClass[0] = 1;
+//                                             ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:101:48: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionIndexGetSet = nullableClass[0] += 1;
+//                                                ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:101:48: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionIndexGetSet = nullableClass[0] += 1;
+//                                                ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:102:49: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localExtensionPropertyGet = nullableClass.extensionProperty;
+//                                                 ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:103:49: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localExtensionPropertySet = nullableClass.extensionProperty = 1;
+//                                                 ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:104:52: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+//                                                    ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:105:54: Error: Method 'extensionMethod' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?. instead.
+//   var localExtensionMethodInvocation = nullableClass.extensionMethod();
+//                                                      ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:106:51: Error: Property 'extensionMethod' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localExtensionMethodTearOff = nullableClass.extensionMethod;
+//                                                   ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:107:61: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localExtensionFunctionTypeImplicitCall = nullableClass();
+//                                                             ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:108:62: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?. instead.
+//   var localExtensionFunctionTypeExplicitCall = nullableClass.call();
+//                                                              ^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:109:57: Error: Property 'call' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localExtensionFunctionTypeTearOff = nullableClass.call;
+//                                                         ^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:110:52: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+//                                                    ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:112:21: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//       nullableClass.extensionFunctionTypeGetter();
+//                     ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -189,83 +429,216 @@
   get functionTypeGetter() → () → void
     return () → core::Null? {};
 }
-static field core::int? topLevelBinary = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:24:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+extension Extension on self::Class {
+  operator + = self::Extension|+;
+  operator unary- = self::Extension|unary-;
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+  method call = self::Extension|call;
+  tearoff call = self::Extension|get#call;
+  get extensionProperty = self::Extension|get#extensionProperty;
+  method extensionMethod = self::Extension|extensionMethod;
+  tearoff extensionMethod = self::Extension|get#extensionMethod;
+  get extensionFunctionGetter = self::Extension|get#extensionFunctionGetter;
+  get extensionFunctionTypeGetter = self::Extension|get#extensionFunctionTypeGetter;
+  set extensionProperty = self::Extension|set#extensionProperty;
+}
+static field core::int? topLevelBinary = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:37:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 var topLevelBinary = nullableInt + 0;
                                  ^" in self::nullableInt.{core::num::+}(0);
-static field core::int topLevelUnary = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:25:21: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+static field core::int topLevelUnary = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:38:21: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
 var topLevelUnary = -nullableInt;
                     ^" in self::nullableInt.{core::int::unary-}();
-static field dynamic topLevelIndexGet = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:26:35: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+static field dynamic topLevelIndexGet = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:39:35: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
 var topLevelIndexGet = nullableMap[0];
                                   ^" in self::nullableMap.{core::Map::[]}(0);
-static field core::int topLevelIndexSet = let final core::Map<dynamic, dynamic>? #t4 = self::nullableMap in let final core::int #t5 = 0 in let final core::int #t6 = 1 in let final void #t7 = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:27:35: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+static field core::int topLevelIndexSet = let final core::Map<dynamic, dynamic>? #t4 = self::nullableMap in let final core::int #t5 = 0 in let final core::int #t6 = 1 in let final void #t7 = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:40:35: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
 var topLevelIndexSet = nullableMap[0] = 1;
                                   ^" in #t4.{core::Map::[]=}(#t5, #t6) in #t6;
-static field dynamic topLevelIndexGetSet = let final core::Map<dynamic, dynamic>? #t9 = self::nullableMap in let final core::int #t10 = 0 in let final dynamic #t11 = (let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:28:38: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+static field dynamic topLevelIndexGetSet = let final core::Map<dynamic, dynamic>? #t9 = self::nullableMap in let final core::int #t10 = 0 in let final dynamic #t11 = (let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:41:38: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
 var topLevelIndexGetSet = nullableMap[0] += 1;
-                                     ^" in #t9.{core::Map::[]}(#t10)).+(1) in let final void #t13 = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:28:38: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+                                     ^" in #t9.{core::Map::[]}(#t10)).+(1) in let final void #t13 = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:41:38: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
 var topLevelIndexGetSet = nullableMap[0] += 1;
                                      ^" in #t9.{core::Map::[]=}(#t10, #t11) in #t11;
-static field core::int topLevelPropertyGet = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:29:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+static field core::int topLevelPropertyGet = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:42:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
 var topLevelPropertyGet = nullableClass.property;
                                         ^^^^^^^^" in self::nullableClass.{self::Class::property};
-static field core::int topLevelPropertySet = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:30:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+static field core::int topLevelPropertySet = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:43:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
 var topLevelPropertySet = nullableClass.property = 1;
                                         ^^^^^^^^" in self::nullableClass.{self::Class::property} = 1;
-static field core::int topLevelPropertyGetSet = let final self::Class? #t17 = self::nullableClass in let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:31:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+static field core::int topLevelPropertyGetSet = let final self::Class? #t17 = self::nullableClass in let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:44:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
 var topLevelPropertyGetSet = nullableClass.property += 1;
-                                           ^^^^^^^^" in #t17.{self::Class::property} = (let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:31:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+                                           ^^^^^^^^" in #t17.{self::Class::property} = (let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:44:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
 var topLevelPropertyGetSet = nullableClass.property += 1;
                                            ^^^^^^^^" in #t17.{self::Class::property}).{core::num::+}(1);
-static field core::int topLevelMethodInvocation = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:32:46: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
+static field core::int topLevelMethodInvocation = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:45:46: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try calling using ?. instead.
 var topLevelMethodInvocation = nullableClass.method();
                                              ^^^^^^" in self::nullableClass.{self::Class::method}();
-static field () → core::int topLevelMethodTearOff = self::nullableClass.{self::Class::method};
-static field dynamic topLevelFunctionImplicitCall = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:34:52: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+static field () → core::int topLevelMethodTearOff = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:46:43: Error: Property 'method' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelMethodTearOff = nullableClass.method;
+                                          ^^^^^^" in self::nullableClass.{self::Class::method};
+static field dynamic topLevelFunctionImplicitCall = let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:47:52: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
  - 'Function' is from 'dart:core'.
 Try calling using ?.call instead.
 var topLevelFunctionImplicitCall = nullableFunction();
                                                    ^" in self::nullableFunction.call();
-static field dynamic topLevelFunctionExplicitCall = let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:35:53: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+static field dynamic topLevelFunctionExplicitCall = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:48:53: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
  - 'Function' is from 'dart:core'.
 Try calling using ?. instead.
 var topLevelFunctionExplicitCall = nullableFunction.call();
                                                     ^^^^" in self::nullableFunction.call();
-static field core::Function? topLevelFunctionTearOff = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:36:48: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
+static field core::Function? topLevelFunctionTearOff = let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:49:48: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
  - 'Function' is from 'dart:core'.
 Try accessing using ?. instead.
 var topLevelFunctionTearOff = nullableFunction.call;
                                                ^^^^" in self::nullableFunction.call;
-static field void topLevelFunctionTypeImplicitCall = let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:37:60: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+static field void topLevelFunctionTypeImplicitCall = let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:60: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
 Try calling using ?.call instead.
 var topLevelFunctionTypeImplicitCall = nullableFunctionType();
                                                            ^" in self::nullableFunctionType.call();
-static field void topLevelFunctionTypeExplicitCall = let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:38:61: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
+static field void topLevelFunctionTypeExplicitCall = let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:51:61: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
 Try calling using ?. instead.
 var topLevelFunctionTypeExplicitCall = nullableFunctionType.call();
                                                             ^^^^" in self::nullableFunctionType.call();
-static field () →? void topLevelFunctionTypeTearOff = let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:39:56: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
+static field () →? void topLevelFunctionTypeTearOff = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:52:56: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
 Try accessing using ?. instead.
 var topLevelFunctionTypeTearOff = nullableFunctionType.call;
                                                        ^^^^" in self::nullableFunctionType.call;
-static field dynamic topLevelFunctionField = self::nullableClass.{self::Class::functionField}.call();
-static field void topLevelFunctionTypeField = self::nullableClass.{self::Class::functionTypeField}.call();
-static field dynamic topLevelFunctionGetter = self::nullableClass.{self::Class::functionGetter}.call();
-static field void topLevelFunctionTypeGetter = self::nullableClass.{self::Class::functionTypeGetter}.call();
+static field dynamic topLevelFunctionField = let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:53:43: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelFunctionField = nullableClass.functionField();
+                                          ^" in self::nullableClass.{self::Class::functionField}.call();
+static field void topLevelFunctionTypeField = let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:54:47: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelFunctionTypeField = nullableClass.functionTypeField();
+                                              ^" in self::nullableClass.{self::Class::functionTypeField}.call();
+static field dynamic topLevelFunctionGetter = let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:55:44: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelFunctionGetter = nullableClass.functionGetter();
+                                           ^" in self::nullableClass.{self::Class::functionGetter}.call();
+static field void topLevelFunctionTypeGetter = let final<BottomType> #t31 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:56:48: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelFunctionTypeGetter = nullableClass.functionTypeGetter();
+                                               ^" in self::nullableClass.{self::Class::functionTypeGetter}.call();
+static field core::int topLevelExtensionBinary = let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:58:45: Error: Operator '+' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionBinary = nullableClass + 0;
+                                            ^" in self::Extension|+(self::nullableClass, 0);
+static field core::int topLevelExtensionUnary = let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:59:30: Error: Operator 'unary-' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionUnary = -nullableClass;
+                             ^" in self::Extension|unary-(self::nullableClass);
+static field core::int topLevelExtensionIndexGet = let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:60:46: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionIndexGet = nullableClass[0];
+                                             ^" in self::Extension|[](self::nullableClass, 0);
+static field core::int topLevelExtensionIndexSet = let final self::Class? #t35 = self::nullableClass in let final core::int #t36 = 0 in let final core::int #t37 = 1 in let final void #t38 = let final<BottomType> #t39 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:61:46: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionIndexSet = nullableClass[0] = 1;
+                                             ^" in self::Extension|[]=(#t35, #t36, #t37) in #t37;
+static field core::int topLevelExtensionIndexGetSet = let final self::Class? #t40 = self::nullableClass in let final core::int #t41 = 0 in let final core::int #t42 = (let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:62:49: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionIndexGetSet = nullableClass[0] += 1;
+                                                ^" in self::Extension|[](#t40, #t41)).{core::num::+}(1) in let final void #t44 = let final<BottomType> #t45 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:62:49: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionIndexGetSet = nullableClass[0] += 1;
+                                                ^" in self::Extension|[]=(#t40, #t41, #t42) in #t42;
+static field core::int topLevelExtensionPropertyGet = let final<BottomType> #t46 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:63:50: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionPropertyGet = nullableClass.extensionProperty;
+                                                 ^^^^^^^^^^^^^^^^^" in self::Extension|get#extensionProperty(self::nullableClass);
+static field core::int topLevelExtensionPropertySet = let final<BottomType> #t47 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:64:50: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionPropertySet = nullableClass.extensionProperty = 1;
+                                                 ^^^^^^^^^^^^^^^^^" in let final core::int #t48 = 1 in let final void #t49 = self::Extension|set#extensionProperty(self::nullableClass, #t48) in #t48;
+static field core::int topLevelExtensionPropertyGetSet = let final self::Class? #t50 = self::nullableClass in let final<BottomType> #t51 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:65:53: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+                                                    ^^^^^^^^^^^^^^^^^" in let final core::int #t52 = (let final<BottomType> #t53 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:65:53: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+                                                    ^^^^^^^^^^^^^^^^^" in self::Extension|get#extensionProperty(#t50)).{core::num::+}(1) in let final void #t54 = self::Extension|set#extensionProperty(#t50, #t52) in #t52;
+static field core::int topLevelExtensionMethodInvocation = let final<BottomType> #t55 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:66:55: Error: Method 'extensionMethod' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?. instead.
+var topLevelExtensionMethodInvocation = nullableClass.extensionMethod();
+                                                      ^^^^^^^^^^^^^^^" in self::Extension|extensionMethod(self::nullableClass);
+static field () → core::int topLevelExtensionMethodTearOff = let final<BottomType> #t56 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:67:52: Error: Property 'extensionMethod' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionMethodTearOff = nullableClass.extensionMethod;
+                                                   ^^^^^^^^^^^^^^^" in self::Extension|get#extensionMethod(self::nullableClass);
+static field core::int topLevelExtensionFunctionTypeImplicitCall = let final<BottomType> #t57 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:68:62: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelExtensionFunctionTypeImplicitCall = nullableClass();
+                                                             ^" in self::Extension|call(self::nullableClass);
+static field core::int topLevelExtensionFunctionTypeExplicitCall = let final<BottomType> #t58 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:69:63: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?. instead.
+var topLevelExtensionFunctionTypeExplicitCall = nullableClass.call();
+                                                              ^^^^" in self::Extension|call(self::nullableClass);
+static field () → core::int topLevelExtensionFunctionTypeTearOff = let final<BottomType> #t59 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:70:58: Error: Property 'call' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionFunctionTypeTearOff = nullableClass.call;
+                                                         ^^^^" in self::Extension|get#call(self::nullableClass);
+static field dynamic topLevelExtensionFunctionGetter = let final<BottomType> #t60 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:71:53: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+                                                    ^" in self::Extension|get#extensionFunctionGetter(self::nullableClass).call();
+static field void topLevelExtensionFunctionTypeGetter = let final<BottomType> #t61 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:73:19: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+    nullableClass.extensionFunctionTypeGetter();
+                  ^" in self::Extension|get#extensionFunctionTypeGetter(self::nullableClass).call();
+static method Extension|+(final self::Class #this, core::int value) → core::int
+  return 0;
+static method Extension|unary-(final self::Class #this) → core::int
+  return 0;
+static method Extension|[](final self::Class #this, core::int index) → core::int
+  return 0;
+static method Extension|[]=(final self::Class #this, core::int index, core::int value) → void {}
+static method Extension|call(final self::Class #this) → core::int
+  return 0;
+static method Extension|get#call(final self::Class #this) → () → core::int
+  return () → core::int => self::Extension|call(#this);
+static method Extension|get#extensionProperty(final self::Class #this) → core::int
+  return 0;
+static method Extension|set#extensionProperty(final self::Class #this, core::int value) → void {}
+static method Extension|extensionMethod(final self::Class #this) → core::int
+  return 0;
+static method Extension|get#extensionMethod(final self::Class #this) → () → core::int
+  return () → core::int => self::Extension|extensionMethod(#this);
+static method Extension|get#extensionFunctionGetter(final self::Class #this) → core::Function
+  return () → core::Null? {};
+static method Extension|get#extensionFunctionTypeGetter(final self::Class #this) → () → void
+  return () → core::Null? {};
 static get nullableFunction() → core::Function?
   return () → core::Null? {};
 static get nullableFunctionType() → () →? void
@@ -277,82 +650,179 @@
 static get nullableClass() → self::Class?
   return new self::Class::•();
 static method test() → dynamic {
-  core::int? localBinary = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:46:33: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+  core::int? localBinary = let final<BottomType> #t62 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:76:33: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
   var localBinary = nullableInt + 0;
                                 ^" in self::nullableInt.{core::num::+}(0);
-  core::int localUnary = let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:47:20: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+  core::int localUnary = let final<BottomType> #t63 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:77:20: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
   var localUnary = -nullableInt;
                    ^" in self::nullableInt.{core::int::unary-}();
-  dynamic localIndexGet = let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:48:34: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+  dynamic localIndexGet = let final<BottomType> #t64 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:78:34: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
   var localIndexGet = nullableMap[0];
                                  ^" in self::nullableMap.{core::Map::[]}(0);
-  core::int localIndexSet = let final core::Map<dynamic, dynamic>? #t30 = self::nullableMap in let final core::int #t31 = 0 in let final core::int #t32 = 1 in let final void #t33 = let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:49:34: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+  core::int localIndexSet = let final core::Map<dynamic, dynamic>? #t65 = self::nullableMap in let final core::int #t66 = 0 in let final core::int #t67 = 1 in let final void #t68 = let final<BottomType> #t69 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:79:34: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
   var localIndexSet = nullableMap[0] = 1;
-                                 ^" in #t30.{core::Map::[]=}(#t31, #t32) in #t32;
-  dynamic localIndexGetSet = let final core::Map<dynamic, dynamic>? #t35 = self::nullableMap in let final core::int #t36 = 0 in let final dynamic #t37 = (let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:37: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+                                 ^" in #t65.{core::Map::[]=}(#t66, #t67) in #t67;
+  dynamic localIndexGetSet = let final core::Map<dynamic, dynamic>? #t70 = self::nullableMap in let final core::int #t71 = 0 in let final dynamic #t72 = (let final<BottomType> #t73 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:80:37: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
   var localIndexGetSet = nullableMap[0] += 1;
-                                    ^" in #t35.{core::Map::[]}(#t36)).+(1) in let final void #t39 = let final<BottomType> #t40 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:37: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+                                    ^" in #t70.{core::Map::[]}(#t71)).+(1) in let final void #t74 = let final<BottomType> #t75 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:80:37: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
   var localIndexGetSet = nullableMap[0] += 1;
-                                    ^" in #t35.{core::Map::[]=}(#t36, #t37) in #t37;
-  core::int localPropertyGet = let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:51:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+                                    ^" in #t70.{core::Map::[]=}(#t71, #t72) in #t72;
+  core::int localPropertyGet = let final<BottomType> #t76 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:81:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
   var localPropertyGet = nullableClass.property;
                                        ^^^^^^^^" in self::nullableClass.{self::Class::property};
-  core::int localPropertySet = let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:52:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+  core::int localPropertySet = let final<BottomType> #t77 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:82:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
   var localPropertySet = nullableClass.property = 1;
                                        ^^^^^^^^" in self::nullableClass.{self::Class::property} = 1;
-  core::int localPropertyGetSet = let final self::Class? #t43 = self::nullableClass in let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:53:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+  core::int localPropertyGetSet = let final self::Class? #t78 = self::nullableClass in let final<BottomType> #t79 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:83:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
   var localPropertyGetSet = nullableClass.property += 1;
-                                          ^^^^^^^^" in #t43.{self::Class::property} = (let final<BottomType> #t45 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:53:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+                                          ^^^^^^^^" in #t78.{self::Class::property} = (let final<BottomType> #t80 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:83:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
   var localPropertyGetSet = nullableClass.property += 1;
-                                          ^^^^^^^^" in #t43.{self::Class::property}).{core::num::+}(1);
-  core::int localMethodInvocation = let final<BottomType> #t46 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:54:45: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
+                                          ^^^^^^^^" in #t78.{self::Class::property}).{core::num::+}(1);
+  core::int localMethodInvocation = let final<BottomType> #t81 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:84:45: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try calling using ?. instead.
   var localMethodInvocation = nullableClass.method();
                                             ^^^^^^" in self::nullableClass.{self::Class::method}();
-  () → core::int localMethodTearOff = self::nullableClass.{self::Class::method};
-  dynamic localFunctionImplicitCall = let final<BottomType> #t47 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:56:51: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+  () → core::int localMethodTearOff = let final<BottomType> #t82 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:85:42: Error: Property 'method' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localMethodTearOff = nullableClass.method;
+                                         ^^^^^^" in self::nullableClass.{self::Class::method};
+  dynamic localFunctionImplicitCall = let final<BottomType> #t83 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:86:51: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
  - 'Function' is from 'dart:core'.
 Try calling using ?.call instead.
   var localFunctionImplicitCall = nullableFunction();
                                                   ^" in self::nullableFunction.call();
-  dynamic localFunctionExplicitCall = let final<BottomType> #t48 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:57:52: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+  dynamic localFunctionExplicitCall = let final<BottomType> #t84 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:87:52: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
  - 'Function' is from 'dart:core'.
 Try calling using ?. instead.
   var localFunctionExplicitCall = nullableFunction.call();
                                                    ^^^^" in self::nullableFunction.call();
-  core::Function? localFunctionTearOff = let final<BottomType> #t49 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:58:47: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
+  core::Function? localFunctionTearOff = let final<BottomType> #t85 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:88:47: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
  - 'Function' is from 'dart:core'.
 Try accessing using ?. instead.
   var localFunctionTearOff = nullableFunction.call;
                                               ^^^^" in self::nullableFunction.call;
-  void localFunctionTypeImplicitCall = let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:59:59: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+  void localFunctionTypeImplicitCall = let final<BottomType> #t86 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:89:59: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
 Try calling using ?.call instead.
   var localFunctionTypeImplicitCall = nullableFunctionType();
                                                           ^" in self::nullableFunctionType.call();
-  void localFunctionTypeExplicitCall = let final<BottomType> #t51 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:60:60: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
+  void localFunctionTypeExplicitCall = let final<BottomType> #t87 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:90:60: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
 Try calling using ?. instead.
   var localFunctionTypeExplicitCall = nullableFunctionType.call();
                                                            ^^^^" in self::nullableFunctionType.call();
-  () →? void localFunctionTypeTearOff = let final<BottomType> #t52 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:61:55: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
+  () →? void localFunctionTypeTearOff = let final<BottomType> #t88 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:91:55: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
 Try accessing using ?. instead.
   var localFunctionTypeTearOff = nullableFunctionType.call;
                                                       ^^^^" in self::nullableFunctionType.call;
-  dynamic localFunctionField = self::nullableClass.{self::Class::functionField}.call();
-  void localFunctionTypeField = self::nullableClass.{self::Class::functionTypeField}.call();
-  dynamic localFunctionGetter = self::nullableClass.{self::Class::functionGetter}.call();
-  void localFunctionTypeGetter = self::nullableClass.{self::Class::functionTypeGetter}.call();
+  dynamic localFunctionField = let final<BottomType> #t89 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:92:42: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localFunctionField = nullableClass.functionField();
+                                         ^" in self::nullableClass.{self::Class::functionField}.call();
+  void localFunctionTypeField = let final<BottomType> #t90 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:93:46: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localFunctionTypeField = nullableClass.functionTypeField();
+                                             ^" in self::nullableClass.{self::Class::functionTypeField}.call();
+  dynamic localFunctionGetter = let final<BottomType> #t91 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:94:43: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localFunctionGetter = nullableClass.functionGetter();
+                                          ^" in self::nullableClass.{self::Class::functionGetter}.call();
+  void localFunctionTypeGetter = let final<BottomType> #t92 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:95:47: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localFunctionTypeGetter = nullableClass.functionTypeGetter();
+                                              ^" in self::nullableClass.{self::Class::functionTypeGetter}.call();
+  core::int localExtensionBinary = let final<BottomType> #t93 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:97:44: Error: Operator '+' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionBinary = nullableClass + 0;
+                                           ^" in self::Extension|+(self::nullableClass, 0);
+  core::int localExtensionUnary = let final<BottomType> #t94 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:98:29: Error: Operator 'unary-' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionUnary = -nullableClass;
+                            ^" in self::Extension|unary-(self::nullableClass);
+  core::int localExtensionIndexGet = let final<BottomType> #t95 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:99:45: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionIndexGet = nullableClass[0];
+                                            ^" in self::Extension|[](self::nullableClass, 0);
+  core::int localExtensionIndexSet = let final self::Class? #t96 = self::nullableClass in let final core::int #t97 = 0 in let final core::int #t98 = 1 in let final void #t99 = let final<BottomType> #t100 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:100:45: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionIndexSet = nullableClass[0] = 1;
+                                            ^" in self::Extension|[]=(#t96, #t97, #t98) in #t98;
+  core::int localExtensionIndexGetSet = let final self::Class? #t101 = self::nullableClass in let final core::int #t102 = 0 in let final core::int #t103 = (let final<BottomType> #t104 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:101:48: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionIndexGetSet = nullableClass[0] += 1;
+                                               ^" in self::Extension|[](#t101, #t102)).{core::num::+}(1) in let final void #t105 = let final<BottomType> #t106 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:101:48: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionIndexGetSet = nullableClass[0] += 1;
+                                               ^" in self::Extension|[]=(#t101, #t102, #t103) in #t103;
+  core::int localExtensionPropertyGet = let final<BottomType> #t107 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:102:49: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionPropertyGet = nullableClass.extensionProperty;
+                                                ^^^^^^^^^^^^^^^^^" in self::Extension|get#extensionProperty(self::nullableClass);
+  core::int localExtensionPropertySet = let final<BottomType> #t108 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:103:49: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionPropertySet = nullableClass.extensionProperty = 1;
+                                                ^^^^^^^^^^^^^^^^^" in let final core::int #t109 = 1 in let final void #t110 = self::Extension|set#extensionProperty(self::nullableClass, #t109) in #t109;
+  core::int localExtensionPropertyGetSet = let final self::Class? #t111 = self::nullableClass in let final<BottomType> #t112 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:104:52: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+                                                   ^^^^^^^^^^^^^^^^^" in let final core::int #t113 = (let final<BottomType> #t114 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:104:52: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+                                                   ^^^^^^^^^^^^^^^^^" in self::Extension|get#extensionProperty(#t111)).{core::num::+}(1) in let final void #t115 = self::Extension|set#extensionProperty(#t111, #t113) in #t113;
+  core::int localExtensionMethodInvocation = let final<BottomType> #t116 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:105:54: Error: Method 'extensionMethod' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?. instead.
+  var localExtensionMethodInvocation = nullableClass.extensionMethod();
+                                                     ^^^^^^^^^^^^^^^" in self::Extension|extensionMethod(self::nullableClass);
+  () → core::int localExtensionMethodTearOff = let final<BottomType> #t117 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:106:51: Error: Property 'extensionMethod' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionMethodTearOff = nullableClass.extensionMethod;
+                                                  ^^^^^^^^^^^^^^^" in self::Extension|get#extensionMethod(self::nullableClass);
+  core::int localExtensionFunctionTypeImplicitCall = let final<BottomType> #t118 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:107:61: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localExtensionFunctionTypeImplicitCall = nullableClass();
+                                                            ^" in self::Extension|call(self::nullableClass);
+  core::int localExtensionFunctionTypeExplicitCall = let final<BottomType> #t119 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:108:62: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?. instead.
+  var localExtensionFunctionTypeExplicitCall = nullableClass.call();
+                                                             ^^^^" in self::Extension|call(self::nullableClass);
+  () → core::int localExtensionFunctionTypeTearOff = let final<BottomType> #t120 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:109:57: Error: Property 'call' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionFunctionTypeTearOff = nullableClass.call;
+                                                        ^^^^" in self::Extension|get#call(self::nullableClass);
+  dynamic localExtensionFunctionGetter = let final<BottomType> #t121 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:110:52: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+                                                   ^" in self::Extension|get#extensionFunctionGetter(self::nullableClass).call();
+  void localExtensionFunctionTypeGetter = let final<BottomType> #t122 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:112:21: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+      nullableClass.extensionFunctionTypeGetter();
+                    ^" in self::Extension|get#extensionFunctionTypeGetter(self::nullableClass).call();
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.weak.expect b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.weak.expect
index eeb102b..7c80c76 100644
--- a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.weak.expect
@@ -2,176 +2,416 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:24:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:37:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 // var topLevelBinary = nullableInt + 0;
 //                                  ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:25:21: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:38:21: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
 // var topLevelUnary = -nullableInt;
 //                     ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:26:35: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:39:35: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 // var topLevelIndexGet = nullableMap[0];
 //                                   ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:27:35: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:40:35: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 // var topLevelIndexSet = nullableMap[0] = 1;
 //                                   ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:28:38: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:41:38: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 // var topLevelIndexGetSet = nullableMap[0] += 1;
 //                                      ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:28:38: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:41:38: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 // var topLevelIndexGetSet = nullableMap[0] += 1;
 //                                      ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:29:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:42:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 // var topLevelPropertyGet = nullableClass.property;
 //                                         ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:30:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:43:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 // var topLevelPropertySet = nullableClass.property = 1;
 //                                         ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:31:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:44:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 // var topLevelPropertyGetSet = nullableClass.property += 1;
 //                                            ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:32:46: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:45:46: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try calling using ?. instead.
 // var topLevelMethodInvocation = nullableClass.method();
 //                                              ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:34:52: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:46:43: Error: Property 'method' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelMethodTearOff = nullableClass.method;
+//                                           ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:47:52: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try calling using ?.call instead.
 // var topLevelFunctionImplicitCall = nullableFunction();
 //                                                    ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:35:53: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:48:53: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try calling using ?. instead.
 // var topLevelFunctionExplicitCall = nullableFunction.call();
 //                                                     ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:36:48: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:49:48: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try accessing using ?. instead.
 // var topLevelFunctionTearOff = nullableFunction.call;
 //                                                ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:37:60: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:60: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
 // Try calling using ?.call instead.
 // var topLevelFunctionTypeImplicitCall = nullableFunctionType();
 //                                                            ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:38:61: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:51:61: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
 // Try calling using ?. instead.
 // var topLevelFunctionTypeExplicitCall = nullableFunctionType.call();
 //                                                             ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:39:56: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:52:56: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
 // Try accessing using ?. instead.
 // var topLevelFunctionTypeTearOff = nullableFunctionType.call;
 //                                                        ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:46:33: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:53:43: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelFunctionField = nullableClass.functionField();
+//                                           ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:54:47: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelFunctionTypeField = nullableClass.functionTypeField();
+//                                               ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:55:44: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelFunctionGetter = nullableClass.functionGetter();
+//                                            ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:56:48: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelFunctionTypeGetter = nullableClass.functionTypeGetter();
+//                                                ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:58:45: Error: Operator '+' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionBinary = nullableClass + 0;
+//                                             ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:59:30: Error: Operator 'unary-' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionUnary = -nullableClass;
+//                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:60:46: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionIndexGet = nullableClass[0];
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:61:46: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionIndexSet = nullableClass[0] = 1;
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:62:49: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionIndexGetSet = nullableClass[0] += 1;
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:62:49: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// var topLevelExtensionIndexGetSet = nullableClass[0] += 1;
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:63:50: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelExtensionPropertyGet = nullableClass.extensionProperty;
+//                                                  ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:64:50: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelExtensionPropertySet = nullableClass.extensionProperty = 1;
+//                                                  ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:65:53: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+//                                                     ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:66:55: Error: Method 'extensionMethod' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?. instead.
+// var topLevelExtensionMethodInvocation = nullableClass.extensionMethod();
+//                                                       ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:67:52: Error: Property 'extensionMethod' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelExtensionMethodTearOff = nullableClass.extensionMethod;
+//                                                    ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:68:62: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelExtensionFunctionTypeImplicitCall = nullableClass();
+//                                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:69:63: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?. instead.
+// var topLevelExtensionFunctionTypeExplicitCall = nullableClass.call();
+//                                                               ^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:70:58: Error: Property 'call' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+// var topLevelExtensionFunctionTypeTearOff = nullableClass.call;
+//                                                          ^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:71:53: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+// var topLevelExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+//                                                     ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:73:19: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//     nullableClass.extensionFunctionTypeGetter();
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:76:33: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 //   var localBinary = nullableInt + 0;
 //                                 ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:47:20: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:77:20: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
 //   var localUnary = -nullableInt;
 //                    ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:48:34: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:78:34: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 //   var localIndexGet = nullableMap[0];
 //                                  ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:49:34: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:79:34: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 //   var localIndexSet = nullableMap[0] = 1;
 //                                  ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:37: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:80:37: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 //   var localIndexGetSet = nullableMap[0] += 1;
 //                                     ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:37: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:80:37: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
 //  - 'Map' is from 'dart:core'.
 //   var localIndexGetSet = nullableMap[0] += 1;
 //                                     ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:51:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:81:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 //   var localPropertyGet = nullableClass.property;
 //                                        ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:52:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:82:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 //   var localPropertySet = nullableClass.property = 1;
 //                                        ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:53:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:83:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try accessing using ?. instead.
 //   var localPropertyGetSet = nullableClass.property += 1;
 //                                           ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:54:45: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:84:45: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
 //  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 // Try calling using ?. instead.
 //   var localMethodInvocation = nullableClass.method();
 //                                             ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:56:51: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:85:42: Error: Property 'method' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localMethodTearOff = nullableClass.method;
+//                                          ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:86:51: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try calling using ?.call instead.
 //   var localFunctionImplicitCall = nullableFunction();
 //                                                   ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:57:52: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:87:52: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try calling using ?. instead.
 //   var localFunctionExplicitCall = nullableFunction.call();
 //                                                    ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:58:47: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:88:47: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
 //  - 'Function' is from 'dart:core'.
 // Try accessing using ?. instead.
 //   var localFunctionTearOff = nullableFunction.call;
 //                                               ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:59:59: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:89:59: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
 // Try calling using ?.call instead.
 //   var localFunctionTypeImplicitCall = nullableFunctionType();
 //                                                           ^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:60:60: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:90:60: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
 // Try calling using ?. instead.
 //   var localFunctionTypeExplicitCall = nullableFunctionType.call();
 //                                                            ^^^^
 //
-// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:61:55: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:91:55: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
 // Try accessing using ?. instead.
 //   var localFunctionTypeTearOff = nullableFunctionType.call;
 //                                                       ^^^^
 //
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:92:42: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localFunctionField = nullableClass.functionField();
+//                                          ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:93:46: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localFunctionTypeField = nullableClass.functionTypeField();
+//                                              ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:94:43: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localFunctionGetter = nullableClass.functionGetter();
+//                                           ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:95:47: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localFunctionTypeGetter = nullableClass.functionTypeGetter();
+//                                               ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:97:44: Error: Operator '+' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionBinary = nullableClass + 0;
+//                                            ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:98:29: Error: Operator 'unary-' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionUnary = -nullableClass;
+//                             ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:99:45: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionIndexGet = nullableClass[0];
+//                                             ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:100:45: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionIndexSet = nullableClass[0] = 1;
+//                                             ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:101:48: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionIndexGetSet = nullableClass[0] += 1;
+//                                                ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:101:48: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+//   var localExtensionIndexGetSet = nullableClass[0] += 1;
+//                                                ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:102:49: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localExtensionPropertyGet = nullableClass.extensionProperty;
+//                                                 ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:103:49: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localExtensionPropertySet = nullableClass.extensionProperty = 1;
+//                                                 ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:104:52: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+//                                                    ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:105:54: Error: Method 'extensionMethod' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?. instead.
+//   var localExtensionMethodInvocation = nullableClass.extensionMethod();
+//                                                      ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:106:51: Error: Property 'extensionMethod' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localExtensionMethodTearOff = nullableClass.extensionMethod;
+//                                                   ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:107:61: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localExtensionFunctionTypeImplicitCall = nullableClass();
+//                                                             ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:108:62: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?. instead.
+//   var localExtensionFunctionTypeExplicitCall = nullableClass.call();
+//                                                              ^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:109:57: Error: Property 'call' cannot be accessed on 'Class?' because it is potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try accessing using ?. instead.
+//   var localExtensionFunctionTypeTearOff = nullableClass.call;
+//                                                         ^^^^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:110:52: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//   var localExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+//                                                    ^
+//
+// pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:112:21: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+// Try calling using ?.call instead.
+//       nullableClass.extensionFunctionTypeGetter();
+//                     ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -189,83 +429,216 @@
   get functionTypeGetter() → () → void
     return () → core::Null? {};
 }
-static field core::int? topLevelBinary = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:24:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+extension Extension on self::Class {
+  operator + = self::Extension|+;
+  operator unary- = self::Extension|unary-;
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+  method call = self::Extension|call;
+  tearoff call = self::Extension|get#call;
+  get extensionProperty = self::Extension|get#extensionProperty;
+  method extensionMethod = self::Extension|extensionMethod;
+  tearoff extensionMethod = self::Extension|get#extensionMethod;
+  get extensionFunctionGetter = self::Extension|get#extensionFunctionGetter;
+  get extensionFunctionTypeGetter = self::Extension|get#extensionFunctionTypeGetter;
+  set extensionProperty = self::Extension|set#extensionProperty;
+}
+static field core::int? topLevelBinary = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:37:34: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
 var topLevelBinary = nullableInt + 0;
                                  ^" in self::nullableInt.{core::num::+}(0);
-static field core::int topLevelUnary = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:25:21: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+static field core::int topLevelUnary = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:38:21: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
 var topLevelUnary = -nullableInt;
                     ^" in self::nullableInt.{core::int::unary-}();
-static field dynamic topLevelIndexGet = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:26:35: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+static field dynamic topLevelIndexGet = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:39:35: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
 var topLevelIndexGet = nullableMap[0];
                                   ^" in self::nullableMap.{core::Map::[]}(0);
-static field core::int topLevelIndexSet = let final core::Map<dynamic, dynamic>? #t4 = self::nullableMap in let final core::int #t5 = 0 in let final core::int #t6 = 1 in let final void #t7 = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:27:35: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+static field core::int topLevelIndexSet = let final core::Map<dynamic, dynamic>? #t4 = self::nullableMap in let final core::int #t5 = 0 in let final core::int #t6 = 1 in let final void #t7 = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:40:35: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
 var topLevelIndexSet = nullableMap[0] = 1;
                                   ^" in #t4.{core::Map::[]=}(#t5, #t6) in #t6;
-static field dynamic topLevelIndexGetSet = let final core::Map<dynamic, dynamic>? #t9 = self::nullableMap in let final core::int #t10 = 0 in let final dynamic #t11 = (let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:28:38: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+static field dynamic topLevelIndexGetSet = let final core::Map<dynamic, dynamic>? #t9 = self::nullableMap in let final core::int #t10 = 0 in let final dynamic #t11 = (let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:41:38: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
 var topLevelIndexGetSet = nullableMap[0] += 1;
-                                     ^" in #t9.{core::Map::[]}(#t10)).+(1) in let final void #t13 = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:28:38: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+                                     ^" in #t9.{core::Map::[]}(#t10)).+(1) in let final void #t13 = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:41:38: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
 var topLevelIndexGetSet = nullableMap[0] += 1;
                                      ^" in #t9.{core::Map::[]=}(#t10, #t11) in #t11;
-static field core::int topLevelPropertyGet = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:29:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+static field core::int topLevelPropertyGet = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:42:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
 var topLevelPropertyGet = nullableClass.property;
                                         ^^^^^^^^" in self::nullableClass.{self::Class::property};
-static field core::int topLevelPropertySet = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:30:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+static field core::int topLevelPropertySet = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:43:41: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
 var topLevelPropertySet = nullableClass.property = 1;
                                         ^^^^^^^^" in self::nullableClass.{self::Class::property} = 1;
-static field core::int topLevelPropertyGetSet = let final self::Class? #t17 = self::nullableClass in let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:31:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+static field core::int topLevelPropertyGetSet = let final self::Class? #t17 = self::nullableClass in let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:44:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
 var topLevelPropertyGetSet = nullableClass.property += 1;
-                                           ^^^^^^^^" in #t17.{self::Class::property} = (let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:31:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+                                           ^^^^^^^^" in #t17.{self::Class::property} = (let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:44:44: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
 var topLevelPropertyGetSet = nullableClass.property += 1;
                                            ^^^^^^^^" in #t17.{self::Class::property}).{core::num::+}(1);
-static field core::int topLevelMethodInvocation = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:32:46: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
+static field core::int topLevelMethodInvocation = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:45:46: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try calling using ?. instead.
 var topLevelMethodInvocation = nullableClass.method();
                                              ^^^^^^" in self::nullableClass.{self::Class::method}();
-static field () → core::int topLevelMethodTearOff = self::nullableClass.{self::Class::method};
-static field dynamic topLevelFunctionImplicitCall = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:34:52: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+static field () → core::int topLevelMethodTearOff = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:46:43: Error: Property 'method' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelMethodTearOff = nullableClass.method;
+                                          ^^^^^^" in self::nullableClass.{self::Class::method};
+static field dynamic topLevelFunctionImplicitCall = let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:47:52: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
  - 'Function' is from 'dart:core'.
 Try calling using ?.call instead.
 var topLevelFunctionImplicitCall = nullableFunction();
                                                    ^" in self::nullableFunction.call();
-static field dynamic topLevelFunctionExplicitCall = let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:35:53: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+static field dynamic topLevelFunctionExplicitCall = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:48:53: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
  - 'Function' is from 'dart:core'.
 Try calling using ?. instead.
 var topLevelFunctionExplicitCall = nullableFunction.call();
                                                     ^^^^" in self::nullableFunction.call();
-static field core::Function? topLevelFunctionTearOff = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:36:48: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
+static field core::Function? topLevelFunctionTearOff = let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:49:48: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
  - 'Function' is from 'dart:core'.
 Try accessing using ?. instead.
 var topLevelFunctionTearOff = nullableFunction.call;
                                                ^^^^" in self::nullableFunction.call;
-static field void topLevelFunctionTypeImplicitCall = let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:37:60: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+static field void topLevelFunctionTypeImplicitCall = let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:60: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
 Try calling using ?.call instead.
 var topLevelFunctionTypeImplicitCall = nullableFunctionType();
                                                            ^" in self::nullableFunctionType.call();
-static field void topLevelFunctionTypeExplicitCall = let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:38:61: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
+static field void topLevelFunctionTypeExplicitCall = let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:51:61: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
 Try calling using ?. instead.
 var topLevelFunctionTypeExplicitCall = nullableFunctionType.call();
                                                             ^^^^" in self::nullableFunctionType.call();
-static field () →? void topLevelFunctionTypeTearOff = let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:39:56: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
+static field () →? void topLevelFunctionTypeTearOff = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:52:56: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
 Try accessing using ?. instead.
 var topLevelFunctionTypeTearOff = nullableFunctionType.call;
                                                        ^^^^" in self::nullableFunctionType.call;
-static field dynamic topLevelFunctionField = self::nullableClass.{self::Class::functionField}.call();
-static field void topLevelFunctionTypeField = self::nullableClass.{self::Class::functionTypeField}.call();
-static field dynamic topLevelFunctionGetter = self::nullableClass.{self::Class::functionGetter}.call();
-static field void topLevelFunctionTypeGetter = self::nullableClass.{self::Class::functionTypeGetter}.call();
+static field dynamic topLevelFunctionField = let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:53:43: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelFunctionField = nullableClass.functionField();
+                                          ^" in self::nullableClass.{self::Class::functionField}.call();
+static field void topLevelFunctionTypeField = let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:54:47: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelFunctionTypeField = nullableClass.functionTypeField();
+                                              ^" in self::nullableClass.{self::Class::functionTypeField}.call();
+static field dynamic topLevelFunctionGetter = let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:55:44: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelFunctionGetter = nullableClass.functionGetter();
+                                           ^" in self::nullableClass.{self::Class::functionGetter}.call();
+static field void topLevelFunctionTypeGetter = let final<BottomType> #t31 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:56:48: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelFunctionTypeGetter = nullableClass.functionTypeGetter();
+                                               ^" in self::nullableClass.{self::Class::functionTypeGetter}.call();
+static field core::int topLevelExtensionBinary = let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:58:45: Error: Operator '+' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionBinary = nullableClass + 0;
+                                            ^" in self::Extension|+(self::nullableClass, 0);
+static field core::int topLevelExtensionUnary = let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:59:30: Error: Operator 'unary-' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionUnary = -nullableClass;
+                             ^" in self::Extension|unary-(self::nullableClass);
+static field core::int topLevelExtensionIndexGet = let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:60:46: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionIndexGet = nullableClass[0];
+                                             ^" in self::Extension|[](self::nullableClass, 0);
+static field core::int topLevelExtensionIndexSet = let final self::Class? #t35 = self::nullableClass in let final core::int #t36 = 0 in let final core::int #t37 = 1 in let final void #t38 = let final<BottomType> #t39 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:61:46: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionIndexSet = nullableClass[0] = 1;
+                                             ^" in self::Extension|[]=(#t35, #t36, #t37) in #t37;
+static field core::int topLevelExtensionIndexGetSet = let final self::Class? #t40 = self::nullableClass in let final core::int #t41 = 0 in let final core::int #t42 = (let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:62:49: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionIndexGetSet = nullableClass[0] += 1;
+                                                ^" in self::Extension|[](#t40, #t41)).{core::num::+}(1) in let final void #t44 = let final<BottomType> #t45 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:62:49: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+var topLevelExtensionIndexGetSet = nullableClass[0] += 1;
+                                                ^" in self::Extension|[]=(#t40, #t41, #t42) in #t42;
+static field core::int topLevelExtensionPropertyGet = let final<BottomType> #t46 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:63:50: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionPropertyGet = nullableClass.extensionProperty;
+                                                 ^^^^^^^^^^^^^^^^^" in self::Extension|get#extensionProperty(self::nullableClass);
+static field core::int topLevelExtensionPropertySet = let final<BottomType> #t47 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:64:50: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionPropertySet = nullableClass.extensionProperty = 1;
+                                                 ^^^^^^^^^^^^^^^^^" in let final core::int #t48 = 1 in let final void #t49 = self::Extension|set#extensionProperty(self::nullableClass, #t48) in #t48;
+static field core::int topLevelExtensionPropertyGetSet = let final self::Class? #t50 = self::nullableClass in let final<BottomType> #t51 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:65:53: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+                                                    ^^^^^^^^^^^^^^^^^" in let final core::int #t52 = (let final<BottomType> #t53 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:65:53: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+                                                    ^^^^^^^^^^^^^^^^^" in self::Extension|get#extensionProperty(#t50)).{core::num::+}(1) in let final void #t54 = self::Extension|set#extensionProperty(#t50, #t52) in #t52;
+static field core::int topLevelExtensionMethodInvocation = let final<BottomType> #t55 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:66:55: Error: Method 'extensionMethod' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?. instead.
+var topLevelExtensionMethodInvocation = nullableClass.extensionMethod();
+                                                      ^^^^^^^^^^^^^^^" in self::Extension|extensionMethod(self::nullableClass);
+static field () → core::int topLevelExtensionMethodTearOff = let final<BottomType> #t56 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:67:52: Error: Property 'extensionMethod' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionMethodTearOff = nullableClass.extensionMethod;
+                                                   ^^^^^^^^^^^^^^^" in self::Extension|get#extensionMethod(self::nullableClass);
+static field core::int topLevelExtensionFunctionTypeImplicitCall = let final<BottomType> #t57 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:68:62: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelExtensionFunctionTypeImplicitCall = nullableClass();
+                                                             ^" in self::Extension|call(self::nullableClass);
+static field core::int topLevelExtensionFunctionTypeExplicitCall = let final<BottomType> #t58 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:69:63: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?. instead.
+var topLevelExtensionFunctionTypeExplicitCall = nullableClass.call();
+                                                              ^^^^" in self::Extension|call(self::nullableClass);
+static field () → core::int topLevelExtensionFunctionTypeTearOff = let final<BottomType> #t59 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:70:58: Error: Property 'call' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+var topLevelExtensionFunctionTypeTearOff = nullableClass.call;
+                                                         ^^^^" in self::Extension|get#call(self::nullableClass);
+static field dynamic topLevelExtensionFunctionGetter = let final<BottomType> #t60 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:71:53: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+var topLevelExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+                                                    ^" in self::Extension|get#extensionFunctionGetter(self::nullableClass).call();
+static field void topLevelExtensionFunctionTypeGetter = let final<BottomType> #t61 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:73:19: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+    nullableClass.extensionFunctionTypeGetter();
+                  ^" in self::Extension|get#extensionFunctionTypeGetter(self::nullableClass).call();
+static method Extension|+(final self::Class #this, core::int value) → core::int
+  return 0;
+static method Extension|unary-(final self::Class #this) → core::int
+  return 0;
+static method Extension|[](final self::Class #this, core::int index) → core::int
+  return 0;
+static method Extension|[]=(final self::Class #this, core::int index, core::int value) → void {}
+static method Extension|call(final self::Class #this) → core::int
+  return 0;
+static method Extension|get#call(final self::Class #this) → () → core::int
+  return () → core::int => self::Extension|call(#this);
+static method Extension|get#extensionProperty(final self::Class #this) → core::int
+  return 0;
+static method Extension|set#extensionProperty(final self::Class #this, core::int value) → void {}
+static method Extension|extensionMethod(final self::Class #this) → core::int
+  return 0;
+static method Extension|get#extensionMethod(final self::Class #this) → () → core::int
+  return () → core::int => self::Extension|extensionMethod(#this);
+static method Extension|get#extensionFunctionGetter(final self::Class #this) → core::Function
+  return () → core::Null? {};
+static method Extension|get#extensionFunctionTypeGetter(final self::Class #this) → () → void
+  return () → core::Null? {};
 static get nullableFunction() → core::Function?
   return () → core::Null? {};
 static get nullableFunctionType() → () →? void
@@ -277,82 +650,179 @@
 static get nullableClass() → self::Class?
   return new self::Class::•();
 static method test() → dynamic {
-  core::int? localBinary = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:46:33: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
+  core::int? localBinary = let final<BottomType> #t62 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:76:33: Error: Operator '+' cannot be called on 'int?' because it is potentially null.
   var localBinary = nullableInt + 0;
                                 ^" in self::nullableInt.{core::num::+}(0);
-  core::int localUnary = let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:47:20: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
+  core::int localUnary = let final<BottomType> #t63 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:77:20: Error: Operator 'unary-' cannot be called on 'int?' because it is potentially null.
   var localUnary = -nullableInt;
                    ^" in self::nullableInt.{core::int::unary-}();
-  dynamic localIndexGet = let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:48:34: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+  dynamic localIndexGet = let final<BottomType> #t64 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:78:34: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
   var localIndexGet = nullableMap[0];
                                  ^" in self::nullableMap.{core::Map::[]}(0);
-  core::int localIndexSet = let final core::Map<dynamic, dynamic>? #t30 = self::nullableMap in let final core::int #t31 = 0 in let final core::int #t32 = 1 in let final void #t33 = let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:49:34: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+  core::int localIndexSet = let final core::Map<dynamic, dynamic>? #t65 = self::nullableMap in let final core::int #t66 = 0 in let final core::int #t67 = 1 in let final void #t68 = let final<BottomType> #t69 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:79:34: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
   var localIndexSet = nullableMap[0] = 1;
-                                 ^" in #t30.{core::Map::[]=}(#t31, #t32) in #t32;
-  dynamic localIndexGetSet = let final core::Map<dynamic, dynamic>? #t35 = self::nullableMap in let final core::int #t36 = 0 in let final dynamic #t37 = (let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:37: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+                                 ^" in #t65.{core::Map::[]=}(#t66, #t67) in #t67;
+  dynamic localIndexGetSet = let final core::Map<dynamic, dynamic>? #t70 = self::nullableMap in let final core::int #t71 = 0 in let final dynamic #t72 = (let final<BottomType> #t73 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:80:37: Error: Operator '[]' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
   var localIndexGetSet = nullableMap[0] += 1;
-                                    ^" in #t35.{core::Map::[]}(#t36)).+(1) in let final void #t39 = let final<BottomType> #t40 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:50:37: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
+                                    ^" in #t70.{core::Map::[]}(#t71)).+(1) in let final void #t74 = let final<BottomType> #t75 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:80:37: Error: Operator '[]=' cannot be called on 'Map<dynamic, dynamic>?' because it is potentially null.
  - 'Map' is from 'dart:core'.
   var localIndexGetSet = nullableMap[0] += 1;
-                                    ^" in #t35.{core::Map::[]=}(#t36, #t37) in #t37;
-  core::int localPropertyGet = let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:51:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+                                    ^" in #t70.{core::Map::[]=}(#t71, #t72) in #t72;
+  core::int localPropertyGet = let final<BottomType> #t76 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:81:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
   var localPropertyGet = nullableClass.property;
                                        ^^^^^^^^" in self::nullableClass.{self::Class::property};
-  core::int localPropertySet = let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:52:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+  core::int localPropertySet = let final<BottomType> #t77 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:82:40: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
   var localPropertySet = nullableClass.property = 1;
                                        ^^^^^^^^" in self::nullableClass.{self::Class::property} = 1;
-  core::int localPropertyGetSet = let final self::Class? #t43 = self::nullableClass in let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:53:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+  core::int localPropertyGetSet = let final self::Class? #t78 = self::nullableClass in let final<BottomType> #t79 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:83:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
   var localPropertyGetSet = nullableClass.property += 1;
-                                          ^^^^^^^^" in #t43.{self::Class::property} = (let final<BottomType> #t45 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:53:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
+                                          ^^^^^^^^" in #t78.{self::Class::property} = (let final<BottomType> #t80 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:83:43: Error: Property 'property' cannot be accessed on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try accessing using ?. instead.
   var localPropertyGetSet = nullableClass.property += 1;
-                                          ^^^^^^^^" in #t43.{self::Class::property}).{core::num::+}(1);
-  core::int localMethodInvocation = let final<BottomType> #t46 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:54:45: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
+                                          ^^^^^^^^" in #t78.{self::Class::property}).{core::num::+}(1);
+  core::int localMethodInvocation = let final<BottomType> #t81 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:84:45: Error: Method 'method' cannot be called on 'Class?' because it is potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
 Try calling using ?. instead.
   var localMethodInvocation = nullableClass.method();
                                             ^^^^^^" in self::nullableClass.{self::Class::method}();
-  () → core::int localMethodTearOff = self::nullableClass.{self::Class::method};
-  dynamic localFunctionImplicitCall = let final<BottomType> #t47 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:56:51: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+  () → core::int localMethodTearOff = let final<BottomType> #t82 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:85:42: Error: Property 'method' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localMethodTearOff = nullableClass.method;
+                                         ^^^^^^" in self::nullableClass.{self::Class::method};
+  dynamic localFunctionImplicitCall = let final<BottomType> #t83 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:86:51: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
  - 'Function' is from 'dart:core'.
 Try calling using ?.call instead.
   var localFunctionImplicitCall = nullableFunction();
                                                   ^" in self::nullableFunction.call();
-  dynamic localFunctionExplicitCall = let final<BottomType> #t48 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:57:52: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+  dynamic localFunctionExplicitCall = let final<BottomType> #t84 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:87:52: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
  - 'Function' is from 'dart:core'.
 Try calling using ?. instead.
   var localFunctionExplicitCall = nullableFunction.call();
                                                    ^^^^" in self::nullableFunction.call();
-  core::Function? localFunctionTearOff = let final<BottomType> #t49 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:58:47: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
+  core::Function? localFunctionTearOff = let final<BottomType> #t85 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:88:47: Error: Property 'call' cannot be accessed on 'Function?' because it is potentially null.
  - 'Function' is from 'dart:core'.
 Try accessing using ?. instead.
   var localFunctionTearOff = nullableFunction.call;
                                               ^^^^" in self::nullableFunction.call;
-  void localFunctionTypeImplicitCall = let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:59:59: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+  void localFunctionTypeImplicitCall = let final<BottomType> #t86 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:89:59: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
 Try calling using ?.call instead.
   var localFunctionTypeImplicitCall = nullableFunctionType();
                                                           ^" in self::nullableFunctionType.call();
-  void localFunctionTypeExplicitCall = let final<BottomType> #t51 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:60:60: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
+  void localFunctionTypeExplicitCall = let final<BottomType> #t87 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:90:60: Error: Method 'call' cannot be called on 'void Function()?' because it is potentially null.
 Try calling using ?. instead.
   var localFunctionTypeExplicitCall = nullableFunctionType.call();
                                                            ^^^^" in self::nullableFunctionType.call();
-  () →? void localFunctionTypeTearOff = let final<BottomType> #t52 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:61:55: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
+  () →? void localFunctionTypeTearOff = let final<BottomType> #t88 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:91:55: Error: Property 'call' cannot be accessed on 'void Function()?' because it is potentially null.
 Try accessing using ?. instead.
   var localFunctionTypeTearOff = nullableFunctionType.call;
                                                       ^^^^" in self::nullableFunctionType.call;
-  dynamic localFunctionField = self::nullableClass.{self::Class::functionField}.call();
-  void localFunctionTypeField = self::nullableClass.{self::Class::functionTypeField}.call();
-  dynamic localFunctionGetter = self::nullableClass.{self::Class::functionGetter}.call();
-  void localFunctionTypeGetter = self::nullableClass.{self::Class::functionTypeGetter}.call();
+  dynamic localFunctionField = let final<BottomType> #t89 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:92:42: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localFunctionField = nullableClass.functionField();
+                                         ^" in self::nullableClass.{self::Class::functionField}.call();
+  void localFunctionTypeField = let final<BottomType> #t90 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:93:46: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localFunctionTypeField = nullableClass.functionTypeField();
+                                             ^" in self::nullableClass.{self::Class::functionTypeField}.call();
+  dynamic localFunctionGetter = let final<BottomType> #t91 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:94:43: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localFunctionGetter = nullableClass.functionGetter();
+                                          ^" in self::nullableClass.{self::Class::functionGetter}.call();
+  void localFunctionTypeGetter = let final<BottomType> #t92 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:95:47: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localFunctionTypeGetter = nullableClass.functionTypeGetter();
+                                              ^" in self::nullableClass.{self::Class::functionTypeGetter}.call();
+  core::int localExtensionBinary = let final<BottomType> #t93 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:97:44: Error: Operator '+' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionBinary = nullableClass + 0;
+                                           ^" in self::Extension|+(self::nullableClass, 0);
+  core::int localExtensionUnary = let final<BottomType> #t94 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:98:29: Error: Operator 'unary-' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionUnary = -nullableClass;
+                            ^" in self::Extension|unary-(self::nullableClass);
+  core::int localExtensionIndexGet = let final<BottomType> #t95 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:99:45: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionIndexGet = nullableClass[0];
+                                            ^" in self::Extension|[](self::nullableClass, 0);
+  core::int localExtensionIndexSet = let final self::Class? #t96 = self::nullableClass in let final core::int #t97 = 0 in let final core::int #t98 = 1 in let final void #t99 = let final<BottomType> #t100 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:100:45: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionIndexSet = nullableClass[0] = 1;
+                                            ^" in self::Extension|[]=(#t96, #t97, #t98) in #t98;
+  core::int localExtensionIndexGetSet = let final self::Class? #t101 = self::nullableClass in let final core::int #t102 = 0 in let final core::int #t103 = (let final<BottomType> #t104 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:101:48: Error: Operator '[]' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionIndexGetSet = nullableClass[0] += 1;
+                                               ^" in self::Extension|[](#t101, #t102)).{core::num::+}(1) in let final void #t105 = let final<BottomType> #t106 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:101:48: Error: Operator '[]=' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+  var localExtensionIndexGetSet = nullableClass[0] += 1;
+                                               ^" in self::Extension|[]=(#t101, #t102, #t103) in #t103;
+  core::int localExtensionPropertyGet = let final<BottomType> #t107 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:102:49: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionPropertyGet = nullableClass.extensionProperty;
+                                                ^^^^^^^^^^^^^^^^^" in self::Extension|get#extensionProperty(self::nullableClass);
+  core::int localExtensionPropertySet = let final<BottomType> #t108 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:103:49: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionPropertySet = nullableClass.extensionProperty = 1;
+                                                ^^^^^^^^^^^^^^^^^" in let final core::int #t109 = 1 in let final void #t110 = self::Extension|set#extensionProperty(self::nullableClass, #t109) in #t109;
+  core::int localExtensionPropertyGetSet = let final self::Class? #t111 = self::nullableClass in let final<BottomType> #t112 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:104:52: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+                                                   ^^^^^^^^^^^^^^^^^" in let final core::int #t113 = (let final<BottomType> #t114 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:104:52: Error: Property 'extensionProperty' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+                                                   ^^^^^^^^^^^^^^^^^" in self::Extension|get#extensionProperty(#t111)).{core::num::+}(1) in let final void #t115 = self::Extension|set#extensionProperty(#t111, #t113) in #t113;
+  core::int localExtensionMethodInvocation = let final<BottomType> #t116 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:105:54: Error: Method 'extensionMethod' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?. instead.
+  var localExtensionMethodInvocation = nullableClass.extensionMethod();
+                                                     ^^^^^^^^^^^^^^^" in self::Extension|extensionMethod(self::nullableClass);
+  () → core::int localExtensionMethodTearOff = let final<BottomType> #t117 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:106:51: Error: Property 'extensionMethod' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionMethodTearOff = nullableClass.extensionMethod;
+                                                  ^^^^^^^^^^^^^^^" in self::Extension|get#extensionMethod(self::nullableClass);
+  core::int localExtensionFunctionTypeImplicitCall = let final<BottomType> #t118 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:107:61: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localExtensionFunctionTypeImplicitCall = nullableClass();
+                                                            ^" in self::Extension|call(self::nullableClass);
+  core::int localExtensionFunctionTypeExplicitCall = let final<BottomType> #t119 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:108:62: Error: Method 'call' cannot be called on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?. instead.
+  var localExtensionFunctionTypeExplicitCall = nullableClass.call();
+                                                             ^^^^" in self::Extension|call(self::nullableClass);
+  () → core::int localExtensionFunctionTypeTearOff = let final<BottomType> #t120 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:109:57: Error: Property 'call' cannot be accessed on 'Class?' because it is potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try accessing using ?. instead.
+  var localExtensionFunctionTypeTearOff = nullableClass.call;
+                                                        ^^^^" in self::Extension|get#call(self::nullableClass);
+  dynamic localExtensionFunctionGetter = let final<BottomType> #t121 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:110:52: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+  var localExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+                                                   ^" in self::Extension|get#extensionFunctionGetter(self::nullableClass).call();
+  void localExtensionFunctionTypeGetter = let final<BottomType> #t122 = invalid-expression "pkg/front_end/testcases/nnbd/potentially_nullable_access.dart:112:21: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/potentially_nullable_access.dart'.
+Try calling using ?.call instead.
+      nullableClass.extensionFunctionTypeGetter();
+                    ^" in self::Extension|get#extensionFunctionTypeGetter(self::nullableClass).call();
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index ca35b47..8103acb 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -40,6 +40,7 @@
 inference/mixin_inference_unification_1: TypeCheckError
 inference/mixin_inference_unification_2: TypeCheckError
 nnbd/inheritance_from_opt_in: TypeCheckError
+nnbd/issue41567: TypeCheckError
 nnbd/messages_with_types_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_out: TypeCheckError
 nnbd/never_opt_out: TypeCheckError
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index bd6eb1d..907af6e 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -167,9 +167,12 @@
 instantiate_to_bound/non_simple_generic_function_in_bound_regress: RuntimeError # Expected
 nnbd/inheritance_from_opt_in: TypeCheckError
 nnbd/issue41180: RuntimeError # Strong mode runtime checking fails due to mixed strong mode.
+nnbd/issue41567: TypeCheckError
 nnbd/messages_with_types_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_out: TypeCheckError
 nnbd/never_opt_out: TypeCheckError
+nnbd/nullable_object_access: TypeCheckError
+nnbd/nullable_receiver: TypeCheckError
 nnbd/potentially_nullable_access: TypeCheckError
 rasta/abstract_constructor: RuntimeError
 rasta/bad_constructor_redirection: RuntimeError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index ec59b90..41d9cf9 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -165,9 +165,12 @@
 instantiate_to_bound/non_simple_generic_function_in_bound_regress: RuntimeError
 nnbd/inheritance_from_opt_in: TypeCheckError
 nnbd/issue41180: RuntimeError
+nnbd/issue41567: TypeCheckError
 nnbd/messages_with_types_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_out: TypeCheckError
 nnbd/never_opt_out: TypeCheckError
+nnbd/nullable_object_access: TypeCheckError
+nnbd/nullable_receiver: TypeCheckError
 nnbd/potentially_nullable_access: TypeCheckError
 rasta/abstract_constructor: RuntimeError
 rasta/bad_constructor_redirection: RuntimeError
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 9be9f1e..4de00b0 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -59,8 +59,11 @@
 general_nnbd_opt_out/unsound_promotion: TypeCheckError
 general_nnbd_opt_out/void_methods: RuntimeError
 nnbd/inheritance_from_opt_in: TypeCheckError
+nnbd/issue41567: TypeCheckError
 nnbd/messages_with_types_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_out: TypeCheckError
 nnbd/never_opt_out: TypeCheckError
+nnbd/nullable_object_access: TypeCheckError
+nnbd/nullable_receiver: TypeCheckError
 nnbd/potentially_nullable_access: TypeCheckError
 
diff --git a/pkg/frontend_server/pubspec.yaml b/pkg/frontend_server/pubspec.yaml
index c14c3b8..2effb3b 100644
--- a/pkg/frontend_server/pubspec.yaml
+++ b/pkg/frontend_server/pubspec.yaml
@@ -3,6 +3,9 @@
 # version: do-not-upload
 description: A resident kernel compiler
 
+environment:
+  sdk: "^2.7.0"
+
 dependencies:
   build_integration:
     path: ../build_integration
diff --git a/pkg/kernel/lib/src/nnbd_top_merge.dart b/pkg/kernel/lib/src/nnbd_top_merge.dart
index 317b1df..f0c5b4e 100644
--- a/pkg/kernel/lib/src/nnbd_top_merge.dart
+++ b/pkg/kernel/lib/src/nnbd_top_merge.dart
@@ -55,8 +55,8 @@
         // NNBD_TOP_MERGE(Object?, dynamic) = Object?
         return coreTypes.objectNullableRawType;
       } else if (b is VoidType) {
-        // NNBD_TOP_MERGE(Object?, void) = void
-        return const VoidType();
+        // NNBD_TOP_MERGE(Object?, void) = Object?
+        return coreTypes.objectNullableRawType;
       } else if (b == coreTypes.objectNullableRawType) {
         // NNBD_TOP_MERGE(Object?, Object?) = Object?
         return coreTypes.objectNullableRawType;
@@ -66,8 +66,8 @@
         // NNBD_TOP_MERGE(Object*, dynamic) = Object?
         return coreTypes.objectNullableRawType;
       } else if (b is VoidType) {
-        // NNBD_TOP_MERGE(Object*, void) = void
-        return const VoidType();
+        // NNBD_TOP_MERGE(Object*, void) = Object?
+        return coreTypes.objectNullableRawType;
       }
     } else if (a == coreTypes.nullType &&
         b is NeverType &&
@@ -81,17 +81,17 @@
   @override
   DartType visitVoidType(VoidType a, DartType b) {
     if (b is DynamicType) {
-      // NNBD_TOP_MERGE(void, dynamic) = void
-      return const VoidType();
+      // NNBD_TOP_MERGE(void, dynamic) = Object?
+      return coreTypes.objectNullableRawType;
     } else if (b is VoidType) {
       // NNBD_TOP_MERGE(void, void) = void
       return const VoidType();
     } else if (b == coreTypes.objectNullableRawType) {
-      // NNBD_TOP_MERGE(void, Object?) = void
-      return const VoidType();
+      // NNBD_TOP_MERGE(void, Object?) = Object?
+      return coreTypes.objectNullableRawType;
     } else if (b == coreTypes.objectLegacyRawType) {
-      // NNBD_TOP_MERGE(void, Object*) = void
-      return const VoidType();
+      // NNBD_TOP_MERGE(void, Object*) = Object?
+      return coreTypes.objectNullableRawType;
     }
     return null;
   }
@@ -102,8 +102,8 @@
       // NNBD_TOP_MERGE(dynamic, dynamic) = dynamic
       return const DynamicType();
     } else if (b is VoidType) {
-      // NNBD_TOP_MERGE(dynamic, void) = void
-      return const VoidType();
+      // NNBD_TOP_MERGE(dynamic, void) = Object?
+      return coreTypes.objectNullableRawType;
     } else if (b == coreTypes.objectNullableRawType) {
       // NNBD_TOP_MERGE(dynamic, Object?) = Object?
       return coreTypes.objectNullableRawType;
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index 59cec06..78cd33e 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -178,6 +178,10 @@
         problem(
             currentParent, "Missing bound for type parameter '$parameter'.");
       }
+      if (parameter.defaultType == null) {
+        problem(currentParent,
+            "Missing default type for type parameter '$parameter'.");
+      }
       if (!typeParametersInScope.add(parameter)) {
         problem(parameter, "Type parameter '$parameter' redeclared.");
       }
diff --git a/pkg/kernel/test/nnbd_top_merge_test.dart b/pkg/kernel/test/nnbd_top_merge_test.dart
index da9bd8d..4eb5d40 100644
--- a/pkg/kernel/test/nnbd_top_merge_test.dart
+++ b/pkg/kernel/test/nnbd_top_merge_test.dart
@@ -17,10 +17,10 @@
   'Object vs Object': 'Object',
   'dynamic vs dynamic': 'dynamic',
   'void vs void': 'void',
-  'Object? vs void': 'void',
-  'Object* vs void': 'void',
+  'Object? vs void': 'Object?',
+  'Object* vs void': 'Object?',
   'Object vs void': null,
-  'dynamic vs void': 'void',
+  'dynamic vs void': 'Object?',
   'Object? vs dynamic': 'Object?',
   'Object* vs dynamic': 'Object?',
   'Object vs dynamic': null,
@@ -41,10 +41,10 @@
   'List<Object> vs List<Object>': 'List<Object>',
   'List<dynamic> vs List<dynamic>': 'List<dynamic>',
   'List<void> vs List<void>': 'List<void>',
-  'List<Object?> vs List<void>': 'List<void>',
-  'List<Object*> vs List<void>': 'List<void>',
+  'List<Object?> vs List<void>': 'List<Object?>',
+  'List<Object*> vs List<void>': 'List<Object?>',
   'List<Object> vs List<void>': null,
-  'List<dynamic> vs List<void>': 'List<void>',
+  'List<dynamic> vs List<void>': 'List<Object?>',
   'List<Object?> vs List<dynamic>': 'List<Object?>',
   'List<Object*> vs List<dynamic>': 'List<Object?>',
   'List<Object> vs List<dynamic>': null,
diff --git a/pkg/kernel/test/verify_test.dart b/pkg/kernel/test/verify_test.dart
index 3219f11..905375c 100644
--- a/pkg/kernel/test/verify_test.dart
+++ b/pkg/kernel/test/verify_test.dart
@@ -733,7 +733,7 @@
   VariableDeclaration makeVariable() => new VariableDeclaration(null);
 
   TypeParameter makeTypeParameter([String name]) {
-    return new TypeParameter(name, objectLegacyRawType);
+    return new TypeParameter(name, objectLegacyRawType, const DynamicType());
   }
 
   TestHarness() {
diff --git a/pkg/nnbd_migration/bin/migrate.dart b/pkg/nnbd_migration/bin/migrate.dart
new file mode 100644
index 0000000..1b87fa3
--- /dev/null
+++ b/pkg/nnbd_migration/bin/migrate.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:nnbd_migration/migration_cli.dart';
+
+main(List<String> args) async {
+  var cli = MigrationCli(binaryName: 'nnbd_migration');
+  await cli.run(args);
+  exit(cli.exitCode ?? 0);
+}
diff --git a/pkg/nnbd_migration/lib/migration_cli.dart b/pkg/nnbd_migration/lib/migration_cli.dart
new file mode 100644
index 0000000..d8d0350
--- /dev/null
+++ b/pkg/nnbd_migration/lib/migration_cli.dart
@@ -0,0 +1,535 @@
+// 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 'dart:io';
+
+import 'package:analysis_server/src/edit/fix/fix_code_task.dart';
+import 'package:analysis_server/src/edit/fix/non_nullable_fix.dart';
+import 'package:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/file_system/file_system.dart' show ResourceProvider;
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/util/sdk.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:args/args.dart';
+import 'package:cli_util/cli_logging.dart';
+import 'package:meta/meta.dart';
+import 'package:nnbd_migration/api_for_analysis_server/dartfix_listener_interface.dart';
+import 'package:nnbd_migration/api_for_analysis_server/driver_provider.dart';
+import 'package:path/path.dart' show Context;
+
+String _pluralize(int count, String single, {String multiple}) {
+  return count == 1 ? single : (multiple ?? '${single}s');
+}
+
+/// Data structure recording command-line options for the migration tool that
+/// have been passed in by the client.
+@visibleForTesting
+class CommandLineOptions {
+  static const applyChangesFlag = 'apply-changes';
+  static const helpFlag = 'help';
+  static const previewPortOption = 'preview-port';
+  static const sdkPathOption = 'sdk-path';
+  static const verboseFlag = 'verbose';
+  static const webPreviewFlag = 'web-preview';
+
+  final bool applyChanges;
+
+  final String directory;
+
+  final int previewPort;
+
+  final String sdkPath;
+
+  final bool webPreview;
+
+  CommandLineOptions(
+      {@required this.applyChanges,
+      @required this.directory,
+      @required this.previewPort,
+      @required this.sdkPath,
+      @required this.webPreview});
+}
+
+/// Command-line API for the migration tool, with additional methods exposed for
+/// testing.
+class MigrationCli {
+  /// The name of the executable, for reporting in help messages.
+  final String binaryName;
+
+  /// The SDK path that should be used if none is provided by the user.  Used in
+  /// testing to install a mock SDK.
+  final String defaultSdkPathOverride;
+
+  /// Factory to create an appropriate Logger instance to give feedback to the
+  /// user.  Used in testing to allow user feedback messages to be tested.
+  final Logger Function(bool isVerbose) loggerFactory;
+
+  /// Resource provider that should be used to access the filesystem.  Used in
+  /// testing to redirect to an in-memory filesystem.
+  final ResourceProvider resourceProvider;
+
+  /// Logger instance we use to give feedback to the user.
+  Logger logger;
+
+  /// The result of parsing command-line options.
+  @visibleForTesting
+  /*late*/ CommandLineOptions options;
+
+  /// The exit code that should be used when the process terminates, or `null`
+  /// if there is still more work to do.
+  int exitCode;
+
+  MigrationCli(
+      {@required this.binaryName,
+      @visibleForTesting this.loggerFactory = _defaultLoggerFactory,
+      @visibleForTesting this.defaultSdkPathOverride,
+      @visibleForTesting ResourceProvider resourceProvider})
+      : logger = loggerFactory(false),
+        resourceProvider =
+            resourceProvider ?? PhysicalResourceProvider.INSTANCE;
+
+  Ansi get ansi => logger.ansi;
+
+  Context get pathContext => resourceProvider.pathContext;
+
+  /// Blocks until an interrupt signal (control-C) is received.  Tests may
+  /// override this method to simulate control-C.
+  @visibleForTesting
+  Future<void> blockUntilSignalInterrupt() {
+    Stream<ProcessSignal> stream = ProcessSignal.sigint.watch();
+    return stream.first;
+  }
+
+  /// Parses and validates command-line arguments, and stores the results in
+  /// [options].
+  ///
+  /// If no additional work should be done (e.g. because the user asked for
+  /// help, or supplied a bad option), a nonzero value is stored in [exitCode].
+  @visibleForTesting
+  void parseCommandLineArgs(List<String> args) {
+    try {
+      var argResults = _createParser().parse(args);
+      var isVerbose = argResults[CommandLineOptions.verboseFlag] as bool;
+      if (argResults[CommandLineOptions.helpFlag] as bool) {
+        _showUsage(isVerbose);
+        exitCode = 0;
+        return;
+      }
+      var rest = argResults.rest;
+      String migratePath;
+      if (rest.isEmpty) {
+        migratePath = Directory.current.path;
+      } else if (rest.length > 1) {
+        throw _BadArgException('No more than one path may be specified.');
+      } else {
+        migratePath = rest[0];
+      }
+      var applyChanges =
+          argResults[CommandLineOptions.applyChangesFlag] as bool;
+      var previewPortRaw =
+          argResults[CommandLineOptions.previewPortOption] as String;
+      int previewPort;
+      try {
+        previewPort = previewPortRaw == null ? null : int.parse(previewPortRaw);
+      } on FormatException catch (_) {
+        throw _BadArgException(
+            'Invalid value for --${CommandLineOptions.previewPortOption}');
+      }
+      var webPreview = argResults[CommandLineOptions.webPreviewFlag] as bool;
+      if (applyChanges && webPreview) {
+        throw _BadArgException('--apply-changes requires --no-web-preview');
+      }
+      options = CommandLineOptions(
+          applyChanges: applyChanges,
+          directory: migratePath,
+          previewPort: previewPort,
+          sdkPath: argResults[CommandLineOptions.sdkPathOption] as String ??
+              defaultSdkPathOverride ??
+              getSdkPath(),
+          webPreview: webPreview);
+      if (isVerbose) {
+        logger = loggerFactory(true);
+      }
+    } on Object catch (exception) {
+      String message;
+      if (exception is FormatException) {
+        message = exception.message;
+      } else if (exception is _BadArgException) {
+        message = exception.message;
+      } else {
+        message =
+            'Exception occurred while parsing command-line options: $exception';
+      }
+      logger.stderr(message);
+      _showUsage(false);
+      exitCode = 1;
+      return;
+    }
+  }
+
+  /// Runs the full migration process.
+  void run(List<String> args) async {
+    parseCommandLineArgs(args);
+    if (exitCode != null) return;
+
+    // TODO(paulberry): if debugging, create instrumentation log
+
+    logger.stdout('Migrating ${options.directory}');
+    logger.stdout('');
+
+    // TODO(paulberry): analyze project and report about any errors found
+
+    List<String> previewUrls;
+    NonNullableFix nonNullableFix;
+    _DartFixListener dartFixListener;
+    await _withProgress(
+        '${ansi.emphasized('Generating migration suggestions')}', () async {
+      var contextCollection = AnalysisContextCollectionImpl(
+          includedPaths: [options.directory],
+          resourceProvider: resourceProvider,
+          sdkPath: options.sdkPath);
+      var context = contextCollection.contexts.single;
+      var fixCodeProcessor = _FixCodeProcessor(context);
+      dartFixListener = _DartFixListener(
+          _DriverProvider(resourceProvider, context.currentSession));
+      nonNullableFix = NonNullableFix(dartFixListener,
+          included: [options.directory],
+          preferredPort: options.previewPort,
+          enablePreview: options.webPreview);
+      fixCodeProcessor.registerCodeTask(nonNullableFix);
+      previewUrls = await fixCodeProcessor.run();
+    });
+
+    if (options.applyChanges) {
+      logger.stdout(ansi.emphasized('Applying changes:'));
+
+      var allEdits = dartFixListener.sourceChange.edits;
+      _applyMigrationSuggestions(allEdits);
+
+      logger.stdout('');
+      logger.stdout(
+          'Applied ${allEdits.length} ${_pluralize(allEdits.length, 'edit')}.');
+
+      // Note: do not open the web preview if apply-changes is specified, as we
+      // currently cannot tell the web preview to disable the "apply migration"
+      // button.
+      exitCode = 0;
+      return;
+    }
+
+    if (options.webPreview) {
+      String url = previewUrls.first;
+      assert(previewUrls.length <= 1,
+          'Got unexpected extra preview URLs from server');
+
+      logger.stdout(ansi.emphasized('View migration results:'));
+
+      // TODO(devoncarew): Open a browser automatically.
+      logger.stdout('''
+Visit:
+  
+  ${ansi.emphasized(url)}
+
+to see the migration results. Use the interactive web view to review, improve, or apply
+the results (alternatively, to apply the results without using the web preview, re-run
+the tool with --${CommandLineOptions.applyChangesFlag}).
+''');
+
+      logger.stdout('When finished with the preview, hit ctrl-c '
+          'to terminate this process.');
+
+      // Block until sigint (ctrl-c).
+      await blockUntilSignalInterrupt();
+      nonNullableFix.shutdownServer();
+    } else {
+      logger.stdout(ansi.emphasized('Summary of changes:'));
+
+      _displayChangeSummary(dartFixListener);
+
+      logger.stdout('');
+      logger.stdout('To apply these changes, re-run the tool with '
+          '--${CommandLineOptions.applyChangesFlag}.');
+    }
+    exitCode = 0;
+  }
+
+  /// Perform the indicated source edits to the given source, returning the
+  /// resulting transformed text.
+  String _applyEdits(SourceFileEdit sourceFileEdit, String source) {
+    List<SourceEdit> edits = _sortEdits(sourceFileEdit);
+    return SourceEdit.applySequence(source, edits);
+  }
+
+  void _applyMigrationSuggestions(List<SourceFileEdit> edits) {
+    // Apply the changes to disk.
+    for (SourceFileEdit sourceFileEdit in edits) {
+      String relPath =
+          pathContext.relative(sourceFileEdit.file, from: options.directory);
+      int count = sourceFileEdit.edits.length;
+      logger.stdout('  $relPath ($count ${_pluralize(count, 'change')})');
+
+      String source;
+      var file = resourceProvider.getFile(sourceFileEdit.file);
+      try {
+        source = file.readAsStringSync();
+      } catch (_) {}
+
+      if (source == null) {
+        logger.stdout('    Unable to retrieve source for file.');
+      } else {
+        source = _applyEdits(sourceFileEdit, source);
+
+        try {
+          file.writeAsStringSync(source);
+        } catch (e) {
+          logger.stdout('    Unable to write source for file: $e');
+        }
+      }
+    }
+  }
+
+  ArgParser _createParser({bool hide = true}) {
+    var parser = ArgParser();
+    parser.addFlag(CommandLineOptions.applyChangesFlag,
+        defaultsTo: false,
+        negatable: false,
+        help: 'Apply the proposed null safety changes to the files on disk.');
+    parser.addFlag(CommandLineOptions.helpFlag,
+        abbr: 'h',
+        help:
+            'Display this help message. Add --verbose to show hidden options.',
+        defaultsTo: false,
+        negatable: false);
+    parser.addOption(CommandLineOptions.previewPortOption,
+        help:
+            'Run the preview server on the specified port.  If not specified, '
+            'dynamically allocate a port.');
+    parser.addOption(CommandLineOptions.sdkPathOption,
+        help: 'The path to the Dart SDK.', hide: hide);
+    parser.addFlag(CommandLineOptions.verboseFlag,
+        abbr: 'v',
+        defaultsTo: false,
+        help: 'Verbose output.',
+        negatable: false);
+    parser.addFlag(CommandLineOptions.webPreviewFlag,
+        defaultsTo: true,
+        negatable: true,
+        help: 'Show an interactive preview of the proposed null safety changes '
+            'in a browser window.\n'
+            'With --no-web-preview, the proposed changes are instead printed to '
+            'the console.');
+    return parser;
+  }
+
+  void _displayChangeSummary(_DartFixListener migrationResults) {
+    Map<String, List<_DartFixSuggestion>> fileSuggestions = {};
+    for (_DartFixSuggestion suggestion in migrationResults.suggestions) {
+      String file = suggestion.location.file;
+      fileSuggestions.putIfAbsent(file, () => <_DartFixSuggestion>[]);
+      fileSuggestions[file].add(suggestion);
+    }
+
+    // present a diff-like view
+    for (SourceFileEdit sourceFileEdit in migrationResults.sourceChange.edits) {
+      String file = sourceFileEdit.file;
+      String relPath = pathContext.relative(file, from: options.directory);
+      int count = sourceFileEdit.edits.length;
+
+      logger.stdout('');
+      logger.stdout('${ansi.emphasized(relPath)} '
+          '($count ${_pluralize(count, 'change')}):');
+
+      String source;
+      try {
+        source = resourceProvider.getFile(file).readAsStringSync();
+      } catch (_) {}
+
+      if (source == null) {
+        logger.stdout('  (unable to retrieve source for file)');
+      } else {
+        // TODO(paulberry): implement this
+        logger.stdout('  (diff view not yet functional)');
+      }
+    }
+  }
+
+  void _showUsage(bool isVerbose) {
+    logger.stderr('Usage: $binaryName [options...] [<package directory>]');
+
+    logger.stderr('');
+    logger.stderr(_createParser(hide: !isVerbose).usage);
+    if (!isVerbose) {
+      logger.stderr('');
+      logger
+          .stderr('Run "$binaryName -h -v" for verbose help output, including '
+              'less commonly used options.');
+    }
+  }
+
+  List<SourceEdit> _sortEdits(SourceFileEdit sourceFileEdit) {
+    // Sort edits in reverse offset order.
+    List<SourceEdit> edits = sourceFileEdit.edits.toList();
+    edits.sort((a, b) {
+      return b.offset - a.offset;
+    });
+    return edits;
+  }
+
+  Future<void> _withProgress(String message, FutureOr<void> callback()) async {
+    var progress = logger.progress(message);
+    try {
+      await callback();
+      progress.finish(showTiming: true);
+    } finally {
+      progress.cancel();
+    }
+  }
+
+  static Logger _defaultLoggerFactory(bool isVerbose) {
+    var ansi = Ansi(Ansi.terminalSupportsAnsi);
+    if (isVerbose) {
+      return Logger.verbose(ansi: ansi);
+    } else {
+      return Logger.standard(ansi: ansi);
+    }
+  }
+}
+
+class _BadArgException implements Exception {
+  final String message;
+
+  _BadArgException(this.message);
+}
+
+class _DartFixListener implements DartFixListenerInterface {
+  @override
+  final DriverProvider server;
+
+  @override
+  final SourceChange sourceChange = SourceChange('null safety migration');
+
+  final List<_DartFixSuggestion> suggestions = [];
+
+  _DartFixListener(this.server);
+
+  @override
+  void addDetail(String detail) {
+    throw UnimplementedError('TODO(paulberry)');
+  }
+
+  @override
+  void addEditWithoutSuggestion(Source source, SourceEdit edit) {
+    sourceChange.addEdit(source.fullName, -1, edit);
+  }
+
+  @override
+  void addRecommendation(String description, [Location location]) {
+    throw UnimplementedError('TODO(paulberry)');
+  }
+
+  @override
+  void addSourceFileEdit(
+      String description, Location location, SourceFileEdit fileEdit) {
+    throw UnimplementedError('TODO(paulberry)');
+  }
+
+  @override
+  void addSuggestion(String description, Location location) {
+    suggestions.add(_DartFixSuggestion(description, location: location));
+  }
+}
+
+class _DartFixSuggestion {
+  final String description;
+
+  final Location location;
+
+  _DartFixSuggestion(this.description, {@required this.location});
+}
+
+class _DriverProvider implements DriverProvider {
+  @override
+  final ResourceProvider resourceProvider;
+
+  final AnalysisSession analysisSession;
+
+  _DriverProvider(this.resourceProvider, this.analysisSession);
+
+  @override
+  AnalysisSession getAnalysisSession(String path) => analysisSession;
+}
+
+class _FixCodeProcessor extends Object with FixCodeProcessor {
+  final AnalysisContext context;
+
+  final Set<String> pathsToProcess;
+
+  _FixCodeProcessor(this.context)
+      : pathsToProcess = context.contextRoot
+            .analyzedFiles()
+            .where((s) => s.endsWith('.dart'))
+            .toSet();
+
+  /// Call the supplied [process] function to process each compilation unit.
+  Future processResources(
+      Future<void> Function(ResolvedUnitResult result) process) async {
+    var driver = context.currentSession;
+    var pathsProcessed = <String>{};
+    for (var path in pathsToProcess) {
+      if (pathsProcessed.contains(path)) continue;
+      switch (await driver.getSourceKind(path)) {
+        case SourceKind.PART:
+          // Parts will either be found in a library, below, or if the library
+          // isn't [isIncluded], will be picked up in the final loop.
+          continue;
+          break;
+        case SourceKind.LIBRARY:
+          var result = await driver.getResolvedLibrary(path);
+          if (result != null) {
+            for (var unit in result.units) {
+              if (pathsToProcess.contains(unit.path) &&
+                  !pathsProcessed.contains(unit.path)) {
+                await process(unit);
+                pathsProcessed.add(unit.path);
+              }
+            }
+          }
+          break;
+        default:
+          break;
+      }
+    }
+
+    for (var path in pathsToProcess.difference(pathsProcessed)) {
+      var result = await driver.getResolvedUnit(path);
+      if (result == null || result.unit == null) {
+        continue;
+      }
+      await process(result);
+    }
+  }
+
+  Future<List<String>> run() async {
+    // TODO(paulberry): do more things from EditDartFix.runAllTasks
+    await processResources((ResolvedUnitResult result) async {
+      // TODO(paulberry): check for errors
+      if (numPhases > 0) {
+        await processCodeTasks(0, result);
+      }
+    });
+    for (var phase = 1; phase < numPhases; phase++) {
+      await processResources((ResolvedUnitResult result) async {
+        await processCodeTasks(phase, result);
+      });
+    }
+    await finishCodeTasks();
+
+    return nonNullableFixTask.previewUrls;
+  }
+}
diff --git a/pkg/nnbd_migration/lib/src/decorated_type_operations.dart b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
index f69f365..323d579 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
@@ -20,6 +20,12 @@
       this._typeSystem, this._variableRepository, this._graph);
 
   @override
+  DecoratedType factor(DecoratedType from, DecoratedType what) {
+    // TODO(scheglov): https://github.com/dart-lang/sdk/issues/41672
+    return from;
+  }
+
+  @override
   bool isSameType(DecoratedType type1, DecoratedType type2) {
     return type1 == type2;
   }
diff --git a/pkg/nnbd_migration/test/migration_cli_test.dart b/pkg/nnbd_migration/test/migration_cli_test.dart
new file mode 100644
index 0000000..a841013
--- /dev/null
+++ b/pkg/nnbd_migration/test/migration_cli_test.dart
@@ -0,0 +1,337 @@
+// 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 'dart:io';
+
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/test_utilities/mock_sdk.dart' as mock_sdk;
+import 'package:cli_util/cli_logging.dart';
+import 'package:http/http.dart' as http;
+import 'package:meta/meta.dart';
+import 'package:nnbd_migration/migration_cli.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(_MigrationCliTest);
+  });
+}
+
+class _MigrationCli extends MigrationCli {
+  Completer<void> _previewServerStartedCompleter;
+
+  Completer<void> _signalInterruptCompleter;
+
+  _MigrationCli(_MigrationCliTest test)
+      : super(
+            binaryName: 'nnbd_migration',
+            loggerFactory: (isVerbose) => test.logger = _TestLogger(isVerbose),
+            defaultSdkPathOverride: mock_sdk.sdkRoot,
+            resourceProvider: test.resourceProvider);
+
+  @override
+  Future<void> blockUntilSignalInterrupt() {
+    _previewServerStartedCompleter.complete();
+    _signalInterruptCompleter = Completer<void>();
+    return _signalInterruptCompleter.future;
+  }
+
+  Future<void> runWithPreviewServer(
+      List<String> args, Future<void> callback()) async {
+    _previewServerStartedCompleter = Completer<void>();
+    var done = run(args);
+    await _previewServerStartedCompleter.future;
+    await callback();
+    _signalInterruptCompleter.complete();
+    return done;
+  }
+}
+
+@reflectiveTest
+class _MigrationCliTest {
+  /*late*/ _TestLogger logger;
+
+  final hasVerboseHelpMessage = contains('for verbose help output');
+
+  final hasUsageText = contains('Usage: nnbd_migration');
+
+  final resourceProvider = MemoryResourceProvider();
+
+  String assertErrorExit(MigrationCli cli) {
+    expect(cli.exitCode, isNotNull);
+    expect(cli.exitCode, isNot(0));
+    var stderrText = logger.stderrBuffer.toString();
+    expect(stderrText, hasUsageText);
+    expect(stderrText, hasVerboseHelpMessage);
+    return stderrText;
+  }
+
+  Future<String> assertParseArgsFailure(List<String> args) async {
+    var cli = _createCli();
+    await cli.run(args);
+    var stderrText = assertErrorExit(cli);
+    expect(stderrText, isNot(contains('Exception')));
+    return stderrText;
+  }
+
+  CommandLineOptions assertParseArgsSuccess(List<String> args) {
+    var cli = _createCli();
+    cli.parseCommandLineArgs(args);
+    expect(cli.exitCode, isNull);
+    var options = cli.options;
+    return options;
+  }
+
+  void assertProjectContents(String projectDir, Map<String, String> expected) {
+    for (var entry in expected.entries) {
+      var relativePathPosix = entry.key;
+      assert(!path.posix.isAbsolute(relativePathPosix));
+      var filePath = resourceProvider.pathContext
+          .join(projectDir, resourceProvider.convertPath(relativePathPosix));
+      expect(
+          resourceProvider.getFile(filePath).readAsStringSync(), entry.value);
+    }
+  }
+
+  String createProjectDir(Map<String, String> contents) {
+    var projectPathPosix = '/test_project';
+    for (var entry in contents.entries) {
+      var relativePathPosix = entry.key;
+      assert(!path.posix.isAbsolute(relativePathPosix));
+      var filePathPosix = path.posix.join(projectPathPosix, relativePathPosix);
+      resourceProvider.newFile(
+          resourceProvider.convertPath(filePathPosix), entry.value);
+    }
+    return resourceProvider.convertPath(projectPathPosix);
+  }
+
+  Map<String, String> simpleProject({bool migrated: false}) {
+    // TODO(paulberry): pubspec needs to be updated when migrating.
+    return {
+      'pubspec.yaml': '''
+name: test
+environment:
+sdk: '>=2.6.0 <3.0.0'
+''',
+      'lib/test.dart': '''
+int${migrated ? '?' : ''} f() => null;
+'''
+    };
+  }
+
+  test_default_logger() {
+    // When running normally, we don't override the logger; make sure it has a
+    // non-null default so that there won't be a crash.
+    expect(MigrationCli(binaryName: 'nnbd_migration').logger, isNotNull);
+  }
+
+  test_flag_apply_changes_default() {
+    expect(assertParseArgsSuccess([]).applyChanges, isFalse);
+  }
+
+  test_flag_apply_changes_disable() async {
+    // "--no-apply-changes" is not an option.
+    await assertParseArgsFailure(['--no-apply-changes']);
+  }
+
+  test_flag_apply_changes_enable() {
+    expect(
+        assertParseArgsSuccess(['--no-web-preview', '--apply-changes'])
+            .applyChanges,
+        isTrue);
+  }
+
+  test_flag_apply_changes_incompatible_with_web_preview() async {
+    expect(await assertParseArgsFailure(['--web-preview', '--apply-changes']),
+        contains('--apply-changes requires --no-web-preview'));
+  }
+
+  test_flag_help() async {
+    var helpText = await _getHelpText(verbose: false);
+    expect(helpText, hasUsageText);
+    expect(helpText, hasVerboseHelpMessage);
+  }
+
+  test_flag_help_verbose() async {
+    var helpText = await _getHelpText(verbose: true);
+    expect(helpText, hasUsageText);
+    expect(helpText, isNot(hasVerboseHelpMessage));
+  }
+
+  test_flag_web_preview_default() {
+    expect(assertParseArgsSuccess([]).webPreview, isTrue);
+  }
+
+  test_flag_web_preview_disable() {
+    expect(assertParseArgsSuccess(['--no-web-preview']).webPreview, isFalse);
+  }
+
+  test_flag_web_preview_enable() {
+    expect(assertParseArgsSuccess(['--web-preview']).webPreview, isTrue);
+  }
+
+  test_lifecycle_apply_changes() async {
+    var projectContents = simpleProject();
+    var projectDir = await createProjectDir(projectContents);
+    var cli = _createCli();
+    await cli.run(['--no-web-preview', '--apply-changes', projectDir]);
+    // Check that a summary was printed
+    expect(logger.stdoutBuffer.toString(), contains('Applying changes'));
+    // And that it refers to test.dart
+    expect(logger.stdoutBuffer.toString(), contains('test.dart'));
+    // And that it does not tell the user they can rerun with `--apply-changes`
+    expect(logger.stdoutBuffer.toString(), isNot(contains('--apply-changes')));
+    // Changes should have been made
+    assertProjectContents(projectDir, simpleProject(migrated: true));
+  }
+
+  test_lifecycle_no_preview() async {
+    var projectContents = simpleProject();
+    var projectDir = await createProjectDir(projectContents);
+    var cli = _createCli();
+    await cli.run(['--no-web-preview', projectDir]);
+    // Check that a summary was printed
+    expect(logger.stdoutBuffer.toString(), contains('Summary'));
+    // And that it refers to test.dart
+    expect(logger.stdoutBuffer.toString(), contains('test.dart'));
+    // And that it tells the user they can rerun with `--apply-changes`
+    expect(logger.stdoutBuffer.toString(), contains('--apply-changes'));
+    // No changes should have been made
+    assertProjectContents(projectDir, projectContents);
+  }
+
+  test_lifecycle_preview() async {
+    var projectContents = simpleProject();
+    var projectDir = await createProjectDir(projectContents);
+    var cli = _createCli();
+    String url;
+    await cli.runWithPreviewServer([projectDir], () async {
+      // Server should be running now
+      url = RegExp('http://.*', multiLine: true)
+          .stringMatch(logger.stdoutBuffer.toString());
+      var response = await http.get(url);
+      expect(response.statusCode, 200);
+    });
+    // Server should be stopped now
+    expect(http.get(url), throwsA(anything));
+    // And no changes should have been made.
+    assertProjectContents(projectDir, projectContents);
+  }
+
+  test_migrate_path_none() {
+    expect(assertParseArgsSuccess([]).directory, Directory.current.path);
+  }
+
+  test_migrate_path_one() {
+    expect(assertParseArgsSuccess(['foo']).directory, 'foo');
+  }
+
+  test_migrate_path_two() async {
+    var cli = _createCli();
+    await cli.run(['foo', 'bar']);
+    var stderrText = assertErrorExit(cli);
+    expect(stderrText, contains('No more than one path may be specified'));
+  }
+
+  test_option_preview_port() {
+    expect(
+        assertParseArgsSuccess(['--preview-port', '4040']).previewPort, 4040);
+  }
+
+  test_option_preview_port_default() {
+    expect(assertParseArgsSuccess([]).previewPort, isNull);
+  }
+
+  test_option_preview_port_format_error() async {
+    expect(await assertParseArgsFailure(['--preview-port', 'abc']),
+        contains('Invalid value for --preview-port'));
+  }
+
+  test_option_sdk() {
+    var path = Uri.parse('file:///foo/bar/baz').toFilePath();
+    expect(assertParseArgsSuccess(['--sdk-path', path]).sdkPath, same(path));
+  }
+
+  test_option_sdk_default() {
+    var cli = MigrationCli(binaryName: 'nnbd_migration');
+    cli.parseCommandLineArgs([]);
+    expect(
+        File(path.join(cli.options.sdkPath, 'version')).existsSync(), isTrue);
+  }
+
+  test_option_sdk_hidden() async {
+    var optionName = '--sdk-path';
+    expect(await _getHelpText(verbose: false), isNot(contains(optionName)));
+    expect(await _getHelpText(verbose: true), contains(optionName));
+  }
+
+  test_option_unrecognized() async {
+    expect(
+        await assertParseArgsFailure(['--this-option-does-not-exist']),
+        contains(
+            'Could not find an option named "this-option-does-not-exist"'));
+  }
+
+  test_uses_physical_resource_provider_by_default() {
+    var cli = MigrationCli(binaryName: 'nnbd_migration');
+    expect(cli.resourceProvider, same(PhysicalResourceProvider.INSTANCE));
+  }
+
+  _MigrationCli _createCli() {
+    mock_sdk.MockSdk(resourceProvider: resourceProvider);
+    return _MigrationCli(this);
+  }
+
+  Future<String> _getHelpText({@required bool verbose}) async {
+    var cli = _createCli();
+    await cli
+        .run(['--${CommandLineOptions.helpFlag}', if (verbose) '--verbose']);
+    expect(cli.exitCode, 0);
+    var helpText = logger.stderrBuffer.toString();
+    return helpText;
+  }
+}
+
+/// TODO(paulberry): move into cli_util
+class _TestLogger implements Logger {
+  final stderrBuffer = StringBuffer();
+
+  final stdoutBuffer = StringBuffer();
+
+  final bool isVerbose;
+
+  _TestLogger(this.isVerbose);
+
+  @override
+  Ansi get ansi => Ansi(false);
+
+  @override
+  void flush() {
+    throw UnimplementedError('TODO(paulberry)');
+  }
+
+  @override
+  Progress progress(String message) {
+    return SimpleProgress(this, message);
+  }
+
+  @override
+  void stderr(String message) {
+    stderrBuffer.writeln(message);
+  }
+
+  @override
+  void stdout(String message) {
+    stdoutBuffer.writeln(message);
+  }
+
+  @override
+  void trace(String message) {
+    throw UnimplementedError('TODO(paulberry)');
+  }
+}
diff --git a/pkg/vm/pubspec.yaml b/pkg/vm/pubspec.yaml
index ef74ee0..27d6379 100644
--- a/pkg/vm/pubspec.yaml
+++ b/pkg/vm/pubspec.yaml
@@ -3,6 +3,9 @@
 # version: do-not-upload
 description: VM specific Dart code and helper scripts
 
+environment:
+  sdk: "^2.7.0"
+
 dependencies:
   build_integration:
     path: ../build_integration
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index 8c81f4d..b78c771 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -625,8 +625,13 @@
 Bytecode {
   Entry                2
   CheckFunctionTypeArgs 1, r0
+  JumpIfNotZeroTypeArgs L1
+  Push                 FP[-8]
+  LoadTypeArgumentsField CP#0
+  PopLocal             r0
+L1:
   CheckStack           0
-  JumpIfUnchecked      L1
+  JumpIfUnchecked      L2
   Push                 FP[-8]
   LoadTypeArgumentsField CP#0
   Push                 r0
@@ -642,7 +647,7 @@
   PushConstant         CP#4
   AssertAssignable     0, CP#5
   Drop1
-L1:
+L2:
   Push                 FP[-6]
   PushConstant         CP#6
   PushNull
@@ -660,6 +665,7 @@
 }
 Parameter flags: [0, 1, 2]
 Forwarding stub target: CP#11
+Default function type arguments: CP#12
 ConstantPool {
   [0] = TypeArgumentsField #lib::H
   [1] = Type #lib::H::foo7::TypeParam/0
@@ -673,6 +679,7 @@
   [9] = DirectCall '#lib::G::foo7', ArgDesc num-args 4, num-type-args 1, names []
   [10] = Reserved
   [11] = ObjectRef #lib::G::foo7
+  [12] = ObjectRef < #lib::H::TypeParam/0 >
 }
 
 
@@ -745,7 +752,7 @@
       : super #lib::G::•()
       ;
     method foo8<generic-covariant-impl Q extends #lib::H::T* = #lib::H::T*>(#lib::H::foo8::Q* a, covariant dart.core::int* b, generic-covariant-impl #lib::H::T* c) → void {}
-    forwarding-stub method foo7<generic-covariant-impl Q extends #lib::H::T*>(#lib::H::foo7::Q* a, covariant dart.core::num* b, generic-covariant-impl #lib::H::T* c) → void
+    forwarding-stub method foo7<generic-covariant-impl Q extends #lib::H::T* = #lib::H::T*>(#lib::H::foo7::Q* a, covariant dart.core::num* b, generic-covariant-impl #lib::H::T* c) → void
       return super.{#lib::G::foo7}<#lib::H::foo7::Q*>(a, b, c);
   }
   static field dart.core::List<dart.core::Iterable<dynamic>*>* globalVar;
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index a1845c0..0f04e7d 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -442,10 +442,11 @@
 
   // Get the script name.
   if (i < argc) {
-    // If the script name isn't a valid file or a URL, this might be a DartDev
-    // command. Try to find the DartDev snapshot so we can forward the command
-    // and its arguments.
-    if (!DartDevUtils::ShouldParseCommand(argv[i])) {
+    if (Options::disable_dart_dev() ||
+        !DartDevUtils::ShouldParseCommand(argv[i])) {
+      // If the script name isn't a valid file or a URL, this might be a DartDev
+      // command. Try to find the DartDev snapshot so we can forward the command
+      // and its arguments.
       *script_name = strdup(argv[i]);
       i++;
     } else if (!DartDevUtils::TryResolveDartDevSnapshotPath(script_name)) {
@@ -454,6 +455,13 @@
           argv[i]);
       Platform::Exit(kErrorExitCode);
     }
+  } else if (!Options::disable_dart_dev() &&
+             ((Options::help_option() && !Options::verbose_option()) ||
+              (argc == 1)) &&
+             DartDevUtils::TryResolveDartDevSnapshotPath(script_name)) {
+    // Let DartDev handle the default help message.
+    dart_options->AddArgument("help");
+    return 0;
   } else {
     return -1;
   }
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 3fe9f74..6493349 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -46,7 +46,8 @@
   V(disable_exit, exit_disabled)                                               \
   V(preview_dart_2, nop_option)                                                \
   V(suppress_core_dump, suppress_core_dump)                                    \
-  V(enable_service_port_fallback, enable_service_port_fallback)
+  V(enable_service_port_fallback, enable_service_port_fallback)                \
+  V(disable_dart_dev, disable_dart_dev)
 
 // Boolean flags that have a short form.
 #define SHORT_BOOL_OPTIONS_LIST(V)                                             \
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 5648867..f2264a3 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -9,6 +9,7 @@
 
 #include <process.h>  // NOLINT
 #include <psapi.h>    // NOLINT
+#include <vector>
 
 #include "bin/builtin.h"
 #include "bin/dartutils.h"
@@ -531,14 +532,13 @@
         if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) {
           return CleanupAndReturnError();
         }
-        static const int kNumInheritedHandles = 3;
-        HANDLE inherited_handles[kNumInheritedHandles] = {
-            stdin_handles_[kReadHandle], stdout_handles_[kWriteHandle],
-            stderr_handles_[kWriteHandle]};
+        inherited_handles_ = {stdin_handles_[kReadHandle],
+                              stdout_handles_[kWriteHandle],
+                              stderr_handles_[kWriteHandle]};
         if (!update_proc_thread_attr(
                 attribute_list_, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
-                inherited_handles, kNumInheritedHandles * sizeof(HANDLE), NULL,
-                NULL)) {
+                inherited_handles_.data(),
+                inherited_handles_.size() * sizeof(HANDLE), NULL, NULL)) {
           return CleanupAndReturnError();
         }
         startup_info.lpAttributeList = attribute_list_;
@@ -664,6 +664,7 @@
   const wchar_t* system_working_directory_;
   wchar_t* command_line_;
   wchar_t* environment_block_;
+  std::vector<HANDLE> inherited_handles_;
   LPPROC_THREAD_ATTRIBUTE_LIST attribute_list_;
 
   const char* path_;
diff --git a/runtime/observatory/tests/service/observatory_test_package/pubspec.yaml b/runtime/observatory/tests/service/observatory_test_package/pubspec.yaml
new file mode 100644
index 0000000..db61a01f
--- /dev/null
+++ b/runtime/observatory/tests/service/observatory_test_package/pubspec.yaml
@@ -0,0 +1,4 @@
+name: observatory_test_package
+publish_to: none
+environment:
+  sdk: '^2.7.0'
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 0d3d961..026478e 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -30,8 +30,8 @@
 rewind_test: SkipByDesign # No incremental compiler available.
 
 [ $compiler == dartkp ]
-add_breakpoint_rpc_kernel_test: RuntimeError
-async_generator_breakpoint_test: RuntimeError
+add_breakpoint_rpc_kernel_test: SkipByDesign
+async_generator_breakpoint_test: SkipByDesign
 async_next_regession_18877_test: Skip, Timeout
 async_next_test: Skip, Timeout
 async_scope_test: Skip, Timeout
@@ -43,49 +43,49 @@
 async_step_out_test: Skip, Timeout
 awaiter_async_stack_contents_2_test: Skip, Timeout
 awaiter_async_stack_contents_test: Skip, Timeout
-bad_reload_test: RuntimeError
-break_on_activation_test: RuntimeError
+bad_reload_test: SkipByDesign
+break_on_activation_test: SkipByDesign
 break_on_async_function_test: Skip, Timeout
-break_on_default_constructor_test: RuntimeError
+break_on_default_constructor_test: SkipByDesign
 break_on_function_test: Skip, Timeout
-breakpoint_async_break_test: RuntimeError
-breakpoint_in_package_parts_class_file_uri_test: RuntimeError
-breakpoint_in_package_parts_class_test: RuntimeError
-breakpoint_in_parts_class_test: RuntimeError
-breakpoint_non_debuggable_library_test: RuntimeError
-breakpoint_on_if_null_1_test: RuntimeError
-breakpoint_on_if_null_2_test: RuntimeError
-breakpoint_on_if_null_3_test: RuntimeError
-breakpoint_on_if_null_4_test: RuntimeError
-breakpoint_partfile_test: RuntimeError
+breakpoint_async_break_test: SkipByDesign
+breakpoint_in_package_parts_class_file_uri_test: SkipByDesign
+breakpoint_in_package_parts_class_test: SkipByDesign
+breakpoint_in_parts_class_test: SkipByDesign
+breakpoint_non_debuggable_library_test: SkipByDesign
+breakpoint_on_if_null_1_test: SkipByDesign
+breakpoint_on_if_null_2_test: SkipByDesign
+breakpoint_on_if_null_3_test: SkipByDesign
+breakpoint_on_if_null_4_test: SkipByDesign
+breakpoint_partfile_test: SkipByDesign
 breakpoint_two_args_checked_test: Skip, Timeout
-breakpoints_with_mixin_test: RuntimeError # Debugger is disabled in AOT mode.
+breakpoints_with_mixin_test: SkipByDesign # Debugger is disabled in AOT mode.
 capture_stdio_test: Skip, Timeout
 causal_async_stack_contents_test: Skip, Timeout
 causal_async_stack_presence_test: Skip, Timeout
 causal_async_star_stack_contents_test: Skip, Timeout
 causal_async_star_stack_presence_test: Skip, Timeout
-client_resume_approvals_reload_test: RuntimeError # Compiler is disabled in AOT mode.
-code_test: RuntimeError
-column_breakpoint_test: RuntimeError
-complex_reload_test: RuntimeError
+client_resume_approvals_reload_test: SkipByDesign # Compiler is disabled in AOT mode.
+code_test: SkipByDesign
+column_breakpoint_test: SkipByDesign
+complex_reload_test: SkipByDesign
 coverage_const_field_async_closure_test: Skip, Timeout
 coverage_leaf_function_test: Skip, Timeout
 coverage_optimized_function_test: Skip, Timeout
-debugger_inspect_test: RuntimeError
+debugger_inspect_test: SkipByDesign
 debugger_location_second_test: Skip, Timeout
 debugger_location_test: Skip, Timeout
 debugging_inlined_finally_test: Skip, Timeout
-debugging_test: RuntimeError
-dev_fs_spawn_test: RuntimeError
+debugging_test: SkipByDesign
+dev_fs_spawn_test: SkipByDesign
 developer_extension_test: Skip, Timeout
 developer_service_get_isolate_id_test: Skip, Timeout
-eval_internal_class_test: RuntimeError
+eval_internal_class_test: SkipByDesign
 eval_regression_flutter20255_test: Skip, Timeout
 eval_test: Skip, Timeout
 evaluate_activation_in_method_class_test: Skip, Timeout
-evaluate_activation_test: RuntimeError
-evaluate_async_closure_test: RuntimeError
+evaluate_activation_test: SkipByDesign
+evaluate_async_closure_test: SkipByDesign
 evaluate_class_type_parameters_test: Skip, Timeout
 evaluate_function_type_parameters_test: Skip, Timeout
 evaluate_in_async_activation_test: Skip, Timeout
@@ -93,22 +93,22 @@
 evaluate_in_frame_rpc_test: Skip, Timeout
 evaluate_in_frame_with_scope_test: Skip, Timeout
 evaluate_in_sync_star_activation_test: Skip, Timeout
-evaluate_with_escaping_closure_test: RuntimeError
-evaluate_with_scope_test: RuntimeError
-field_script_test: RuntimeError
+evaluate_with_escaping_closure_test: SkipByDesign
+evaluate_with_scope_test: SkipByDesign
+field_script_test: SkipByDesign
 get_allocation_samples_test: Skip, Timeout
 get_isolate_after_language_error_test: CompileTimeError
-get_object_rpc_test: RuntimeError
+get_object_rpc_test: SkipByDesign
 get_source_report_test: Skip, Timeout
 get_source_report_with_mixin_test: Skip, Timeout
 get_stack_rpc_test: Skip, Timeout
-implicit_getter_setter_test: RuntimeError
+implicit_getter_setter_test: SkipByDesign
 invoke_test: Skip, Timeout
-isolate_lifecycle_test: RuntimeError
-issue_25465_test: RuntimeError
+isolate_lifecycle_test: SkipByDesign
+issue_25465_test: SkipByDesign
 issue_27238_test: Skip, Timeout
 issue_27287_test: Skip, Timeout
-issue_30555_test: RuntimeError
+issue_30555_test: SkipByDesign
 kill_paused_test: Skip, Timeout
 library_dependency_test: CompileTimeError
 local_variable_declaration_test: Skip, Timeout
@@ -116,68 +116,68 @@
 mirror_references_test: CompileTimeError
 mixin_break_test: Skip, Timeout
 network_profiling_test: Skip, Timeout
-next_through_assign_call_test: RuntimeError
-next_through_assign_int_test: RuntimeError
-next_through_await_for_test: RuntimeError
-next_through_call_on_field_in_class_test: RuntimeError
-next_through_call_on_field_test: RuntimeError
-next_through_call_on_static_field_in_class_test: RuntimeError
-next_through_catch_test: RuntimeError
-next_through_closure_test: RuntimeError
-next_through_create_list_and_map_test: RuntimeError
-next_through_for_each_loop_test: RuntimeError
-next_through_for_loop_with_break_and_continue_test: RuntimeError
-next_through_function_expression_test: RuntimeError
-next_through_implicit_call_test: RuntimeError
-next_through_is_and_as_test: RuntimeError
-next_through_multi_catch_test: RuntimeError
-next_through_new_test: RuntimeError
-next_through_operator_bracket_on_super_test: RuntimeError
-next_through_operator_bracket_on_this_test: RuntimeError
-next_through_operator_bracket_test: RuntimeError
-next_through_simple_async_test: RuntimeError
-next_through_simple_async_with_returns_test: RuntimeError
-next_through_simple_linear_2_test: RuntimeError
-next_through_simple_linear_test: RuntimeError
+next_through_assign_call_test: SkipByDesign
+next_through_assign_int_test: SkipByDesign
+next_through_await_for_test: SkipByDesign
+next_through_call_on_field_in_class_test: SkipByDesign
+next_through_call_on_field_test: SkipByDesign
+next_through_call_on_static_field_in_class_test: SkipByDesign
+next_through_catch_test: SkipByDesign
+next_through_closure_test: SkipByDesign
+next_through_create_list_and_map_test: SkipByDesign
+next_through_for_each_loop_test: SkipByDesign
+next_through_for_loop_with_break_and_continue_test: SkipByDesign
+next_through_function_expression_test: SkipByDesign
+next_through_implicit_call_test: SkipByDesign
+next_through_is_and_as_test: SkipByDesign
+next_through_multi_catch_test: SkipByDesign
+next_through_new_test: SkipByDesign
+next_through_operator_bracket_on_super_test: SkipByDesign
+next_through_operator_bracket_on_this_test: SkipByDesign
+next_through_operator_bracket_test: SkipByDesign
+next_through_simple_async_test: SkipByDesign
+next_through_simple_async_with_returns_test: SkipByDesign
+next_through_simple_linear_2_test: SkipByDesign
+next_through_simple_linear_test: SkipByDesign
 parameters_in_scope_at_entry_test: Skip, Timeout
 pause_idle_isolate_test: Skip, Timeout
-pause_on_exceptions_test: RuntimeError
-pause_on_start_then_step_test: RuntimeError
-pause_on_unhandled_async_exceptions2_test: RuntimeError
-pause_on_unhandled_async_exceptions3_test: RuntimeError
-pause_on_unhandled_async_exceptions_test: RuntimeError
-pause_on_unhandled_exceptions_test: RuntimeError
+pause_on_exceptions_test: SkipByDesign
+pause_on_start_then_step_test: SkipByDesign
+pause_on_unhandled_async_exceptions2_test: SkipByDesign
+pause_on_unhandled_async_exceptions3_test: SkipByDesign
+pause_on_unhandled_async_exceptions_test: SkipByDesign
+pause_on_unhandled_exceptions_test: SkipByDesign
 positive_token_pos_test: Skip, Timeout
-regress_28443_test: RuntimeError
-regress_28980_test: RuntimeError
+regress_28443_test: SkipByDesign
+regress_28980_test: SkipByDesign
 regress_34841_test: Skip, Timeout
 reload_sources_test: Skip, Timeout
 rewind_optimized_out_test: Skip, Timeout
 rewind_test: Skip, Timeout
 set_library_debuggable_test: Skip, Timeout
-simple_reload_test: RuntimeError
-steal_breakpoint_test: RuntimeError
+simple_reload_test: SkipByDesign
+steal_breakpoint_test: SkipByDesign
 step_into_async_no_await_test: Skip, Timeout
 step_over_await_test: Skip, Timeout
-step_test: RuntimeError
-step_through_arithmetic_test: RuntimeError
-step_through_constructor_calls_test: RuntimeError
-step_through_constructor_test: RuntimeError
-step_through_for_each_sync_star_2_test: RuntimeError
-step_through_for_each_sync_star_test: RuntimeError
-step_through_function_2_test: RuntimeError
-step_through_function_test: RuntimeError
-step_through_getter_test: RuntimeError
-step_through_mixin_from_sdk_test: RuntimeError
-step_through_property_get_test: RuntimeError
-step_through_property_set_test: RuntimeError
-step_through_setter_test: RuntimeError
-step_through_switch_test: RuntimeError
-step_through_switch_with_continue_test: RuntimeError
+step_test: SkipByDesign
+step_through_arithmetic_test: SkipByDesign
+step_through_constructor_calls_test: SkipByDesign
+step_through_constructor_test: SkipByDesign
+step_through_for_each_sync_star_2_test: SkipByDesign
+step_through_for_each_sync_star_test: SkipByDesign
+step_through_function_2_test: SkipByDesign
+step_through_function_test: SkipByDesign
+step_through_getter_test: SkipByDesign
+step_through_mixin_from_sdk_test: SkipByDesign
+step_through_property_get_test: SkipByDesign
+step_through_property_set_test: SkipByDesign
+step_through_setter_test: SkipByDesign
+step_through_switch_test: SkipByDesign
+step_through_switch_with_continue_test: SkipByDesign
 valid_source_locations_test: Skip, Timeout
 vm_timeline_flags_test: Skip, Timeout
 weak_properties_test: CompileTimeError
-yield_positions_with_finally_test: RuntimeError
+yield_positions_with_finally_test: SkipByDesign
 
 [ $fasta ]
 get_isolate_after_language_error_test: CompileTimeError
diff --git a/runtime/tests/vm/dart/sendandexit_test.dart b/runtime/tests/vm/dart/sendandexit_test.dart
index cbc617e..f1fb1db 100644
--- a/runtime/tests/vm/dart/sendandexit_test.dart
+++ b/runtime/tests/vm/dart/sendandexit_test.dart
@@ -77,9 +77,32 @@
   port.close();
 }
 
+verifyExitMessageIsPostedLast() async {
+  final port = ReceivePort();
+  final inbox = new StreamIterator<dynamic>(port);
+  final isolate = await Isolate.spawn(worker, Message(port.sendPort, add),
+      onExit: port.sendPort);
+
+  final receivedData = Completer<dynamic>();
+  final isolateExited = Completer<bool>();
+  port.listen((dynamic resultData) {
+    if (receivedData.isCompleted) {
+      Expect.equals(
+          resultData, null); // exit message comes after data is receivedData
+      isolateExited.complete(true);
+    } else {
+      receivedData.complete(resultData);
+    }
+  });
+  Expect.equals(await isolateExited.future, true);
+  Expect.equals(await receivedData.future, 5);
+  port.close();
+}
+
 main() async {
   await verifyCantSendAnonymousClosure();
   await verifyCantSendNative();
   await verifyCantSendRegexp();
   await verifyCanSendStaticMethod();
+  await verifyExitMessageIsPostedLast();
 }
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index 716d281..44a7031 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -485,13 +485,7 @@
 #ifndef PRODUCT
   TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessObjectIdTable");
   ObjectIdRingClearPointerVisitor visitor(isolate_group_);
-  isolate_group_->ForEachIsolate(
-      [&](Isolate* isolate) {
-        ObjectIdRing* ring = isolate->object_id_ring();
-        ASSERT(ring != NULL);
-        ring->VisitPointers(&visitor);
-      },
-      /*at_safepoint=*/true);
+  isolate_group_->VisitObjectIdRingPointers(&visitor);
 #endif  // !PRODUCT
 }
 
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index f708317..8278400 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -861,17 +861,6 @@
 
   // All objects in the to space have been copied from the from space at this
   // moment.
-
-  // Ensure the mutator thread will fail the next allocation. This will force
-  // mutator to allocate a new TLAB
-  heap_->isolate_group()->ForEachIsolate(
-      [&](Isolate* isolate) {
-        Thread* mutator_thread = isolate->mutator_thread();
-        ASSERT(mutator_thread == nullptr ||
-               mutator_thread->tlab().IsAbandoned());
-      },
-      /*at_safepoint=*/true);
-
   double avg_frac = stats_history_.Get(0).PromoCandidatesSuccessFraction();
   if (stats_history_.Size() >= 2) {
     // Previous scavenge is only given half as much weight.
@@ -1020,11 +1009,7 @@
 void Scavenger::IterateObjectIdTable(ObjectPointerVisitor* visitor) {
 #ifndef PRODUCT
   TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "IterateObjectIdTable");
-  heap_->isolate_group()->ForEachIsolate(
-      [&](Isolate* isolate) {
-        isolate->object_id_ring()->VisitPointers(visitor);
-      },
-      /*at_safepoint=*/true);
+  heap_->isolate_group()->VisitObjectIdRingPointers(visitor);
 #endif  // !PRODUCT
 }
 
@@ -1331,18 +1316,6 @@
     current = current->next();
   }
 
-  // All unscheduled mutator threads should have already abnadoned their TLABs.
-  isolate_group->ForEachIsolate(
-      [&](Isolate* isolate) {
-        Thread* mutator_thread = isolate->mutator_thread();
-        if (mutator_thread != NULL) {
-          if (isolate->scheduled_mutator_thread_ == nullptr) {
-            RELEASE_ASSERT(mutator_thread->tlab().IsAbandoned());
-          }
-        }
-      },
-      /*at_safepoint=*/true);
-
   for (intptr_t i = 0; i < free_tlabs_.length(); ++i) {
     MakeTLABIterable(free_tlabs_[i]);
   }
@@ -1361,18 +1334,6 @@
     current->set_tlab(TLAB());
     current = current->next();
   }
-  // All unscheduled mutator threads should have already abandoned their TLAB.
-  isolate_group->ForEachIsolate(
-      [&](Isolate* isolate) {
-        Thread* mutator_thread = isolate->mutator_thread();
-        if (mutator_thread != NULL) {
-          if (isolate->scheduled_mutator_thread_ == nullptr) {
-            RELEASE_ASSERT(mutator_thread->tlab().IsAbandoned());
-          }
-        }
-      },
-      /*at_safepoint=*/true);
-
   while (free_tlabs_.length() > 0) {
     const TLAB tlab = free_tlabs_.RemoveLast();
     AddAbandonedInBytesLocked(tlab.RemainingSize());
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 1a74498..b8f886b 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2387,14 +2387,17 @@
 
   // Then, proceed with low-level teardown.
   Isolate::UnMarkIsolateReady(this);
-  LowLevelShutdown();
 
+  // Post message before LowLevelShutdown that sends onExit message.
+  // This ensures that exit message comes last.
   if (bequest_.get() != nullptr) {
     auto beneficiary = bequest_->beneficiary();
     PortMap::PostMessage(Message::New(beneficiary, bequest_.release(),
                                       Message::kNormalPriority));
   }
 
+  LowLevelShutdown();
+
   // Now we can unregister from the thread, invoke cleanup callback, delete the
   // isolate (and possibly the isolate group).
   Isolate::LowLevelCleanup(this);
@@ -2646,11 +2649,9 @@
 
 void IsolateGroup::VisitObjectPointers(ObjectPointerVisitor* visitor,
                                        ValidationPolicy validate_frames) {
-  ForEachIsolate(
-      [&](Isolate* isolate) {
-        isolate->VisitObjectPointers(visitor, validate_frames);
-      },
-      /*at_safepoint=*/true);
+  for (Isolate* isolate : isolates_) {
+    isolate->VisitObjectPointers(visitor, validate_frames);
+  }
   api_state()->VisitObjectPointersUnlocked(visitor);
   // Visit objects in the object store.
   if (object_store() != nullptr) {
@@ -2668,20 +2669,25 @@
   // for the mutator threads themselves.
   thread_registry()->VisitObjectPointers(this, visitor, validate_frames);
 
-  ForEachIsolate(
-      [&](Isolate* isolate) {
-        // Visit mutator thread, even if the isolate isn't entered/scheduled
-        // (there might be live API handles to visit).
-        if (isolate->mutator_thread_ != nullptr) {
-          isolate->mutator_thread_->VisitObjectPointers(visitor,
-                                                        validate_frames);
-        }
-      },
-      /*at_safepoint=*/true);
+  for (Isolate* isolate : isolates_) {
+    // Visit mutator thread, even if the isolate isn't entered/scheduled
+    // (there might be live API handles to visit).
+    if (isolate->mutator_thread_ != nullptr) {
+      isolate->mutator_thread_->VisitObjectPointers(visitor, validate_frames);
+    }
+  }
 
   visitor->clear_gc_root_type();
 }
 
+void IsolateGroup::VisitObjectIdRingPointers(ObjectPointerVisitor* visitor) {
+#if !defined(PRODUCT)
+  for (Isolate* isolate : isolates_) {
+    isolate->object_id_ring()->VisitPointers(visitor);
+  }
+#endif  // !defined(PRODUCT)
+}
+
 void IsolateGroup::VisitWeakPersistentHandles(HandleVisitor* visitor) {
   api_state()->VisitWeakHandlesUnlocked(visitor);
 }
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 7b784b9..3516672 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -475,6 +475,7 @@
                            ValidationPolicy validate_frames);
   void VisitStackPointers(ObjectPointerVisitor* visitor,
                           ValidationPolicy validate_frames);
+  void VisitObjectIdRingPointers(ObjectPointerVisitor* visitor);
   void VisitWeakPersistentHandles(HandleVisitor* visitor);
 
   bool compaction_in_progress() const {
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 48d4884..afbd027 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -1321,13 +1321,13 @@
 }
 
 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder()
-    : head_(NULL), block_index_(0) {}
+    : head_(nullptr), tail_(nullptr), block_index_(0) {}
 
 TimelineEventEndlessRecorder::~TimelineEventEndlessRecorder() {
   TimelineEventBlock* current = head_;
-  head_ = NULL;
+  head_ = tail_ = nullptr;
 
-  while (current != NULL) {
+  while (current != nullptr) {
     TimelineEventBlock* next = current->next();
     delete current;
     current = next;
@@ -1374,45 +1374,30 @@
 
 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked() {
   TimelineEventBlock* block = new TimelineEventBlock(block_index_++);
-  block->set_next(head_);
   block->Open();
-  head_ = block;
+  if (head_ == nullptr) {
+    head_ = tail_ = block;
+  } else {
+    tail_->set_next(block);
+    tail_ = block;
+  }
   if (FLAG_trace_timeline) {
     OS::PrintErr("Created new block %p\n", block);
   }
-  return head_;
+  return block;
 }
 
 #ifndef PRODUCT
-static int TimelineEventBlockCompare(TimelineEventBlock* const* a,
-                                     TimelineEventBlock* const* b) {
-  return (*a)->LowerTimeBound() - (*b)->LowerTimeBound();
-}
-
 void TimelineEventEndlessRecorder::PrintJSONEvents(
     JSONArray* events,
     TimelineEventFilter* filter) {
   MutexLocker ml(&lock_);
   ResetTimeTracking();
-  // Collect all interesting blocks.
-  MallocGrowableArray<TimelineEventBlock*> blocks(8);
-  TimelineEventBlock* current = head_;
-  while (current != NULL) {
-    if (filter->IncludeBlock(current)) {
-      blocks.Add(current);
+  for (TimelineEventBlock* current = head_; current != nullptr;
+       current = current->next()) {
+    if (!filter->IncludeBlock(current)) {
+      continue;
     }
-    current = current->next();
-  }
-  // Bail early.
-  if (blocks.length() == 0) {
-    return;
-  }
-  // Sort the interesting blocks so that blocks with earlier events are
-  // outputted first.
-  blocks.Sort(TimelineEventBlockCompare);
-  // Output blocks in sorted order.
-  for (intptr_t block_idx = 0; block_idx < blocks.length(); block_idx++) {
-    current = blocks[block_idx];
     intptr_t length = current->length();
     for (intptr_t i = 0; i < length; i++) {
       TimelineEvent* event = current->At(i);
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index e45b144..8841258 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -866,6 +866,7 @@
 #endif
 
   TimelineEventBlock* head_;
+  TimelineEventBlock* tail_;
   intptr_t block_index_;
 
   friend class TimelineTestHelper;
diff --git a/sdk_nnbd/lib/developer/service.dart b/sdk_nnbd/lib/developer/service.dart
index 9fab7f4..6d90667 100644
--- a/sdk_nnbd/lib/developer/service.dart
+++ b/sdk_nnbd/lib/developer/service.dart
@@ -42,12 +42,12 @@
   static Future<ServiceProtocolInfo> getInfo() async {
     // Port to receive response from service isolate.
     final RawReceivePort receivePort = new RawReceivePort();
-    final Completer<Uri> uriCompleter = new Completer<Uri>();
-    receivePort.handler = (Uri uri) => uriCompleter.complete(uri);
+    final Completer<Uri?> uriCompleter = new Completer<Uri?>();
+    receivePort.handler = (Uri? uri) => uriCompleter.complete(uri);
     // Request the information from the service isolate.
     _getServerInfo(receivePort.sendPort);
     // Await the response from the service isolate.
-    Uri uri = await uriCompleter.future;
+    Uri? uri = await uriCompleter.future;
     // Close the port.
     receivePort.close();
     return new ServiceProtocolInfo(uri);
diff --git a/tests/compiler/dart2js/analyses/analysis_helper.dart b/tests/compiler/dart2js/analyses/analysis_helper.dart
index d70a4bc..ba0e1f5 100644
--- a/tests/compiler/dart2js/analyses/analysis_helper.dart
+++ b/tests/compiler/dart2js/analyses/analysis_helper.dart
@@ -310,6 +310,8 @@
     assert(
         node is! ir.Expression ||
             staticType == typeEnvironment.nullType ||
+            staticType is ir.InterfaceType &&
+                staticType.classNode == typeEnvironment.futureOrClass ||
             typeEnvironment.isSubtypeOf(
                 staticType,
                 _getStaticTypeFromExpression(node),
diff --git a/tests/compiler/dart2js/inference/data/closure_tracer_28919.dart b/tests/compiler/dart2js/inference/data/closure_tracer_28919.dart
index 2f1dcc5..8ca5209 100644
--- a/tests/compiler/dart2js/inference/data/closure_tracer_28919.dart
+++ b/tests/compiler/dart2js/inference/data/closure_tracer_28919.dart
@@ -57,8 +57,8 @@
       i /*invoke: [subclass=JSPositiveInt]*/ ++) {
     methods. /*invoke: [exact=JSExtendableArray]*/ add(
         /*[null]*/ (int
-            /*spec:nnbd-off.[null|subclass=Object]*/
-            /*prod:nnbd-off.[null|subclass=JSInt]*/
+            /*spec:nnbd-off|spec:nnbd-sdk.[null|subclass=Object]*/
+            /*prod:nnbd-off|prod:nnbd-sdk.[null|subclass=JSInt]*/
             x) {
       res = x;
       sum = x /*invoke: [null|subclass=JSInt]*/ + i;
diff --git a/tests/compiler/dart2js/inference/data/no_such_method.dart b/tests/compiler/dart2js/inference/data/no_such_method.dart
index 792f6eb..671f70c 100644
--- a/tests/compiler/dart2js/inference/data/no_such_method.dart
+++ b/tests/compiler/dart2js/inference/data/no_such_method.dart
@@ -17,8 +17,8 @@
   /*member: Class1.noSuchMethod:[exact=JSUInt31]*/
   noSuchMethod(
           Invocation
-              /*spec:nnbd-off.[null|subclass=Object]*/
-              /*prod:nnbd-off.[null|exact=JSInvocationMirror]*/
+              /*spec:nnbd-off|spec:nnbd-sdk.[null|subclass=Object]*/
+              /*prod:nnbd-off|prod:nnbd-sdk.[null|exact=JSInvocationMirror]*/
               _) =>
       42;
 
@@ -41,8 +41,8 @@
   /*member: Class2.noSuchMethod:[exact=JSUInt31]*/
   noSuchMethod(
           Invocation
-              /*spec:nnbd-off.[null|subclass=Object]*/
-              /*prod:nnbd-off.[null|exact=JSInvocationMirror]*/
+              /*spec:nnbd-off|spec:nnbd-sdk.[null|subclass=Object]*/
+              /*prod:nnbd-off|prod:nnbd-sdk.[null|exact=JSInvocationMirror]*/
               _) =>
       42;
 
@@ -65,8 +65,8 @@
   /*member: Class3.noSuchMethod:[null|subclass=Object]*/
   noSuchMethod(
       Invocation
-          /*spec:nnbd-off.[null|subclass=Object]*/
-          /*prod:nnbd-off.[null|exact=JSInvocationMirror]*/
+          /*spec:nnbd-off|spec:nnbd-sdk.[null|subclass=Object]*/
+          /*prod:nnbd-off|prod:nnbd-sdk.[null|exact=JSInvocationMirror]*/
           invocation) {
     return invocation
         .
@@ -101,8 +101,8 @@
   /*member: Class4.noSuchMethod:[null]*/
   noSuchMethod(
       Invocation
-          /*spec:nnbd-off.[null|subclass=Object]*/
-          /*prod:nnbd-off.[null|exact=JSInvocationMirror]*/
+          /*spec:nnbd-off|spec:nnbd-sdk.[null|subclass=Object]*/
+          /*prod:nnbd-off|prod:nnbd-sdk.[null|exact=JSInvocationMirror]*/
           invocation) {
     this. /*update: [exact=Class4]*/ field = invocation
         .
diff --git a/tests/compiler/dart2js/inference/data/no_such_method1.dart b/tests/compiler/dart2js/inference/data/no_such_method1.dart
index 2c7d7d3..8b37b2c 100644
--- a/tests/compiler/dart2js/inference/data/no_such_method1.dart
+++ b/tests/compiler/dart2js/inference/data/no_such_method1.dart
@@ -8,8 +8,8 @@
 class A {
   /*member: A.noSuchMethod:[exact=JSUInt31]*/
   noSuchMethod(
-          /*spec:nnbd-off.[null|subclass=Object]*/
-          /*prod:nnbd-off.[null|exact=JSInvocationMirror]*/
+          /*spec:nnbd-off|spec:nnbd-sdk.[null|subclass=Object]*/
+          /*prod:nnbd-off|prod:nnbd-sdk.[null|exact=JSInvocationMirror]*/
           im) =>
       42;
 }
diff --git a/tests/compiler/dart2js/inference/data/no_such_method2.dart b/tests/compiler/dart2js/inference/data/no_such_method2.dart
index e50ec96..9c5f719 100644
--- a/tests/compiler/dart2js/inference/data/no_such_method2.dart
+++ b/tests/compiler/dart2js/inference/data/no_such_method2.dart
@@ -8,8 +8,8 @@
 abstract class A {
   /*member: A.noSuchMethod:[exact=JSUInt31]*/
   noSuchMethod(
-          /*spec:nnbd-off.[null|subclass=Object]*/
-          /*prod:nnbd-off.[null|exact=JSInvocationMirror]*/
+          /*spec:nnbd-off|spec:nnbd-sdk.[null|subclass=Object]*/
+          /*prod:nnbd-off|prod:nnbd-sdk.[null|exact=JSInvocationMirror]*/
           im) =>
       42;
 }
@@ -33,8 +33,8 @@
 
   /*member: D.noSuchMethod:[exact=JSDouble]*/
   noSuchMethod(
-          /*prod:nnbd-off.[null|exact=JSInvocationMirror]*/
-          /*spec:nnbd-off.[null|subclass=Object]*/
+          /*prod:nnbd-off|prod:nnbd-sdk.[null|exact=JSInvocationMirror]*/
+          /*spec:nnbd-off|spec:nnbd-sdk.[null|subclass=Object]*/
           im) =>
       42.5;
 }
diff --git a/tests/compiler/dart2js/inference/data/no_such_method3.dart b/tests/compiler/dart2js/inference/data/no_such_method3.dart
index 275d209..473e312 100644
--- a/tests/compiler/dart2js/inference/data/no_such_method3.dart
+++ b/tests/compiler/dart2js/inference/data/no_such_method3.dart
@@ -10,8 +10,8 @@
   // throws an exception.
   /*member: A.noSuchMethod:[empty]*/
   noSuchMethod(
-          /*spec:nnbd-off.[null|subclass=Object]*/
-          /*prod:nnbd-off.[null|exact=JSInvocationMirror]*/
+          /*spec:nnbd-off|spec:nnbd-sdk.[null|subclass=Object]*/
+          /*prod:nnbd-off|prod:nnbd-sdk.[null|exact=JSInvocationMirror]*/
           im) =>
       throw 'foo';
 }
diff --git a/tests/compiler/dart2js/inference/data/parameters_trust.dart b/tests/compiler/dart2js/inference/data/parameters_trust.dart
index ddf89ec..e73c209 100644
--- a/tests/compiler/dart2js/inference/data/parameters_trust.dart
+++ b/tests/compiler/dart2js/inference/data/parameters_trust.dart
@@ -18,8 +18,8 @@
 /*member: _trustParameters:[exact=JSUInt31]*/
 _trustParameters(
     int
-        /*spec:nnbd-off.Union([exact=JSString], [exact=JSUInt31])*/
-        /*prod:nnbd-off.[exact=JSUInt31]*/
+        /*spec:nnbd-off|spec:nnbd-sdk.Union([exact=JSString], [exact=JSUInt31])*/
+        /*prod:nnbd-off|prod:nnbd-sdk.[exact=JSUInt31]*/
         i) {
   return i;
 }
diff --git a/tests/compiler/dart2js/inference/data/try_catch.dart b/tests/compiler/dart2js/inference/data/try_catch.dart
index 0a3d09a..0a41400 100644
--- a/tests/compiler/dart2js/inference/data/try_catch.dart
+++ b/tests/compiler/dart2js/inference/data/try_catch.dart
@@ -122,7 +122,7 @@
   return a;
 }
 
-/*spec:nnbd-off|prod:nnbd-off.member: returnInt6:[subclass=JSInt]*/
+/*member: returnInt6:[subclass=JSInt]*/
 returnInt6() {
   try {
     throw 42;
diff --git a/tests/corelib/regexp/regexp_test.dart b/tests/corelib/regexp/regexp_test.dart
index 1cb8ac7..9f42f43 100644
--- a/tests/corelib/regexp/regexp_test.dart
+++ b/tests/corelib/regexp/regexp_test.dart
@@ -32,10 +32,12 @@
   assertEquals("foo:bar:baz", str.split(regexp).join(":"));
 }
 
-void assertEquals(actual, expected, [message]) =>
+void assertEquals(actual, expected, [String message = ""]) =>
     Expect.equals(actual, expected, message);
-void assertTrue(actual, [message]) => Expect.isTrue(actual, message);
-void assertFalse(actual, [message]) => Expect.isFalse(actual, message);
+void assertTrue(actual, [String message = ""]) =>
+    Expect.isTrue(actual, message);
+void assertFalse(actual, [String message = ""]) =>
+    Expect.isFalse(actual, message);
 void assertThrows(fn) => Expect.throws(fn);
 
 void main() {
diff --git a/tests/corelib/uri_test.dart b/tests/corelib/uri_test.dart
index bb45fe0..550fc57 100644
--- a/tests/corelib/uri_test.dart
+++ b/tests/corelib/uri_test.dart
@@ -470,8 +470,8 @@
   });
   var params = uri.queryParametersAll;
   Expect.equals(2, params.length);
-  Expect.listEquals(["42", "37"], params["x"]);
-  Expect.listEquals(["43", "38"], params["y"]);
+  Expect.listEquals(["42", "37"], params["x"]!);
+  Expect.listEquals(["43", "38"], params["y"]!);
 }
 
 main() {
diff --git a/tests/language_2/variance/syntax/variance_disabled_syntax_test.dart b/tests/language_2/variance/syntax/variance_disabled_syntax_test.dart
index 0ae03df..2811208 100644
--- a/tests/language_2/variance/syntax/variance_disabled_syntax_test.dart
+++ b/tests/language_2/variance/syntax/variance_disabled_syntax_test.dart
@@ -10,25 +10,25 @@
 abstract class A<in X> {
 //               ^^
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
-// [cfe] This requires the 'variance' experiment to be enabled.
+// [cfe] This requires the 'variance' language feature to be enabled.
   int foo(X bar);
 }
 
 class B<out X, in Y, inout Z> {}
 //      ^^^
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
-// [cfe] This requires the 'variance' experiment to be enabled.
+// [cfe] This requires the 'variance' language feature to be enabled.
 //             ^^
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
-// [cfe] This requires the 'variance' experiment to be enabled.
+// [cfe] This requires the 'variance' language feature to be enabled.
 //                   ^^^^^
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
-// [cfe] This requires the 'variance' experiment to be enabled.
+// [cfe] This requires the 'variance' language feature to be enabled.
 
 class C<in T> extends A<T> {
 //      ^^
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
-// [cfe] This requires the 'variance' experiment to be enabled.
+// [cfe] This requires the 'variance' language feature to be enabled.
   @override
   int foo(T bar) {
     return 2;
@@ -38,29 +38,29 @@
 mixin D<out T> {}
 //      ^^^
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
-// [cfe] This requires the 'variance' experiment to be enabled.
+// [cfe] This requires the 'variance' language feature to be enabled.
 
 class E1 {}
 
 mixin E<in T extends E1> {}
 //      ^^
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
-// [cfe] This requires the 'variance' experiment to be enabled.
+// [cfe] This requires the 'variance' language feature to be enabled.
 
 class F<out T> = Object with D<T>;
 //      ^^^
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
-// [cfe] This requires the 'variance' experiment to be enabled.
+// [cfe] This requires the 'variance' language feature to be enabled.
 
 class G<out out> {}
 //      ^^^
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
-// [cfe] This requires the 'variance' experiment to be enabled.
+// [cfe] This requires the 'variance' language feature to be enabled.
 
 class H<out inout> {}
 //      ^^^
 // [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
-// [cfe] This requires the 'variance' experiment to be enabled.
+// [cfe] This requires the 'variance' language feature to be enabled.
 
 main() {
   B<int, String, bool> b = B();
diff --git a/tests/lib/isolate/function_send_test.dart b/tests/lib/isolate/function_send_test.dart
index 4b22fa1..38b4698 100644
--- a/tests/lib/isolate/function_send_test.dart
+++ b/tests/lib/isolate/function_send_test.dart
@@ -191,10 +191,10 @@
   });
   Expect.throws(() {
     noReply.sendPort.send(func);
-  }, null, "send direct");
+  }, (_) => true, "send direct");
   Expect.throws(() {
     noReply.sendPort.send([func]);
-  }, null, "send wrapped");
+  }, (_) => true, "send wrapped");
   scheduleMicrotask(() {
     noReply.close();
     asyncEnd();
diff --git a/tests/lib/math/implement_rectangle_test.dart b/tests/lib/math/implement_rectangle_test.dart
index 3a31ed8..f6f6a91 100644
--- a/tests/lib/math/implement_rectangle_test.dart
+++ b/tests/lib/math/implement_rectangle_test.dart
@@ -25,9 +25,9 @@
 
   Rectangle(this.left, this.top, this.width, this.height);
 
-  T get right => left + width;
+  T get right => (left + width) as T;
 
-  T get bottom => top + height;
+  T get bottom => (top + height) as T;
 
   Point<T> get topLeft => new Point<T>(left, top);
 
@@ -58,7 +58,8 @@
     T rTop = min(top, other.top);
     T rRight = max(right, other.right);
     T rBottom = max(bottom, other.bottom);
-    return new Rectangle<T>(rLeft, rTop, rRight - rLeft, rBottom - rTop);
+    return new Rectangle<T>(
+        rLeft, rTop, (rRight - rLeft) as T, (rBottom - rTop) as T);
   }
 
   /// Tests whether `this` entirely contains [another].
@@ -75,6 +76,7 @@
     T rTop = max(top, rect.top);
     T rRight = min(right, rect.right);
     T rBottom = min(bottom, rect.bottom);
-    return new Rectangle<T>(rLeft, rTop, rRight - rLeft, rBottom - rTop);
+    return new Rectangle<T>(
+        rLeft, rTop, (rRight - rLeft) as T, (rBottom - rTop) as T);
   }
 }
diff --git a/tools/VERSION b/tools/VERSION
index 8324ed2..2aa401e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
 MAJOR 2
 MINOR 9
 PATCH 0
-PRERELEASE 4
+PRERELEASE 5
 PRERELEASE_PATCH 0
 ABI_VERSION 32
 OLDEST_SUPPORTED_ABI_VERSION 32
diff --git a/tools/gardening/pubspec.yaml b/tools/gardening/pubspec.yaml
index ca78789..dc6fcca 100644
--- a/tools/gardening/pubspec.yaml
+++ b/tools/gardening/pubspec.yaml
@@ -2,6 +2,8 @@
 # gardening by making it a package.
 name: gardening
 #version: do-not-upload
+environment:
+  sdk: "^2.7.0"
 dependencies:
   args:
   http:
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index 19e9c94..e0ddfb8 100755
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -8,9 +8,6 @@
 import 'package:pub_semver/pub_semver.dart';
 import 'package:yaml/yaml.dart';
 
-/// Version to use if a package doesn't constrain the language version.
-final defaultVersion = Version(2, 7, 0);
-
 final repoRoot = p.dirname(p.dirname(p.fromUri(Platform.script)));
 final configFilePath = p.join(repoRoot, '.dart_tool/package_config.json');
 
@@ -75,18 +72,14 @@
     List<String> packageDirs) sync* {
   for (var packageDir in packageDirs) {
     var version = pubspecLanguageVersion(packageDir);
-    if (version == null) {
-      print('Warning: Unknown language version for ${p.basename(packageDir)}.');
-      version = defaultVersion;
-    }
-
     var hasLibDirectory = Directory(p.join(packageDir, 'lib')).existsSync();
 
     yield {
       'name': p.basename(packageDir),
       'rootUri': p.relative(packageDir, from: p.dirname(configFilePath)),
       if (hasLibDirectory) 'packageUri': 'lib/',
-      'languageVersion': '${version.major}.${version.minor}'
+      if (version != null)
+        'languageVersion': '${version.major}.${version.minor}'
     };
   }
 }