Version 2.8.0-dev.3.0

Merge commit 'd302d7f10ad90a7e093f38c17b804127db906ae7' into dev
diff --git a/DEPS b/DEPS
index 7b089e9..55417bd 100644
--- a/DEPS
+++ b/DEPS
@@ -476,7 +476,7 @@
     "packages": [
       {
         "package": "dart/cfe/dart2js_dills",
-        "version": "binary_version:29_36",
+        "version": "binary_version:29_37",
       }
     ],
     "dep_type": "cipd",
diff --git a/benchmarks/ListCopy/dart/ListCopy.dart b/benchmarks/ListCopy/dart/ListCopy.dart
new file mode 100644
index 0000000..e058928
--- /dev/null
+++ b/benchmarks/ListCopy/dart/ListCopy.dart
@@ -0,0 +1,151 @@
+// 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:collection';
+import 'dart:typed_data';
+import 'package:benchmark_harness/benchmark_harness.dart';
+
+// Benchmark for polymorphic list copying.
+//
+// Each benchmark creates a list from an Iterable. There are many slightly
+// different ways to do this.
+//
+// In each benchmark the call site is polymorphic in the input type to simulate
+// the behaviour of library methods in the context of a large application. The
+// input lists are skewed heavily to the default growable list. This attempts to
+// model 'real world' copying of 'ordinary' lists.
+//
+// The benchmarks are run for small lists (2 elements, names ending in
+// `.2`) and 'large' lists (100 elements or `.100`). The benchmarks are
+// normalized on the number of elements to make the input sizes comparable.
+//
+// Most inputs have type `Iterable<num>`, but contain only `int` values. This
+// allows is to compare the down-conversion versions of copying where each
+// element must be checked.
+
+class Benchmark extends BenchmarkBase {
+  final int length;
+  final Function() copy;
+
+  final List<Iterable<num>> inputs = [];
+
+  Benchmark(String name, this.length, this.copy)
+      : super('ListCopy.$name.$length');
+
+  void setup() {
+    // Ensure setup() is idempotent.
+    if (inputs.isNotEmpty) return;
+    List<num> base = List.generate(length, (i) => i + 1);
+    List<Iterable<num>> makeVariants() {
+      return [
+        // Weight ordinary lists more.
+        ...List.generate(19, (_) => List<num>.of(base)),
+
+        base.toList(growable: false),
+        List<num>.unmodifiable(base),
+        UnmodifiableListView(base),
+        base.reversed,
+        String.fromCharCodes(List<int>.from(base)).codeUnits,
+        Uint8List.fromList(List<int>.from(base)),
+      ];
+    }
+
+    const elements = 10000;
+    int totalLength = 0;
+    while (totalLength < elements) {
+      var variants = makeVariants();
+      inputs.addAll(variants);
+      totalLength += variants.fold(0, (sum, iterable) => sum + iterable.length);
+    }
+
+    // Sanity checks.
+    for (var sample in inputs) {
+      if (sample.length != length) throw 'Wrong length: $length $sample';
+    }
+    if (totalLength != elements) {
+      throw 'totalLength $totalLength != expected $elements';
+    }
+  }
+
+  void run() {
+    for (var sample in inputs) {
+      input = sample;
+      // Unroll loop 10 times to reduce loop overhead, which is about 15% for
+      // the fastest short input benchmarks.
+      copy();
+      copy();
+      copy();
+      copy();
+      copy();
+      copy();
+      copy();
+      copy();
+      copy();
+      copy();
+    }
+    if (output.length != inputs.first.length) throw 'Bad result: $output';
+  }
+}
+
+// All the 'copy' methods use [input] and [output] rather than a parameter and
+// return value to avoid any possibility of type check in the call sequence.
+Iterable<num> input;
+var output;
+
+List<Benchmark> makeBenchmarks(int length) => [
+      Benchmark('toList', length, () {
+        output = input.toList();
+      }),
+      Benchmark('toList.fixed', length, () {
+        output = input.toList(growable: false);
+      }),
+      Benchmark('List.of', length, () {
+        output = List<num>.of(input);
+      }),
+      Benchmark('List.of.fixed', length, () {
+        output = List<num>.of(input, growable: false);
+      }),
+      Benchmark('List.num.from', length, () {
+        output = List<num>.from(input);
+      }),
+      Benchmark('List.int.from', length, () {
+        output = List<int>.from(input);
+      }),
+      Benchmark('List.num.from.fixed', length, () {
+        output = List<num>.from(input, growable: false);
+      }),
+      Benchmark('List.int.from.fixed', length, () {
+        output = List<int>.from(input, growable: false);
+      }),
+      Benchmark('List.num.unmodifiable', length, () {
+        output = List<num>.unmodifiable(input);
+      }),
+      Benchmark('List.int.unmodifiable', length, () {
+        output = List<int>.unmodifiable(input);
+      }),
+      Benchmark('spread.num', length, () {
+        output = <num>[...input];
+      }),
+      Benchmark('spread.int', length, () {
+        output = <int>[...input];
+      }),
+    ];
+
+main() {
+  var benchmarks = [...makeBenchmarks(2), ...makeBenchmarks(100)];
+
+  // Warmup all benchmarks to ensure JIT compilers see full polymorphism.
+  for (var benchmark in benchmarks) {
+    benchmark.setup();
+  }
+
+  for (var benchmark in benchmarks) {
+    benchmark.warmup();
+  }
+
+  for (var benchmark in benchmarks) {
+    // `report` calls `setup`, but `setup` is idempotent.
+    benchmark.report();
+  }
+}
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 7a8e5b1..7aabba9 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -197,6 +197,16 @@
         r"""Try marking the function body with either 'async' or 'async*', or removing the 'await' before the for loop.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeAwaitInLateLocalInitializer =
+    messageAwaitInLateLocalInitializer;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageAwaitInLateLocalInitializer = const MessageCode(
+    "AwaitInLateLocalInitializer",
+    message:
+        r"""`await` expressions are not supported in late local initializers.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeAwaitNotAsync = messageAwaitNotAsync;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_in/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_in/main.dart
new file mode 100644
index 0000000..d6be79f
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_in/main.dart
@@ -0,0 +1,286 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+/*library: nnbd=false*/
+
+import 'opt_in.dart';
+
+/*class: LegacyClass:Class,Interface,LegacyClass,Object*/
+class LegacyClass extends Class implements Interface {
+  /*member: LegacyClass.method1:int* Function()**/
+  /*member: LegacyClass.method2:int* Function()**/
+
+  /*member: LegacyClass.method3:int* Function()**/
+  int method3() => 0;
+
+  /*member: LegacyClass.method4:int* Function()**/
+  int method4() => 0;
+
+  /*member: LegacyClass.method5a:int* Function(int*,int*)**/
+  /*member: LegacyClass.method5b:int* Function(int*,[int*])**/
+  /*member: LegacyClass.method5c:int* Function([int*,int*])**/
+
+  /*member: LegacyClass.method6a:int* Function(int*,int*)**/
+  int method6a(int a, int b) => 0;
+
+  /*member: LegacyClass.method6b:int* Function(int*,[int*])**/
+  int method6b(int a, [int b]) => 0;
+
+  /*member: LegacyClass.method6c:int* Function([int*,int*])**/
+  int method6c([int a, int b]) => 0;
+
+  /*member: LegacyClass.method7a:int* Function(int*,{int* b})**/
+  /*member: LegacyClass.method7b:int* Function({int* a,int* b})**/
+
+  /*member: LegacyClass.method8a:int* Function(int*,{int* b})**/
+  int method8a(int a, {int b: 0}) => 0;
+
+  /*member: LegacyClass.method8b:int* Function({int* a,int* b})**/
+  int method8b({int a, int b: 0}) => 0;
+
+  /*member: LegacyClass.method9a:int* Function(int*,{int* b})**/
+  /*member: LegacyClass.method9b:int* Function({int* a,int* b})**/
+
+  /*member: LegacyClass.method10a:int* Function(int*,{int* b})**/
+  int method10a(int a, {int b}) => 0;
+
+  /*member: LegacyClass.method10b:int* Function({int* a,int* b})**/
+  int method10b({int a, int b}) => 0;
+
+  /*member: LegacyClass.getter1:int**/
+  /*member: LegacyClass.getter2:int**/
+
+  /*member: LegacyClass.getter3:int**/
+  int get getter3 => 0;
+
+  /*member: LegacyClass.getter4:int**/
+  int get getter4 => 0;
+
+  /*member: LegacyClass.setter1=:int**/
+
+  /*member: LegacyClass.setter2=:int**/
+
+  /*member: LegacyClass.setter3=:int**/
+  void set setter3(int value) {}
+
+  /*member: LegacyClass.setter4=:int**/
+  void set setter4(int value) {}
+
+  /*member: LegacyClass.field1:int**/
+  /*member: LegacyClass.field1=:int**/
+  /*member: LegacyClass.field2:int**/
+  /*member: LegacyClass.field2=:int**/
+
+  /*member: LegacyClass.field3:int**/
+  int field3;
+
+  /*member: LegacyClass.field4:int**/
+  int field4;
+
+  /*member: LegacyClass.field6a:int**/
+  var field6a = 0;
+
+  /*member: LegacyClass.field6b:int**/
+  var field6b = constant;
+
+  /*member: LegacyClass.field5:int**/
+  /*member: LegacyClass.field5=:int**/
+
+  /*member: LegacyClass.property1:int**/
+  /*member: LegacyClass.property1=:int**/
+  /*member: LegacyClass.property2:int**/
+  /*member: LegacyClass.property2=:int**/
+
+  /*member: LegacyClass.property3:int**/
+  int get property3 => 0;
+
+  /*member: LegacyClass.property3=:int**/
+  void set property3(int value) {}
+
+  /*member: LegacyClass.property4:int**/
+  int get property4 => 0;
+
+  /*member: LegacyClass.property4=:int**/
+  void set property4(int value) {}
+
+  /*member: LegacyClass.property5:int**/
+  /*member: LegacyClass.property5=:int**/
+  /*member: LegacyClass.property6:int**/
+  /*member: LegacyClass.property6=:int**/
+
+  /*member: LegacyClass.property7:int**/
+  int property7;
+
+  /*member: LegacyClass.property8:int**/
+  int property8;
+}
+
+/*class: LegacyClass2a:Class,LegacyClass2a,Object*/
+abstract class LegacyClass2a extends Class {
+  /*member: LegacyClass2a.field1:int**/
+  /*member: LegacyClass2a.field1=:int**/
+  /*member: LegacyClass2a.field2:int**/
+  /*member: LegacyClass2a.field2=:int**/
+  /*member: LegacyClass2a.field5:int**/
+  /*member: LegacyClass2a.field5=:int**/
+  /*member: LegacyClass2a.field6a:int**/
+  /*member: LegacyClass2a.field6a=:int**/
+  /*member: LegacyClass2a.field6b:int**/
+  /*member: LegacyClass2a.field6b=:int**/
+
+  /*member: LegacyClass2a.getter1:int**/
+  /*member: LegacyClass2a.getter2:int**/
+
+  /*member: LegacyClass2a.method1:int* Function()**/
+  /*member: LegacyClass2a.method2:int* Function()**/
+  /*member: LegacyClass2a.method5a:int* Function(int*,int*)**/
+  /*member: LegacyClass2a.method5b:int* Function(int*,[int*])**/
+  /*member: LegacyClass2a.method5c:int* Function([int*,int*])**/
+  /*member: LegacyClass2a.method7a:int* Function(int*,{int* b})**/
+  /*member: LegacyClass2a.method7b:int* Function({int* a,int* b})**/
+  /*member: LegacyClass2a.method9a:int* Function(int*,{int* b})**/
+  /*member: LegacyClass2a.method9b:int* Function({int* a,int* b})**/
+
+  /*member: LegacyClass2a.property1:int**/
+  /*member: LegacyClass2a.property1=:int**/
+  /*member: LegacyClass2a.property2:int**/
+  /*member: LegacyClass2a.property2=:int**/
+  /*member: LegacyClass2a.property5:int**/
+  /*member: LegacyClass2a.property5=:int**/
+  /*member: LegacyClass2a.property6:int**/
+  /*member: LegacyClass2a.property6=:int**/
+
+  /*member: LegacyClass2a.setter1=:int**/
+  /*member: LegacyClass2a.setter2=:int**/
+}
+
+/*class: LegacyInterface2:Interface,LegacyInterface2,Object*/
+abstract class LegacyInterface2 implements Interface {
+  /*member: LegacyInterface2.field1:int**/
+  /*member: LegacyInterface2.field1=:int**/
+  /*member: LegacyInterface2.field2:int**/
+  /*member: LegacyInterface2.field2=:int**/
+  /*member: LegacyInterface2.field3:int**/
+  /*member: LegacyInterface2.field3=:int**/
+  /*member: LegacyInterface2.field4:int**/
+  /*member: LegacyInterface2.field4=:int**/
+
+  /*member: LegacyInterface2.getter1:int**/
+  /*member: LegacyInterface2.getter2:int**/
+  /*member: LegacyInterface2.getter3:int**/
+  /*member: LegacyInterface2.getter4:int**/
+
+  /*member: LegacyInterface2.method1:int* Function()**/
+  /*member: LegacyInterface2.method2:int* Function()**/
+  /*member: LegacyInterface2.method3:int* Function()**/
+  /*member: LegacyInterface2.method4:int* Function()**/
+  /*member: LegacyInterface2.method5a:int* Function(int*,int*)**/
+  /*member: LegacyInterface2.method5b:int* Function(int*,[int*])**/
+  /*member: LegacyInterface2.method5c:int* Function([int*,int*])**/
+  /*member: LegacyInterface2.method6a:int* Function(int*,int*)**/
+  /*member: LegacyInterface2.method6b:int* Function(int*,[int*])**/
+  /*member: LegacyInterface2.method6c:int* Function([int*,int*])**/
+  /*member: LegacyInterface2.method7a:int* Function(int*,{int* b})**/
+  /*member: LegacyInterface2.method7b:int* Function({int* a,int* b})**/
+  /*member: LegacyInterface2.method8a:int* Function(int*,{int* b})**/
+  /*member: LegacyInterface2.method8b:int* Function({int* a,int* b})**/
+  /*member: LegacyInterface2.method9a:int* Function(int*,{int* b})**/
+  /*member: LegacyInterface2.method9b:int* Function({int* a,int* b})**/
+  /*member: LegacyInterface2.method10a:int* Function(int*,{int* b})**/
+  /*member: LegacyInterface2.method10b:int* Function({int* a,int* b})**/
+
+  /*member: LegacyInterface2.property1:int**/
+  /*member: LegacyInterface2.property1=:int**/
+  /*member: LegacyInterface2.property2:int**/
+  /*member: LegacyInterface2.property2=:int**/
+  /*member: LegacyInterface2.property3:int**/
+  /*member: LegacyInterface2.property3=:int**/
+  /*member: LegacyInterface2.property4:int**/
+  /*member: LegacyInterface2.property4=:int**/
+  /*member: LegacyInterface2.property5:int**/
+  /*member: LegacyInterface2.property5=:int**/
+  /*member: LegacyInterface2.property6:int**/
+  /*member: LegacyInterface2.property6=:int**/
+  /*member: LegacyInterface2.property7:int**/
+  /*member: LegacyInterface2.property7=:int**/
+  /*member: LegacyInterface2.property8:int**/
+  /*member: LegacyInterface2.property8=:int**/
+
+  /*member: LegacyInterface2.setter1=:int**/
+  /*member: LegacyInterface2.setter2=:int**/
+  /*member: LegacyInterface2.setter3=:int**/
+  /*member: LegacyInterface2.setter4=:int**/
+}
+
+/*class: LegacyClass2b:Class,Interface,LegacyClass2a,LegacyClass2b,LegacyInterface2,Object*/
+abstract class LegacyClass2b extends LegacyClass2a implements LegacyInterface2 {
+  /*member: LegacyClass2b.field1:int**/
+  /*member: LegacyClass2b.field1=:int**/
+  /*member: LegacyClass2b.field2:int**/
+  /*member: LegacyClass2b.field2=:int**/
+  /*member: LegacyClass2b.field3:int**/
+  /*member: LegacyClass2b.field3=:int**/
+  /*member: LegacyClass2b.field4:int**/
+  /*member: LegacyClass2b.field4=:int**/
+  /*member: LegacyClass2b.field5:int**/
+  /*member: LegacyClass2b.field5=:int**/
+  /*member: LegacyClass2b.field6a:int**/
+  /*member: LegacyClass2b.field6a=:int**/
+  /*member: LegacyClass2b.field6b:int**/
+  /*member: LegacyClass2b.field6b=:int**/
+
+  /*member: LegacyClass2b.getter1:int**/
+  /*member: LegacyClass2b.getter2:int**/
+  /*member: LegacyClass2b.getter3:int**/
+  /*member: LegacyClass2b.getter4:int**/
+
+  /*member: LegacyClass2b.method1:int* Function()**/
+  /*member: LegacyClass2b.method2:int* Function()**/
+  /*member: LegacyClass2b.method3:int* Function()**/
+  /*member: LegacyClass2b.method4:int* Function()**/
+  /*member: LegacyClass2b.method5a:int* Function(int*,int*)**/
+  /*member: LegacyClass2b.method5b:int* Function(int*,[int*])**/
+  /*member: LegacyClass2b.method5c:int* Function([int*,int*])**/
+  /*member: LegacyClass2b.method6a:int* Function(int*,int*)**/
+  /*member: LegacyClass2b.method6b:int* Function(int*,[int*])**/
+  /*member: LegacyClass2b.method6c:int* Function([int*,int*])**/
+  /*member: LegacyClass2b.method7a:int* Function(int*,{int* b})**/
+  /*member: LegacyClass2b.method7b:int* Function({int* a,int* b})**/
+  /*member: LegacyClass2b.method8a:int* Function(int*,{int* b})**/
+  /*member: LegacyClass2b.method8b:int* Function({int* a,int* b})**/
+  /*member: LegacyClass2b.method9a:int* Function(int*,{int* b})**/
+  /*member: LegacyClass2b.method9b:int* Function({int* a,int* b})**/
+  /*member: LegacyClass2b.method10a:int* Function(int*,{int* b})**/
+  /*member: LegacyClass2b.method10b:int* Function({int* a,int* b})**/
+
+  /*member: LegacyClass2b.property1:int**/
+  /*member: LegacyClass2b.property1=:int**/
+  /*member: LegacyClass2b.property2:int**/
+  /*member: LegacyClass2b.property2=:int**/
+  /*member: LegacyClass2b.property3:int**/
+  /*member: LegacyClass2b.property3=:int**/
+  /*member: LegacyClass2b.property4:int**/
+  /*member: LegacyClass2b.property4=:int**/
+  /*member: LegacyClass2b.property5:int**/
+  /*member: LegacyClass2b.property5=:int**/
+  /*member: LegacyClass2b.property6:int**/
+  /*member: LegacyClass2b.property6=:int**/
+  /*member: LegacyClass2b.property7:int**/
+  /*member: LegacyClass2b.property7=:int**/
+  /*member: LegacyClass2b.property8:int**/
+  /*member: LegacyClass2b.property8=:int**/
+
+  /*member: LegacyClass2b.setter1=:int**/
+  /*member: LegacyClass2b.setter2=:int**/
+  /*member: LegacyClass2b.setter3=:int**/
+  /*member: LegacyClass2b.setter4=:int**/
+}
+
+/*class: LegacyGenericClass1:GenericInterface<T*>,LegacyGenericClass1<T*>,Object*/
+abstract class LegacyGenericClass1<T> implements GenericInterface<T> {
+  /*member: LegacyGenericClass1.genericMethod1:S* Function<S>(T*,S*,{T* c,S* d})**/
+  /*member: LegacyGenericClass1.genericMethod2:S* Function<S>(T*,S*,[T*,S*])**/
+}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_in/opt_in.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_in/opt_in.dart
new file mode 100644
index 0000000..ed18fed
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_in/opt_in.dart
@@ -0,0 +1,232 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*library: nnbd=true*/
+
+/*class: Interface:Interface,Object*/
+abstract class Interface {
+  /*member: Interface.method1:int? Function()!*/
+  int? method1();
+
+  /*member: Interface.method2:int! Function()!*/
+  int method2();
+
+  /*member: Interface.method3:int! Function()!*/
+  int method3();
+
+  /*member: Interface.method4:int? Function()!*/
+  int? method4();
+
+  /*member: Interface.method5a:int! Function(int!,int?)!*/
+  int method5a(int a, int? b);
+
+  /*member: Interface.method5b:int! Function(int!,[int?])!*/
+  int method5b(int a, [int? b]);
+
+  /*member: Interface.method5c:int! Function([int!,int?])!*/
+  int method5c([int a, int? b]);
+
+  /*member: Interface.method6a:int? Function(int?,int!)!*/
+  int? method6a(int? a, int b);
+
+  /*member: Interface.method6b:int? Function(int?,[int!])!*/
+  int? method6b(int? a, [int b = 0]);
+
+  /*member: Interface.method6c:int? Function([int?,int!])!*/
+  int? method6c([int? a, int b = 0]);
+
+  /*member: Interface.method7a:int! Function(int!,{int? b})!*/
+  int method7a(int a, {int? b});
+
+  /*member: Interface.method7b:int! Function({int! a,int? b})!*/
+  int method7b({int a: 0, int? b});
+
+  /*member: Interface.method8a:int? Function(int?,{int! b})!*/
+  int? method8a(int? a, {int b: 0});
+
+  /*member: Interface.method8b:int? Function({int? a,int! b})!*/
+  int? method8b({int? a, int b: 0});
+
+  /*member: Interface.method9a:int! Function(int!,{required int? b})!*/
+  int method9a(int a, {required int? b});
+
+  /*member: Interface.method9b:int! Function({required int! a,required int? b})!*/
+  int method9b({required int a, required int? b});
+
+  /*member: Interface.method10a:int? Function(int?,{required int! b})!*/
+  int? method10a(int? a, {required int b});
+
+  /*member: Interface.method10b:int? Function({required int? a,required int! b})!*/
+  int? method10b({required int? a, required int b});
+
+  /*member: Interface.getter1:int?*/
+  int? get getter1;
+
+  /*member: Interface.getter2:int!*/
+  int get getter2;
+
+  /*member: Interface.getter3:int!*/
+  int get getter3;
+
+  /*member: Interface.getter4:int?*/
+  int? get getter4;
+
+  /*member: Interface.setter1=:int?*/
+  void set setter1(int? value);
+
+  /*member: Interface.setter2=:int!*/
+  void set setter2(int value);
+
+  /*member: Interface.setter3=:int!*/
+  void set setter3(int value);
+
+  /*member: Interface.setter4=:int?*/
+  void set setter4(int? value);
+
+  /*member: Interface.field1:int?*/
+  int? field1;
+
+  /*member: Interface.field2:int!*/
+  int field2 = 0;
+
+  /*member: Interface.field3:int!*/
+  int field3 = 0;
+
+  /*member: Interface.field4:int?*/
+  int? field4;
+
+  /*member: Interface.property1:int?*/
+  int? get property1;
+
+  /*member: Interface.property1=:int?*/
+  void set property1(int? value);
+
+  /*member: Interface.property2:int!*/
+  int get property2;
+
+  /*member: Interface.property2=:int!*/
+  void set property2(int value);
+
+  /*member: Interface.property3:int!*/
+  int get property3;
+
+  /*member: Interface.property3=:int!*/
+  void set property3(int value);
+
+  /*member: Interface.property4:int?*/
+  int? get property4;
+
+  /*member: Interface.property4=:int?*/
+  void set property4(int? value);
+
+  /*member: Interface.property5:int?*/
+  int? get property5;
+
+  /*member: Interface.property5=:int?*/
+  void set property5(int? value);
+
+  /*member: Interface.property6:int!*/
+  int get property6;
+
+  /*member: Interface.property6=:int!*/
+  void set property6(int value);
+
+  /*member: Interface.property7:int!*/
+  int get property7;
+
+  /*member: Interface.property7=:int!*/
+  void set property7(int value);
+
+  /*member: Interface.property8:int?*/
+  int? get property8;
+
+  /*member: Interface.property8=:int?*/
+  void set property8(int? value);
+}
+
+/*class: Class:Class,Object*/
+class Class {
+  /*member: Class.method1:int! Function()!*/
+  int method1() => 0;
+
+  /*member: Class.method2:int? Function()!*/
+  int? method2() => 0;
+
+  /*member: Class.method5a:int! Function(int!,int?)!*/
+  int method5a(int a, int? b) => 0;
+
+  /*member: Class.method5b:int! Function(int!,[int?])!*/
+  int method5b(int a, [int? b]) => 0;
+
+  /*member: Class.method5c:int! Function([int!,int?])!*/
+  int method5c([int a = 0, int? b]) => 0;
+
+  /*member: Class.method7a:int! Function(int!,{int? b})!*/
+  int method7a(int a, {int? b}) => 0;
+
+  /*member: Class.method7b:int! Function({int! a,int? b})!*/
+  int method7b({int a: 0, int? b}) => 0;
+
+  /*member: Class.method9a:int! Function(int!,{required int? b})!*/
+  int method9a(int a, {required int? b}) => 0;
+
+  /*member: Class.method9b:int! Function({required int! a,required int? b})!*/
+  int method9b({required int a, required int? b}) => 0;
+
+  /*member: Class.getter1:int!*/
+  int get getter1 => 0;
+
+  /*member: Class.getter2:int?*/
+  int? get getter2 => 0;
+
+  /*member: Class.setter1=:int!*/
+  void set setter1(int value) {}
+
+  /*member: Class.setter2=:int?*/
+  void set setter2(int? value) {}
+
+  /*member: Class.field1:int!*/
+  int field1 = 0;
+
+  /*member: Class.field2:int?*/
+  int? field2;
+
+  /*member: Class.field5:int!*/
+  var field5 = 0;
+
+  /*member: Class.field6a:int!*/
+  var field6a = 0;
+
+  /*member: Class.field6b:int?*/
+  var field6b = constant;
+
+  /*member: Class.property1:int!*/
+  int get property1 => 0;
+
+  /*member: Class.property1=:int!*/
+  void set property1(int value) {}
+
+  /*member: Class.property2:int?*/
+  int? get property2 => 0;
+
+  /*member: Class.property2=:int?*/
+  void set property2(int? value) {}
+
+  /*member: Class.property5:int!*/
+  int property5 = 0;
+
+  /*member: Class.property6:int?*/
+  int? property6;
+}
+
+const int? constant = 0;
+
+/*class: GenericInterface:GenericInterface<T>,Object*/
+abstract class GenericInterface<T> {
+  /*member: GenericInterface.genericMethod1:S Function<S>(T,S,{T c,S d})!*/
+  S genericMethod1<S>(T a, S b, {T c, S d});
+
+  /*member: GenericInterface.genericMethod2:S Function<S>(T,S,[T,S])!*/
+  S genericMethod2<S>(T a, S b, [T c, S d]);
+}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_out/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_out/main.dart
new file mode 100644
index 0000000..2af78cb
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_out/main.dart
@@ -0,0 +1,305 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*library: nnbd=true*/
+library main;
+
+import 'opt_out.dart';
+
+/*class: Interface:Interface,Object*/
+abstract class Interface {
+  /*member: Interface.method1:int! Function()!*/
+  int method1();
+
+  /*member: Interface.method2:int? Function()!*/
+  int? method2();
+
+  /*member: Interface.method3a:int! Function(int!,int!)!*/
+  int method3a(int a, int b);
+
+  /*member: Interface.method3b:int! Function(int!,[int!])!*/
+  int method3b(int a, [int b]);
+
+  /*member: Interface.method3c:int! Function([int!,int!])!*/
+  int method3c([int a, int b]);
+
+  /*member: Interface.method4a:int? Function(int?,int?)!*/
+  int? method4a(int? a, int? b);
+
+  /*member: Interface.method4b:int? Function(int?,[int?])!*/
+  int? method4b(int? a, [int? b]);
+
+  /*member: Interface.method4c:int? Function([int?,int?])!*/
+  int? method4c([int? a, int? b]);
+
+  /*member: Interface.method5a:int! Function(int!,{int! b})!*/
+  int method5a(int a, {int b: 0});
+
+  /*member: Interface.method5b:int! Function({int! a,int! b})!*/
+  int method5b({int a: 0, int b: 0});
+
+  /*member: Interface.method5c:int! Function({required int! a,required int! b})!*/
+  int method5c({required int a: 0, required int b: 0});
+
+  /*member: Interface.method6a:int? Function(int?,{int? b})!*/
+  int? method6a(int? a, {int? b});
+
+  /*member: Interface.method6b:int? Function({int? a,int? b})!*/
+  int? method6b({int? a, int? b});
+
+  /*member: Interface.method6c:int? Function({required int? a,required int? b})!*/
+  int? method6c({required int? a, required int? b});
+
+  /*member: Interface.getter1:int!*/
+  int get getter1;
+
+  /*member: Interface.getter2:int?*/
+  int? get getter2;
+
+  /*member: Interface.setter1=:int!*/
+  void set setter1(int value);
+
+  /*member: Interface.setter2=:int?*/
+  void set setter2(int? value);
+
+  /*member: Interface.field1:int!*/
+  int field1 = 0;
+
+  /*member: Interface.field2:int?*/
+  int? field2;
+
+  /*member: Interface.field3:int!*/
+  int get field3;
+
+  /*member: Interface.field3=:int!*/
+  void set field3(int value);
+
+  /*member: Interface.field4:int?*/
+  int? get field4;
+
+  /*member: Interface.field4=:int?*/
+  void set field4(int? value);
+
+  /*member: Interface.field5:int!*/
+  var field5 = 0;
+
+  /*member: Interface.field6:int?*/
+  var field6 = constant;
+
+  /*member: Interface.property1:int!*/
+  int get property1;
+
+  /*member: Interface.property1=:int!*/
+  void set property1(int value);
+
+  /*member: Interface.property2:int?*/
+  int? get property2;
+
+  /*member: Interface.property2=:int?*/
+  void set property2(int? value);
+
+  /*member: Interface.property3:int!*/
+  int property3 = 0;
+
+  /*member: Interface.property4:int?*/
+  int? property4;
+}
+
+/*class: Class1:Class1,LegacyClass,Object*/
+class Class1 extends LegacyClass {
+  /*member: Class1.method1:int* Function()**/
+  /*member: Class1.method2:int* Function()**/
+  /*member: Class1.method3a:int* Function(int*,int*)**/
+  /*member: Class1.method3b:int* Function(int*,[int*])**/
+  /*member: Class1.method3c:int* Function([int*,int*])**/
+  /*member: Class1.method4a:int* Function(int*,int*)**/
+  /*member: Class1.method4b:int* Function(int*,[int*])**/
+  /*member: Class1.method4c:int* Function([int*,int*])**/
+  /*member: Class1.method5a:int* Function(int*,{int* b})**/
+  /*member: Class1.method5b:int* Function({int* a,int* b})**/
+  /*member: Class1.method5c:int* Function({int* a,int* b})**/
+  /*member: Class1.method6a:int* Function(int*,{int* b})**/
+  /*member: Class1.method6b:int* Function({int* a,int* b})**/
+  /*member: Class1.method6c:int* Function({int* a,int* b})**/
+  /*member: Class1.getter1:int**/
+  /*member: Class1.getter2:int**/
+  /*member: Class1.setter1=:int**/
+  /*member: Class1.setter2=:int**/
+  /*member: Class1.field1:int**/
+  /*member: Class1.field2:int**/
+  /*member: Class1.field3:int**/
+  /*member: Class1.field4:int**/
+  /*member: Class1.field5:int**/
+  /*member: Class1.field6:int**/
+  /*member: Class1.property1:int**/
+  /*member: Class1.property1=:int**/
+  /*member: Class1.property2:int**/
+  /*member: Class1.property2=:int**/
+  /*member: Class1.property3:int**/
+  /*member: Class1.property3=:int**/
+  /*member: Class1.property4:int**/
+  /*member: Class1.property4=:int**/
+}
+
+/*class: Class2a:Class2a,Interface,LegacyClass,Object*/
+class Class2a extends LegacyClass implements Interface {
+  /*member: Class2a.method1:int! Function()!*/
+  /*member: Class2a.method2:int? Function()!*/
+  /*member: Class2a.method3a:int! Function(int!,int!)!*/
+  /*member: Class2a.method3b:int! Function(int!,[int!])!*/
+  /*member: Class2a.method3c:int! Function([int!,int!])!*/
+  /*member: Class2a.method4a:int? Function(int?,int?)!*/
+  /*member: Class2a.method4b:int? Function(int?,[int?])!*/
+  /*member: Class2a.method4c:int? Function([int?,int?])!*/
+  /*member: Class2a.method5a:int! Function(int!,{int! b})!*/
+  /*member: Class2a.method5b:int! Function({int! a,int! b})!*/
+  // TODO(johnniwinther): Should `method5c` be an error? It mixes required
+  // and optional named parameters.
+  /*member: Class2a.method5c:int! Function({int! a,int! b})!*/
+  /*member: Class2a.method6a:int? Function(int?,{int? b})!*/
+  /*member: Class2a.method6b:int? Function({int? a,int? b})!*/
+  // TODO(johnniwinther): Should `method6c` be an error? It mixes required
+  // and optional named parameters.
+  /*member: Class2a.method6c:int? Function({int? a,int? b})!*/
+  /*member: Class2a.getter1:int!*/
+  /*member: Class2a.getter2:int?*/
+  /*member: Class2a.setter1=:int!*/
+  /*member: Class2a.setter2=:int?*/
+  /*member: Class2a.field1:int!*/
+  /*member: Class2a.field1=:int!*/
+  /*member: Class2a.field2:int?*/
+  /*member: Class2a.field2=:int?*/
+  /*member: Class2a.field3:int!*/
+  /*member: Class2a.field3=:int!*/
+  /*member: Class2a.field4:int?*/
+  /*member: Class2a.field4=:int?*/
+  /*member: Class2a.field5:int!*/
+  /*member: Class2a.field5=:int!*/
+  /*member: Class2a.field6:int?*/
+  /*member: Class2a.field6=:int?*/
+  /*member: Class2a.property1:int!*/
+  /*member: Class2a.property1=:int!*/
+  /*member: Class2a.property2:int?*/
+  /*member: Class2a.property2=:int?*/
+  /*member: Class2a.property3:int!*/
+  /*member: Class2a.property3=:int!*/
+  /*member: Class2a.property4:int?*/
+  /*member: Class2a.property4=:int?*/
+}
+
+/*class: Class2b:Class2b,Interface,LegacyClass,Object*/
+class Class2b extends LegacyClass implements Interface {
+  /*member: Class2b.method1:int! Function()!*/
+  int method1() => 0;
+
+  /*member: Class2b.method2:int? Function()!*/
+  int? method2() => 0;
+
+  /*member: Class2b.method3a:int! Function(int!,int!)!*/
+  int method3a(int a, int b) => 0;
+
+  /*member: Class2b.method3b:int! Function(int!,[int!])!*/
+  int method3b(int a, [int b]) => 0;
+
+  /*member: Class2b.method3c:int! Function([int!,int!])!*/
+  int method3c([int a, int b]) => 0;
+
+  /*member: Class2b.method4a:int? Function(int?,int?)!*/
+  int? method4a(int? a, int? b) => 0;
+
+  /*member: Class2b.method4b:int? Function(int?,[int?])!*/
+  int? method4b(int? a, [int? b]) => 0;
+
+  /*member: Class2b.method4c:int? Function([int?,int?])!*/
+  int? method4c([int? a, int? b]) => 0;
+
+  /*member: Class2b.method5a:int! Function(int!,{int! b})!*/
+  int method5a(int a, {int b: 0}) => 0;
+
+  /*member: Class2b.method5b:int! Function({int! a,int! b})!*/
+  int method5b({int a: 0, int b: 0}) => 0;
+
+  /*member: Class2b.method5c:int! Function({required int! a,required int! b})!*/
+  int method5c({required int a: 0, required int b: 0}) => 0;
+
+  /*member: Class2b.method6a:int? Function(int?,{int? b})!*/
+  int? method6a(int? a, {int? b}) => 0;
+
+  /*member: Class2b.method6b:int? Function({int? a,int? b})!*/
+  int? method6b({int? a, int? b}) => 0;
+
+  /*member: Class2b.method6c:int? Function({required int? a,required int? b})!*/
+  int? method6c({required int? a, required int? b}) => 0;
+
+  /*member: Class2b.getter1:int!*/
+  int get getter1 => 0;
+
+  /*member: Class2b.getter2:int?*/
+  int? get getter2 => 0;
+
+  /*member: Class2b.setter1=:int!*/
+  void set setter1(int value) {}
+
+  /*member: Class2b.setter2=:int?*/
+  void set setter2(int? value) {}
+
+  /*member: Class2b.field1:int!*/
+  int field1 = 0;
+
+  /*member: Class2b.field2:int?*/
+  int? field2;
+
+  /*member: Class2b.field3:int!*/
+  int get field3 => 0;
+
+  /*member: Class2b.field3=:int!*/
+  void set field3(int value) {}
+
+  /*member: Class2b.field4:int?*/
+  int? get field4 => 0;
+
+  /*member: Class2b.field5:int!*/
+  int field5;
+
+  /*member: Class2b.field6:int?*/
+  int? field6;
+
+  /*member: Class2b.field4=:int?*/
+  void set field4(int? value) {}
+
+  /*member: Class2b.property1:int!*/
+  int get property1 => 0;
+
+  /*member: Class2b.property1=:int!*/
+  void set property1(int value) {}
+
+  /*member: Class2b.property2:int?*/
+  int? get property2 => 0;
+
+  /*member: Class2b.property2=:int?*/
+  void set property2(int? value) {}
+
+  /*member: Class2b.property3:int!*/
+  int property3 = 0;
+
+  /*member: Class2b.property4:int?*/
+  int? property4;
+}
+
+/*class: Class3a:Class3a,GenericLegacyClass<int!>,Object*/
+class Class3a extends GenericLegacyClass<int> {
+  /*member: Class3a.method1:int* Function()**/
+}
+
+/*class: Class3b:Class3b,GenericLegacyClass<int?>,Object*/
+class Class3b extends GenericLegacyClass<int?> {
+  /*member: Class3b.method1:int? Function()**/
+}
+
+/*class: Class3c:Class3c<S>,GenericLegacyClass<S>,Object*/
+class Class3c<S> extends GenericLegacyClass<S> {
+  /*member: Class3c.method1:S* Function()**/
+}
+
+const int? constant = 0;
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_out/opt_out.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_out/opt_out.dart
new file mode 100644
index 0000000..c1bd807
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/members_from_opt_out/opt_out.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+/*library: nnbd=false*/
+library opt_out;
+
+/*class: LegacyClass:LegacyClass,Object*/
+class LegacyClass {
+  /*member: LegacyClass.method1:int* Function()**/
+  int method1() => 0;
+
+  /*member: LegacyClass.method2:int* Function()**/
+  int method2() => 0;
+
+  /*member: LegacyClass.method3a:int* Function(int*,int*)**/
+  int method3a(int a, int b) => 0;
+
+  /*member: LegacyClass.method3b:int* Function(int*,[int*])**/
+  int method3b(int a, [int b]) => 0;
+
+  /*member: LegacyClass.method3c:int* Function([int*,int*])**/
+  int method3c([int a, int b]) => 0;
+
+  /*member: LegacyClass.method4a:int* Function(int*,int*)**/
+  int method4a(int a, int b) => 0;
+
+  /*member: LegacyClass.method4b:int* Function(int*,[int*])**/
+  int method4b(int a, [int b]) => 0;
+
+  /*member: LegacyClass.method4c:int* Function([int*,int*])**/
+  int method4c([int a, int b]) => 0;
+
+  /*member: LegacyClass.method5a:int* Function(int*,{int* b})**/
+  int method5a(int a, {int b}) => 0;
+
+  /*member: LegacyClass.method5b:int* Function({int* a,int* b})**/
+  int method5b({int a, int b}) => 0;
+
+  /*member: LegacyClass.method5c:int* Function({int* a,int* b})**/
+  int method5c({int a, int b}) => 0;
+
+  /*member: LegacyClass.method6a:int* Function(int*,{int* b})**/
+  int method6a(int a, {int b}) => 0;
+
+  /*member: LegacyClass.method6b:int* Function({int* a,int* b})**/
+  int method6b({int a, int b}) => 0;
+
+  /*member: LegacyClass.method6c:int* Function({int* a,int* b})**/
+  int method6c({int a, int b}) => 0;
+
+  /*member: LegacyClass.getter1:int**/
+  int get getter1 => 0;
+
+  /*member: LegacyClass.getter2:int**/
+  int get getter2 => 0;
+
+  /*member: LegacyClass.setter1=:int**/
+  void set setter1(int value) {}
+
+  /*member: LegacyClass.setter2=:int**/
+  void set setter2(int value) {}
+
+  /*member: LegacyClass.field1:int**/
+  int field1;
+
+  /*member: LegacyClass.field2:int**/
+  int field2;
+
+  /*member: LegacyClass.field3:int**/
+  int field3;
+
+  /*member: LegacyClass.field4:int**/
+  int field4;
+
+  /*member: LegacyClass.field5:int**/
+  var field5 = 0;
+
+  /*member: LegacyClass.field6:int**/
+  int field6 = 0;
+
+  /*member: LegacyClass.property1:int**/
+  int get property1 => 0;
+
+  /*member: LegacyClass.property1=:int**/
+  void set property1(int value) {}
+
+  /*member: LegacyClass.property2:int**/
+  int get property2 => 0;
+
+  /*member: LegacyClass.property2=:int**/
+  void set property2(int value) {}
+
+  /*member: LegacyClass.property3:int**/
+  int get property3 => 0;
+
+  /*member: LegacyClass.property3=:int**/
+  void set property3(int value) {}
+
+  /*member: LegacyClass.property4:int**/
+  int get property4 => 0;
+
+  /*member: LegacyClass.property4=:int**/
+  void set property4(int value) {}
+}
+
+/*class: GenericLegacyClass:GenericLegacyClass<T*>,Object*/
+class GenericLegacyClass<T> {
+  /*member: GenericLegacyClass.method1:T* Function()**/
+  T method1() => null;
+}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/members_opt_in.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/members_opt_in.dart
new file mode 100644
index 0000000..199378bf
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/members_opt_in.dart
@@ -0,0 +1,39 @@
+// 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*/
+
+abstract class /*class: A1:A1,Object*/ A1 {
+  void /*member: A1.close:void Function()!*/ close();
+}
+
+abstract class /*class: B1:B1,Object*/ B1 {
+  Object /*member: B1.close:Object! Function()!*/ close();
+}
+
+abstract class /*class: C1a:A1,B1,C1a,Object*/ C1a implements A1, B1 {
+  Object /*member: C1a.close:Object! Function()!*/ close();
+}
+
+abstract class /*class: C1b:A1,B1,C1b,Object*/ C1b implements B1, A1 {
+  Object /*member: C1b.close:Object! Function()!*/ close();
+}
+
+abstract class /*class: A2:A2<T>,Object*/ A2<T> {
+  void /*member: A2.close:void Function()!*/ close();
+}
+
+abstract class /*class: B2:B2<T>,Object*/ B2<T> {
+  Object /*member: B2.close:Object! Function()!*/ close();
+}
+
+abstract class /*class: C2a:A2<T>,B2<T>,C2a<T>,Object*/ C2a<T>
+    implements A2<T>, B2<T> {
+  Object /*member: C2a.close:Object! Function()!*/ close();
+}
+
+abstract class /*class: C2b:A2<T>,B2<T>,C2b<T>,Object*/ C2b<T>
+    implements B2<T>, A2<T> {
+  Object /*member: C2b.close:Object! Function()!*/ close();
+}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/members_opt_out.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/members_opt_out.dart
new file mode 100644
index 0000000..db11524
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/members_opt_out.dart
@@ -0,0 +1,68 @@
+// 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
+
+/*library: nnbd=false*/
+
+abstract class /*class: A1:A1,Object*/ A1 {
+  void /*member: A1.close:void Function()**/ close();
+}
+
+abstract class /*class: B1:B1,Object*/ B1 {
+  Object /*member: B1.close:Object* Function()**/ close();
+}
+
+abstract class /*class: C1a:A1,B1,C1a,Object*/ C1a implements A1, B1 {
+  Object /*member: C1a.close:Object* Function()**/ close();
+}
+
+abstract class /*class: C1b:A1,B1,C1b,Object*/ C1b implements B1, A1 {
+  Object /*member: C1b.close:Object* Function()**/ close();
+}
+
+abstract class /*class: A2:A2<T*>,Object*/ A2<T> {
+  void /*member: A2.close:void Function()**/ close();
+}
+
+abstract class /*class: B2a:B2a<T*>,Object*/ B2a<T> {
+  Object /*member: B2a.close:Object* Function()**/ close();
+}
+
+abstract class /*class: B2b:B2a<dynamic>,B2b<T*>,Object*/ B2b<T>
+    implements B2a {
+  Object /*member: B2b.close:Object* Function()**/ close();
+}
+
+abstract class /*class: C2a:A2<T*>,B2a<dynamic>,B2b<T*>,C2a<T*>,Object*/ C2a<T>
+    implements A2<T>, B2b<T> {
+  Object /*member: C2a.close:Object* Function()**/ close();
+}
+
+abstract class /*class: C2b:A2<T*>,B2a<dynamic>,B2b<T*>,C2b<T*>,Object*/ C2b<T>
+    implements B2b<T>, A2<T> {
+  Object /*member: C2b.close:Object* Function()**/ close();
+}
+
+abstract class /*class: A3a:A3a<T*>,Object*/ A3a<T> {
+  void /*member: A3a.close:void Function()**/ close();
+}
+
+abstract class /*class: A3b:A3a<T*>,A3b<T*>,Object*/ A3b<T> implements A3a<T> {
+  void /*member: A3b.close:void Function()**/ close();
+}
+
+abstract class /*class: B3:B3<T*>,Object*/ B3<T> {
+  Object /*member: B3.close:Object* Function()**/ close();
+}
+
+abstract class /*class: C3a:A3a<T*>,A3b<T*>,B3<T*>,C3a<T*>,Object*/ C3a<T>
+    implements A3b<T>, B3<T> {
+  Object /*member: C3a.close:Object* Function()**/ close();
+}
+
+abstract class /*class: C3b:A3a<T*>,A3b<T*>,B3<T*>,C3b<T*>,Object*/ C3b<T>
+    implements B3<T>, A3b<T> {
+  Object /*member: C3b.close:Object* Function()**/ close();
+}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/sink.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/sink.dart
new file mode 100644
index 0000000..e1cc6c6
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/sink.dart
@@ -0,0 +1,31 @@
+// 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=false*/
+
+// @dart=2.6
+
+/*class: Sink:Object,Sink<T*>*/
+abstract class Sink<T> {
+  /*member: Sink.close:void Function()**/
+  void close();
+}
+
+/*class: EventSink:EventSink<T*>,Object,Sink<T*>*/
+abstract class EventSink<T> implements Sink<T> {
+  /*member: EventSink.close:void Function()**/
+  void close();
+}
+
+/*class: StreamConsumer:Object,StreamConsumer<S*>*/
+abstract class StreamConsumer<S> {
+  /*member: StreamConsumer.close:Future<dynamic>* Function()**/
+  Future close();
+}
+
+/*class: StreamSink:EventSink<S*>,Object,Sink<S*>,StreamConsumer<S*>,StreamSink<S*>*/
+abstract class StreamSink<S> implements EventSink<S>, StreamConsumer<S> {
+  /*member: StreamSink.close:Future<dynamic>* Function()**/
+  Future close();
+}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/dart_page_script.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/dart_page_script.dart
index c991788..08077fa 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/dart_page_script.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/dart_page_script.dart
@@ -173,6 +173,28 @@
   });
 }
 
+function debounce(fn, delay) {
+  var timeout;
+  return function() {
+    var later = function() {
+      timeout = null;
+    };
+    var callNow = !timeout;
+    clearTimeout(timeout);
+    timeout = setTimeout(later, delay);
+    if (callNow) fn.apply(this);
+	};
+};
+
+// Resize the fixed-size and fixed-position navigation panel.
+function resizeNav() {
+  const navInner = document.querySelector(".nav-inner");
+  // TODO(srawlins): I'm honestly not sure where 30 comes from; but without
+  // `- 30`, the navigation is too tall and the bottom cannot be seen.
+  const height = window.innerHeight - 30;
+  navInner.style.height = height + "px";
+}
+
 document.addEventListener("DOMContentLoaded", (event) => {
   const path = window.location.pathname;
   const offset = getOffset(window.location.href);
@@ -183,6 +205,7 @@
     loadFile(path, offset, lineNumber,
         () => { pushState(path, offset, lineNumber) });
   }
+  resizeNav();
   addClickHandlers(".nav");
 });
 
@@ -198,4 +221,28 @@
     updatePage("&nbsp;", null);
   }
 });
+
+window.addEventListener("resize", (event) => {
+  debounce(resizeNav, 200)();
+});
+
+window.addEventListener("scroll", (event) => {
+  const nav = document.querySelector(".nav");
+  const navInner = nav.querySelector(".nav-inner");
+  const navTip = nav.querySelector(".nav-tip");
+  const navTipMarginBottom = 14;
+  if (window.pageYOffset >
+          nav.offsetTop + navTip.offsetHeight + navTipMarginBottom) {
+    if (!navInner.classList.contains("fixed")) {
+      nav.style.width = nav.offsetWidth + "px";
+      navInner.classList.add("fixed");
+    }
+  } else {
+    if (navInner.classList.contains("fixed")) {
+      nav.style.width = "";
+      navInner.classList.remove("fixed");
+    }
+  }
+  debounce(resizeNav, 200)();
+});
 ''';
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/dart_page_style.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/dart_page_style.dart
index a89349e..2be57cc 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/dart_page_style.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/dart_page_style.dart
@@ -10,7 +10,7 @@
   /* This allows very small files to be displayed lower than the very top of the
    * screen.
    */
-  margin-bottom: 100px;
+  margin: 8px;
   padding: 0.5em;
 }
 
@@ -20,7 +20,7 @@
   margin: 0;
 }
 
-h2.unit-name {
+h2#unit-name {
   font-size: 1.2em;
   font-weight: 600;
   margin: 0;
@@ -31,7 +31,6 @@
   flex-wrap: wrap;
 }
 
-
 .nav-link {
   cursor: pointer;
 }
@@ -39,30 +38,40 @@
 .nav {
   background-color: #282b2e;
   flex-basis: 0;
-  flex-grow: 1;
+  flex: 0 1 auto;
   font-size: 14px;
   /* 10px to match exact top margin of .content.
    * 0.8em to pair with the -0.5em margin of .content, producing a net margin
    * between the two of 0.3em.
    */
-  margin: 10px 0.8em 10px 0;
-  padding: 0.5em;
+  margin: 10px 0.8em 0 0;
 }
 
 .nav :first-child {
   margin-top: 0;
 }
 
-.nav .root {
+.nav-inner {
+  background-color: #282b2e;
+  overflow: auto;
+  padding: 7px 0 7px 7px;
+}
+
+.nav-inner.fixed {
+  position: fixed;
+  top: 0;
+}
+
+.nav-inner .root {
   margin: 0;
 }
 
-.nav .nav-link {
+.nav-inner .nav-link {
   color: #33ccff;
   margin-left: 1em;
 }
 
-.nav .selected-file {
+.nav-inner .selected-file {
   color: white;
   cursor: inherit;
   font-weight: 600;
@@ -70,13 +79,12 @@
 }
 
 .content {
-  flex: 1;
+  flex: 1 1 700px;
   font-family: monospace;
   /* Vertical margin around content. */
   margin: 10px 0;
   /* Offset the margin introduced by the absolutely positioned child div. */
   margin-left: -0.5em;
-  min-width: 900px;
   position: relative;
   white-space: pre;
 }
@@ -215,4 +223,8 @@
   position: relative;
   visibility: visible;
 }
+
+.footer {
+  padding: 8px 8px 100px 8px;
+}
 ''';
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
index bc23fbf..632fc35 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
@@ -29,15 +29,19 @@
     <h2 id="unit-name">&nbsp;</h2>
     <div class="panels">
     <div class="horizontal">
-    <div class="nav" style="">
-      <p>Select a source file below to preview the modifications.</p>
-      <p class="root">{{ root }}</p>
-      {{# links }}
-        <a href="{{ path }}" class="nav-link"
-            data-name="{{ name }}">{{ name }}</a>
-        {{ modificationCount }}
-        <br/>
-      {{/ links }}
+    <div class="nav">
+      <p class="nav-tip">
+      Select a source file below to preview the modifications.
+      </p>
+      <div class="nav-inner">
+        <p class="root">{{ root }}</p>
+        {{# links }}
+          <a href="{{ path }}" class="nav-link"
+              data-name="{{ name }}">{{ name }}</a>
+          {{ modificationCount }}
+          <br/>
+        {{/ links }}
+      </div><!-- /nav-inner -->
     </div><!-- /nav -->
     '''
     '<div class="content">'
@@ -46,10 +50,10 @@
     '{{! The regions are then written again, overlaying the first copy of }}'
     '{{! the content, to provide tooltips for modified regions. }}'
     '</div><!-- /regions -->'
+    '<div class="footer"><em>Generated on {{ generationDate }}</em></div>'
     '</div><!-- /content -->'
     '''
     </div><!-- /horizontal -->
-    <div><em>Generated on {{ generationDate }}</em></div>
     </div><!-- /panels -->
     <script lang="javascript">
 document.addEventListener("DOMContentLoaded", highlightAllCode);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index c2dbb1e..a3fdab1 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -12,7 +12,9 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/util/comment.dart';
+import 'package:meta/meta.dart';
 
 /**
  * Determine the number of arguments.
@@ -139,6 +141,64 @@
   DartCompletionRequest request;
   List<CompletionSuggestion> suggestions;
 
+  List<CompletionSuggestion> buildClosureSuggestions(
+    DartCompletionRequest request,
+    Expression argument,
+    DartType type,
+  ) {
+    if (type is FunctionType) {
+      var indent = getRequestLineIndent(request);
+      var parametersString = _buildClosureParameters(type);
+
+      var blockBuffer = StringBuffer(parametersString);
+      blockBuffer.writeln(' {');
+      blockBuffer.write('$indent  ');
+      var blockSelectionOffset = blockBuffer.length;
+      blockBuffer.writeln();
+      blockBuffer.write('$indent}');
+
+      var expressionBuffer = StringBuffer(parametersString);
+      expressionBuffer.write(' => ');
+      var expressionSelectionOffset = expressionBuffer.length;
+
+      if (argument.endToken.next?.type != TokenType.COMMA) {
+        blockBuffer.write(',');
+        expressionBuffer.write(',');
+      }
+
+      CompletionSuggestion createSuggestion({
+        @required String completion,
+        @required String displayText,
+        @required int selectionOffset,
+      }) {
+        return CompletionSuggestion(
+          CompletionSuggestionKind.INVOCATION,
+          DART_RELEVANCE_HIGH,
+          completion,
+          selectionOffset,
+          0,
+          false,
+          false,
+          displayText: displayText,
+        );
+      }
+
+      return [
+        createSuggestion(
+          completion: blockBuffer.toString(),
+          displayText: '$parametersString {}',
+          selectionOffset: blockSelectionOffset,
+        ),
+        createSuggestion(
+          completion: expressionBuffer.toString(),
+          displayText: '$parametersString =>',
+          selectionOffset: expressionSelectionOffset,
+        ),
+      ];
+    }
+    return const <CompletionSuggestion>[];
+  }
+
   @override
   Future<List<CompletionSuggestion>> computeSuggestions(
       DartCompletionRequest request) async {
@@ -245,6 +305,14 @@
       _addDefaultParamSuggestions(parameters, true);
     } else if (_isInsertingToArgListWithSynthetic(request)) {
       _addDefaultParamSuggestions(parameters, !_isFollowedByAComma(request));
+    } else {
+      final argument = request.target.containingNode;
+      if (argument is NamedExpression) {
+        final type = argument.staticParameterElement?.type;
+        final closureSuggestions =
+            buildClosureSuggestions(request, argument, type);
+        suggestions.addAll(closureSuggestions);
+      }
     }
   }
 
@@ -272,6 +340,38 @@
     return newExpr != null && flutter.isWidgetCreation(newExpr);
   }
 
+  static String _buildClosureParameters(FunctionType type) {
+    var buffer = StringBuffer();
+    buffer.write('(');
+
+    var hasNamed = false;
+    var hasOptionalPositional = false;
+    var parameters = type.parameters;
+    for (var i = 0; i < parameters.length; ++i) {
+      var parameter = parameters[i];
+      if (i != 0) {
+        buffer.write(', ');
+      }
+      if (parameter.isNamed && !hasNamed) {
+        hasNamed = true;
+        buffer.write('{');
+      } else if (parameter.isOptionalPositional && !hasOptionalPositional) {
+        hasOptionalPositional = true;
+        buffer.write('[');
+      }
+      buffer.write(parameter.name);
+    }
+
+    if (hasNamed) {
+      buffer.write('}');
+    } else if (hasOptionalPositional) {
+      buffer.write(']');
+    }
+
+    buffer.write(')');
+    return buffer.toString();
+  }
+
   /**
    * If the given [comment] is not `null`, fill the [suggestion] documentation
    * fields.
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 21c0085..e1c138d 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
@@ -6,6 +6,7 @@
 
 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';
@@ -127,19 +128,7 @@
         element.name == 'setState' &&
         Flutter.of(request.result).isExactState(element.enclosingElement)) {
       // Find the line indentation.
-      String content = request.result.content;
-      int lineStartOffset = request.offset;
-      int notWhitespaceOffset = request.offset;
-      for (; lineStartOffset > 0; lineStartOffset--) {
-        var char = content.substring(lineStartOffset - 1, lineStartOffset);
-        if (char == '\n') {
-          break;
-        }
-        if (char != ' ' && char != '\t') {
-          notWhitespaceOffset = lineStartOffset - 1;
-        }
-      }
-      String indent = content.substring(lineStartOffset, notWhitespaceOffset);
+      String indent = getRequestLineIndent(request);
 
       // Let the user know that we are going to insert a complete statement.
       suggestion.displayText = 'setState(() {});';
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index cf43ac8..b2140d3 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -24,6 +24,17 @@
 const DYNAMIC = 'dynamic';
 
 /**
+ * Sort by relevance first, highest to lowest, and then by the completion
+ * alphabetically.
+ */
+Comparator<CompletionSuggestion> completionComparator = (a, b) {
+  if (a.relevance == b.relevance) {
+    return a.completion.compareTo(b.completion);
+  }
+  return b.relevance.compareTo(a.relevance);
+};
+
+/**
  * A marker used in place of `null` when a function has no return type.
  */
 final TypeName NO_RETURN_TYPE = astFactory.typeName(
@@ -174,6 +185,22 @@
   return null;
 }
 
+String getRequestLineIndent(DartCompletionRequest request) {
+  var content = request.result.content;
+  var lineStartOffset = request.offset;
+  var notWhitespaceOffset = request.offset;
+  for (; lineStartOffset > 0; lineStartOffset--) {
+    var char = content.substring(lineStartOffset - 1, lineStartOffset);
+    if (char == '\n') {
+      break;
+    }
+    if (char != ' ' && char != '\t') {
+      notWhitespaceOffset = lineStartOffset - 1;
+    }
+  }
+  return content.substring(lineStartOffset, notWhitespaceOffset);
+}
+
 String getTypeString(DartType type) {
   if (type.isDynamic) {
     return '';
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 57f0293..e379cc2 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -1465,6 +1465,11 @@
       int replaceOffset = 0;
       bool hasBuildMethod = false;
 
+      var typeParams = '';
+      if (widgetClass.typeParameters != null) {
+        typeParams = utils.getNodeText(widgetClass.typeParameters);
+      }
+
       /// Replace code between [replaceOffset] and [replaceEnd] with
       /// `createState()`, empty line, or nothing.
       void replaceInterval(int replaceEnd,
@@ -1480,7 +1485,8 @@
                 builder.writeln();
               }
               builder.writeln('  @override');
-              builder.writeln('  $stateName createState() => $stateName();');
+              builder.writeln(
+                  '  $stateName$typeParams createState() => $stateName$typeParams();');
               if (hasEmptyLineAfterCreateState) {
                 builder.writeln();
               }
@@ -1533,11 +1539,6 @@
         builder.writeln();
         builder.writeln();
 
-        var typeParams = '';
-        if (widgetClass.typeParameters != null) {
-          typeParams = utils.getNodeText(widgetClass.typeParameters);
-        }
-
         builder.write('class $stateName$typeParams extends ');
         builder.writeReference(stateClass);
 
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index e52b7b0..4b10bed 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -193,8 +193,8 @@
     MockSdk(resourceProvider: resourceProvider);
 
     newFolder('/home/test');
-    newFile('/home/test/.packages', content: r'''
-test:file:///home/test/lib
+    newFile('/home/test/.packages', content: '''
+test:${toUriStr('/home/test/lib')}
 ''');
 
     createAnalysisContexts();
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index d4fee97..b5319f5 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:convert';
 
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
@@ -648,18 +647,8 @@
 }
 ''');
     var hover = await prepareHover('f(null)');
-    _assertJsonText(hover, r'''
-{
-  "offset": 39,
-  "length": 1,
-  "containingLibraryPath": "/project/bin/test.dart",
-  "containingLibraryName": "bin/test.dart",
-  "elementDescription": "int? f(double? a)",
-  "elementKind": "function",
-  "isDeprecated": false,
-  "staticType": "int? Function(double?)"
-}
-''');
+    expect(hover.elementDescription, 'int? f(double? a)');
+    expect(hover.staticType, 'int? Function(double?)');
   }
 
   test_parameter_declaration_fieldFormal() async {
@@ -727,15 +716,4 @@
     expect(hover.elementKind, 'parameter');
     expect(hover.staticType, 'int');
   }
-
-  void _assertJsonText(Object object, String expected) {
-    expected = expected.trimRight();
-    var actual = JsonEncoder.withIndent('  ').convert(object);
-    if (actual != expected) {
-      print('-----');
-      print(actual);
-      print('-----');
-    }
-    expect(actual, expected);
-  }
 }
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 895a345..3fa52ff 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -621,7 +621,7 @@
     String packagePathFoo = convertPath('/package1/foo');
     String packageRootPath = convertPath('/package2/foo');
     newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
-        content: 'foo:file:///package1/foo');
+        content: 'foo:${toUriStr('/package1/foo')}');
     Folder packageFolder = resourceProvider.newFolder(packagePathFoo);
     List<String> includedPaths = <String>[projPath];
     List<String> excludedPaths = <String>[];
@@ -874,7 +874,7 @@
   void test_setRoots_newlyAddedFoldersGetProperPackageMap() {
     String packagePath = convertPath('/package/foo');
     newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
-        content: 'foo:file:///package/foo');
+        content: 'foo:${toUriStr('/package/foo')}');
     Folder packageFolder = resourceProvider.newFolder(packagePath);
     manager.setRoots(<String>[projPath], <String>[], <String, String>{});
     expect(
@@ -1058,7 +1058,7 @@
     String packageRootPath = convertPath('/package2/foo');
     Folder packageFolder = resourceProvider.newFolder(packagePathFoo);
     newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
-        content: 'foo:file:///package1/foo');
+        content: 'foo:${toUriStr('/package1/foo')}');
     List<String> includedPaths = <String>[projPath];
     List<String> excludedPaths = <String>[];
     manager.setRoots(includedPaths, excludedPaths,
@@ -1879,7 +1879,7 @@
 ''');
     // Setup analysis options file which includes another options file.
     newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
-        content: 'boo:$booLibPosixPath\n');
+        content: 'boo:${toUriStr(booLibPosixPath)}\n');
     newFile('$projPath/$optionsFileName', content: r'''
 include: package:boo/other_options.yaml
 ''');
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index 6213a77..a3b10b3 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -319,7 +319,8 @@
 library lib_a;
 class A {}
 ''').path;
-    newFile('/project/.packages', content: 'pkgA:file:///packages/pkgA');
+    newFile('/project/.packages',
+        content: 'pkgA:${toUriStr('/packages/pkgA')}');
     addTestFile('''
 import 'package:pkgA/libA.dart';
 main(A a) {
diff --git a/pkg/analysis_server/test/integration/completion/list_token_details_test.dart b/pkg/analysis_server/test/integration/completion/list_token_details_test.dart
index 486ba83..c49b7fb 100644
--- a/pkg/analysis_server/test/integration/completion/list_token_details_test.dart
+++ b/pkg/analysis_server/test/integration/completion/list_token_details_test.dart
@@ -42,7 +42,7 @@
 class A {}
 ''');
     writeFile(path.join(testPackagePath, '.packages'), '''
-a:file://$aLibPath
+a:file://${path.toUri(aLibPath)}
 test_package:lib/
 ''');
     String testFilePath = path.join(testPackagePath, 'lib', 'test.dart');
diff --git a/pkg/analysis_server/test/search/type_hierarchy_test.dart b/pkg/analysis_server/test/search/type_hierarchy_test.dart
index 9ba052d..a2a1be0 100644
--- a/pkg/analysis_server/test/search/type_hierarchy_test.dart
+++ b/pkg/analysis_server/test/search/type_hierarchy_test.dart
@@ -170,10 +170,10 @@
 class B extends A {}
 ''');
     newFile('/packages/pkgA/.packages',
-        content: 'pkgA:file:///packages/pkgA/lib');
+        content: 'pkgA:${toUriStr('/packages/pkgA/lib')}');
     // reference the package from a project
     newFile('$projectPath/.packages',
-        content: 'pkgA:file:///packages/pkgA/lib');
+        content: 'pkgA:${toUriStr('/packages/pkgA/lib')}');
     addTestFile('''
 import 'package:pkgA/libA.dart';
 class C extends A {}
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index d1e5ff2..8336ebe 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -248,6 +248,134 @@
     assertNoSuggestions();
   }
 
+  test_ArgumentList_closureFunction_namedParameter() async {
+    addTestSource(r'''
+void f({void Function(int a, String b) closure}) {}
+
+void main() {
+  f(closure: ^);
+}
+''');
+    await computeSuggestions();
+
+    assertSuggest(
+      '(a, b) => ,',
+      relevance: DART_RELEVANCE_HIGH,
+      selectionOffset: 10,
+    );
+
+    assertSuggest(
+      '''
+(a, b) {
+${' ' * 4}
+${' ' * 2}},''',
+      selectionOffset: 13,
+    );
+  }
+
+  test_ArgumentList_closureFunction_namedParameter_hasComma() async {
+    addTestSource(r'''
+void f({void Function(int a, String b) closure}) {}
+
+void main() {
+  f(
+    closure: ^,
+  );
+}
+''');
+    await computeSuggestions();
+
+    assertSuggest(
+      '(a, b) => ',
+      selectionOffset: 10,
+    );
+
+    assertSuggest(
+      '''
+(a, b) {
+${' ' * 6}
+${' ' * 4}}''',
+      selectionOffset: 15,
+    );
+  }
+
+  /// todo (pq): implement positional functional parameters
+  @failingTest
+  test_ArgumentList_closureFunction_positionalParameter() async {
+    addTestSource(r'''
+void f(void Function(int a, int b) closure) {}
+
+void main() {
+  f(^);
+}
+''');
+    await computeSuggestions();
+
+    assertSuggest(
+      '(a, b, c) => ,',
+      selectionOffset: 13,
+    );
+  }
+
+  test_ArgumentList_closureMethod_namedParameter() async {
+    addTestSource(r'''
+class C {
+  void f({void Function(int a, String b) closure}) {}
+
+  void main() {
+    f(closure: ^);
+  }
+}
+''');
+    await computeSuggestions();
+
+    assertSuggest(
+      '(a, b) => ,',
+      selectionOffset: 10,
+    );
+
+    assertSuggest(
+      '''
+(a, b) {
+${' ' * 6}
+${' ' * 4}},''',
+      selectionOffset: 15,
+    );
+  }
+
+  test_ArgumentList_closureParameterOptionalNamed() async {
+    addTestSource(r'''
+void f({void Function(int a, {int b, int c}) closure}) {}
+
+void main() {
+  f(closure: ^);
+}
+''');
+    await computeSuggestions();
+
+    assertSuggest(
+      '(a, {b, c}) => ,',
+      selectionOffset: 15,
+    );
+  }
+
+  test_ArgumentList_closureParameterOptionalPositional() async {
+    addTestSource(r'''
+void f({void Function(int a, [int b, int c]) closure]) {}
+
+void main() {
+  f(closure: ^);
+}
+''');
+    await computeSuggestions();
+
+    assertSuggest(
+      '(a, [b, c]) => ,',
+      relevance: DART_RELEVANCE_HIGH,
+      selectionOffset: 15,
+    );
+  }
+
   test_ArgumentList_Flutter_InstanceCreationExpression_0() async {
     addFlutterPackage();
 
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index 25ba5d3..df904f2 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -9,6 +9,7 @@
 import 'package:analysis_server/src/services/completion/completion_performance.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart'
     show DartCompletionManager, DartCompletionRequestImpl;
+import 'package:analysis_server/src/services/completion/dart/utilities.dart';
 import 'package:analyzer/src/generated/parser.dart' as analyzer;
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:meta/meta.dart';
@@ -22,6 +23,25 @@
   return c1.compareTo(c2);
 }
 
+SuggestionMatcher suggestionHas(
+        {@required String completion,
+        ElementKind element,
+        CompletionSuggestionKind kind}) =>
+    (CompletionSuggestion s) {
+      if (s.completion == completion) {
+        if (element != null && s.element?.kind != element) {
+          return false;
+        }
+        if (kind != null && s.kind != kind) {
+          return false;
+        }
+        return true;
+      }
+      return false;
+    };
+
+typedef SuggestionMatcher = bool Function(CompletionSuggestion suggestion);
+
 /// Base class for tests that validate individual [DartCompletionContributor]
 /// suggestions.
 abstract class DartCompletionContributorTest
@@ -57,6 +77,15 @@
     return completionManager.computeSuggestions(baseRequest);
   }
 
+  /// Display sorted suggestions.
+  void printSuggestions() {
+    suggestions.sort(completionComparator);
+    for (var s in suggestions) {
+      print(
+          '[${s.relevance}] ${s.completion} • ${s.element?.kind?.name ?? ""} ${s.kind.name} ${s.element?.location?.file ?? ""}');
+    }
+  }
+
   @override
   setUp() {
     super.setUp();
@@ -74,6 +103,7 @@
   DartCompletionRequest request;
 
   List<CompletionSuggestion> suggestions;
+
   /**
    * If `true` and `null` is specified as the suggestion's expected returnType
    * then the actual suggestion is expected to have a `dynamic` returnType.
@@ -82,7 +112,6 @@
    * Eventually all tests should be converted and this getter removed.
    */
   bool get isNullExpectedReturnTypeConsideredDynamic => true;
-
   /**
    * Return `true` if contributors should suggest constructors in contexts where
    * there is no `new` or `const` keyword.
@@ -144,7 +173,7 @@
 
   CompletionSuggestion assertSuggest(String completion,
       {CompletionSuggestionKind csKind = CompletionSuggestionKind.INVOCATION,
-      int relevance = DART_RELEVANCE_DEFAULT,
+      int relevance,
       ElementKind elemKind,
       bool isDeprecated = false,
       bool isPotential = false,
@@ -161,9 +190,9 @@
       failedCompletion('expected $completion $csKind $elemKind', suggestions);
     }
     expect(cs.kind, equals(csKind));
-    if (isDeprecated) {
-      expect(cs.relevance, equals(DART_RELEVANCE_LOW));
-    } else {
+    // todo (pq): remove when all relevance tests have been migrated
+    // see: https://github.com/dart-lang/sdk/issues/40104
+    if (relevance != null) {
       expect(cs.relevance, equals(relevance), reason: completion);
     }
     expect(cs.selectionOffset, equals(selectionOffset ?? completion.length));
@@ -200,7 +229,7 @@
   }
 
   CompletionSuggestion assertSuggestClass(String name,
-      {int relevance = DART_RELEVANCE_DEFAULT,
+      {int relevance,
       CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
       bool isDeprecated = false,
       String elemFile,
@@ -224,7 +253,7 @@
   }
 
   CompletionSuggestion assertSuggestClassTypeAlias(String name,
-      {int relevance = DART_RELEVANCE_DEFAULT,
+      {int relevance,
       CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION}) {
     CompletionSuggestion cs =
         assertSuggest(name, csKind: kind, relevance: relevance);
@@ -239,7 +268,7 @@
   }
 
   CompletionSuggestion assertSuggestConstructor(String name,
-      {int relevance = DART_RELEVANCE_DEFAULT,
+      {int relevance,
       String elementName,
       int elemOffset,
       String defaultArgListString = _UNCHECKED,
@@ -272,6 +301,11 @@
       {int relevance = DART_RELEVANCE_DEFAULT,
       bool isDeprecated = false,
       bool hasTypeBoost = false}) {
+    // todo (pq): remove when all relevance tests have been migrated
+    // see: https://github.com/dart-lang/sdk/issues/40104
+    if (isDeprecated) {
+      relevance = DART_RELEVANCE_LOW;
+    }
     if (hasTypeBoost) {
       relevance += DART_RELEVANCE_BOOST_TYPE;
     }
@@ -284,7 +318,7 @@
   }
 
   CompletionSuggestion assertSuggestField(String name, String type,
-      {int relevance = DART_RELEVANCE_DEFAULT,
+      {int relevance,
       CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
       bool isDeprecated = false}) {
     CompletionSuggestion cs = assertSuggest(name,
@@ -308,7 +342,7 @@
   CompletionSuggestion assertSuggestFunction(String name, String returnType,
       {CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
       bool isDeprecated = false,
-      int relevance = DART_RELEVANCE_DEFAULT,
+      int relevance,
       String defaultArgListString = _UNCHECKED,
       List<int> defaultArgumentListTextRanges}) {
     CompletionSuggestion cs = assertSuggest(name,
@@ -344,7 +378,7 @@
     String name,
     String returnType, {
     bool isDeprecated = false,
-    int relevance = DART_RELEVANCE_DEFAULT,
+    int relevance,
     CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
   }) {
     CompletionSuggestion cs = assertSuggest(name,
@@ -374,7 +408,7 @@
   }
 
   CompletionSuggestion assertSuggestGetter(String name, String returnType,
-      {int relevance = DART_RELEVANCE_DEFAULT,
+      {int relevance,
       CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
       bool isDeprecated = false}) {
     CompletionSuggestion cs = assertSuggest(name,
@@ -396,7 +430,7 @@
 
   CompletionSuggestion assertSuggestMethod(
       String name, String declaringType, String returnType,
-      {int relevance = DART_RELEVANCE_DEFAULT,
+      {int relevance,
       CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
       bool isDeprecated = false,
       String defaultArgListString = _UNCHECKED,
@@ -423,7 +457,7 @@
   }
 
   CompletionSuggestion assertSuggestMixin(String name,
-      {int relevance = DART_RELEVANCE_DEFAULT,
+      {int relevance,
       CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
       bool isDeprecated = false,
       String elemFile,
@@ -447,7 +481,7 @@
   }
 
   CompletionSuggestion assertSuggestName(String name,
-      {int relevance = DART_RELEVANCE_DEFAULT,
+      {int relevance,
       CompletionSuggestionKind kind = CompletionSuggestionKind.IDENTIFIER,
       bool isDeprecated = false}) {
     CompletionSuggestion cs = assertSuggest(name,
@@ -459,7 +493,7 @@
   }
 
   CompletionSuggestion assertSuggestSetter(String name,
-      {int relevance = DART_RELEVANCE_DEFAULT,
+      {int relevance,
       CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION}) {
     CompletionSuggestion cs = assertSuggest(name,
         csKind: kind, relevance: relevance, elemKind: ElementKind.SETTER);
@@ -480,7 +514,7 @@
   CompletionSuggestion assertSuggestTopLevelVar(
     String name,
     String returnType, {
-    int relevance = DART_RELEVANCE_DEFAULT,
+    int relevance,
     CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
   }) {
     CompletionSuggestion cs =
@@ -530,7 +564,7 @@
     if (completions != null) {
       sb.write('\n  found');
       completions.toList()
-        ..sort(suggestionComparator)
+        ..sort(completionComparator)
         ..forEach((CompletionSuggestion suggestion) {
           sb.write('\n    ${suggestion.completion} -> $suggestion');
         });
@@ -591,4 +625,14 @@
     super.setUp();
     testFile = convertPath('/home/test/lib/test.dart');
   }
+
+  CompletionSuggestion suggestionWith(
+      {@required String completion,
+      ElementKind element,
+      CompletionSuggestionKind kind}) {
+    final matches = suggestions.where(
+        suggestionHas(completion: completion, element: element, kind: kind));
+    expect(matches, hasLength(1));
+    return matches.first;
+  }
 }
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 feae0c9..a717054 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
@@ -4464,4 +4464,16 @@
     await computeSuggestions();
     assertSuggestMixin('M');
   }
+
+  test_YieldStatement() async {
+    addTestSource('''
+void main() async* {
+  yield ^
+}
+''');
+    await computeSuggestions();
+
+    // Sanity check any completions.
+    assertSuggestClass('Object');
+  }
 }
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 c0111db..28662d4 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
@@ -5007,6 +5007,18 @@
     await computeSuggestions();
     assertSuggestMixin('M');
   }
+
+  test_YieldStatement() async {
+    addTestSource('''
+void main() async* {
+  var value;
+  yield v^
+}
+''');
+    await computeSuggestions();
+
+    assertSuggestLocalVariable('value', null);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/arglist_parameter_relevance_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/arglist_parameter_relevance_test.dart
new file mode 100644
index 0000000..34e36ee
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/arglist_parameter_relevance_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer_plugin/utilities/completion/relevance.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../completion_contributor_util.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ArglistParameterRelevanceTest);
+  });
+}
+
+@reflectiveTest
+class ArglistParameterRelevanceTest extends DartCompletionManagerTest {
+  test_closureParam() async {
+    addTestSource(r'''
+void f({void Function(int a, {int b, int c}) closure}) {}
+
+void main() {
+  f(closure: ^);
+}
+''');
+    await computeSuggestions();
+
+    assertSuggest(
+      '(a, {b, c}) => ,',
+      // todo (pq): replace w/ a test of relative relevance
+      relevance: DART_RELEVANCE_HIGH,
+      selectionOffset: 15,
+    );
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/bool_assignment_relevance_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/bool_assignment_relevance_test.dart
new file mode 100644
index 0000000..f39ef0d
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/bool_assignment_relevance_test.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../completion_contributor_util.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(BoolAssignmentRelevanceTest);
+  });
+}
+
+@reflectiveTest
+class BoolAssignmentRelevanceTest extends DartCompletionManagerTest {
+  /// These are 2 failing tests for http://dartbug.com/37907:
+  /// "Suggest `false` above other results when autocompleting a bool setter"
+  @failingTest
+  test_boolLiterals_local() async {
+    addTestSource('''
+foo() {
+  bool b;
+  b = ^
+}
+''');
+    await computeSuggestions();
+
+    var trueSuggestion = suggestionWith(
+        completion: 'true', kind: CompletionSuggestionKind.KEYWORD);
+
+    var falseSuggestion = suggestionWith(
+        completion: 'false', kind: CompletionSuggestionKind.KEYWORD);
+
+    var bLocalVar = suggestionWith(
+        completion: 'b',
+        element: ElementKind.LOCAL_VARIABLE,
+        kind: CompletionSuggestionKind.INVOCATION);
+
+    expect(trueSuggestion.relevance, greaterThan(bLocalVar.relevance));
+    expect(falseSuggestion.relevance, greaterThan(bLocalVar.relevance));
+  }
+
+  @failingTest
+  test_boolLiterals_imported() async {
+    addTestSource('''
+foo() {
+  bool b;
+  b = ^
+}
+''');
+    await computeSuggestions();
+
+    var trueSuggestion = suggestionWith(
+        completion: 'true', kind: CompletionSuggestionKind.KEYWORD);
+
+    var falseSuggestion = suggestionWith(
+        completion: 'false', kind: CompletionSuggestionKind.KEYWORD);
+
+    var boolFromEnvironment = suggestionWith(
+        completion: 'bool.fromEnvironment',
+        element: ElementKind.CONSTRUCTOR,
+        kind: CompletionSuggestionKind.INVOCATION);
+
+    expect(
+        trueSuggestion.relevance, greaterThan(boolFromEnvironment.relevance));
+    expect(
+        falseSuggestion.relevance, greaterThan(boolFromEnvironment.relevance));
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/deprecated_member_relevance_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/deprecated_member_relevance_test.dart
new file mode 100644
index 0000000..dbc3884
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/deprecated_member_relevance_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../completion_contributor_util.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DeprecatedMemberRelevanceTest);
+  });
+}
+
+@reflectiveTest
+class DeprecatedMemberRelevanceTest extends DartCompletionManagerTest {
+  test_deprecated() async {
+    addTestSource('''
+class A {
+  void a1() { }
+  @deprecated
+  void a2() { }
+}
+
+void main() {
+  var a = A();
+  a.^
+}
+''');
+    await computeSuggestions();
+
+    expect(
+        suggestionWith(
+                completion: 'a2',
+                element: ElementKind.METHOD,
+                kind: CompletionSuggestionKind.INVOCATION)
+            .relevance,
+        lessThan(suggestionWith(
+                completion: 'a1',
+                element: ElementKind.METHOD,
+                kind: CompletionSuggestionKind.INVOCATION)
+            .relevance));
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/test_all.dart b/pkg/analysis_server/test/services/completion/dart/relevance/test_all.dart
new file mode 100644
index 0000000..36651e0
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/test_all.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 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'arglist_parameter_relevance_test.dart' as arglist_parameters;
+import 'bool_assignment_relevance_test.dart' as bool_assignments;
+import 'deprecated_member_relevance_test.dart' as deprecated_members;
+
+main() {
+  defineReflectiveSuite(() {
+    arglist_parameters.main();
+    bool_assignments.main();
+    deprecated_members.main();
+  });
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/test_all.dart b/pkg/analysis_server/test/services/completion/dart/test_all.dart
index 3bf866a..834e5cf 100644
--- a/pkg/analysis_server/test/services/completion/dart/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/test_all.dart
@@ -27,6 +27,7 @@
 import 'local_reference_contributor_test.dart' as local_ref_test;
 import 'named_constructor_contributor_test.dart' as named_contributor_test;
 import 'override_contributor_test.dart' as override_contributor_test;
+import 'relevance/test_all.dart' as relevance_tests;
 import 'static_member_contributor_test.dart' as static_contributor_test;
 import 'type_member_contributor_test.dart' as type_member_contributor_test;
 import 'uri_contributor_test.dart' as uri_contributor_test;
@@ -58,6 +59,7 @@
     local_ref_test.main();
     named_contributor_test.main();
     override_contributor_test.main();
+    relevance_tests.main();
     static_contributor_test.main();
     type_member_contributor_test.main();
     uri_contributor_test.main();
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
index 8d38b88..bb90063 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
@@ -65,7 +65,7 @@
 
 class MyWidget<T> extends StatefulWidget {
   @override
-  _MyWidgetState createState() => _MyWidgetState();
+  _MyWidgetState<T> createState() => _MyWidgetState<T>();
 }
 
 class _MyWidgetState<T> extends State<MyWidget<T>> {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_element_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_element_test.dart
index 77d6f54..9f6a7928 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_element_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_element_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -22,12 +24,13 @@
   test_class_notUsed_inClassMember() async {
     await resolveTestUnit(r'''
 class _A {
-  static staticMethod() {
+  staticMethod() {
     new _A();
   }
 }
 ''');
-    // todo (pq): consider supporting the case where references are limited to within the class.
+    // TODO(pq): consider supporting the case where references are limited to
+    //  within the class.
     await assertNoFix();
   }
 
@@ -57,7 +60,9 @@
 enum _MyEnum {A, B, C}
 ''');
     await assertHasFix(r'''
-''');
+''', errorFilter: (AnalysisError error) {
+      return error.errorCode == HintCode.UNUSED_ELEMENT;
+    });
   }
 
   test_functionLocal_notUsed_noReference() async {
@@ -132,6 +137,52 @@
 ''');
   }
 
+  test_staticMethod_extension_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+extension _E on String {
+  static int m1() => 3;
+  int m2() => 7;
+}
+void f() => print(_E("hello").m2());
+''');
+    await assertHasFix(r'''
+extension _E on String {
+  int m2() => 7;
+}
+void f() => print(_E("hello").m2());
+''');
+  }
+
+  test_staticMethod_mixim_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+mixin _M {
+  static int m1() => 3;
+}
+class C with _M {}
+void f(C c) {}
+''');
+    await assertHasFix(r'''
+mixin _M {
+}
+class C with _M {}
+void f(C c) {}
+''');
+  }
+
+  test_staticMethod_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+class _A {
+  static int m() => 7;
+}
+void f(_A a) {}
+''');
+    await assertHasFix(r'''
+class _A {
+}
+void f(_A a) {}
+''');
+  }
+
   test_topLevelVariable_notUsed() async {
     await resolveTestUnit(r'''
 int _a = 1;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_field_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_field_test.dart
index a398ef8..139fb95 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_field_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_field_test.dart
@@ -19,6 +19,18 @@
   @override
   FixKind get kind => DartFixKind.REMOVE_UNUSED_FIELD;
 
+  @FailingTest(reason: 'Unimplemented')
+  test_enumValue_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+enum _E { a, b, c }
+bool f(_E e) => e == _E.a || e == _E.b;
+''');
+    await assertHasFix(r'''
+enum _E { a, b }
+bool f(_E e) => e == _E.a || e == _E.b;
+''');
+  }
+
   test_unusedField_notUsed_assign() async {
     await resolveTestUnit(r'''
 class A {
diff --git a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
new file mode 100644
index 0000000..792ee56
--- /dev/null
+++ b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
@@ -0,0 +1,105 @@
+// 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:math';
+
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analysis_server/src/services/completion/completion_core.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/utilities.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/generated/engine.dart';
+
+import 'visitors.dart';
+
+int includedCount = 0;
+int notIncludedCount = 0;
+
+const bool doPrintExpectedCompletions = true;
+
+main() {
+  List<String> analysisRoots = [''];
+  _computeCompletionMetrics(PhysicalResourceProvider.INSTANCE, analysisRoots);
+}
+
+/// TODO(jwren) put the following methods into a class
+Future _computeCompletionMetrics(
+    ResourceProvider resourceProvider, List<String> analysisRoots) async {
+  for (var root in analysisRoots) {
+    print('Analyzing root: $root');
+    final collection = AnalysisContextCollection(
+      includedPaths: [root],
+      resourceProvider: resourceProvider,
+    );
+
+    for (var context in collection.contexts) {
+      for (var filePath in context.contextRoot.analyzedFiles()) {
+        if (AnalysisEngine.isDartFileName(filePath)) {
+          try {
+            final result =
+                await context.currentSession.getResolvedUnit(filePath);
+            final visitor = CompletionMetricVisitor();
+
+            result.unit.accept(visitor);
+            var expectedCompletions = visitor.expectedCompletions;
+
+            for (var expectedCompletion in expectedCompletions) {
+              var completionContributor = DartCompletionManager();
+              var completionRequestImpl = CompletionRequestImpl(
+                result,
+                expectedCompletion.offset,
+                CompletionPerformance(),
+              );
+              var suggestions = await completionContributor
+                  .computeSuggestions(completionRequestImpl);
+              suggestions.sort(completionComparator);
+
+              var fraction =
+                  _placementInSuggestionList(suggestions, expectedCompletion);
+              if (fraction.y != 0) {
+                includedCount++;
+              } else {
+                notIncludedCount++;
+                if (doPrintExpectedCompletions) {
+                  print(
+                      '\t$filePath at ${expectedCompletion.offset} did not include \'${expectedCompletion.completion}\'');
+                }
+              }
+            }
+          } catch (e) {
+            print('Exception caught analyzing: $filePath');
+            print(e.toString());
+          }
+        }
+      }
+    }
+  }
+  print('done $includedCount $notIncludedCount');
+
+  final percentIncluded = includedCount / (includedCount + notIncludedCount);
+  final percentNotIncluded =
+      notIncludedCount / (includedCount + notIncludedCount);
+  print(
+      'done ${_formatPercentToString(percentIncluded)} ${_formatPercentToString(percentNotIncluded)}');
+}
+
+Point<int> _placementInSuggestionList(List<CompletionSuggestion> suggestions,
+    ExpectedCompletion expectedCompletion) {
+  var i = 1;
+  for (var completionSuggestion in suggestions) {
+    if (expectedCompletion.matches(completionSuggestion)) {
+      return Point(i, suggestions.length);
+    }
+    i++;
+  }
+  return Point(0, 0);
+}
+
+String _formatPercentToString(double percent, [fractionDigits = 1]) {
+  return (percent * 100).toStringAsFixed(fractionDigits) + '%';
+}
diff --git a/pkg/analysis_server/tool/completion_metrics/visitors.dart b/pkg/analysis_server/tool/completion_metrics/visitors.dart
new file mode 100644
index 0000000..f569338
--- /dev/null
+++ b/pkg/analysis_server/tool/completion_metrics/visitors.dart
@@ -0,0 +1,132 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/protocol_server.dart' as protocol;
+import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+
+class CompletionMetricVisitor extends RecursiveAstVisitor {
+  // TODO(jwren) implement missing visit* methods
+
+  final List<ExpectedCompletion> expectedCompletions;
+
+  CompletionMetricVisitor() : expectedCompletions = <ExpectedCompletion>[];
+
+  safelyRecordKeywordCompletion(SyntacticEntity entity) {
+    safelyRecordEntity(entity, kind: protocol.CompletionSuggestionKind.KEYWORD);
+  }
+
+  safelyRecordEntity(SyntacticEntity entity,
+      {protocol.CompletionSuggestionKind kind,
+      protocol.ElementKind elementKind}) {
+    // Only record if this entity is not null, has a length, etc.
+    if (entity != null && entity.offset > 0 && entity.length > 0) {
+      // Some special cases in the if and if-else blocks, 'import' from the
+      // DAS is "import '';" which we want to be sure to match.
+      if (entity.toString() == 'async') {
+        expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            entity, ASYNC_STAR, kind, elementKind));
+      } else if (entity.toString() == 'default') {
+        expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            entity, DEFAULT_COLON, kind, elementKind));
+      } else if (entity.toString() == 'deferred') {
+        expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            entity, DEFERRED_AS, kind, elementKind));
+      } else if (entity.toString() == 'export') {
+        expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            entity, EXPORT_STATEMENT, kind, elementKind));
+      } else if (entity.toString() == 'import') {
+        expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            entity, IMPORT_STATEMENT, kind, elementKind));
+      } else if (entity.toString() == 'part') {
+        expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            entity, PART_STATEMENT, kind, elementKind));
+      } else if (entity.toString() == 'sync') {
+        expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            entity, SYNC_STAR, kind, elementKind));
+      } else if (entity.toString() == 'yield') {
+        expectedCompletions.add(ExpectedCompletion.specialCompletionString(
+            entity, YIELD_STAR, kind, elementKind));
+      } else {
+        expectedCompletions.add(ExpectedCompletion(entity, kind, elementKind));
+      }
+    }
+  }
+
+  @override
+  visitDoStatement(DoStatement node) {
+    safelyRecordKeywordCompletion(node.doKeyword);
+    return super.visitDoStatement(node);
+  }
+
+  @override
+  visitIfStatement(IfStatement node) {
+    safelyRecordKeywordCompletion(node.ifKeyword);
+    return super.visitIfStatement(node);
+  }
+
+  @override
+  visitImportDirective(ImportDirective node) {
+    safelyRecordKeywordCompletion(node.keyword);
+    safelyRecordKeywordCompletion(node.asKeyword);
+    return super.visitImportDirective(node);
+  }
+
+  @override
+  visitSimpleIdentifier(SimpleIdentifier node) {
+    if (!node.isSynthetic && !node.inDeclarationContext()) {
+      var elementKind;
+      if (node.staticElement?.kind != null) {
+        elementKind = protocol.convertElementKind(node.staticElement?.kind);
+      }
+      safelyRecordEntity(node, elementKind: elementKind);
+    }
+    return super.visitSimpleIdentifier(node);
+  }
+}
+
+class ExpectedCompletion {
+  final SyntacticEntity _entity;
+
+  /// Some completions are special cased from the DAS "import" for instance is
+  /// suggested as a completion "import '';", the completion string here in this
+  /// instance would have the value "import '';".
+  final String _completionString;
+
+  final protocol.CompletionSuggestionKind _kind;
+
+  final protocol.ElementKind _elementKind;
+
+  ExpectedCompletion(this._entity, this._kind, this._elementKind)
+      : _completionString = null;
+
+  ExpectedCompletion.specialCompletionString(
+      this._entity, this._completionString, this._kind, this._elementKind);
+
+  SyntacticEntity get syntacticEntity => _entity;
+
+  String get completion => _completionString ?? _entity.toString();
+
+  int get offset => _entity.offset;
+
+  protocol.CompletionSuggestionKind get kind => _kind;
+
+  protocol.ElementKind get elementKind => _elementKind;
+
+  bool matches(protocol.CompletionSuggestion completionSuggestion) {
+    if (completionSuggestion.completion == completion) {
+      if (kind != null && completionSuggestion.kind != kind) {
+        return false;
+      }
+      if (elementKind != null &&
+          completionSuggestion.element?.kind != elementKind) {
+        return false;
+      }
+      return true;
+    }
+    return false;
+  }
+}
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 53e94bc..61084a9 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -417,6 +417,7 @@
   HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD,
   HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER,
   HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT,
+  HintCode.RECEIVER_OF_TYPE_NEVER,
   HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE,
   HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT,
   HintCode.SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT,
@@ -735,7 +736,6 @@
   StaticWarningCode.INSTANTIATE_ABSTRACT_CLASS,
   StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
   StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
-  StaticWarningCode.INVALID_USE_OF_NEVER_VALUE,
   StaticWarningCode.INVALID_USE_OF_NULL_VALUE,
   StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
   StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index b12d22e..0ac63bf 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -41,7 +41,6 @@
 import 'package:analyzer/src/workspace/pub.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:args/args.dart';
-import 'package:package_config/packages.dart' as package_config;
 import 'package:path/src/context.dart';
 import 'package:yaml/yaml.dart';
 
@@ -538,21 +537,6 @@
     return null;
   }
 
-  static Map<String, List<Folder>> convertPackagesToMap(
-    ResourceProvider resourceProvider,
-    package_config.Packages packages,
-  ) {
-    Map<String, List<Folder>> folderMap = HashMap<String, List<Folder>>();
-    if (packages != null && packages != package_config.Packages.noPackages) {
-      var pathContext = resourceProvider.pathContext;
-      packages.asMap().forEach((String packageName, Uri uri) {
-        String path = fileUriToNormalizedPath(pathContext, uri);
-        folderMap[packageName] = [resourceProvider.getFolder(path)];
-      });
-    }
-    return folderMap;
-  }
-
   static Workspace createWorkspace(ResourceProvider resourceProvider,
       String rootPath, ContextBuilder contextBuilder) {
     var packages = contextBuilder.createPackageMap(rootPath);
diff --git a/pkg/analyzer/lib/src/context/packages.dart b/pkg/analyzer/lib/src/context/packages.dart
index 2552f33..b66b107 100644
--- a/pkg/analyzer/lib/src/context/packages.dart
+++ b/pkg/analyzer/lib/src/context/packages.dart
@@ -9,6 +9,37 @@
 import 'package:package_config/packages_file.dart' as dot_packages;
 import 'package:pub_semver/pub_semver.dart';
 
+/// Find [Packages] starting from the given [start] resource.
+///
+/// Looks for `.dart_tool/package_config.json` or `.packages` in the given
+/// and parent directories.
+Packages findPackagesFrom(ResourceProvider provider, Resource start) {
+  for (var current = start; current != null; current = current.parent) {
+    if (current is Folder) {
+      try {
+        var jsonFile = current
+            .getChildAssumingFolder('.dart_tool')
+            .getChildAssumingFile('package_config.json');
+        if (jsonFile.exists) {
+          return parsePackageConfigJsonFile(provider, jsonFile);
+        }
+      } catch (e) {
+        return Packages.empty;
+      }
+
+      try {
+        var dotFile = current.getChildAssumingFile('.packages');
+        if (dotFile.exists) {
+          return parseDotPackagesFile(provider, dotFile);
+        }
+      } catch (e) {
+        return Packages.empty;
+      }
+    }
+  }
+  return Packages.empty;
+}
+
 /// Parse the [file] as a `.packages` file.
 Packages parseDotPackagesFile(ResourceProvider provider, File file) {
   var uri = file.toUri();
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index bdd7dc6..ceabe27 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -89,7 +89,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 94;
+  static const int DATA_VERSION = 95;
 
   /// The length of the list returned by [_computeDeclaredVariablesSignature].
   static const int _declaredVariablesSignatureLength = 4;
diff --git a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
index 1d30292..092f0b2 100644
--- a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
@@ -102,25 +102,7 @@
       return Packages(const {});
     }
 
-    var current = resourceProvider.getFolder(contextRoot.root);
-    for (; current != null; current = current.parent) {
-      try {
-        var jsonFile = current
-            .getChildAssumingFolder('.dart_tool')
-            .getChildAssumingFile('package_config.json');
-        if (jsonFile.exists) {
-          return parsePackageConfigJsonFile(resourceProvider, jsonFile);
-        }
-      } catch (_) {}
-
-      try {
-        var dotFile = current.getChildAssumingFile('.packages');
-        if (dotFile.exists) {
-          return parseDotPackagesFile(resourceProvider, dotFile);
-        }
-      } catch (_) {}
-    }
-
-    return Packages(const {});
+    var rootFolder = resourceProvider.getFolder(contextRoot.root);
+    return findPackagesFrom(resourceProvider, rootFolder);
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index be22490..d0a5a00 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -1351,6 +1351,27 @@
       "A package import shouldn't contain '..'.");
 
   /**
+   * It is not an error to call or tear-off a method, setter, or getter, or to
+   * read or write a field, on a receiver of static type `Never`.
+   * Implementations that provide feedback about dead or unreachable code are
+   * encouraged to indicate that any arguments to the invocation are
+   * unreachable.
+   *
+   * It is not an error to apply an expression of type `Never` in the function
+   * position of a function call. Implementations that provide feedback about
+   * dead or unreachable code are encouraged to indicate that any arguments to
+   * the call are unreachable.
+   *
+   * Parameters: none
+   */
+  static const HintCode RECEIVER_OF_TYPE_NEVER = HintCode(
+      'RECEIVER_OF_TYPE_NEVER',
+      'The receiver expression is of type Never, and will never complete '
+          'with a value.',
+      correction: 'Try checking for throw expressions or type errors in the'
+          ' target expression');
+
+  /**
    * No parameters.
    */
   // #### Description
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
new file mode 100644
index 0000000..fea4045
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -0,0 +1,328 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/resolution_result.dart';
+import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/element_type_provider.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/task/strong/checker.dart';
+import 'package:meta/meta.dart';
+
+/// Helper for resolving [AssignmentExpression]s.
+class AssignmentExpressionResolver {
+  final ResolverVisitor _resolver;
+  final FlowAnalysisHelper _flowAnalysis;
+  final ElementTypeProvider _elementTypeProvider;
+  final TypePropertyResolver _typePropertyResolver;
+  final InvocationInferenceHelper _inferenceHelper;
+
+  AssignmentExpressionResolver({
+    @required ResolverVisitor resolver,
+    @required FlowAnalysisHelper flowAnalysis,
+    @required ElementTypeProvider elementTypeProvider,
+  })  : _resolver = resolver,
+        _flowAnalysis = flowAnalysis,
+        _elementTypeProvider = elementTypeProvider,
+        _typePropertyResolver = resolver.typePropertyResolver,
+        _inferenceHelper = resolver.inferenceHelper;
+
+  ErrorReporter get _errorReporter => _resolver.errorReporter;
+
+  bool get _isNonNullableByDefault => _typeSystem.isNonNullableByDefault;
+
+  TypeProvider get _typeProvider => _resolver.typeProvider;
+
+  TypeSystemImpl get _typeSystem => _resolver.typeSystem;
+
+  void resolve(AssignmentExpressionImpl node) {
+    var left = node.leftHandSide;
+    var right = node.rightHandSide;
+
+    left?.accept(_resolver);
+    left = node.leftHandSide;
+
+    var leftLocalVariable = _flowAnalysis?.assignmentExpression(node);
+
+    TokenType operator = node.operator.type;
+    if (operator == TokenType.EQ ||
+        operator == TokenType.QUESTION_QUESTION_EQ) {
+      InferenceContext.setType(right, left.staticType);
+    }
+
+    right?.accept(_resolver);
+    right = node.rightHandSide;
+
+    _resolve1(node);
+    _resolve2(node);
+
+    _flowAnalysis?.assignmentExpression_afterRight(
+        node,
+        leftLocalVariable,
+        operator == TokenType.QUESTION_QUESTION_EQ
+            ? node.rightHandSide.staticType
+            : node.staticType);
+  }
+
+  void _resolve1(AssignmentExpressionImpl node) {
+    Token operator = node.operator;
+    TokenType operatorType = operator.type;
+    Expression leftHandSide = node.leftHandSide;
+    DartType staticType = _getStaticType1(leftHandSide, read: true);
+
+    if (identical(staticType, NeverTypeImpl.instance)) {
+      return;
+    }
+
+    // For any compound assignments to a void or nullable variable, report it.
+    // Example: `y += voidFn()`, not allowed.
+    if (operatorType != TokenType.EQ) {
+      if (staticType != null && staticType.isVoid) {
+        _errorReporter.reportErrorForToken(
+          StaticWarningCode.USE_OF_VOID_RESULT,
+          operator,
+        );
+        return;
+      }
+    }
+
+    if (operatorType != TokenType.AMPERSAND_AMPERSAND_EQ &&
+        operatorType != TokenType.BAR_BAR_EQ &&
+        operatorType != TokenType.EQ &&
+        operatorType != TokenType.QUESTION_QUESTION_EQ) {
+      operatorType = operatorFromCompoundAssignment(operatorType);
+      if (leftHandSide != null) {
+        String methodName = operatorType.lexeme;
+        // TODO(brianwilkerson) Change the [methodNameNode] from the left hand
+        //  side to the operator.
+        var result = _typePropertyResolver.resolve(
+          receiver: leftHandSide,
+          receiverType: staticType,
+          name: methodName,
+          receiverErrorNode: leftHandSide,
+          nameErrorNode: leftHandSide,
+        );
+        node.staticElement = result.getter;
+        if (_shouldReportInvalidMember(staticType, result)) {
+          _errorReporter.reportErrorForToken(
+            StaticTypeWarningCode.UNDEFINED_OPERATOR,
+            operator,
+            [methodName, staticType],
+          );
+        }
+      }
+    }
+  }
+
+  /**
+   * Return `true` if we should report an error for the lookup [result] on
+   * the [type].
+   *
+   * TODO(scheglov) this is duplicate
+   */
+  bool _shouldReportInvalidMember(DartType type, ResolutionResult result) {
+    if (result.isNone && type != null && !type.isDynamic) {
+      if (_typeSystem.isNonNullableByDefault &&
+          _typeSystem.isPotentiallyNullable(type)) {
+        return false;
+      }
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Return the static type of the given [expression] that is to be used for
+   * type analysis.
+   *
+   * TODO(scheglov) this is duplicate
+   */
+  DartType _getStaticType1(Expression expression, {bool read = false}) {
+    if (expression is NullLiteral) {
+      return _typeProvider.nullType;
+    }
+    DartType type = read
+        ? getReadType(expression, elementTypeProvider: _elementTypeProvider)
+        : expression.staticType;
+    return _resolveTypeParameter(type);
+  }
+
+  /**
+   * If the given [type] is a type parameter, resolve it to the type that should
+   * be used when looking up members. Otherwise, return the original type.
+   *
+   * TODO(scheglov) this is duplicate
+   */
+  DartType _resolveTypeParameter(DartType type) =>
+      type?.resolveToBound(_typeProvider.objectType);
+
+  void _resolve2(AssignmentExpressionImpl node) {
+    TokenType operator = node.operator.type;
+    if (operator == TokenType.EQ) {
+      Expression rightHandSide = node.rightHandSide;
+      DartType staticType = _getStaticType2(rightHandSide);
+      _inferenceHelper.recordStaticType(node, staticType);
+    } else if (operator == TokenType.QUESTION_QUESTION_EQ) {
+      if (_isNonNullableByDefault) {
+        // The static type of a compound assignment using ??= with NNBD is the
+        // least upper bound of the static types of the LHS and RHS after
+        // promoting the LHS/ to non-null (as we know its value will not be used
+        // if null)
+        _analyzeLeastUpperBoundTypes(
+            node,
+            _typeSystem.promoteToNonNull(
+                _getExpressionType(node.leftHandSide, read: true)),
+            _getExpressionType(node.rightHandSide, read: true));
+      } else {
+        // The static type of a compound assignment using ??= before NNBD is the
+        // least upper bound of the static types of the LHS and RHS.
+        _analyzeLeastUpperBound(node, node.leftHandSide, node.rightHandSide,
+            read: true);
+      }
+    } else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ ||
+        operator == TokenType.BAR_BAR_EQ) {
+      _inferenceHelper.recordStaticType(
+          node, _nonNullable(_typeProvider.boolType));
+    } else {
+      var rightType = node.rightHandSide.staticType;
+
+      var leftReadType = _getStaticType2(node.leftHandSide, read: true);
+      if (identical(leftReadType, NeverTypeImpl.instance)) {
+        _inferenceHelper.recordStaticType(node, rightType);
+        return;
+      }
+
+      var operatorElement = node.staticElement;
+      var type =
+          _elementTypeProvider.safeExecutableReturnType(operatorElement) ??
+              DynamicTypeImpl.instance;
+      type = _typeSystem.refineBinaryExpressionType(
+        leftReadType,
+        operator,
+        rightType,
+        type,
+      );
+      _inferenceHelper.recordStaticType(node, type);
+
+      var leftWriteType = _getStaticType2(node.leftHandSide);
+      if (!_typeSystem.isAssignableTo(type, leftWriteType)) {
+        _resolver.errorReporter.reportErrorForNode(
+          StaticTypeWarningCode.INVALID_ASSIGNMENT,
+          node.rightHandSide,
+          [type, leftWriteType],
+        );
+      }
+    }
+    _resolver.nullShortingTermination(node);
+  }
+
+  /// Return the non-nullable variant of the [type] if NNBD is enabled, otherwise
+  /// return the type itself.
+  ///
+  /// TODO(scheglov) this is duplicate
+  DartType _nonNullable(DartType type) {
+    if (_isNonNullableByDefault) {
+      return _typeSystem.promoteToNonNull(type);
+    }
+    return type;
+  }
+
+  /**
+   * Set the static type of [node] to be the least upper bound of the static
+   * types of subexpressions [expr1] and [expr2].
+   *
+   * TODO(scheglov) this is duplicate
+   */
+  void _analyzeLeastUpperBound(
+      Expression node, Expression expr1, Expression expr2,
+      {bool read = false}) {
+    DartType staticType1 = _getExpressionType(expr1, read: read);
+    DartType staticType2 = _getExpressionType(expr2, read: read);
+
+    _analyzeLeastUpperBoundTypes(node, staticType1, staticType2);
+  }
+
+  /**
+   * Gets the definite type of expression, which can be used in cases where
+   * the most precise type is desired, for example computing the least upper
+   * bound.
+   *
+   * See [getExpressionType] for more information. Without strong mode, this is
+   * equivalent to [_getStaticType].
+   *
+   * TODO(scheglov) this is duplicate
+   */
+  DartType _getExpressionType(Expression expr, {bool read = false}) =>
+      getExpressionType(expr, _typeSystem, _typeProvider,
+          read: read, elementTypeProvider: _elementTypeProvider);
+
+  /**
+   * Set the static type of [node] to be the least upper bound of the static
+   * types [staticType1] and [staticType2].
+   *
+   * TODO(scheglov) this is duplicate
+   */
+  void _analyzeLeastUpperBoundTypes(
+      Expression node, DartType staticType1, DartType staticType2) {
+    if (staticType1 == null) {
+      // TODO(brianwilkerson) Determine whether this can still happen.
+      staticType1 = DynamicTypeImpl.instance;
+    }
+
+    if (staticType2 == null) {
+      // TODO(brianwilkerson) Determine whether this can still happen.
+      staticType2 = DynamicTypeImpl.instance;
+    }
+
+    DartType staticType =
+        _typeSystem.getLeastUpperBound(staticType1, staticType2) ??
+            DynamicTypeImpl.instance;
+
+    staticType = _resolver.toLegacyTypeIfOptOut(staticType);
+
+    _inferenceHelper.recordStaticType(node, staticType);
+  }
+
+  /**
+   * Return the static type of the given [expression].
+   *
+   * TODO(scheglov) this is duplicate
+   */
+  DartType _getStaticType2(Expression expression, {bool read = false}) {
+    DartType type;
+    if (read) {
+      type = getReadType(expression, elementTypeProvider: _elementTypeProvider);
+    } else {
+      if (expression is SimpleIdentifier && expression.inSetterContext()) {
+        var element = expression.staticElement;
+        if (element is PromotableElement) {
+          // We're writing to the element so ignore promotions.
+          type = _elementTypeProvider.getVariableType(element);
+        } else {
+          type = expression.staticType;
+        }
+      } else {
+        type = expression.staticType;
+      }
+    }
+    if (type == null) {
+      // TODO(brianwilkerson) Determine the conditions for which the static type
+      // is null.
+      return DynamicTypeImpl.instance;
+    }
+    return type;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
index 061b865..9d93bd7 100644
--- a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
@@ -52,7 +52,13 @@
   TypeSystemImpl get _typeSystem => _resolver.typeSystem;
 
   void resolve(BinaryExpressionImpl node) {
-    TokenType operator = node.operator.type;
+    var operator = node.operator.type;
+
+    if (operator == TokenType.QUESTION_QUESTION) {
+      _resolveIfNull(node);
+      return;
+    }
+
     Expression left = node.leftOperand;
     Expression right = node.rightOperand;
     var flow = _flowAnalysis?.flow;
@@ -101,13 +107,6 @@
       _flowAnalysis?.flow?.equalityOp_end(node, right,
           notEqual: operator == TokenType.BANG_EQ);
     } else {
-      if (operator == TokenType.QUESTION_QUESTION) {
-        var leftContextType = InferenceContext.getContext(node);
-        if (leftContextType != null && _isNonNullableByDefault) {
-          leftContextType = _typeSystem.makeNullable(leftContextType);
-        }
-        InferenceContext.setType(left, leftContextType);
-      }
       // TODO(scheglov) Do we need these checks for null?
       left?.accept(_resolver);
 
@@ -115,52 +114,22 @@
       // operator method, if applicable.
       _resolve1(node);
 
-      if (operator == TokenType.QUESTION_QUESTION) {
-        // Set the right side, either from the context, or using the information
-        // from the left side if it is more precise.
-        DartType contextType = InferenceContext.getContext(node);
-        DartType leftType = left?.staticType;
-        if (contextType == null || contextType.isDynamic) {
-          contextType = leftType;
-        }
-        InferenceContext.setType(right, contextType);
-      } else {
-        var invokeType = node.staticInvokeType;
-        if (invokeType != null && invokeType.parameters.isNotEmpty) {
-          // If this is a user-defined operator, set the right operand context
-          // using the operator method's parameter type.
-          var rightParam = invokeType.parameters[0];
-          InferenceContext.setType(
-              right, _elementTypeProvider.getVariableType(rightParam));
-        }
+      var invokeType = node.staticInvokeType;
+      if (invokeType != null && invokeType.parameters.isNotEmpty) {
+        // If this is a user-defined operator, set the right operand context
+        // using the operator method's parameter type.
+        var rightParam = invokeType.parameters[0];
+        InferenceContext.setType(
+            right, _elementTypeProvider.getVariableType(rightParam));
       }
 
-      if (operator == TokenType.QUESTION_QUESTION) {
-        flow?.ifNullExpression_rightBegin(node.leftOperand);
-        right.accept(_resolver);
-        flow?.ifNullExpression_end();
-      } else {
-        // TODO(scheglov) Do we need these checks for null?
-        right?.accept(_resolver);
-      }
+      // TODO(scheglov) Do we need these checks for null?
+      right?.accept(_resolver);
     }
     _resolve2(node);
   }
 
   /// Set the static type of [node] to be the least upper bound of the static
-  /// types of subexpressions [expr1] and [expr2].
-  ///
-  /// TODO(scheglov) this is duplicate
-  void _analyzeLeastUpperBound(
-      Expression node, Expression expr1, Expression expr2,
-      {bool read = false}) {
-    DartType staticType1 = _getExpressionType(expr1, read: read);
-    DartType staticType2 = _getExpressionType(expr2, read: read);
-
-    _analyzeLeastUpperBoundTypes(node, staticType1, staticType2);
-  }
-
-  /// Set the static type of [node] to be the least upper bound of the static
   /// types [staticType1] and [staticType2].
   ///
   /// TODO(scheglov) this is duplicate
@@ -221,27 +190,6 @@
   }
 
   void _resolve2(BinaryExpressionImpl node) {
-    if (node.operator.type == TokenType.QUESTION_QUESTION) {
-      if (_isNonNullableByDefault) {
-        // The static type of a compound assignment using ??= with NNBD is the
-        // least upper bound of the static types of the LHS and RHS after
-        // promoting the LHS/ to non-null (as we know its value will not be used
-        // if null)
-        _analyzeLeastUpperBoundTypes(
-            node,
-            _typeSystem.promoteToNonNull(
-                _getExpressionType(node.leftOperand, read: true)),
-            _getExpressionType(node.rightOperand, read: true));
-      } else {
-        // Without NNBD, evaluation of an if-null expression e of the form
-        // e1 ?? e2 is equivalent to the evaluation of the expression
-        // ((x) => x == null ? e2 : x)(e1).  The static type of e is the least
-        // upper bound of the static type of e1 and the static type of e2.
-        _analyzeLeastUpperBound(node, node.leftOperand, node.rightOperand);
-      }
-      return;
-    }
-
     if (identical(node.leftOperand.staticType, NeverTypeImpl.instance)) {
       _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance);
       return;
@@ -281,7 +229,7 @@
 
     if (identical(leftType, NeverTypeImpl.instance)) {
       _resolver.errorReporter.reportErrorForNode(
-        StaticWarningCode.INVALID_USE_OF_NEVER_VALUE,
+        HintCode.RECEIVER_OF_TYPE_NEVER,
         leftOperand,
       );
       return;
@@ -315,6 +263,43 @@
     }
   }
 
+  void _resolveIfNull(BinaryExpressionImpl node) {
+    var left = node.leftOperand;
+    var right = node.rightOperand;
+    var flow = _flowAnalysis?.flow;
+
+    var leftContextType = InferenceContext.getContext(node);
+    if (leftContextType != null && _isNonNullableByDefault) {
+      leftContextType = _typeSystem.makeNullable(leftContextType);
+    }
+    InferenceContext.setType(left, leftContextType);
+
+    left.accept(_resolver);
+    left = node.leftOperand;
+    var leftType = _getExpressionType(left, read: false);
+
+    var rightContextType = InferenceContext.getContext(node);
+    if (rightContextType == null || rightContextType.isDynamic) {
+      rightContextType = leftType;
+    }
+    InferenceContext.setType(right, rightContextType);
+
+    flow?.ifNullExpression_rightBegin(left);
+    right.accept(_resolver);
+    right = node.rightOperand;
+    flow?.ifNullExpression_end();
+
+    // TODO(scheglov) This (and above) is absolutely wrong, and convoluted.
+    // This is just the status quo, until we can make types straight.
+    var rightType = _getExpressionType(right, read: false);
+    if (_isNonNullableByDefault) {
+      var promotedLeftType = _typeSystem.promoteToNonNull(leftType);
+      _analyzeLeastUpperBoundTypes(node, promotedLeftType, rightType);
+    } else {
+      _analyzeLeastUpperBoundTypes(node, leftType, rightType);
+    }
+  }
+
   /// If the given [type] is a type parameter, resolve it to the type that should
   /// be used when looking up members. Otherwise, return the original type.
   ///
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
index 6acef20..516298a 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
@@ -36,16 +36,33 @@
   ExtensionMemberResolver get _extensionResolver => _resolver.extensionResolver;
 
   void resolve(FunctionExpressionInvocationImpl node) {
-    var rawType = _resolveCallElement(node);
+    var function = node.function;
 
-    if (rawType == null) {
-      _setExplicitTypeArgumentTypes(node);
-      _resolveArguments(node);
-      node.staticInvokeType = DynamicTypeImpl.instance;
-      node.staticType = DynamicTypeImpl.instance;
+    if (function is ExtensionOverride) {
+      _resolveReceiverExtensionOverride(node, function);
       return;
     }
 
+    var receiverType = function.staticType;
+    if (receiverType is FunctionType) {
+      _resolve(node, receiverType);
+      return;
+    }
+
+    if (receiverType is InterfaceType) {
+      _resolveReceiverInterfaceType(node, function, receiverType);
+      return;
+    }
+
+    if (identical(receiverType, NeverTypeImpl.instance)) {
+      _unresolved(node, NeverTypeImpl.instance);
+      return;
+    }
+
+    _unresolved(node, DynamicTypeImpl.instance);
+  }
+
+  void _resolve(FunctionExpressionInvocationImpl node, FunctionType rawType) {
     _inferenceHelper.resolveFunctionExpressionInvocation(
       node: node,
       rawType: rawType,
@@ -62,60 +79,66 @@
     node.argumentList.accept(_resolver);
   }
 
-  FunctionType _resolveCallElement(FunctionExpressionInvocation node) {
-    Expression function = node.function;
+  void _resolveReceiverExtensionOverride(
+    FunctionExpressionInvocation node,
+    ExtensionOverride function,
+  ) {
+    var result = _extensionResolver.getOverrideMember(
+      function,
+      FunctionElement.CALL_METHOD_NAME,
+    );
+    var callElement = result.getter;
+    node.staticElement = callElement;
 
-    if (function is ExtensionOverride) {
-      var result = _extensionResolver.getOverrideMember(
+    if (callElement == null) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.INVOCATION_OF_EXTENSION_WITHOUT_CALL,
         function,
-        FunctionElement.CALL_METHOD_NAME,
+        [function.extensionName.name],
       );
-      var callElement = result.getter;
-      node.staticElement = callElement;
-
-      if (callElement == null) {
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.INVOCATION_OF_EXTENSION_WITHOUT_CALL,
-          function,
-          [function.extensionName.name],
-        );
-        return null;
-      }
-
-      if (callElement.isStatic) {
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
-          node.argumentList,
-        );
-      }
-
-      return _elementTypeProvider.getExecutableType(callElement);
+      return _unresolved(node, DynamicTypeImpl.instance);
     }
 
-    var receiverType = function.staticType;
-    if (receiverType is FunctionType) {
-      return receiverType;
-    }
-
-    if (receiverType is InterfaceType) {
-      var result = _typePropertyResolver.resolve(
-        receiver: function,
-        receiverType: receiverType,
-        name: FunctionElement.CALL_METHOD_NAME,
-        receiverErrorNode: function,
-        nameErrorNode: function,
+    if (callElement.isStatic) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
+        node.argumentList,
       );
-      var callElement = result.getter;
-
-      if (callElement?.kind != ElementKind.METHOD) {
-        return null;
-      }
-
-      node.staticElement = callElement;
-      return _elementTypeProvider.getExecutableType(callElement);
     }
 
-    return null;
+    var rawType = _elementTypeProvider.getExecutableType(callElement);
+    _resolve(node, rawType);
+  }
+
+  void _resolveReceiverInterfaceType(
+    FunctionExpressionInvocationImpl node,
+    Expression function,
+    InterfaceType receiverType,
+  ) {
+    var result = _typePropertyResolver.resolve(
+      receiver: function,
+      receiverType: receiverType,
+      name: FunctionElement.CALL_METHOD_NAME,
+      receiverErrorNode: function,
+      nameErrorNode: function,
+    );
+    var callElement = result.getter;
+
+    if (callElement?.kind != ElementKind.METHOD) {
+      _unresolved(node, DynamicTypeImpl.instance);
+      return;
+    }
+
+    node.staticElement = callElement;
+    var rawType = _elementTypeProvider.getExecutableType(callElement);
+    _resolve(node, rawType);
+  }
+
+  void _unresolved(FunctionExpressionInvocationImpl node, DartType type) {
+    _setExplicitTypeArgumentTypes(node);
+    _resolveArguments(node);
+    node.staticInvokeType = DynamicTypeImpl.instance;
+    node.staticType = type;
   }
 
   /// Inference cannot be done, we still want to fill type argument types.
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index a80d2d0..92b8434 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -474,7 +474,7 @@
       _resolveArguments(node);
 
       _resolver.errorReporter.reportErrorForNode(
-        StaticWarningCode.INVALID_USE_OF_NEVER_VALUE,
+        HintCode.RECEIVER_OF_TYPE_NEVER,
         receiver,
       );
       return;
diff --git a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
index 4416b89..696c113 100644
--- a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
@@ -45,11 +45,6 @@
   TypeSystemImpl get _typeSystem => _resolver.typeSystem;
 
   void resolve(PostfixExpressionImpl node) {
-    if (node.operator.type == TokenType.BANG) {
-      _resolveNullCheck(node);
-      return;
-    }
-
     node.operand.accept(_resolver);
 
     var receiverType = getReadType(
@@ -57,6 +52,11 @@
       elementTypeProvider: _elementTypeProvider,
     );
 
+    if (node.operator.type == TokenType.BANG) {
+      _resolveNullCheck(node, receiverType);
+      return;
+    }
+
     _resolve1(node, receiverType);
     _resolve2(node, receiverType);
   }
@@ -131,7 +131,7 @@
 
     if (identical(receiverType, NeverTypeImpl.instance)) {
       _resolver.errorReporter.reportErrorForNode(
-        StaticWarningCode.INVALID_USE_OF_NEVER_VALUE,
+        HintCode.RECEIVER_OF_TYPE_NEVER,
         operand,
       );
       return;
@@ -189,28 +189,11 @@
     _inferenceHelper.recordStaticType(node, receiverType);
   }
 
-  void _resolveNullCheck(PostfixExpressionImpl node) {
-    var operand = node.operand;
-
-    var contextType = InferenceContext.getContext(node);
-    if (contextType != null) {
-      if (_isNonNullableByDefault) {
-        contextType = _typeSystem.makeNullable(contextType);
-      }
-      InferenceContext.setType(operand, contextType);
-    }
-
-    operand.accept(_resolver);
-
-    var operandType = getReadType(
-      operand,
-      elementTypeProvider: _elementTypeProvider,
-    );
-
+  void _resolveNullCheck(PostfixExpressionImpl node, DartType operandType) {
     var type = _typeSystem.promoteToNonNull(operandType);
     _inferenceHelper.recordStaticType(node, type);
 
-    _flowAnalysis?.flow?.nonNullAssert_end(operand);
+    _flowAnalysis?.flow?.nonNullAssert_end(node.operand);
   }
 
   /// Return `true` if we should report an error for the lookup [result] on
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
index 1ad1850..12a9597 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
@@ -190,7 +190,7 @@
 
       if (identical(staticType, NeverTypeImpl.instance)) {
         _resolver.errorReporter.reportErrorForNode(
-          StaticWarningCode.INVALID_USE_OF_NEVER_VALUE,
+          HintCode.RECEIVER_OF_TYPE_NEVER,
           operand,
         );
         return;
diff --git a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
index d46d7d8..e268abc 100644
--- a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
@@ -21,24 +21,24 @@
 /// Helper for resolving [ListLiteral]s and [SetOrMapLiteral]s.
 class TypedLiteralResolver {
   final ResolverVisitor _resolver;
-
   final TypeSystemImpl _typeSystem;
   final TypeProviderImpl _typeProvider;
   final ErrorReporter _errorReporter;
 
   final bool _strictInference;
   final bool _uiAsCodeEnabled;
+
   final bool _isNonNullableByDefault;
 
-  factory TypedLiteralResolver(
-      ResolverVisitor resolver, FeatureSet featureSet) {
+  factory TypedLiteralResolver(ResolverVisitor resolver, FeatureSet featureSet,
+      TypeSystemImpl typeSystem, TypeProviderImpl typeProvider) {
     var library = resolver.definingLibrary as LibraryElementImpl;
     var analysisOptions = library.context.analysisOptions;
     var analysisOptionsImpl = analysisOptions as AnalysisOptionsImpl;
     return TypedLiteralResolver._(
       resolver,
-      library.typeSystem,
-      library.typeProvider,
+      typeSystem,
+      typeProvider,
       resolver.errorReporter,
       analysisOptionsImpl.strictInference,
       featureSet.isEnabled(Feature.control_flow_collections) ||
@@ -541,6 +541,9 @@
       InferenceContext.setType(element.key, keyType);
       InferenceContext.setType(element.value, valueType);
     } else if (element is SpreadElement) {
+      if (_isNonNullableByDefault && element.isNullAware) {
+        iterableType = _typeSystem.makeNullable(iterableType);
+      }
       InferenceContext.setType(element.expression, iterableType);
     }
   }
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
index ec2b621..6058b89 100644
--- a/pkg/analyzer/lib/src/dart/scanner/scanner.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -4,9 +4,9 @@
 
 import 'package:_fe_analyzer_shared/src/scanner/errors.dart'
     show translateErrorToken;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
 import 'package:_fe_analyzer_shared/src/scanner/token.dart'
     show Token, TokenType;
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
@@ -190,9 +190,11 @@
   void _languageVersionChanged(
       fasta.Scanner scanner, fasta.LanguageVersionToken languageVersion) {
     if (_featureSet != null) {
-      _featureSet = _featureSet.restrictToVersion(
-          Version(languageVersion.major, languageVersion.minor, 0));
-      scanner.configuration = buildConfig(_featureSet);
+      if (languageVersion.major >= 0 && languageVersion.minor >= 0) {
+        _featureSet = _featureSet.restrictToVersion(
+            Version(languageVersion.major, languageVersion.minor, 0));
+        scanner.configuration = buildConfig(_featureSet);
+      }
     }
   }
 
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 305d02c..3696add 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -7589,24 +7589,6 @@
           errorSeverity: ErrorSeverity.WARNING);
 
   /**
-   * It is an error to call a method or getter on an expression of type `Never`,
-   * or to invoke it as if it were a function.
-   *
-   * Go out of our way to provide a *little* more information here because many
-   * dart users probably have never heard of the type Never. Be careful however
-   * of providing too much information or it only becomes more confusing. Hard
-   * balance to strike.
-   *
-   * Parameters: none
-   */
-  static const StaticWarningCode INVALID_USE_OF_NEVER_VALUE = StaticWarningCode(
-      'INVALID_USE_OF_NEVER_VALUE',
-      'This expression is invalid because its target is of type Never and'
-          ' will never complete with a value',
-      correction: 'Try checking for throw expressions or type errors in the'
-          ' target expression');
-
-  /**
    * For the purposes of experimenting with potential non-null type semantics.
    *
    * Whereas [UNCHECKED_USE_OF_NULLABLE] refers to using a value of type T? as
diff --git a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
index e753bd3..1b84b71 100644
--- a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
+++ b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
@@ -264,11 +264,23 @@
     return false;
   }
 
+  bool _isPrivateClassOrExtension(Element element) =>
+      (element is ClassElement || element is ExtensionElement) &&
+      element.isPrivate;
+
   /// Returns whether [element] is a private element which is read somewhere in
   /// the library.
   bool _isReadMember(Element element) {
+    bool elementIsStaticVariable =
+        element is VariableElement && element.isStatic;
     if (element.isPublic) {
-      return true;
+      if (_isPrivateClassOrExtension(element.enclosingElement) &&
+          elementIsStaticVariable) {
+        // Public static fields of private classes, mixins, and extensions are
+        // inaccessible from outside the library in which they are declared.
+      } else {
+        return true;
+      }
     }
     if (element.isSynthetic) {
       return true;
@@ -281,6 +293,9 @@
       return true;
     }
 
+    if (elementIsStaticVariable) {
+      return false;
+    }
     return _overridesUsedElement(element);
   }
 
@@ -301,7 +316,14 @@
 
   bool _isUsedMember(Element element) {
     if (element.isPublic) {
-      return true;
+      if (_isPrivateClassOrExtension(element.enclosingElement) &&
+          element is ExecutableElement &&
+          element.isStatic) {
+        // Public static members of private classes, mixins, and extensions are
+        // inaccessible from outside the library in which they are declared.
+      } else {
+        return true;
+      }
     }
     if (element.isSynthetic) {
       return true;
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 885602f..bec6557 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -159,53 +159,6 @@
   TypeSystemImpl get _typeSystem => _resolver.typeSystem;
 
   @override
-  void visitAssignmentExpression(AssignmentExpression node) {
-    Token operator = node.operator;
-    TokenType operatorType = operator.type;
-    Expression leftHandSide = node.leftHandSide;
-    DartType staticType = _getStaticType(leftHandSide, read: true);
-
-    // For any compound assignments to a void or nullable variable, report it.
-    // Example: `y += voidFn()`, not allowed.
-    if (operatorType != TokenType.EQ) {
-      if (staticType != null && staticType.isVoid) {
-        _errorReporter.reportErrorForToken(
-          StaticWarningCode.USE_OF_VOID_RESULT,
-          operator,
-        );
-        return;
-      }
-    }
-
-    if (operatorType != TokenType.AMPERSAND_AMPERSAND_EQ &&
-        operatorType != TokenType.BAR_BAR_EQ &&
-        operatorType != TokenType.EQ &&
-        operatorType != TokenType.QUESTION_QUESTION_EQ) {
-      operatorType = operatorFromCompoundAssignment(operatorType);
-      if (leftHandSide != null) {
-        String methodName = operatorType.lexeme;
-        // TODO(brianwilkerson) Change the [methodNameNode] from the left hand
-        //  side to the operator.
-        var result = _typePropertyResolver.resolve(
-          receiver: leftHandSide,
-          receiverType: staticType,
-          name: methodName,
-          receiverErrorNode: leftHandSide,
-          nameErrorNode: leftHandSide,
-        );
-        node.staticElement = result.getter;
-        if (_shouldReportInvalidMember(staticType, result)) {
-          _errorReporter.reportErrorForToken(
-            StaticTypeWarningCode.UNDEFINED_OPERATOR,
-            operator,
-            [methodName, staticType],
-          );
-        }
-      }
-    }
-  }
-
-  @override
   void visitBreakStatement(BreakStatement node) {
     node.target = _lookupBreakOrContinueTarget(node, node.label, false);
   }
@@ -454,7 +407,7 @@
 
     if (identical(targetType, NeverTypeImpl.instance)) {
       _resolver.errorReporter.reportErrorForNode(
-        StaticWarningCode.INVALID_USE_OF_NEVER_VALUE,
+        HintCode.RECEIVER_OF_TYPE_NEVER,
         target,
       );
       return;
@@ -967,7 +920,7 @@
       );
     } else if (identical(staticType, NeverTypeImpl.instance)) {
       _resolver.errorReporter.reportErrorForNode(
-        StaticWarningCode.INVALID_USE_OF_NEVER_VALUE,
+        HintCode.RECEIVER_OF_TYPE_NEVER,
         target,
       );
     } else {
@@ -1591,11 +1544,15 @@
           // A more specific error will be reported in ErrorVerifier.
         }
       } else if (result.isNone) {
-        _errorReporter.reportErrorForNode(
-          StaticTypeWarningCode.UNDEFINED_SETTER,
-          propertyName,
-          [propertyName.name, staticType],
-        );
+        if (staticType is NeverTypeImpl) {
+          // OK
+        } else {
+          _errorReporter.reportErrorForNode(
+            StaticTypeWarningCode.UNDEFINED_SETTER,
+            propertyName,
+            [propertyName.name, staticType],
+          );
+        }
       }
     }
   }
@@ -1686,21 +1643,6 @@
       type?.resolveToBound(_typeProvider.objectType);
 
   /**
-   * Return `true` if we should report an error for the lookup [result] on
-   * the [type].
-   */
-  bool _shouldReportInvalidMember(DartType type, ResolutionResult result) {
-    if (result.isNone && type != null && !type.isDynamic) {
-      if (_typeSystem.isNonNullableByDefault &&
-          _typeSystem.isPotentiallyNullable(type)) {
-        return false;
-      }
-      return true;
-    }
-    return false;
-  }
-
-  /**
    * Checks whether the given [expression] is a reference to a class. If it is
    * then the element representing the class is returned, otherwise `null` is
    * returned.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 1672467..a3d1669 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -3177,8 +3177,7 @@
       return;
     }
 
-    if (lhs is IndexExpression &&
-        identical(lhs.staticType, NeverTypeImpl.instance)) {
+    if (identical(lhs.staticType, NeverTypeImpl.instance)) {
       return;
     }
 
@@ -4812,7 +4811,7 @@
    * `(throw x).toString()` which is clearly something between a mistake and
    * dead code.
    *
-   * See [StaticWarningCode.INVALID_USE_OF_NEVER_VALUE].
+   * See [StaticWarningCode.RECEIVER_OF_TYPE_NEVER].
    */
   bool _checkForUseOfNever(Expression expression) {
     if (expression == null ||
@@ -4821,7 +4820,7 @@
     }
 
     _errorReporter.reportErrorForNode(
-        StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, expression);
+        HintCode.RECEIVER_OF_TYPE_NEVER, expression);
 
     return true;
   }
diff --git a/pkg/analyzer/lib/src/generated/migration.dart b/pkg/analyzer/lib/src/generated/migration.dart
index 0e9647d..29ab66e 100644
--- a/pkg/analyzer/lib/src/generated/migration.dart
+++ b/pkg/analyzer/lib/src/generated/migration.dart
@@ -11,6 +11,14 @@
 
 /// Hooks used by resolution to communicate with the migration engine.
 abstract class MigrationResolutionHooks implements ElementTypeProvider {
+  /// Called when the resolver is visiting an if statement, if element, or
+  /// conditional expression, to determine whether the condition is known to
+  /// evaluate to `true` or `false`.
+  ///
+  /// If the condition is known to evaluate to `true` or `false`, then the value
+  /// it is known to evaluate to is returned.  Otherwise `null` is returned.
+  bool getConditionalKnownValue(AstNode node);
+
   /// Called when the resolver is visiting a [TypeAnnotation] AST node.  Should
   /// return the type of the [TypeAnnotation] after migrations have been
   /// applied.
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 50f345c..20f89af 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -6,7 +6,6 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
@@ -23,6 +22,7 @@
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/binary_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
@@ -209,6 +209,7 @@
   /// Helper for resolving [ListLiteral] and [SetOrMapLiteral].
   TypedLiteralResolver _typedLiteralResolver;
 
+  AssignmentExpressionResolver _assignmentExpressionResolver;
   BinaryExpressionResolver _binaryExpressionResolver;
   FunctionExpressionInvocationResolver _functionExpressionInvocationResolver;
   PostfixExpressionResolver _postfixExpressionResolver;
@@ -266,7 +267,7 @@
   ///
   /// The stack contains a `null` sentinel as its first entry so that it is
   /// always safe to use `.last` to examine the top of the stack.
-  final List<Expression> unfinishedNullShorts = [null];
+  final List<Expression> _unfinishedNullShorts = [null];
 
   /// Initialize a newly created visitor to resolve the nodes in an AST node.
   ///
@@ -329,7 +330,8 @@
       typeSystem: typeSystem,
       errorReporter: errorReporter,
     );
-    this._typedLiteralResolver = TypedLiteralResolver(this, _featureSet);
+    this._typedLiteralResolver =
+        TypedLiteralResolver(this, _featureSet, typeSystem, typeProvider);
     this.extensionResolver = ExtensionMemberResolver(this);
     this.typePropertyResolver = TypePropertyResolver(this);
     this.inferenceHelper = InvocationInferenceHelper(
@@ -340,6 +342,11 @@
       errorReporter: errorReporter,
       typeSystem: typeSystem,
     );
+    this._assignmentExpressionResolver = AssignmentExpressionResolver(
+      resolver: this,
+      flowAnalysis: _flowAnalysis,
+      elementTypeProvider: _elementTypeProvider,
+    );
     this._binaryExpressionResolver = BinaryExpressionResolver(
       resolver: this,
       promoteManager: _promoteManager,
@@ -464,6 +471,20 @@
     }).toList());
   }
 
+  /// If we reached a null-shorting termination, and the [node] has null
+  /// shorting, make the type of the [node] nullable.
+  void nullShortingTermination(Expression node) {
+    if (!_isNonNullableByDefault) return;
+
+    if (identical(_unfinishedNullShorts.last, node)) {
+      do {
+        _unfinishedNullShorts.removeLast();
+        _flowAnalysis.flow.nullAwareAccess_end();
+      } while (identical(_unfinishedNullShorts.last, node));
+      node.staticType = typeSystem.makeNullable(node.staticType);
+    }
+  }
+
   /// If it is appropriate to do so, override the current type of the static
   /// element associated with the given expression with the given type.
   /// Generally speaking, it is appropriate if the given type is more specific
@@ -621,28 +642,7 @@
 
   @override
   void visitAssignmentExpression(AssignmentExpression node) {
-    var left = node.leftHandSide;
-    var right = node.rightHandSide;
-
-    left?.accept(this);
-
-    var leftLocalVariable = _flowAnalysis?.assignmentExpression(node);
-
-    TokenType operator = node.operator.type;
-    if (operator == TokenType.EQ ||
-        operator == TokenType.QUESTION_QUESTION_EQ) {
-      InferenceContext.setType(right, left.staticType);
-    }
-
-    right?.accept(this);
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
-    _flowAnalysis?.assignmentExpression_afterRight(
-        node,
-        leftLocalVariable,
-        operator == TokenType.QUESTION_QUESTION_EQ
-            ? node.rightHandSide.staticType
-            : node.staticType);
+    _assignmentExpressionResolver.resolve(node);
   }
 
   @override
@@ -1374,7 +1374,7 @@
     node.target?.accept(this);
     if (node.isNullAware && _isNonNullableByDefault) {
       _flowAnalysis.flow.nullAwareAccess_rightBegin(node.target);
-      unfinishedNullShorts.add(node.nullShortingTermination);
+      _unfinishedNullShorts.add(node.nullShortingTermination);
     }
     node.accept(elementResolver);
     var method = node.staticElement;
@@ -1542,7 +1542,7 @@
     node.target?.accept(this);
     if (node.isNullAware && _isNonNullableByDefault) {
       _flowAnalysis.flow.nullAwareAccess_rightBegin(node.target);
-      unfinishedNullShorts.add(node.nullShortingTermination);
+      _unfinishedNullShorts.add(node.nullShortingTermination);
     }
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
@@ -2098,6 +2098,20 @@
             FlowAnalysisHelperForMigration(
                 typeSystem, migrationResolutionHooks),
             migrationResolutionHooks);
+
+  @override
+  void visitIfStatement(IfStatement node) {
+    var conditionalKnownValue =
+        (_elementTypeProvider as MigrationResolutionHooks)
+            .getConditionalKnownValue(node);
+    if (conditionalKnownValue == null) {
+      super.visitIfStatement(node);
+      return;
+    } else {
+      (conditionalKnownValue ? node.thenStatement : node.elseStatement)
+          ?.accept(this);
+    }
+  }
 }
 
 /// The abstract class `ScopedVisitor` maintains name and label scopes as an AST
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 7114129..0507f27 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
@@ -227,97 +226,6 @@
   }
 
   /**
-   * The Dart Language Specification, 12.18: <blockquote>... an assignment <i>a</i> of the form <i>v
-   * = e</i> ...
-   *
-   * It is a static type warning if the static type of <i>e</i> may not be assigned to the static
-   * type of <i>v</i>.
-   *
-   * The static type of the expression <i>v = e</i> is the static type of <i>e</i>.
-   *
-   * ... an assignment of the form <i>C.v = e</i> ...
-   *
-   * It is a static type warning if the static type of <i>e</i> may not be assigned to the static
-   * type of <i>C.v</i>.
-   *
-   * The static type of the expression <i>C.v = e</i> is the static type of <i>e</i>.
-   *
-   * ... an assignment of the form <i>e<sub>1</sub>.v = e<sub>2</sub></i> ...
-   *
-   * Let <i>T</i> be the static type of <i>e<sub>1</sub></i>. It is a static type warning if
-   * <i>T</i> does not have an accessible instance setter named <i>v=</i>. It is a static type
-   * warning if the static type of <i>e<sub>2</sub></i> may not be assigned to <i>T</i>.
-   *
-   * The static type of the expression <i>e<sub>1</sub>.v = e<sub>2</sub></i> is the static type of
-   * <i>e<sub>2</sub></i>.
-   *
-   * ... an assignment of the form <i>e<sub>1</sub>[e<sub>2</sub>] = e<sub>3</sub></i> ...
-   *
-   * The static type of the expression <i>e<sub>1</sub>[e<sub>2</sub>] = e<sub>3</sub></i> is the
-   * static type of <i>e<sub>3</sub></i>.
-   *
-   * A compound assignment of the form <i>v op= e</i> is equivalent to <i>v = v op e</i>. A compound
-   * assignment of the form <i>C.v op= e</i> is equivalent to <i>C.v = C.v op e</i>. A compound
-   * assignment of the form <i>e<sub>1</sub>.v op= e<sub>2</sub></i> is equivalent to <i>((x) => x.v
-   * = x.v op e<sub>2</sub>)(e<sub>1</sub>)</i> where <i>x</i> is a variable that is not used in
-   * <i>e<sub>2</sub></i>. A compound assignment of the form <i>e<sub>1</sub>[e<sub>2</sub>] op=
-   * e<sub>3</sub></i> is equivalent to <i>((a, i) => a[i] = a[i] op e<sub>3</sub>)(e<sub>1</sub>,
-   * e<sub>2</sub>)</i> where <i>a</i> and <i>i</i> are a variables that are not used in
-   * <i>e<sub>3</sub></i>.</blockquote>
-   */
-  @override
-  void visitAssignmentExpression(AssignmentExpression node) {
-    TokenType operator = node.operator.type;
-    if (operator == TokenType.EQ) {
-      Expression rightHandSide = node.rightHandSide;
-      DartType staticType = _getStaticType(rightHandSide);
-      _recordStaticType(node, staticType);
-    } else if (operator == TokenType.QUESTION_QUESTION_EQ) {
-      if (_isNonNullableByDefault) {
-        // The static type of a compound assignment using ??= with NNBD is the
-        // least upper bound of the static types of the LHS and RHS after
-        // promoting the LHS/ to non-null (as we know its value will not be used
-        // if null)
-        _analyzeLeastUpperBoundTypes(
-            node,
-            _typeSystem.promoteToNonNull(
-                _getExpressionType(node.leftHandSide, read: true)),
-            _getExpressionType(node.rightHandSide, read: true));
-      } else {
-        // The static type of a compound assignment using ??= before NNBD is the
-        // least upper bound of the static types of the LHS and RHS.
-        _analyzeLeastUpperBound(node, node.leftHandSide, node.rightHandSide,
-            read: true);
-      }
-    } else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ ||
-        operator == TokenType.BAR_BAR_EQ) {
-      _recordStaticType(node, _nonNullable(_typeProvider.boolType));
-    } else {
-      var operatorElement = node.staticElement;
-      var type =
-          _elementTypeProvider.safeExecutableReturnType(operatorElement) ??
-              _dynamicType;
-      type = _typeSystem.refineBinaryExpressionType(
-        _getStaticType(node.leftHandSide, read: true),
-        operator,
-        node.rightHandSide.staticType,
-        type,
-      );
-      _recordStaticType(node, type);
-
-      var leftWriteType = _getStaticType(node.leftHandSide);
-      if (!_typeSystem.isAssignableTo(type, leftWriteType)) {
-        _resolver.errorReporter.reportErrorForNode(
-          StaticTypeWarningCode.INVALID_ASSIGNMENT,
-          node.rightHandSide,
-          [type, leftWriteType],
-        );
-      }
-    }
-    _nullShortingTermination(node);
-  }
-
-  /**
    * The Dart Language Specification, 16.29 (Await Expressions):
    *
    *   The static type of [the expression "await e"] is flatten(T) where T is
@@ -472,7 +380,7 @@
       _recordStaticType(node, type);
     }
 
-    _nullShortingTermination(node);
+    _resolver.nullShortingTermination(node);
   }
 
   /**
@@ -670,7 +578,7 @@
     if (!_inferObjectAccess(node, staticType, propertyName)) {
       _recordStaticType(propertyName, staticType);
       _recordStaticType(node, staticType);
-      _nullShortingTermination(node);
+      _resolver.nullShortingTermination(node);
     }
   }
 
@@ -1197,20 +1105,6 @@
     return type;
   }
 
-  /// If we reached a null-shorting termination, and the [node] has null
-  /// shorting, make the type of the [node] nullable.
-  void _nullShortingTermination(Expression node) {
-    if (!_isNonNullableByDefault) return;
-
-    if (identical(_resolver.unfinishedNullShorts.last, node)) {
-      do {
-        _resolver.unfinishedNullShorts.removeLast();
-        _flowAnalysis.flow.nullAwareAccess_end();
-      } while (identical(_resolver.unfinishedNullShorts.last, node));
-      node.staticType = _typeSystem.makeNullable(node.staticType);
-    }
-  }
-
   /**
    * Record that the static type of the given node is the given type.
    *
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index 5075f49..12bcfe9 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -147,6 +147,10 @@
     return _node(search, (n) => n is GenericFunctionType);
   }
 
+  IfElement ifElement(String search) {
+    return _node(search, (n) => n is IfElement);
+  }
+
   ImportDirective import(String search) {
     return _node(search, (n) => n is ImportDirective);
   }
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index 8cf3d18..5deef1f 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -419,28 +419,6 @@
     _listener.assertNoErrors();
   }
 
-  test_visitAssignmentExpression_compound() async {
-    InterfaceType intType = _typeProvider.intType;
-    SimpleIdentifier leftHandSide = AstTestFactory.identifier3("a");
-    leftHandSide.staticType = intType;
-    AssignmentExpression assignment = AstTestFactory.assignmentExpression(
-        leftHandSide, TokenType.PLUS_EQ, AstTestFactory.integer(1));
-    _resolveNode(assignment);
-    expect(
-        assignment.staticElement, same(_typeProvider.numType.getMethod('+')));
-    _listener.assertNoErrors();
-  }
-
-  test_visitAssignmentExpression_simple() async {
-    AssignmentExpression expression = AstTestFactory.assignmentExpression(
-        AstTestFactory.identifier3("x"),
-        TokenType.EQ,
-        AstTestFactory.integer(0));
-    _resolveNode(expression);
-    expect(expression.staticElement, isNull);
-    _listener.assertNoErrors();
-  }
-
   test_visitBreakStatement_withLabel() async {
     // loop: while (true) {
     //   break loop;
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index bec2ac5..f37d25e 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -5,11 +5,14 @@
 import 'package:_fe_analyzer_shared/src/scanner/error_token.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/string_source.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -18,6 +21,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(LineInfoTest);
+    defineReflectiveTests(ScannerTest);
   });
 }
 
@@ -183,6 +187,49 @@
   }
 }
 
+@reflectiveTest
+class ScannerTest with ResourceProviderMixin {
+  test_featureSet() {
+    var scanner = _createScanner(r'''
+// @dart = 2.0
+''');
+    var defaultFeatureSet = FeatureSet.fromEnableFlags([]);
+    expect(defaultFeatureSet.isEnabled(Feature.extension_methods), isTrue);
+
+    scanner.configureFeatures(FeatureSet.forTesting());
+    scanner.tokenize();
+
+    var featureSet = scanner.featureSet;
+    expect(featureSet.isEnabled(Feature.extension_methods), isFalse);
+  }
+
+  test_featureSet_majorOverflow() {
+    var scanner = _createScanner(r'''
+// @dart = 99999999999999999999999999999999.0
+''');
+    scanner.configureFeatures(FeatureSet.forTesting());
+    scanner.tokenize();
+    // Don't check features, but should not crash.
+  }
+
+  test_featureSet_minorOverflow() {
+    var scanner = _createScanner(r'''
+// @dart = 2.99999999999999999999999999999999
+''');
+    scanner.configureFeatures(FeatureSet.forTesting());
+    scanner.tokenize();
+    // Don't check features, but should not crash.
+  }
+
+  Scanner _createScanner(String content) {
+    var path = convertPath('/test/lib/a.dart');
+    var source = StringSource(content, path);
+    var reader = CharSequenceReader(content);
+    var errorCollector = RecordingErrorListener();
+    return Scanner(source, reader, errorCollector);
+  }
+}
+
 /**
  * An `ExpectedLocation` encodes information about the expected location of a
  * given offset in source code.
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index 90ae072..0fb0a7f 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -403,29 +403,6 @@
     _listener.assertNoErrors();
   }
 
-  void test_visitAssignmentExpression_compound_lazy() {
-    validate(TokenType operator) {
-      InterfaceType boolType = _typeProvider.boolType;
-      SimpleIdentifier identifier = _resolvedVariable(boolType, "b");
-      AssignmentExpression node = AstTestFactory.assignmentExpression(
-          identifier, operator, _resolvedBool(true));
-      expect(_analyze(node), same(boolType));
-      _listener.assertNoErrors();
-    }
-
-    validate(TokenType.AMPERSAND_AMPERSAND_EQ);
-    validate(TokenType.BAR_BAR_EQ);
-  }
-
-  void test_visitAssignmentExpression_simple() {
-    // i = 0
-    InterfaceType intType = _typeProvider.intType;
-    Expression node = AstTestFactory.assignmentExpression(
-        _resolvedVariable(intType, "i"), TokenType.EQ, _resolvedInteger(0));
-    expect(_analyze(node), same(intType));
-    _listener.assertNoErrors();
-  }
-
   void test_visitAwaitExpression_flattened() {
     // await e, where e has type Future<Future<int>>
     InterfaceType intType = _typeProvider.intType;
@@ -1120,16 +1097,6 @@
   DartType _flatten(DartType type) => _typeSystem.flatten(type);
 
   /**
-   * Return a boolean literal with the given [value] that has been resolved to
-   * the correct type.
-   */
-  BooleanLiteral _resolvedBool(bool value) {
-    BooleanLiteral literal = AstTestFactory.booleanLiteral(value);
-    literal.staticType = _typeProvider.intType;
-    return literal;
-  }
-
-  /**
    * Return an integer literal that has been resolved to the correct type.
    *
    * @param value the value of the literal
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index ff0feb7..7e58e58 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -599,7 +599,9 @@
     expected.lint = true;
     expected.lintRules = <Linter>[_mockLintRule];
     String packagesFilePath = convertPath('/some/directory/path/.packages');
-    newFile(packagesFilePath, content: 'flutter:/pkg/flutter/lib/');
+    newFile(packagesFilePath, content: '''
+flutter:${toUriStr('/pkg/flutter/lib/')}
+''');
     newFile('/pkg/flutter/lib/analysis_options_user.yaml', content: '''
 linter:
   rules:
diff --git a/pkg/analyzer/test/src/context/packages_test.dart b/pkg/analyzer/test/src/context/packages_test.dart
index 0e01a4f..044313a 100644
--- a/pkg/analyzer/test/src/context/packages_test.dart
+++ b/pkg/analyzer/test/src/context/packages_test.dart
@@ -21,6 +21,87 @@
     newFile('/test/lib/test.dart', content: '');
   }
 
+  void test_findPackagesFrom_fallbackToDotPackages() {
+    newFile('/test/.packages', content: '''
+test:lib/
+bbb:${toUriStr('/packages/bbb/lib')}
+''');
+
+    var packages = findPackagesFrom(
+      resourceProvider,
+      getFile('/test/lib/a.dart'),
+    );
+
+    _assertPackage(
+      packages,
+      name: 'test',
+      expectedLibPath: '/test/lib',
+      expectedVersion: null,
+    );
+
+    _assertPackage(
+      packages,
+      name: 'bbb',
+      expectedLibPath: '/packages/bbb/lib',
+      expectedVersion: null,
+    );
+  }
+
+  void test_findPackagesFrom_missing() {
+    var packages = findPackagesFrom(
+      resourceProvider,
+      getFile('/test/lib/a.dart'),
+    );
+
+    expect(packages.packages, isEmpty);
+  }
+
+  void test_findPackagesFrom_preferPackageConfig() {
+    newFile('/test/.dart_tool/package_config.json', content: '''
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "test",
+      "rootUri": "../",
+      "packageUri": "lib/",
+      "languageVersion": "2.6"
+    },
+    {
+      "name": "aaa",
+      "rootUri": "${toUriStr('/packages/aaa')}",
+      "packageUri": "lib/",
+      "languageVersion": "2.3"
+    }
+  ]
+}
+''');
+
+    newFile('/test/.packages', content: '''
+test:lib/
+bbb:${toUriStr('/packages/bbb/lib')}
+''');
+
+    var packages = findPackagesFrom(
+      resourceProvider,
+      getFile('/test/lib/a.dart'),
+    );
+
+    _assertPackage(
+      packages,
+      name: 'test',
+      expectedLibPath: '/test/lib',
+      expectedVersion: Version(2, 6, 0),
+    );
+
+    _assertPackage(
+      packages,
+      name: 'aaa',
+      expectedLibPath: '/packages/aaa/lib',
+      expectedVersion: Version(2, 3, 0),
+    );
+  }
+
   test_parseDotPackagesFile() {
     var file = newFile('/test/.packages', content: '''
 # Generated by pub
diff --git a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
index 083f98c..ab574a6 100644
--- a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
@@ -196,7 +196,7 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  test_ifNull_left_nullable() async {
+  test_ifNull_left_nullableContext() async {
     await assertNoErrorsInCode(r'''
 T f<T>(T t) => t;
 
@@ -217,4 +217,46 @@
       type: 'int',
     );
   }
+
+  test_ifNull_nullableInt_int() async {
+    await assertNoErrorsInCode(r'''
+main(int? x, int y) {
+  x ?? y;
+}
+''');
+
+    assertBinaryExpression(
+      findNode.binary('x ?? y'),
+      element: null,
+      type: 'int',
+    );
+  }
+
+  test_ifNull_nullableInt_nullableDouble() async {
+    await assertNoErrorsInCode(r'''
+main(int? x, double? y) {
+  x ?? y;
+}
+''');
+
+    assertBinaryExpression(
+      findNode.binary('x ?? y'),
+      element: null,
+      type: 'num?',
+    );
+  }
+
+  test_ifNull_nullableInt_nullableInt() async {
+    await assertNoErrorsInCode(r'''
+main(int? x) {
+  x ?? x;
+}
+''');
+
+    assertBinaryExpression(
+      findNode.binary('x ?? x'),
+      element: null,
+      type: 'int?',
+    );
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/class_test.dart b/pkg/analyzer/test/src/dart/resolution/class_test.dart
index f5fceea..72deb9d 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_test.dart
@@ -18,139 +18,6 @@
 @reflectiveTest
 class ClassDriverResolutionTest extends DriverResolutionTest
     with ElementsTypesMixin {
-  test_abstractSuperMemberReference_getter() async {
-    await assertErrorsInCode(r'''
-abstract class A {
-  get foo;
-}
-abstract class B extends A {
-  bar() {
-    super.foo; // ref
-  }
-}
-''', [
-      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 81, 3),
-    ]);
-    assertElement(findNode.simple('foo; // ref'), findElement.getter('foo'));
-  }
-
-  test_abstractSuperMemberReference_getter2() async {
-    await assertErrorsInCode(r'''
-abstract class Foo {
-  String get foo;
-}
-
-abstract class Bar implements Foo {
-}
-
-class Baz extends Bar {
-  String get foo => super.foo; // ref
-}
-''', [
-      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 131, 3),
-    ]);
-    assertElement(
-      findNode.simple('foo; // ref'),
-      findElement.getter('foo', of: 'Foo'),
-    );
-  }
-
-  test_abstractSuperMemberReference_method_reference() async {
-    await assertErrorsInCode(r'''
-abstract class A {
-  foo();
-}
-abstract class B extends A {
-  bar() {
-    super.foo; // ref
-  }
-}
-''', [
-      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 79, 3),
-    ]);
-    assertElement(findNode.simple('foo; // ref'), findElement.method('foo'));
-  }
-
-  test_abstractSuperMemberReference_OK_superHasConcrete_mixinHasAbstract_method() async {
-    await assertNoErrorsInCode('''
-class A {
-  void foo() {}
-}
-
-abstract class B {
-  void foo();
-}
-
-class C extends A with B {
-  void bar() {
-    super.foo(); // ref
-  }
-}
-''');
-    assertElement(
-      findNode.simple('foo(); // ref'),
-      findElement.method('foo', of: 'A'),
-    );
-  }
-
-  test_abstractSuperMemberReference_OK_superSuperHasConcrete_getter() async {
-    await assertNoErrorsInCode('''
-abstract class A {
-  int get foo => 0;
-}
-
-abstract class B extends A {
-  int get foo;
-}
-
-class C extends B {
-  int get bar => super.foo; // ref
-}
-''');
-    assertElement(
-      findNode.simple('foo; // ref'),
-      findElement.getter('foo', of: 'A'),
-    );
-  }
-
-  test_abstractSuperMemberReference_OK_superSuperHasConcrete_setter() async {
-    await assertNoErrorsInCode('''
-abstract class A {
-  void set foo(_) {}
-}
-
-abstract class B extends A {
-  void set foo(_);
-}
-
-class C extends B {
-  void bar() {
-    super.foo = 0;
-  }
-}
-''');
-    assertElement(
-      findNode.simple('foo = 0;'),
-      findElement.setter('foo', of: 'A'),
-    );
-  }
-
-  test_abstractSuperMemberReference_setter() async {
-    await assertErrorsInCode(r'''
-abstract class A {
-  set foo(_);
-}
-abstract class B extends A {
-  bar() {
-    super.foo = 0;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 84, 3),
-    ]);
-    assertElement(findNode.simple('foo = 0;'), findElement.setter('foo'));
-  }
-
   test_element_allSupertypes() async {
     await assertNoErrorsInCode(r'''
 class A {}
diff --git a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
index 4de479a..bd90019 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -145,4 +146,44 @@
       type: 'int',
     );
   }
+
+  test_never() async {
+    await assertErrorsInCode(r'''
+main(Never x) {
+  x<int>(1 + 2);
+}
+''', [
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 18, 1),
+    ]);
+
+    assertFunctionExpressionInvocation(
+      findNode.functionExpressionInvocation('x<int>(1 + 2)'),
+      element: null,
+      typeArgumentTypes: ['int'],
+      invokeType: 'dynamic',
+      type: 'Never',
+    );
+
+    assertType(findNode.binary('1 + 2'), 'int');
+  }
+
+  test_neverQ() async {
+    await assertErrorsInCode(r'''
+main(Never? x) {
+  x<int>(1 + 2);
+}
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 19, 1),
+    ]);
+
+    assertFunctionExpressionInvocation(
+      findNode.functionExpressionInvocation('x<int>(1 + 2)'),
+      element: null,
+      typeArgumentTypes: ['int'],
+      invokeType: 'dynamic',
+      type: 'dynamic',
+    );
+
+    assertType(findNode.binary('1 + 2'), 'int');
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index 0420fdf..8bedd48 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -4,7 +4,9 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
@@ -12,158 +14,12 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MethodInvocationResolutionTest);
+    defineReflectiveTests(MethodInvocationResolutionWithNnbdTest);
   });
 }
 
 @reflectiveTest
 class MethodInvocationResolutionTest extends DriverResolutionTest {
-  test_error_abstractSuperMemberReference() async {
-    await assertErrorsInCode(r'''
-abstract class A {
-  void foo(int _);
-}
-abstract class B extends A {
-  void bar() {
-    super.foo(0);
-  }
-
-  void foo(int _) {} // does not matter
-}
-''', [
-      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 94, 3),
-    ]);
-
-    var invocation = findNode.methodInvocation('foo(0)');
-    assertMethodInvocation(
-      invocation,
-      findElement.method('foo', of: 'A'),
-      'void Function(int)',
-    );
-    assertSuperExpression(invocation.target);
-  }
-
-  test_error_abstractSuperMemberReference_mixin_implements() async {
-    await assertErrorsInCode(r'''
-class A {
-  void foo(int _) {}
-}
-
-mixin M implements A {
-  void bar() {
-    super.foo(0);
-  }
-}
-''', [
-      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 82, 3),
-    ]);
-
-    var invocation = findNode.methodInvocation('foo(0)');
-    assertMethodInvocation(
-      invocation,
-      findElement.method('foo', of: 'A'),
-      'void Function(int)',
-    );
-    assertSuperExpression(invocation.target);
-  }
-
-  test_error_abstractSuperMemberReference_mixinHasNoSuchMethod() async {
-    await assertErrorsInCode('''
-class A {
-  int foo();
-  noSuchMethod(im) => 42;
-}
-
-class B extends Object with A {
-  foo() => super.foo(); // ref
-  noSuchMethod(im) => 87;
-}
-''', [
-      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 101, 3),
-    ]);
-
-    var invocation = findNode.methodInvocation('foo(); // ref');
-    assertMethodInvocation(
-      invocation,
-      findElement.method('foo', of: 'A'),
-      'int Function()',
-    );
-    assertSuperExpression(invocation.target);
-  }
-
-  test_error_abstractSuperMemberReference_OK_mixinHasConcrete() async {
-    await assertNoErrorsInCode('''
-class A {}
-
-class M {
-  void foo(int _) {}
-}
-
-class B = A with M;
-
-class C extends B {
-  void bar() {
-    super.foo(0);
-  }
-}
-''');
-
-    var invocation = findNode.methodInvocation('foo(0)');
-    assertMethodInvocation(
-      invocation,
-      findElement.method('foo', of: 'M'),
-      'void Function(int)',
-    );
-    assertSuperExpression(invocation.target);
-  }
-
-  test_error_abstractSuperMemberReference_OK_superHasNoSuchMethod() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int foo();
-  noSuchMethod(im) => 42;
-}
-
-class B extends A {
-  int foo() => super.foo(); // ref
-  noSuchMethod(im) => 87;
-}
-''');
-
-    var invocation = findNode.methodInvocation('super.foo(); // ref');
-    assertMethodInvocation(
-      invocation,
-      findElement.method('foo', of: 'A'),
-      'int Function()',
-    );
-    assertSuperExpression(invocation.target);
-  }
-
-  test_error_abstractSuperMemberReference_OK_superSuperHasConcrete() async {
-    await assertNoErrorsInCode('''
-abstract class A {
-  void foo(int _) {}
-}
-
-abstract class B extends A {
-  void foo(int _);
-}
-
-class C extends B {
-  void bar() {
-    super.foo(0);
-  }
-}
-''');
-
-    var invocation = findNode.methodInvocation('foo(0)');
-    assertMethodInvocation(
-      invocation,
-      findElement.method('foo', of: 'A'),
-      'void Function(int)',
-    );
-    assertSuperExpression(invocation.target);
-  }
-
   test_error_ambiguousImport_topFunction() async {
     newFile('/test/lib/a.dart', content: r'''
 void foo(int _) {}
@@ -1836,3 +1692,150 @@
 //    );
   }
 }
+
+@reflectiveTest
+class MethodInvocationResolutionWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
+
+  test_hasReceiver_interfaceTypeQ_defined() async {
+    await assertErrorsInCode(r'''
+class A {
+  void foo() {}
+}
+
+main(A? a) {
+  a.foo();
+}
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 44, 1),
+    ]);
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('a.foo()'),
+      element: findElement.method('foo', of: 'A'),
+      typeArgumentTypes: [],
+      invokeType: 'void Function()',
+      type: 'void',
+    );
+  }
+
+  test_hasReceiver_interfaceTypeQ_defined_extension() async {
+    await assertErrorsInCode(r'''
+class A {
+  void foo() {}
+}
+
+extension E on A {
+  void foo() {}
+}
+
+main(A? a) {
+  a.foo();
+}
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 82, 1),
+    ]);
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('a.foo()'),
+      element: findElement.method('foo', of: 'A'),
+      typeArgumentTypes: [],
+      invokeType: 'void Function()',
+      type: 'void',
+    );
+  }
+
+  test_hasReceiver_interfaceTypeQ_defined_extensionQ() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  void foo() {}
+}
+
+extension E on A? {
+  void foo() {}
+}
+
+main(A? a) {
+  a.foo();
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('a.foo()'),
+      element: findElement.method('foo', of: 'E'),
+      typeArgumentTypes: [],
+      invokeType: 'void Function()',
+      type: 'void',
+    );
+  }
+
+  test_hasReceiver_interfaceTypeQ_notDefined() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+main(A? a) {
+  a.foo();
+}
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 27, 1),
+      error(StaticTypeWarningCode.UNDEFINED_METHOD, 29, 3),
+    ]);
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('a.foo()'),
+      element: null,
+      typeArgumentTypes: [],
+      invokeType: 'dynamic',
+      type: 'dynamic',
+    );
+  }
+
+  test_hasReceiver_interfaceTypeQ_notDefined_extension() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+extension E on A {
+  void foo() {}
+}
+
+main(A? a) {
+  a.foo();
+}
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 65, 1),
+      error(StaticTypeWarningCode.UNDEFINED_METHOD, 67, 3),
+    ]);
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('a.foo()'),
+      element: null,
+      typeArgumentTypes: [],
+      invokeType: 'dynamic',
+      type: 'dynamic',
+    );
+  }
+
+  test_hasReceiver_interfaceTypeQ_notDefined_extensionQ() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+
+extension E on A? {
+  void foo() {}
+}
+
+main(A? a) {
+  a.foo();
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('a.foo()'),
+      element: findElement.method('foo', of: 'E'),
+      typeArgumentTypes: [],
+      invokeType: 'void Function()',
+      type: 'void',
+    );
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index 1f63ff2..5b0222e 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
@@ -150,27 +150,6 @@
     assertType(findNode.methodInvocation('c?.x()'), 'bool?');
   }
 
-  test_local_nullCoalesce_nullableInt_int() async {
-    await assertNoErrorsInCode(r'''
-main() {
-  int? x;
-  int y = 0;
-  x ?? y;
-}
-''');
-    assertType(findNode.binary('x ?? y'), 'int');
-  }
-
-  test_local_nullCoalesce_nullableInt_nullableInt() async {
-    await assertNoErrorsInCode(r'''
-main() {
-  int? x;
-  x ?? x;
-}
-''');
-    assertType(findNode.binary('x ?? x'), 'int?');
-  }
-
   test_local_nullCoalesceAssign_nullableInt_int() async {
     await assertNoErrorsInCode(r'''
 main() {
@@ -376,24 +355,6 @@
     assertType(findNode.methodInvocation('c?.x()'), 'bool?');
   }
 
-  test_parameter_nullCoalesce_nullableInt_int() async {
-    await assertNoErrorsInCode(r'''
-main(int? x, int y) {
-  x ?? y;
-}
-''');
-    assertType(findNode.binary('x ?? y'), 'int');
-  }
-
-  test_parameter_nullCoalesce_nullableInt_nullableInt() async {
-    await assertNoErrorsInCode(r'''
-main(int? x) {
-  x ?? x;
-}
-''');
-    assertType(findNode.binary('x ?? x'), 'int?');
-  }
-
   test_parameter_nullCoalesceAssign_nullableInt_int() async {
     await assertNoErrorsInCode(r'''
 main(int? x, int y) {
diff --git a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
index ea38101..c8e1653 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -129,28 +129,6 @@
     assertType(findNode.postfix('x!'), 'Never');
   }
 
-  test_nullCheck_nullableContext() async {
-    await assertNoErrorsInCode(r'''
-T f<T>(T t) => t;
-
-int g() => f(null)!;
-''');
-
-    assertMethodInvocation2(
-      findNode.methodInvocation('f(null)'),
-      element: findElement.topFunction('f'),
-      typeArgumentTypes: ['int?'],
-      invokeType: 'int? Function(int?)',
-      type: 'int?',
-    );
-
-    assertPostfixExpression(
-      findNode.postfix('f(null)!'),
-      element: null,
-      type: 'int',
-    );
-  }
-
   test_nullCheck_typeParameter() async {
     await assertNoErrorsInCode(r'''
 f<T>(T? x) {
diff --git a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
index a407ade..0f92987 100644
--- a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
@@ -18,90 +18,6 @@
 
 @reflectiveTest
 class PropertyAccessResolutionTest extends DriverResolutionTest {
-  test_get_error_abstractSuperMemberReference_mixinHasNoSuchMethod() async {
-    await assertErrorsInCode('''
-class A {
-  int get foo;
-  noSuchMethod(im) => 1;
-}
-
-class B extends Object with A {
-  get foo => super.foo; // ref
-  noSuchMethod(im) => 2;
-}
-''', [
-      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 104, 3),
-    ]);
-
-    var access = findNode.propertyAccess('foo; // ref');
-    assertPropertyAccess(access, findElement.getter('foo', of: 'A'), 'int');
-    assertSuperExpression(access.target);
-  }
-
-  test_get_error_abstractSuperMemberReference_OK_superHasNoSuchMethod() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int get foo;
-  noSuchMethod(im) => 1;
-}
-
-class B extends A {
-  get foo => super.foo; // ref
-  noSuchMethod(im) => 2;
-}
-''');
-
-    var access = findNode.propertyAccess('super.foo; // ref');
-    assertPropertyAccess(access, findElement.getter('foo', of: 'A'), 'int');
-    assertSuperExpression(access.target);
-  }
-
-  test_set_error_abstractSuperMemberReference_mixinHasNoSuchMethod() async {
-    await assertErrorsInCode('''
-class A {
-  set foo(int a);
-  noSuchMethod(im) {}
-}
-
-class B extends Object with A {
-  set foo(v) => super.foo = v; // ref
-  noSuchMethod(im) {}
-}
-''', [
-      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 107, 3),
-    ]);
-
-    var access = findNode.propertyAccess('foo = v; // ref');
-    assertPropertyAccess(
-      access,
-      findElement.setter('foo', of: 'A'),
-      'int',
-    );
-    assertSuperExpression(access.target);
-  }
-
-  test_set_error_abstractSuperMemberReference_OK_superHasNoSuchMethod() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  set foo(int a);
-  noSuchMethod(im) => 1;
-}
-
-class B extends A {
-  set foo(v) => super.foo = v; // ref
-  noSuchMethod(im) => 2;
-}
-''');
-
-    var access = findNode.propertyAccess('foo = v; // ref');
-    assertPropertyAccess(
-      access,
-      findElement.setter('foo', of: 'A'),
-      'int',
-    );
-    assertSuperExpression(access.target);
-  }
-
   test_tearOff_method() async {
     await assertNoErrorsInCode('''
 class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 2f29a52..0ca1c8b 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -75,6 +75,15 @@
     newFile('/test/lib/test.dart', content: content);
   }
 
+  void assertAssignment(
+    AssignmentExpression node, {
+    @required ExecutableElement operatorElement,
+    @required String type,
+  }) {
+    expect(node.staticElement, same(operatorElement));
+    assertType(node, type);
+  }
+
   void assertAuxElement(AstNode node, Element expected) {
     var auxElements = getNodeAuxElements(node);
     expect(auxElements?.staticElement, same(expected));
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
index 913e53b..f7fad59 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
@@ -311,6 +311,24 @@
   @override
   bool get typeToStringWithNullability => true;
 
+  test_context_spread_nullAware() async {
+    await assertNoErrorsInCode('''
+T f<T>(T t) => t;
+
+main() {
+  <int>[...?f(null)];
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('f(null)'),
+      element: findElement.topFunction('f'),
+      typeArgumentTypes: ['Iterable<int>?'],
+      invokeType: 'Iterable<int>? Function(Iterable<int>?)',
+      type: 'Iterable<int>?',
+    );
+  }
+
   test_nested_hasNull_1() async {
     await assertNoErrorsInCode('''
 main() {
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
index b14de64..9ec241a 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
@@ -358,4 +358,22 @@
     assertType(setOrMapLiteral('{}; // 3'), 'Map<String, T?>');
     assertType(setOrMapLiteral('{}; // 4'), 'Map<String, T?>');
   }
+
+  test_context_spread_nullAware() async {
+    await assertNoErrorsInCode('''
+T f<T>(T t) => t;
+
+main() {
+  <int, double>{...?f(null)};
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('f(null)'),
+      element: findElement.topFunction('f'),
+      typeArgumentTypes: ['Map<int, double>?'],
+      invokeType: 'Map<int, double>? Function(Map<int, double>?)',
+      type: 'Map<int, double>?',
+    );
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/abstract_super_member_reference_test.dart b/pkg/analyzer/test/src/diagnostics/abstract_super_member_reference_test.dart
new file mode 100644
index 0000000..cb4fedd
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/abstract_super_member_reference_test.dart
@@ -0,0 +1,410 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AbstractSuperMemberReferenceTest);
+  });
+}
+
+@reflectiveTest
+class AbstractSuperMemberReferenceTest extends DriverResolutionTest {
+  test_methodInvocation_mixin_implements() async {
+    await assertErrorsInCode(r'''
+class A {
+  void foo(int _) {}
+}
+
+mixin M implements A {
+  void bar() {
+    super.foo(0);
+  }
+}
+''', [
+      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 82, 3),
+    ]);
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('super.foo(0)'),
+      element: findElement.method('foo', of: 'A'),
+      typeArgumentTypes: [],
+      invokeType: 'void Function(int)',
+      type: 'void',
+    );
+  }
+
+  test_methodInvocation_mixinHasConcrete() async {
+    await assertNoErrorsInCode('''
+class A {}
+
+class M {
+  void foo() {}
+}
+
+class B = A with M;
+
+class C extends B {
+  void bar() {
+    super.foo();
+  }
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('super.foo()'),
+      element: findElement.method('foo', of: 'M'),
+      typeArgumentTypes: [],
+      invokeType: 'void Function()',
+      type: 'void',
+    );
+  }
+
+  test_methodInvocation_mixinHasNoSuchMethod() async {
+    await assertErrorsInCode('''
+class A {
+  void foo();
+  noSuchMethod(im) => 42;
+}
+
+class B extends Object with A {
+  void foo() => super.foo(); // ref
+  noSuchMethod(im) => 87;
+}
+''', [
+      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 107, 3),
+    ]);
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('super.foo()'),
+      element: findElement.method('foo', of: 'A'),
+      typeArgumentTypes: [],
+      invokeType: 'void Function()',
+      type: 'void',
+    );
+  }
+
+  test_methodInvocation_superHasAbstract() async {
+    await assertErrorsInCode(r'''
+abstract class A {
+  void foo(int _);
+}
+
+abstract class B extends A {
+  void bar() {
+    super.foo(0);
+  }
+
+  void foo(int _) {} // does not matter
+}
+''', [
+      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 95, 3),
+    ]);
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('super.foo(0)'),
+      element: findElement.method('foo', of: 'A'),
+      typeArgumentTypes: [],
+      invokeType: 'void Function(int)',
+      type: 'void',
+    );
+  }
+
+  test_methodInvocation_superHasConcrete_mixinHasAbstract() async {
+    await assertNoErrorsInCode('''
+class A {
+  void foo() {}
+}
+
+abstract class B {
+  void foo();
+}
+
+class C extends A with B {
+  void bar() {
+    super.foo(); // ref
+  }
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('foo(); // ref'),
+      element: findElement.method('foo', of: 'A'),
+      typeArgumentTypes: [],
+      invokeType: 'void Function()',
+      type: 'void',
+    );
+  }
+
+  test_methodInvocation_superHasNoSuchMethod() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int foo();
+  noSuchMethod(im) => 42;
+}
+
+class B extends A {
+  int foo() => super.foo(); // ref
+  noSuchMethod(im) => 87;
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('super.foo()'),
+      element: findElement.method('foo', of: 'A'),
+      typeArgumentTypes: [],
+      invokeType: 'int Function()',
+      type: 'int',
+    );
+  }
+
+  test_methodInvocation_superSuperHasConcrete() async {
+    await assertNoErrorsInCode('''
+abstract class A {
+  void foo() {}
+}
+
+abstract class B extends A {
+  void foo();
+}
+
+class C extends B {
+  void bar() {
+    super.foo();
+  }
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('super.foo()'),
+      element: findElement.method('foo', of: 'A'),
+      typeArgumentTypes: [],
+      invokeType: 'void Function()',
+      type: 'void',
+    );
+  }
+
+  test_propertyAccess_getter() async {
+    await assertErrorsInCode(r'''
+abstract class A {
+  int get foo;
+}
+
+abstract class B extends A {
+  bar() {
+    super.foo; // ref
+  }
+}
+''', [
+      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 86, 3),
+    ]);
+
+    assertPropertyAccess(
+      findNode.propertyAccess('super.foo'),
+      findElement.getter('foo'),
+      'int',
+    );
+  }
+
+  test_propertyAccess_getter_mixinHasNoSuchMethod() async {
+    await assertErrorsInCode('''
+class A {
+  int get foo;
+  noSuchMethod(im) => 1;
+}
+
+class B extends Object with A {
+  int get foo => super.foo; // ref
+  noSuchMethod(im) => 2;
+}
+''', [
+      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 108, 3),
+    ]);
+
+    assertPropertyAccess(
+      findNode.propertyAccess('super.foo'),
+      findElement.getter('foo', of: 'A'),
+      'int',
+    );
+  }
+
+  test_propertyAccess_getter_superHasNoSuchMethod() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int get foo;
+  noSuchMethod(im) => 1;
+}
+
+class B extends A {
+  get foo => super.foo; // ref
+  noSuchMethod(im) => 2;
+}
+''');
+
+    assertPropertyAccess(
+      findNode.propertyAccess('super.foo'),
+      findElement.getter('foo', of: 'A'),
+      'int',
+    );
+  }
+
+  test_propertyAccess_getter_superImplements() async {
+    await assertErrorsInCode(r'''
+class A {
+  int get foo => 0;
+}
+
+abstract class B implements A {
+}
+
+class C extends B {
+  int get foo => super.foo; // ref
+}
+''', [
+      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 111, 3),
+    ]);
+
+    assertPropertyAccess(
+      findNode.propertyAccess('super.foo'),
+      findElement.getter('foo', of: 'A'),
+      'int',
+    );
+  }
+
+  test_propertyAccess_getter_superSuperHasConcrete() async {
+    await assertNoErrorsInCode('''
+abstract class A {
+  int get foo => 0;
+}
+
+abstract class B extends A {
+  int get foo;
+}
+
+class C extends B {
+  int get bar => super.foo; // ref
+}
+''');
+
+    assertPropertyAccess(
+      findNode.propertyAccess('super.foo'),
+      findElement.getter('foo', of: 'A'),
+      'int',
+    );
+  }
+
+  test_propertyAccess_method_tearOff_abstract() async {
+    await assertErrorsInCode(r'''
+abstract class A {
+  void foo();
+}
+
+abstract class B extends A {
+  void bar() {
+    super.foo; // ref
+  }
+}
+''', [
+      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 90, 3),
+    ]);
+
+    assertPropertyAccess(
+      findNode.propertyAccess('super.foo'),
+      findElement.method('foo'),
+      'void Function()',
+    );
+  }
+
+  test_propertyAccess_setter() async {
+    await assertErrorsInCode(r'''
+abstract class A {
+  set foo(int _);
+}
+
+abstract class B extends A {
+  void bar() {
+    super.foo = 0;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 94, 3),
+    ]);
+
+    assertPropertyAccess(
+      findNode.propertyAccess('super.foo'),
+      findElement.setter('foo', of: 'A'),
+      'int',
+    );
+  }
+
+  test_propertyAccess_setter_mixinHasNoSuchMethod() async {
+    await assertErrorsInCode('''
+class A {
+  set foo(int a);
+  noSuchMethod(im) {}
+}
+
+class B extends Object with A {
+  set foo(int a) => super.foo = a; // ref
+  noSuchMethod(im) {}
+}
+''', [
+      error(CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE, 111, 3),
+    ]);
+
+    assertPropertyAccess(
+      findNode.propertyAccess('super.foo'),
+      findElement.setter('foo', of: 'A'),
+      'int',
+    );
+  }
+
+  test_propertyAccess_setter_superHasNoSuchMethod() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  set foo(int a);
+  noSuchMethod(im) => 1;
+}
+
+class B extends A {
+  set foo(int a) => super.foo = a; // ref
+  noSuchMethod(im) => 2;
+}
+''');
+
+    assertPropertyAccess(
+      findNode.propertyAccess('super.foo'),
+      findElement.setter('foo', of: 'A'),
+      'int',
+    );
+  }
+
+  test_propertyAccess_setter_superSuperHasConcrete() async {
+    await assertNoErrorsInCode('''
+abstract class A {
+  void set foo(int _) {}
+}
+
+abstract class B extends A {
+  void set foo(int _);
+}
+
+class C extends B {
+  void bar() {
+    super.foo = 0;
+  }
+}
+''');
+
+    assertPropertyAccess(
+      findNode.propertyAccess('super.foo'),
+      findElement.setter('foo', of: 'A'),
+      'int',
+    );
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_visibility_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_visibility_annotation_test.dart
index b827bcc..24aa6a1 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_visibility_annotation_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_visibility_annotation_test.dart
@@ -82,10 +82,10 @@
   test_privateEnum() async {
     await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
-@visibleForTesting enum _E {a, b, c}
+@visibleForTesting enum _E {a, b}
+void f(_E e) => e == _E.a || e == _E.b;
 ''', [
       error(HintCode.INVALID_VISIBILITY_ANNOTATION, 33, 18),
-      error(HintCode.UNUSED_ELEMENT, 57, 2),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_use_of_never_value_test.dart b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
similarity index 87%
rename from pkg/analyzer/test/src/diagnostics/invalid_use_of_never_value_test.dart
rename to pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
index 7994df2..441ecf9 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_use_of_never_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
@@ -31,7 +31,7 @@
   x == 1 + 2;
 }
 ''', [
-      error(StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, 23, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
     ]);
 
     assertBinaryExpression(
@@ -49,7 +49,7 @@
   x + (1 + 2);
 }
 ''', [
-      error(StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, 23, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
     ]);
 
     assertBinaryExpression(
@@ -117,7 +117,7 @@
   x();
 }
 ''', [
-      error(StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, 23, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
     ]);
   }
 
@@ -137,7 +137,7 @@
   x[0];
 }
 ''', [
-      error(StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, 23, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
     ]);
 
     assertIndexExpression(
@@ -154,7 +154,7 @@
   x[0] += 1 + 2;
 }
 ''', [
-      error(StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, 23, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
     ]);
 
     assertIndexExpression(
@@ -173,7 +173,7 @@
   x[0] = 1 + 2;
 }
 ''', [
-      error(StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, 23, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
     ]);
 
     assertIndexExpression(
@@ -259,7 +259,7 @@
   x.foo(1 + 2);
 }
 ''', [
-      error(StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, 23, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
     ]);
 
     assertMethodInvocation(
@@ -279,7 +279,7 @@
   x.toString(1 + 2);
 }
 ''', [
-      error(StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, 23, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
     ]);
 
     assertMethodInvocation(
@@ -319,7 +319,7 @@
   x++;
 }
 ''', [
-      error(StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, 23, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
     ]);
 
     assertPostfixExpression(
@@ -352,7 +352,7 @@
   ++x;
 }
 ''', [
-      error(StaticWarningCode.INVALID_USE_OF_NEVER_VALUE, 25, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 25, 1),
     ]);
 
     assertPrefixExpression(
@@ -378,7 +378,7 @@
     );
   }
 
-  test_propertyAccess_never() async {
+  test_propertyAccess_never_read() async {
     await assertNoErrorsInCode(r'''
 void main(Never x) {
   x.foo;
@@ -392,7 +392,7 @@
     );
   }
 
-  test_propertyAccess_never_hashCode() async {
+  test_propertyAccess_never_read_hashCode() async {
     await assertNoErrorsInCode(r'''
 void main(Never x) {
   x.hashCode;
@@ -406,6 +406,26 @@
     );
   }
 
+  test_propertyAccess_never_readWrite() async {
+    await assertNoErrorsInCode(r'''
+void main(Never x) {
+  x.foo += 0;
+}
+''');
+
+    assertSimpleIdentifier(
+      findNode.simple('foo'),
+      element: null,
+      type: 'Never',
+    );
+
+    assertAssignment(
+      findNode.assignment('foo += 0'),
+      operatorElement: null,
+      type: 'int',
+    );
+  }
+
   test_propertyAccess_never_tearOff_toString() async {
     await assertNoErrorsInCode(r'''
 void main(Never x) {
@@ -420,7 +440,27 @@
     );
   }
 
-  test_propertyAccess_neverQ() async {
+  test_propertyAccess_never_write() async {
+    await assertNoErrorsInCode(r'''
+void main(Never x) {
+  x.foo = 0;
+}
+''');
+
+    assertSimpleIdentifier(
+      findNode.simple('foo'),
+      element: null,
+      type: 'Never',
+    );
+
+    assertAssignment(
+      findNode.assignment('foo = 0'),
+      operatorElement: null,
+      type: 'int',
+    );
+  }
+
+  test_propertyAccess_neverQ_read() async {
     await assertErrorsInCode(r'''
 void main(Never? x) {
   x.foo;
@@ -436,7 +476,7 @@
     );
   }
 
-  test_propertyAccess_neverQ_hashCode() async {
+  test_propertyAccess_neverQ_read_hashCode() async {
     await assertNoErrorsInCode(r'''
 void main(Never? x) {
   x.hashCode;
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 85bb4cc..51c8156 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -4,6 +4,8 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'abstract_super_member_reference_test.dart'
+    as abstract_super_member_reference;
 import 'ambiguous_export_test.dart' as ambiguous_export;
 import 'ambiguous_extension_member_access_test.dart'
     as ambiguous_extension_member_access;
@@ -207,7 +209,6 @@
 import 'invalid_uri_test.dart' as invalid_uri;
 import 'invalid_use_of_covariant_in_extension_test.dart'
     as invalid_use_of_covariant_in_extension;
-import 'invalid_use_of_never_value_test.dart' as invalid_use_of_never_value;
 import 'invalid_use_of_null_value_test.dart' as invalid_use_of_null_value;
 import 'invalid_use_of_protected_member_test.dart'
     as invalid_use_of_protected_member;
@@ -342,6 +343,7 @@
 import 'private_collision_in_mixin_application_test.dart'
     as private_collision_in_mixin_application;
 import 'private_optional_parameter_test.dart' as private_optional_parameter;
+import 'receiver_of_type_never_test.dart' as receiver_of_type_never;
 import 'recursive_compile_time_constant_test.dart'
     as recursive_compile_time_constant;
 import 'recursive_constructor_redirect_test.dart'
@@ -481,6 +483,7 @@
 
 main() {
   defineReflectiveSuite(() {
+    abstract_super_member_reference.main();
     ambiguous_export.main();
     ambiguous_extension_member_access.main();
     ambiguous_import.main();
@@ -618,7 +621,6 @@
     invalid_type_argument_in_const_set.main();
     invalid_uri.main();
     invalid_use_of_covariant_in_extension.main();
-    invalid_use_of_never_value.main();
     invalid_use_of_null_value.main();
     invalid_use_of_protected_member.main();
     invalid_use_of_visible_for_template_member.main();
@@ -711,6 +713,7 @@
     prefix_identifier_not_followed_by_dot.main();
     private_collision_in_mixin_application.main();
     private_optional_parameter.main();
+    receiver_of_type_never.main();
     recursive_compile_time_constant.main();
     recursive_constructor_redirect.main();
     recursive_factory_redirect.main();
diff --git a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
index ed63a7e..c74fea2 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
@@ -96,6 +96,7 @@
 }
 ''', [
       error(HintCode.UNUSED_ELEMENT, 6, 2),
+      error(HintCode.UNUSED_ELEMENT, 20, 12),
     ]);
   }
 
@@ -205,17 +206,19 @@
 
   test_enum_isUsed_fieldReference() async {
     await assertNoErrorsInCode(r'''
-enum _MyEnum {A, B, C}
+enum _MyEnum {A}
 main() {
-  print(_MyEnum.B);
+  _MyEnum.A;
 }
 ''');
   }
 
   test_enum_notUsed_noReference() async {
     await assertErrorsInCode(r'''
-enum _MyEnum {A, B, C}
-main() {
+enum _MyEnum {A, B}
+void f(d) {
+  d.A;
+  d.B;
 }
 ''', [
       error(HintCode.UNUSED_ELEMENT, 5, 7),
@@ -782,6 +785,79 @@
     ]);
   }
 
+  test_publicStaticMethod_privateClass_isUsed() async {
+    await assertNoErrorsInCode(r'''
+class _A {
+  static void m() {}
+}
+void main() {
+  _A.m();
+}
+''');
+  }
+
+  test_publicStaticMethod_privateClass_notUsed() async {
+    await assertErrorsInCode(r'''
+class _A {
+  static void m() {}
+}
+void f(_A a) {}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 25, 1),
+    ]);
+  }
+
+  test_publicStaticMethod_privateExtension_isUsed() async {
+    await assertNoErrorsInCode(r'''
+extension _A on String {
+  static void m() {}
+}
+void main() {
+  _A.m();
+}
+''');
+  }
+
+  test_publicStaticMethod_privateExtension_notUsed() async {
+    await assertErrorsInCode(r'''
+extension _A on String {
+  static void m() {}
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 39, 1),
+    ]);
+  }
+
+  test_publicStaticMethod_privateMixin_isUsed() async {
+    await assertNoErrorsInCode(r'''
+mixin _A {
+  static void m() {}
+}
+void main() {
+  _A.m();
+}
+''');
+  }
+
+  test_publicStaticMethod_privateMixin_notUsed() async {
+    await assertErrorsInCode(r'''
+mixin _A {
+  static void m() {}
+}
+void main() {
+  _A;
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 25, 1),
+    ]);
+  }
+
+  test_publicTopLevelFunction_notUsed() async {
+    await assertNoErrorsInCode(r'''
+int get a => 1;
+''');
+  }
+
   test_setter_isUsed_invocation_implicitThis() async {
     await assertNoErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/unused_field_test.dart b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
index c898d14..cb92c0d 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
@@ -88,6 +88,47 @@
 ''');
   }
 
+  test_isUsed_privateEnum_publicValue() async {
+    await assertNoErrorsInCode(r'''
+enum _Foo {a, b}
+f() => print('${_Foo.a}${_Foo.b}');
+''');
+  }
+
+  test_isUsed_publicEnum_privateValue() async {
+    await assertNoErrorsInCode(r'''
+enum Foo {_a, _b}
+f() => print('${Foo._a}${Foo._b}');
+''');
+  }
+
+  test_isUsed_publicStaticField_privateClass() async {
+    await assertNoErrorsInCode(r'''
+class _A {
+  static String f1 = "x";
+}
+void main() => print(_A.f1);
+''');
+  }
+
+  test_isUsed_publicStaticField_privateExtension() async {
+    await assertNoErrorsInCode(r'''
+extension _A on String {
+  static String f1 = "x";
+}
+void main() => print(_A.f1);
+''');
+  }
+
+  test_isUsed_publicStaticField_privateMixin() async {
+    await assertNoErrorsInCode(r'''
+mixin _A {
+  static String f1 = "x";
+}
+void main() => print(_A.f1);
+''');
+  }
+
   test_isUsed_reference_implicitThis() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -278,6 +319,55 @@
     ]);
   }
 
+  test_notUsed_privateEnum_publicValue() async {
+    await assertErrorsInCode(r'''
+enum _Foo {a}
+f() => _Foo;
+''', [
+      error(HintCode.UNUSED_FIELD, 11, 1),
+    ]);
+  }
+
+  test_notUsed_publicEnum_privateValue() async {
+    await assertErrorsInCode(r'''
+enum Foo {_a}
+''', [
+      error(HintCode.UNUSED_FIELD, 10, 2),
+    ]);
+  }
+
+  test_notUsed_publicStaticField_privateClass() async {
+    await assertErrorsInCode(r'''
+class _A {
+  static String f1 = "x";
+}
+void main() => print(_A);
+''', [
+      error(HintCode.UNUSED_FIELD, 27, 2),
+    ]);
+  }
+
+  test_notUsed_publicStaticField_privateExtension() async {
+    await assertErrorsInCode(r'''
+extension _A on String {
+  static String f1 = "x";
+}
+''', [
+      error(HintCode.UNUSED_FIELD, 41, 2),
+    ]);
+  }
+
+  test_notUsed_publicStaticField_privateMixin() async {
+    await assertErrorsInCode(r'''
+mixin _A {
+  static String f1 = "x";
+}
+void main() => print(_A);
+''', [
+      error(HintCode.UNUSED_FIELD, 27, 2),
+    ]);
+  }
+
   test_notUsed_referenceInComment() async {
     await assertErrorsInCode(r'''
 /// [A._f] is great.
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 1c968c8..1aa38a4 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/context/context_root.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
@@ -34,7 +35,6 @@
 import 'package:analyzer/src/summary/summary_file_builder.dart';
 import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
 import 'package:analyzer/src/task/options.dart';
-import 'package:analyzer/src/util/uri.dart';
 import 'package:analyzer/src/util/yaml.dart';
 import 'package:analyzer_cli/src/analyzer_impl.dart';
 import 'package:analyzer_cli/src/batch_mode.dart';
@@ -48,10 +48,6 @@
 import 'package:analyzer_cli/starter.dart' show CommandLineStarter;
 import 'package:linter/src/rules.dart' as linter;
 import 'package:meta/meta.dart';
-import 'package:package_config/discovery.dart' as pkg_discovery;
-import 'package:package_config/packages.dart' show Packages;
-import 'package:package_config/packages_file.dart' as pkgfile show parse;
-import 'package:package_config/src/packages_impl.dart' show MapPackages;
 import 'package:path/path.dart' as path;
 import 'package:yaml/yaml.dart';
 
@@ -591,44 +587,28 @@
     scheduler.start();
   }
 
-  /// Return discovered packagespec, or `null` if none is found.
-  Packages _discoverPackagespec(Uri root) {
-    try {
-      Packages packages = pkg_discovery.findPackagesFromFile(root);
-      if (packages != Packages.noPackages) {
-        return packages;
-      }
-    } catch (_) {
-      // Ignore and fall through to null.
-    }
-
-    return null;
-  }
-
   _PackageInfo _findPackages(CommandLineOptions options) {
     Packages packages;
     Map<String, List<Folder>> packageMap;
 
     if (options.packageConfigPath != null) {
-      String packageConfigPath = options.packageConfigPath;
-      Uri fileUri = Uri.file(packageConfigPath);
+      String path = normalizePath(options.packageConfigPath);
       try {
-        io.File configFile = io.File.fromUri(fileUri).absolute;
-        List<int> bytes = configFile.readAsBytesSync();
-        Map<String, Uri> map = pkgfile.parse(bytes, configFile.uri);
-        packages = MapPackages(map);
+        var packages = parseDotPackagesFile(
+          resourceProvider,
+          resourceProvider.getFile(path),
+        );
         packageMap = _getPackageMap(packages);
       } catch (e) {
-        printAndFail(
-            'Unable to read package config data from $packageConfigPath: $e');
+        printAndFail('Unable to read package config data from $path: $e');
       }
     } else if (options.packageRootPath != null) {
-      packageMap = _PackageRootPackageMapBuilder.buildPackageMap(
-          options.packageRootPath);
+      var path = normalizePath(options.packageRootPath);
+      packageMap = _PackageRootPackageMapBuilder.buildPackageMap(path);
     } else {
       Resource cwd = resourceProvider.getResource(path.current);
       // Look for .packages.
-      packages = _discoverPackagespec(Uri.directory(cwd.path));
+      packages = findPackagesFrom(resourceProvider, cwd);
       packageMap = _getPackageMap(packages);
     }
 
@@ -640,13 +620,11 @@
       return null;
     }
 
-    Map<String, List<Folder>> folderMap = <String, List<Folder>>{};
-    var pathContext = resourceProvider.pathContext;
-    packages.asMap().forEach((String packagePath, Uri uri) {
-      String path = fileUriToNormalizedPath(pathContext, uri);
-      folderMap[packagePath] = [resourceProvider.getFolder(path)];
-    });
-    return folderMap;
+    var packageMap = <String, List<Folder>>{};
+    for (var package in packages.packages) {
+      packageMap[package.name] = [package.libFolder];
+    }
+    return packageMap;
   }
 
   /// Returns `true` if this relative path is a hidden directory.
diff --git a/pkg/analyzer_cli/tool/perf.dart b/pkg/analyzer_cli/tool/perf.dart
index 5e6e272..3419e96 100644
--- a/pkg/analyzer_cli/tool/perf.dart
+++ b/pkg/analyzer_cli/tool/perf.dart
@@ -10,9 +10,11 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/file_system/file_system.dart'
+    show Folder, ResourceUriResolver;
 import 'package:analyzer/file_system/physical_file_system.dart'
     show PhysicalResourceProvider;
-import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk;
@@ -21,7 +23,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/source/package_map_resolver.dart';
-import 'package:package_config/discovery.dart';
 
 main(List<String> args) async {
   // TODO(sigmund): provide sdk folder as well.
@@ -34,7 +35,7 @@
   var bench = args[0];
   var entryUri = Uri.base.resolve(args[1]);
 
-  await setup(entryUri);
+  await setup(args[1]);
 
   if (bench == 'scan') {
     Set<Source> files = scanReachableFiles(entryUri);
@@ -180,10 +181,19 @@
 
 /// Sets up analyzer to be able to load and resolve app, packages, and sdk
 /// sources.
-Future setup(Uri entryUri) async {
+Future setup(String path) async {
   var provider = PhysicalResourceProvider.INSTANCE;
-  var packageMap = ContextBuilder.convertPackagesToMap(
-      provider, await findPackages(entryUri));
+
+  var packages = findPackagesFrom(
+    provider,
+    provider.getResource(path),
+  );
+
+  var packageMap = <String, List<Folder>>{};
+  for (var package in packages.packages) {
+    packageMap[package.name] = [package.libFolder];
+  }
+
   sources = SourceFactory([
     ResourceUriResolver(provider),
     PackageMapUriResolver(provider, packageMap),
diff --git a/pkg/analyzer_plugin/CHANGELOG.md b/pkg/analyzer_plugin/CHANGELOG.md
index 6172dd2..c9543da 100644
--- a/pkg/analyzer_plugin/CHANGELOG.md
+++ b/pkg/analyzer_plugin/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 0.2.2
+- Change supported analyzer version to `^0.39.0`
+
 ## 0.2.1
 - Bump maximum supported version of the analyzer to `<0.39.0`.
 - Bug fixes: #37916, #38326.
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index 86403e9..0e802e7 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -1202,6 +1202,14 @@
     optype.includeTypeNameSuggestions = true;
   }
 
+  @override
+  void visitYieldStatement(YieldStatement node) {
+    if (identical(entity, node.expression)) {
+      optype.includeReturnValueSuggestions = true;
+      optype.includeTypeNameSuggestions = true;
+    }
+  }
+
   bool _isEntityPrevTokenSynthetic() {
     Object entity = this.entity;
     if (entity is AstNode) {
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 72ea138..2975a31 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -1,6 +1,6 @@
 name: analyzer_plugin
 description: A framework and support code for building plugins for the analysis server.
-version: 0.2.1
+version: 0.2.2
 author: Dart Team <misc@dartlang.org>
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_plugin
 
@@ -8,7 +8,7 @@
   sdk: '>=2.3.0 <3.0.0'
 
 dependencies:
-  analyzer: '>=0.35.3 <0.39.0'
+  analyzer: '^0.39.0'
   charcode: '^1.1.0'
   dart_style: '^1.2.0'
   html: '>=0.13.1 <0.15.0'
diff --git a/pkg/analyzer_plugin/test/support/abstract_context.dart b/pkg/analyzer_plugin/test/support/abstract_context.dart
index eee4c1f..155e3c1 100644
--- a/pkg/analyzer_plugin/test/support/abstract_context.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_context.dart
@@ -118,8 +118,8 @@
     MockSdk(resourceProvider: resourceProvider);
 
     newFolder('/home/test');
-    newFile('/home/test/.packages', content: r'''
-test:file:///home/test/lib
+    newFile('/home/test/.packages', content: '''
+test:${toUriStr('/home/test/lib')}
 ''');
 
     _createDriver();
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 39bb7b7..3ab91bc 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -94,6 +94,8 @@
 
   static const String serverMode = '--server-mode';
 
+  static const String nonNullableMode = '--non-nullable-mode';
+
   static const String newDeferredSplit = '--new-deferred-split';
   static const String reportInvalidInferredDeferredTypes =
       '--report-invalid-deferred-types';
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 24bdf93..304bc8b 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -333,6 +333,16 @@
         "supported formats are: json or binary");
   }
 
+  void setNonNullableMode(String argument) {
+    if (argument == "${Flags.nonNullableMode}=strong" ||
+        argument == "${Flags.nonNullableMode}=weak") {
+      passThrough(argument);
+      return;
+    }
+    helpAndFail("Error: Unsupported '$argument', "
+        "supported modes are: strong (default) or weak");
+  }
+
   void handleThrowOnError(String argument) {
     throwOnError = true;
     String parameter = extractParameter(argument, isOptionalArgument: true);
@@ -456,6 +466,7 @@
     new OptionHandler(Flags.laxRuntimeTypeToString, passThrough),
     new OptionHandler(Flags.benchmarkingProduction, passThrough),
     new OptionHandler(Flags.benchmarkingExperiment, passThrough),
+    new OptionHandler('${Flags.nonNullableMode}=.+', setNonNullableMode),
 
     // TODO(floitsch): remove conditional directives flag.
     // We don't provide the info-message yet, since we haven't publicly
diff --git a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
index 28fbbb1..6eed483 100644
--- a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
@@ -563,10 +563,6 @@
 
   /// Returns an [AbstractBool] that describes if the set of runtime values of
   /// [subset] are known to all be in the set of runtime values of [superset].
-  AbstractBool contains(AbstractValue superset, AbstractValue subset);
-
-  /// Returns an [AbstractBool] that describes if the set of runtime values of
-  /// [subset] are known to all be in the set of runtime values of [superset].
   AbstractBool isIn(AbstractValue subset, AbstractValue superset);
 
   /// Returns the [MemberEntity] that is known to always be hit at runtime
diff --git a/pkg/compiler/lib/src/inferrer/trivial.dart b/pkg/compiler/lib/src/inferrer/trivial.dart
index 07c10d4..b8ea357 100644
--- a/pkg/compiler/lib/src/inferrer/trivial.dart
+++ b/pkg/compiler/lib/src/inferrer/trivial.dart
@@ -57,10 +57,6 @@
       AbstractBool.Maybe;
 
   @override
-  AbstractBool contains(AbstractValue superset, AbstractValue subset) =>
-      AbstractBool.Maybe;
-
-  @override
   AbstractBool needsNoSuchMethodHandling(
           AbstractValue receiver, Selector selector) =>
       AbstractBool.Maybe;
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 0e3fd2d..3cbac15 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -1665,15 +1665,6 @@
     AbstractValue input = inputs.first.type;
     AbstractValue intersection =
         abstractValueDomain.intersection(input, typeAnnotation);
-    if (debug.ANOMALY_WARN) {
-      if (abstractValueDomain.contains(input, intersection).isDefinitelyFalse ||
-          abstractValueDomain
-              .contains(typeAnnotation, intersection)
-              .isDefinitelyFalse) {
-        print("ANOMALY WARNING: narrowed $input to $intersection via "
-            "$typeAnnotation");
-      }
-    }
     return intersection;
   }
 
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
index 4f94658..b14ebae 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
@@ -320,7 +320,7 @@
 
   @override
   AbstractBool containsType(TypeMask typeMask, ClassEntity cls) {
-    return AbstractBool.trueOrMaybe(_containsType(typeMask, cls));
+    return AbstractBool.trueOrFalse(_containsType(typeMask, cls));
   }
 
   bool _containsType(TypeMask typeMask, ClassEntity cls) {
@@ -704,13 +704,6 @@
   }
 
   @override
-  AbstractBool contains(
-      covariant TypeMask superset, covariant TypeMask subset) {
-    return AbstractBool.maybeOrFalse(
-        superset.containsMask(subset, _closedWorld));
-  }
-
-  @override
   AbstractBool isIn(covariant TypeMask subset, covariant TypeMask superset) {
     return AbstractBool.trueOrMaybe(subset.isInMask(superset, _closedWorld));
   }
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index bdfb63f..e7158dd 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -36,13 +36,6 @@
     return a.accept(this, b);
   }
 
-  static int compareNullable<T>(int compare(T a, T b), T a, T b) {
-    if (a == null && b == null) return 0;
-    if (a == null) return -1;
-    if (b == null) return 1;
-    return compare(a, b);
-  }
-
   static int compareLists<S, T>(int compare(S a, T b), List<S> a, List<T> b) {
     int r = a.length.compareTo(b.length);
     if (r != 0) return r;
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index ca2f1be..0b2a816 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -452,13 +452,30 @@
     }
   }
 
+  ClassEntity __functionLub;
+  ClassEntity get _functionLub => __functionLub ??=
+      getLubOfInstantiatedSubtypes(commonElements.functionClass);
+
   @override
   bool includesClosureCall(Selector selector, AbstractValue receiver) {
     return selector.name == Identifiers.call &&
         (receiver == null ||
-            // TODO(johnniwinther): Should this have been `intersects` instead?
+            // This is logically equivalent to the former implementation using
+            // `abstractValueDomain.contains` (which wrapped `containsMask`).
+            // The switch to `abstractValueDomain.containsType` is because
+            // `contains` was generally unsound but happened to work correctly
+            // here. See https://dart-review.googlesource.com/c/sdk/+/130565
+            // for further discussion.
+            //
+            // This checks if the receiver mask contains the entire type cone
+            // originating from [_functionLub] and may therefore be unsound if
+            // the receiver mask contains only part of the type cone. (Is this
+            // possible?)
+            //
+            // TODO(fishythefish): Use `isDisjoint` or equivalent instead of
+            // `containsType` once we can ensure it's fast enough.
             abstractValueDomain
-                .contains(receiver, abstractValueDomain.functionType)
+                .containsType(receiver, _functionLub)
                 .isPotentiallyTrue);
   }
 
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 6cb57dd..207fb45 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -5,7 +5,7 @@
 library dart2js.kernel.env;
 
 import 'package:front_end/src/api_unstable/dart2js.dart'
-    show isRedirectingFactory;
+    show isRedirectingFactory, isRedirectingFactoryField;
 
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/clone.dart';
@@ -119,8 +119,7 @@
       _memberMap = <String, ir.Member>{};
       _setterMap = <String, ir.Member>{};
       for (ir.Member member in library.members) {
-        if (member.name.name.contains('#')) {
-          // Skip synthetic .dill members.
+        if (isRedirectingFactoryField(member)) {
           continue;
         }
         if (member is ir.Procedure) {
@@ -375,11 +374,8 @@
 
     void addField(ir.Field member, {bool includeStatic}) {
       if (!includeStatic && member.isStatic) return;
+      if (isRedirectingFactoryField(member)) return;
       var name = member.name.name;
-      if (name.contains('#')) {
-        // Skip synthetic .dill members.
-        return;
-      }
       _memberMap[name] = member;
       if (member.isMutable) {
         _setterMap[name] = member;
@@ -417,7 +413,6 @@
         }
       }
       var name = member.name.name;
-      assert(!name.contains('#'));
       if (member.kind == ir.ProcedureKind.Factory) {
         if (isRedirectingFactory(member)) {
           // Don't include redirecting factories.
@@ -439,7 +434,6 @@
     void addConstructors(ir.Class c) {
       for (ir.Constructor member in c.constructors) {
         var name = member.name.name;
-        assert(!name.contains('#'));
         _constructorMap[name] = member;
       }
     }
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 3e9206e..2035966 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -326,6 +326,14 @@
   /// Whether to use the new RTI representation (default).
   bool useNewRti = true;
 
+  /// Whether null-safety (non-nullable types) are enabled.
+  bool get useNullSafety =>
+      languageExperiments[fe.ExperimentalFlag.nonNullable];
+
+  /// When null-safety is enabled, whether the compiler should emit code with
+  /// weak or strong semantics.
+  bool useWeakNullSafetySemantics = false;
+
   /// The path to the file that contains the profiled allocations.
   ///
   /// The file must contain the Map that was produced by using
@@ -436,7 +444,10 @@
       ..codegenShard = _extractIntOption(options, '${Flags.codegenShard}=')
       ..codegenShards = _extractIntOption(options, '${Flags.codegenShards}=')
       ..cfeOnly = _hasOption(options, Flags.cfeOnly)
-      ..debugGlobalInference = _hasOption(options, Flags.debugGlobalInference);
+      ..debugGlobalInference = _hasOption(options, Flags.debugGlobalInference)
+      ..useWeakNullSafetySemantics = _extractStringOption(
+              options, '${Flags.nonNullableMode}=', 'strong') ==
+          'weak';
   }
 
   void validate() {
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index e1dc2d3..409aac3 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -4810,20 +4810,9 @@
           .isPotentiallyTrue) {
         // Overwrite the type with the narrower type.
         code.instructionType = trustedMask;
-      } else if (_abstractValueDomain
-          .contains(trustedMask, code.instructionType)
-          .isPotentiallyTrue) {
-        // It is acceptable for the type parameter to be broader than the
-        // specified type.
-      } else {
-        reporter.reportErrorMessage(
-            _elementMap.getSpannable(targetElement, invocation),
-            MessageKind.GENERIC, {
-          'text': 'Type argument too narrow for specified behavior type '
-              '(${trustedMask} does not allow '
-              'all values in ${code.instructionType})'
-        });
       }
+      // It is acceptable for the type parameter to be broader than the
+      // specified type.
     }
   }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index b251b40..6f2fe52 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:collection';
+import 'package:front_end/src/api_unstable/ddc.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/kernel.dart';
 
@@ -239,7 +240,7 @@
 /// if the field [f] is storing that information, otherwise returns `null`.
 Iterable<Member> getRedirectingFactories(Field f) {
   // TODO(jmesserly): this relies on implementation details in Kernel
-  if (f.name.name == '_redirecting#') {
+  if (isRedirectingFactoryField(f)) {
     assert(f.isStatic);
     var list = f.initializer as ListLiteral;
     return list.expressions.map((e) => (e as StaticGet).target);
diff --git a/pkg/front_end/analysis_options_no_lints.yaml b/pkg/front_end/analysis_options_no_lints.yaml
index c24332a..44e9d25 100644
--- a/pkg/front_end/analysis_options_no_lints.yaml
+++ b/pkg/front_end/analysis_options_no_lints.yaml
@@ -11,6 +11,7 @@
     - test/id_testing/data/**
     - test/language_versioning/data/**
     - test/patching/data/**
+    - test/static_types/data/**
   errors:
     # Allow having TODOs in the code
     todo: ignore
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index 668533014..e28f84d 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -109,6 +109,9 @@
 export '../compute_platform_binaries_location.dart'
     show computePlatformBinariesLocation;
 
+export '../fasta/kernel/redirecting_factory_body.dart'
+    show isRedirectingFactoryField;
+
 export '../fasta/operator.dart' show operatorFromString;
 
 export 'compiler_state.dart' show InitializedCompilerState;
diff --git a/pkg/front_end/lib/src/api_unstable/ddc.dart b/pkg/front_end/lib/src/api_unstable/ddc.dart
index bd2044e..412e59f 100644
--- a/pkg/front_end/lib/src/api_unstable/ddc.dart
+++ b/pkg/front_end/lib/src/api_unstable/ddc.dart
@@ -61,7 +61,7 @@
 export '../fasta/incremental_compiler.dart' show IncrementalCompiler;
 
 export '../fasta/kernel/redirecting_factory_body.dart'
-    show RedirectingFactoryBody;
+    show RedirectingFactoryBody, isRedirectingFactoryField;
 
 export '../fasta/type_inference/type_schema_environment.dart'
     show TypeSchemaEnvironment;
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index c6e6a46..469da44 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -60,6 +60,9 @@
 
 export '../fasta/hybrid_file_system.dart' show HybridFileSystem;
 
+export '../fasta/kernel/redirecting_factory_body.dart'
+    show isRedirectingFactoryField;
+
 export '../fasta/kernel/utils.dart'
     show
         createExpressionEvaluationComponent,
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 5015bbd..b9b7fcb 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -101,7 +101,8 @@
         templateRedirectingFactoryIncompatibleTypeArgument,
         templateTypeArgumentMismatch;
 
-import '../kernel/redirecting_factory_body.dart' show getRedirectingFactoryBody;
+import '../kernel/redirecting_factory_body.dart'
+    show getRedirectingFactoryBody, redirectingName;
 
 import '../kernel/kernel_target.dart' show KernelTarget;
 
@@ -252,12 +253,6 @@
       callback(Member declaredMember, Member interfaceMember, bool isSetter),
       {bool isInterfaceCheck = false});
 
-  void checkOverrides(
-      ClassHierarchy hierarchy, TypeEnvironment typeEnvironment);
-
-  void checkAbstractMembers(CoreTypes coreTypes, ClassHierarchy hierarchy,
-      TypeEnvironment typeEnvironment);
-
   bool hasUserDefinedNoSuchMethod(
       Class klass, ClassHierarchy hierarchy, Class objectClass);
 
@@ -970,7 +965,6 @@
     // [constructor.target].
     //
     // TODO(ahe): Add a kernel node to represent redirecting factory bodies.
-    const String redirectingName = "_redirecting#";
     DillMemberBuilder constructorsField =
         origin.scope.lookupLocalMember(redirectingName, setter: false);
     if (constructorsField == null) {
@@ -1077,14 +1071,6 @@
   }
 
   @override
-  void checkOverrides(
-      ClassHierarchy hierarchy, TypeEnvironment typeEnvironment) {}
-
-  @override
-  void checkAbstractMembers(CoreTypes coreTypes, ClassHierarchy hierarchy,
-      TypeEnvironment typeEnvironment) {}
-
-  @override
   bool hasUserDefinedNoSuchMethod(
       Class klass, ClassHierarchy hierarchy, Class objectClass) {
     Member noSuchMethod = hierarchy.getDispatchTarget(klass, noSuchMethodName);
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index ed82b58..b0c57b9 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -8,6 +8,7 @@
 
 import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/core_types.dart';
+import 'package:kernel/src/legacy_erasure.dart';
 
 import '../constant_context.dart' show ConstantContext;
 
@@ -139,6 +140,8 @@
     }
   }
 
+  SourceLibraryBuilder get library => super.library;
+
   Member get member => _fieldEncoding.field;
 
   String get debugName => "FieldBuilder";
@@ -331,6 +334,12 @@
     if (fieldType is ImplicitFieldType) {
       // `fieldType` may have changed if a circularity was detected when
       // [inferredType] was computed.
+      if (library.loader.target.enableNonNullable) {
+        if (!library.isNonNullableByDefault) {
+          inferredType = legacyErasure(
+              library.loader.typeInferenceEngine.coreTypes, inferredType);
+        }
+      }
       fieldType = inferredType;
 
       IncludesTypeParametersNonCovariantly needsCheckVisitor;
@@ -590,6 +599,26 @@
     return initializers;
   }
 
+  /// Creates an [Expression] that reads [_field].
+  ///
+  /// If [needsPromotion] is `true`, the field will be read through a `let`
+  /// expression that promotes the expression to [_type]. This is needed for a
+  /// sound encoding of fields with type variable type of undetermined
+  /// nullability.
+  Expression _createFieldRead({bool needsPromotion: false}) {
+    if (needsPromotion) {
+      VariableDeclaration variable = new VariableDeclaration.forValue(
+          _createFieldGet(_field),
+          type: _type.withNullability(Nullability.nullable))
+        ..fileOffset = fileOffset;
+      return new Let(
+          variable, new VariableGet(variable, _type)..fileOffset = fileOffset);
+    } else {
+      return _createFieldGet(_field);
+    }
+  }
+
+  /// Creates an [Expression] that reads [field].
   Expression _createFieldGet(Field field) {
     if (field.isStatic) {
       return new StaticGet(field)..fileOffset = fileOffset;
@@ -600,6 +629,7 @@
     }
   }
 
+  /// Creates an [Expression] that writes [value] to [field].
   Expression _createFieldSet(Field field, Expression value) {
     if (field.isStatic) {
       return new StaticSet(field, value)..fileOffset = fileOffset;
@@ -769,7 +799,7 @@
     assert(_type != null, "Type has not been computed for field $name.");
     return late_lowering.createGetterWithInitializer(
         fileOffset, name, _type, initializer,
-        createVariableRead: () => _createFieldGet(_field),
+        createVariableRead: _createFieldRead,
         createVariableWrite: (Expression value) =>
             _createFieldSet(_field, value),
         createIsSetRead: () => _createFieldGet(_lateIsSetField),
@@ -785,7 +815,7 @@
     assert(_type != null, "Type has not been computed for field $name.");
     return late_lowering.createGetterBodyWithoutInitializer(
         coreTypes, fileOffset, name, type, 'Field',
-        createVariableRead: () => _createFieldGet(_field),
+        createVariableRead: _createFieldRead,
         createIsSetRead: () => _createFieldGet(_lateIsSetField));
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index 5296ed7..18cdf42 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -43,7 +43,8 @@
         templateTypeNotFound,
         templateUnspecified;
 
-import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
+import '../kernel/redirecting_factory_body.dart'
+    show RedirectingFactoryBody, isRedirectingFactoryField;
 
 import '../problems.dart' show internalProblem, unhandled, unimplemented;
 
@@ -160,7 +161,7 @@
     cls.procedures.forEach(classBulder.addMember);
     cls.constructors.forEach(classBulder.addMember);
     for (Field field in cls.fields) {
-      if (field.name.name == "_redirecting#") {
+      if (isRedirectingFactoryField(field)) {
         ListLiteral initializer = field.initializer;
         for (StaticGet get in initializer.expressions) {
           RedirectingFactoryBody.restoreFromDill(get.target);
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 132c992..0855ea2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -245,7 +245,7 @@
   /// This is used to determine whether instance properties are available.
   bool inFieldInitializer = false;
 
-  /// `true` if this access is directly in a field initializer of a late field.
+  /// `true` if we are directly in a field initializer of a late field.
   ///
   /// For instance in `<init>` in
   ///
@@ -257,6 +257,23 @@
   ///
   bool inLateFieldInitializer = false;
 
+  /// `true` if we are directly in the initializer of a late local.
+  ///
+  /// For instance in `<init>` in
+  ///
+  ///    method() {
+  ///      late var foo = <init>;
+  ///    }
+  ///    class Class {
+  ///      method() {
+  ///        late var bar = <init>;
+  ///      }
+  ///    }
+  ///
+  bool get inLateLocalInitializer => _localInitializerState.head;
+
+  Link<bool> _localInitializerState = const Link<bool>().prepend(false);
+
   List<Initializer> _initializers;
 
   bool inCatchClause = false;
@@ -402,6 +419,15 @@
 
   DartType get implicitTypeArgument => const ImplicitTypeArgument();
 
+  void _enterLocalState({bool inLateLocalInitializer: false}) {
+    _localInitializerState =
+        _localInitializerState.prepend(inLateLocalInitializer);
+  }
+
+  void _exitLocalState() {
+    _localInitializerState = _localInitializerState.tail;
+  }
+
   @override
   void registerVariableAssignment(VariableDeclaration variable) {
     typePromoter?.mutateVariable(variable, functionNestingLevel);
@@ -2353,6 +2379,7 @@
     UnresolvedType type = pop();
     int modifiers = (lateToken != null ? lateMask : 0) |
         Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
+    _enterLocalState(inLateLocalInitializer: lateToken != null);
     super.push(currentLocalVariableModifiers);
     super.push(currentLocalVariableType ?? NullValue.Type);
     currentLocalVariableType = type;
@@ -2405,6 +2432,7 @@
       }
       push(forest.variablesDeclaration(variables, uri));
     }
+    _exitLocalState();
   }
 
   /// Stack containing assigned variables info for try statements.
@@ -2706,7 +2734,14 @@
   @override
   void endAwaitExpression(Token keyword, Token endToken) {
     debugEvent("AwaitExpression");
-    push(forest.createAwaitExpression(offsetForToken(keyword), popForValue()));
+    int fileOffset = offsetForToken(keyword);
+    Expression value = popForValue();
+    if (inLateLocalInitializer) {
+      push(buildProblem(fasta.messageAwaitInLateLocalInitializer, fileOffset,
+          keyword.charCount));
+    } else {
+      push(forest.createAwaitExpression(fileOffset, value));
+    }
   }
 
   @override
@@ -4337,6 +4372,7 @@
   }
 
   void enterFunction() {
+    _enterLocalState();
     debugEvent("enterFunction");
     functionNestingLevel++;
     push(switchScope ?? NullValue.SwitchScope);
@@ -4356,6 +4392,7 @@
     List<TypeVariableBuilder> typeVariables = pop();
     exitLocalScope();
     push(typeVariables ?? NullValue.TypeVariables);
+    _exitLocalState();
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 1febb17..384eff8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -4,24 +4,7 @@
 
 library fasta.class_hierarchy_builder;
 
-import 'package:kernel/ast.dart'
-    show
-        Class,
-        DartType,
-        Field,
-        FunctionNode,
-        InterfaceType,
-        InvalidType,
-        Library,
-        Member,
-        Name,
-        Nullability,
-        Procedure,
-        ProcedureKind,
-        Supertype,
-        TypeParameter,
-        TypeParameterType,
-        VariableDeclaration;
+import 'package:kernel/ast.dart' hide MapEntry;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
@@ -106,6 +89,7 @@
 }
 
 int compareDeclarations(ClassMember a, ClassMember b) {
+  if (a == b) return 0;
   return ClassHierarchy.compareMembers(a.member, b.member);
 }
 
@@ -253,8 +237,9 @@
   }
 
   ClassHierarchyNode getNodeFromClass(ClassBuilder classBuilder) {
-    return nodes[classBuilder.cls] ??=
-        new ClassHierarchyNodeBuilder(this, classBuilder).build();
+    return nodes[classBuilder.cls] ??= new ClassHierarchyNodeBuilder(
+            this, classBuilder, loader.target.enableNonNullable)
+        .build();
   }
 
   ClassHierarchyNode getNodeFromType(TypeBuilder type) {
@@ -280,7 +265,12 @@
     Builder supertypeDeclaration = supertypeNode.classBuilder;
     if (depth < supertypes.length) {
       TypeBuilder asSupertypeOf = supertypes[depth];
-      if (asSupertypeOf.declaration == supertypeDeclaration) {
+      TypeDeclarationBuilder declaration = asSupertypeOf.declaration;
+      if (declaration is TypeAliasBuilder) {
+        TypeAliasBuilder aliasBuilder = declaration;
+        declaration = aliasBuilder.unaliasDeclaration;
+      }
+      if (declaration == supertypeDeclaration) {
         return asSupertypeOf;
       }
     }
@@ -437,8 +427,9 @@
     for (int i = 0; i < classes.length; i++) {
       ClassBuilder classBuilder = classes[i];
       if (!classBuilder.isPatch) {
-        hierarchy.nodes[classBuilder.cls] =
-            new ClassHierarchyNodeBuilder(hierarchy, classBuilder).build();
+        hierarchy.nodes[classBuilder.cls] = new ClassHierarchyNodeBuilder(
+                hierarchy, classBuilder, loader.target.enableNonNullable)
+            .build();
       } else {
         // TODO(ahe): Merge the injected members of patch into the hierarchy
         // node of `cls.origin`.
@@ -453,14 +444,21 @@
 
   final ClassBuilder classBuilder;
 
+  /// Whether non-nullable types are supported.
+  final bool enableNonNullable;
+
   bool hasNoSuchMethod = false;
 
   List<ClassMember> abstractMembers = null;
 
-  ClassHierarchyNodeBuilder(this.hierarchy, this.classBuilder);
+  ClassHierarchyNodeBuilder(
+      this.hierarchy, this.classBuilder, this.enableNonNullable);
 
   ClassBuilder get objectClass => hierarchy.objectClassBuilder;
 
+  bool get shouldModifyKernel =>
+      classBuilder.library.loader == hierarchy.loader;
+
   final Map<Class, Substitution> substitutions = <Class, Substitution>{};
 
   /// When merging `aList` and `bList`, [a] (from `aList`) and [b] (from
@@ -512,18 +510,14 @@
                 classBuilder,
                 a,
                 AbstractMemberOverridingImplementation.selectConcrete(b),
-                mergeKind == MergeKind.superclassSetters,
-                classBuilder.library.loader == hierarchy.loader);
+                mergeKind.forSetters,
+                shouldModifyKernel);
             hierarchy.delayedMemberChecks.add(result);
           }
         } else if (classBuilder.isMixinApplication &&
             a.classBuilder != classBuilder) {
           result = InheritedImplementationInterfaceConflict.combined(
-              classBuilder,
-              a,
-              b,
-              mergeKind == MergeKind.superclassSetters,
-              classBuilder.library.loader == hierarchy.loader,
+              classBuilder, a, b, mergeKind.forSetters, shouldModifyKernel,
               isInheritableConflict: false);
           if (result is DelayedMember) {
             hierarchy.delayedMemberChecks.add(result);
@@ -560,13 +554,13 @@
         break;
 
       case MergeKind.interfacesMembers:
-        result = InterfaceConflict.combined(classBuilder, a, b, false,
-            classBuilder.library.loader == hierarchy.loader);
+        result = InterfaceConflict.combined(
+            classBuilder, a, b, false, shouldModifyKernel);
         break;
 
       case MergeKind.interfacesSetters:
-        result = InterfaceConflict.combined(classBuilder, a, b, true,
-            classBuilder.library.loader == hierarchy.loader);
+        result = InterfaceConflict.combined(
+            classBuilder, a, b, true, shouldModifyKernel);
         break;
 
       case MergeKind.supertypesMembers:
@@ -592,18 +586,10 @@
         } else {
           if (isAbstract(a)) {
             result = InterfaceConflict.combined(
-                classBuilder,
-                a,
-                b,
-                mergeKind == MergeKind.supertypesSetters,
-                classBuilder.library.loader == hierarchy.loader);
+                classBuilder, a, b, mergeKind.forSetters, shouldModifyKernel);
           } else {
             result = InheritedImplementationInterfaceConflict.combined(
-                classBuilder,
-                a,
-                b,
-                mergeKind == MergeKind.supertypesSetters,
-                classBuilder.library.loader == hierarchy.loader);
+                classBuilder, a, b, mergeKind.forSetters, shouldModifyKernel);
           }
           debug?.log("supertypes: ${result}");
           if (result is DelayedMember) {
@@ -1160,20 +1146,18 @@
   ///
   /// If [mergeKind] is `MergeKind.supertypes`, [member] isn't
   /// implementing/overriding anything.
-  void handleOnlyA(ClassMember member, MergeKind mergeKind) {
-    if (mergeKind == MergeKind.interfacesMembers ||
-        mergeKind == MergeKind.interfacesSetters) {
-      return;
+  ClassMember handleOnlyA(ClassMember member, MergeKind mergeKind) {
+    if (mergeKind.betweenInterfaces) {
+      return member;
     }
     // TODO(ahe): Enable this optimization:
     // if (cls is DillClassBuilder) return;
-    // assert(mergeKind == MergeKind.interfaces ||
+    // assert(mergeKind.betweenInterfaces ||
     //    member is! InterfaceConflict);
-    if ((mergeKind == MergeKind.superclassMembers ||
-            mergeKind == MergeKind.superclassSetters) &&
-        isAbstract(member)) {
+    if ((mergeKind.fromSuperclass) && isAbstract(member)) {
       recordAbstractMember(member);
     }
+    return member;
   }
 
   /// When merging `aList` and `bList`, [member] was only found in `bList`.
@@ -1186,32 +1170,40 @@
   /// If [mergeKind] is `MergeKind.supertypes`, [member] is implicitly
   /// abstract, and not implemented.
   ClassMember handleOnlyB(ClassMember member, MergeKind mergeKind) {
-    if (mergeKind == MergeKind.interfacesMembers ||
-        mergeKind == MergeKind.interfacesSetters) {
+    if (mergeKind.betweenInterfaces) {
       return member;
     }
     // TODO(ahe): Enable this optimization:
     // if (cls is DillClassBuilder) return member;
     Member target = member.member;
-    if ((mergeKind == MergeKind.supertypesMembers ||
-            mergeKind == MergeKind.supertypesSetters) ||
-        ((mergeKind == MergeKind.superclassMembers ||
-                mergeKind == MergeKind.superclassSetters) &&
-            target.isAbstract)) {
+    if (mergeKind.fromInterfaces ||
+        (mergeKind.fromSuperclass && target.isAbstract)) {
       if (isNameVisibleIn(target.name, classBuilder.library)) {
         recordAbstractMember(member);
       }
     }
-    if (mergeKind == MergeKind.superclassMembers &&
+    if (mergeKind.fromSuperclass &&
         target.enclosingClass != objectClass.cls &&
         target.name == noSuchMethodName) {
       hasNoSuchMethod = true;
     }
-    if (mergeKind != MergeKind.membersWithSetters &&
-        mergeKind != MergeKind.settersWithMembers &&
+    if (!mergeKind.forMembersVsSetters &&
         member is DelayedMember &&
         member.isInheritableConflict) {
-      hierarchy.delayedMemberChecks.add(member.withParent(classBuilder));
+      DelayedMember delayedMember = member;
+      member = delayedMember.withParent(classBuilder);
+      hierarchy.delayedMemberChecks.add(member);
+    }
+    if (mergeKind.intoCurrentClass &&
+        hierarchy.loader.target.enableNonNullable) {
+      if (member.classBuilder.library.isNonNullableByDefault &&
+          !classBuilder.library.isNonNullableByDefault) {
+        if (member is! DelayedMember) {
+          member = new InterfaceConflict(
+              classBuilder, [member], mergeKind.forSetters, shouldModifyKernel);
+          hierarchy.delayedMemberChecks.add(member);
+        }
+      }
     }
     return member;
   }
@@ -1697,6 +1689,7 @@
 
   List<ClassMember> merge(
       List<ClassMember> aList, List<ClassMember> bList, MergeKind mergeKind) {
+    bool changed = false;
     final List<ClassMember> result = new List<ClassMember>.filled(
         aList.length + bList.length, null,
         growable: true);
@@ -1706,9 +1699,7 @@
     while (i < aList.length && j < bList.length) {
       final ClassMember a = aList[i];
       final ClassMember b = bList[j];
-      if ((mergeKind == MergeKind.interfacesMembers ||
-              mergeKind == MergeKind.interfacesSetters) &&
-          a.isStatic) {
+      if (mergeKind.betweenInterfaces && a.isStatic) {
         i++;
         continue;
       }
@@ -1719,36 +1710,61 @@
       final int compare = compareDeclarations(a, b);
       if (compare == 0) {
         result[storeIndex++] = handleMergeConflict(a, b, mergeKind);
+        changed = true;
         i++;
         j++;
       } else if (compare < 0) {
-        handleOnlyA(a, mergeKind);
-        result[storeIndex++] = a;
+        ClassMember member = handleOnlyA(a, mergeKind);
+        result[storeIndex++] = member;
+        if (!identical(member, a)) {
+          changed = true;
+        }
         i++;
       } else {
-        result[storeIndex++] = handleOnlyB(b, mergeKind);
+        ClassMember member = handleOnlyB(b, mergeKind);
+        result[storeIndex++] = member;
+        if (!identical(member, b)) {
+          changed = true;
+        }
         j++;
       }
     }
     while (i < aList.length) {
       final ClassMember a = aList[i];
-      if (!(mergeKind == MergeKind.interfacesMembers ||
-              mergeKind == MergeKind.interfacesSetters) ||
-          !a.isStatic) {
-        handleOnlyA(a, mergeKind);
-        result[storeIndex++] = a;
+      if (!mergeKind.betweenInterfaces || !a.isStatic) {
+        ClassMember member = handleOnlyA(a, mergeKind);
+        result[storeIndex++] = member;
+        if (!identical(member, a)) {
+          changed = true;
+        }
       }
       i++;
     }
     while (j < bList.length) {
       final ClassMember b = bList[j];
       if (!b.isStatic) {
-        result[storeIndex++] = handleOnlyB(b, mergeKind);
+        ClassMember member = handleOnlyB(b, mergeKind);
+        result[storeIndex++] = member;
+        if (!identical(member, b)) {
+          changed = true;
+        }
       }
       j++;
     }
-    if (aList.isEmpty && storeIndex == bList.length) return bList;
-    if (bList.isEmpty && storeIndex == aList.length) return aList;
+    if (!changed && aList.isEmpty && storeIndex == bList.length) {
+      assert(
+          _equalsList(result, bList, storeIndex),
+          "List mismatch: Expected: ${bList}, "
+          "actual ${result.sublist(0, storeIndex)}");
+      return bList;
+    }
+    if (!changed && bList.isEmpty && storeIndex == aList.length) {
+      assert(
+          _equalsList(result, aList, storeIndex),
+          "List mismatch: Expected: ${aList}, "
+          "actual ${result.sublist(0, storeIndex)}");
+      return aList;
+    }
     return result..length = storeIndex;
   }
 
@@ -1980,30 +1996,77 @@
   MergeResult(this.mergedMembers, this.mergedSetters);
 }
 
-enum MergeKind {
+class MergeKind {
+  final String name;
+
+  final bool forSetters;
+
+  final bool betweenInterfaces;
+
+  final bool fromSuperclass;
+
+  final bool fromInterfaces;
+
+  final bool forMembersVsSetters;
+
+  final bool intoCurrentClass;
+
+  const MergeKind(this.name,
+      {this.forSetters: false,
+      this.betweenInterfaces: false,
+      this.fromSuperclass: false,
+      this.fromInterfaces: false,
+      this.forMembersVsSetters: false,
+      this.intoCurrentClass: false});
+
+  String toString() => 'MergeKind($name)';
+
   /// Merging superclass members with the current class.
-  superclassMembers,
+  static const MergeKind superclassMembers = const MergeKind(
+      'Merging superclass members with the current class.',
+      fromSuperclass: true,
+      intoCurrentClass: true);
 
   /// Merging superclass setters with the current class.
-  superclassSetters,
+  static const MergeKind superclassSetters = const MergeKind(
+      'Merging superclass setters with the current class.',
+      fromSuperclass: true,
+      intoCurrentClass: true,
+      forSetters: true);
 
   /// Merging members of two interfaces.
-  interfacesMembers,
+  static const MergeKind interfacesMembers = const MergeKind(
+      'Merging members of two interfaces.',
+      betweenInterfaces: true);
 
   /// Merging setters of two interfaces.
-  interfacesSetters,
+  static const MergeKind interfacesSetters = const MergeKind(
+      'Merging setters of two interfaces.',
+      betweenInterfaces: true,
+      forSetters: true);
 
   /// Merging class members with interface members.
-  supertypesMembers,
+  static const MergeKind supertypesMembers = const MergeKind(
+      'Merging class members with interface members.',
+      fromInterfaces: true,
+      intoCurrentClass: true);
 
   /// Merging class setters with interface setters.
-  supertypesSetters,
+  static const MergeKind supertypesSetters = const MergeKind(
+      'Merging class setters with interface setters.',
+      fromInterfaces: true,
+      intoCurrentClass: true,
+      forSetters: true);
 
   /// Merging members with inherited setters.
-  membersWithSetters,
+  static const MergeKind membersWithSetters = const MergeKind(
+      'Merging members with inherited setters.',
+      forMembersVsSetters: true);
 
   /// Merging setters with inherited members.
-  settersWithMembers,
+  static const MergeKind settersWithMembers = const MergeKind(
+      'Merging setters with inherited members.',
+      forMembersVsSetters: true);
 }
 
 List<LocatedMessage> inheritedConflictContext(ClassMember a, ClassMember b) {
@@ -2637,6 +2700,13 @@
             concreteImplementation, isSetter, modifyKernel);
   }
 
+  @override
+  String toString() {
+    return "AbstractMemberOverridingImplementation("
+        "${classBuilder.fullNameForErrors}, "
+        "[${declarations.map(fullName).join(', ')}])";
+  }
+
   static ClassMember selectAbstract(ClassMember declaration) {
     if (declaration is AbstractMemberOverridingImplementation) {
       return declaration.abstractMember;
@@ -2830,3 +2900,14 @@
       ? declaration.formals[index].type != null
       : true;
 }
+
+/// Returns `true` if the first [length] elements of [a] and [b] are the same.
+bool _equalsList(List<ClassMember> a, List<ClassMember> b, int length) {
+  if (a.length < length || b.length < length) return false;
+  for (int index = 0; index < length; index++) {
+    if (a[index] != b[index]) {
+      return false;
+    }
+  }
+  return true;
+}
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 55ee9ab..7e3c6140 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
@@ -30,6 +30,9 @@
 
 import "package:kernel/type_algebra.dart" show Substitution;
 
+import "package:kernel/src/legacy_erasure.dart";
+import "package:kernel/src/nnbd_top_merge.dart";
+
 import "../builder/class_builder.dart";
 
 import "../problems.dart" show unhandled;
@@ -77,8 +80,38 @@
   /// stub is introduced as a place to put the checks.
   Member _computeCovarianceFixes() {
     Member interfaceMember = combinedMemberSignatureResult.member;
-    Substitution substitution =
-        _substitutionFor(interfaceMember, enclosingClass);
+
+    List<TypeParameter> interfaceMemberTypeParameters =
+        interfaceMember.function?.typeParameters ?? [];
+
+    List<TypeParameter> stubTypeParameters;
+    if (interfaceMember.enclosingClass != enclosingClass &&
+        interfaceMemberTypeParameters.isNotEmpty) {
+      // Create type parameters for the stub up front. These are needed to
+      // ensure the [substitutions] are alpha renamed to the same type
+      // parameters.
+      stubTypeParameters = new List<TypeParameter>.filled(
+          interfaceMemberTypeParameters.length, null);
+      for (int i = 0; i < interfaceMemberTypeParameters.length; i++) {
+        TypeParameter targetTypeParameter = interfaceMemberTypeParameters[i];
+        TypeParameter typeParameter = new TypeParameter(
+            targetTypeParameter.name, null)
+          ..isGenericCovariantImpl = targetTypeParameter.isGenericCovariantImpl;
+        stubTypeParameters[i] = typeParameter;
+      }
+    }
+
+    List<Substitution> substitutions =
+        new List<Substitution>(_candidates.length);
+    Substitution substitution;
+    for (int j = 0; j < _candidates.length; j++) {
+      Member otherMember = getCandidateAt(j);
+      substitutions[j] =
+          _substitutionFor(stubTypeParameters, otherMember, enclosingClass);
+      if (otherMember == interfaceMember) {
+        substitution = substitutions[j];
+      }
+    }
     // We always create a forwarding stub when we've inherited a member from an
     // interface other than the first override candidate.  This is to work
     // around a bug in the Kernel type checker where it chooses the first
@@ -89,7 +122,8 @@
     Member stub = interfaceMember.enclosingClass == enclosingClass ||
             interfaceMember == getCandidateAt(0)
         ? interfaceMember
-        : _createForwardingStub(substitution, interfaceMember);
+        : _createForwardingStub(
+            stubTypeParameters, substitution, interfaceMember);
 
     FunctionNode interfaceFunction = interfaceMember.function;
     List<VariableDeclaration> interfacePositionalParameters =
@@ -99,10 +133,20 @@
     List<TypeParameter> interfaceTypeParameters =
         interfaceFunction?.typeParameters ?? [];
 
-    void createStubIfNeeded() {
-      if (stub != interfaceMember) return;
+    void createStubIfNeeded({bool forMemberSignature: false}) {
+      if (stub != interfaceMember) {
+        Procedure procedure = stub;
+        if (forMemberSignature) {
+          procedure.isMemberSignature = true;
+        } else {
+          procedure.isForwardingStub = true;
+        }
+        return;
+      }
       if (interfaceMember.enclosingClass == enclosingClass) return;
-      stub = _createForwardingStub(substitution, interfaceMember);
+      stub = _createForwardingStub(
+          stubTypeParameters, substitution, interfaceMember,
+          forMemberSignature: forMemberSignature);
     }
 
     bool isImplCreated = false;
@@ -125,15 +169,36 @@
     bool needsCheck(DartType type) => needsCheckVisitor == null
         ? false
         : substitution.substituteType(type).accept(needsCheckVisitor);
+    bool enableNonNullable = hierarchy.loader.target.enableNonNullable;
+    bool isNonNullableByDefault =
+        enableNonNullable && parent.library.isNonNullableByDefault;
+
+    DartType initialType(DartType a) {
+      if (!enableNonNullable) return null;
+      if (!isNonNullableByDefault) {
+        a = legacyErasure(hierarchy.coreTypes, a);
+      }
+      return a;
+    }
+
+    DartType mergeTypes(DartType a, DartType b) {
+      if (a == null) return null;
+      if (!isNonNullableByDefault) {
+        b = legacyErasure(hierarchy.coreTypes, b);
+      }
+      return nnbdTopMerge(hierarchy.coreTypes, a, b);
+    }
+
     for (int i = 0; i < interfacePositionalParameters.length; i++) {
       VariableDeclaration parameter = interfacePositionalParameters[i];
+      DartType parameterType = parameter.type;
+      DartType type = initialType(substitution.substituteType(parameterType));
       bool isGenericCovariantImpl =
           parameter.isGenericCovariantImpl || needsCheck(parameter.type);
       bool isCovariant = parameter.isCovariant;
       VariableDeclaration superParameter = parameter;
       for (int j = 0; j < _candidates.length; j++) {
         Member otherMember = getCandidateAt(j);
-        if (otherMember is ForwardingNode) continue;
         List<VariableDeclaration> otherPositionalParameters =
             getPositionalParameters(otherMember);
         if (otherPositionalParameters.length <= i) continue;
@@ -146,6 +211,8 @@
         if (otherParameter.isCovariant) {
           isCovariant = true;
         }
+        type = mergeTypes(
+            type, substitutions[j].substituteType(otherParameter.type));
       }
       if (isGenericCovariantImpl) {
         if (!superParameter.isGenericCovariantImpl) {
@@ -165,9 +232,19 @@
           stub.function.positionalParameters[i].isCovariant = true;
         }
       }
+      if (enableNonNullable) {
+        if (type != null && type != parameterType) {
+          // TODO(johnniwinther): Report an error when [type] is null; this
+          // means that nnbd-top-merge was not defined.
+          createStubIfNeeded(forMemberSignature: true);
+          stub.function.positionalParameters[i].type = type;
+        }
+      }
     }
     for (int i = 0; i < interfaceNamedParameters.length; i++) {
       VariableDeclaration parameter = interfaceNamedParameters[i];
+      DartType parameterType = parameter.type;
+      DartType type = initialType(substitution.substituteType(parameterType));
       bool isGenericCovariantImpl =
           parameter.isGenericCovariantImpl || needsCheck(parameter.type);
       bool isCovariant = parameter.isCovariant;
@@ -186,6 +263,8 @@
         if (otherParameter.isCovariant) {
           isCovariant = true;
         }
+        type = mergeTypes(
+            type, substitutions[j].substituteType(otherParameter.type));
       }
       if (isGenericCovariantImpl) {
         if (!superParameter.isGenericCovariantImpl) {
@@ -205,6 +284,14 @@
           stub.function.namedParameters[i].isCovariant = true;
         }
       }
+      if (enableNonNullable) {
+        if (type != null && type != parameterType) {
+          // TODO(johnniwinther): Report an error when [type] is null; this
+          // means that nnbd-top-merge was not defined.
+          createStubIfNeeded(forMemberSignature: true);
+          stub.function.namedParameters[i].type = type;
+        }
+      }
     }
     for (int i = 0; i < interfaceTypeParameters.length; i++) {
       TypeParameter typeParameter = interfaceTypeParameters[i];
@@ -234,6 +321,22 @@
         }
       }
     }
+    if (enableNonNullable) {
+      DartType returnType =
+          substitution.substituteType(getReturnType(interfaceMember));
+      DartType type = initialType(returnType);
+      for (int j = 0; j < _candidates.length; j++) {
+        Member otherMember = getCandidateAt(j);
+        type = mergeTypes(
+            type, substitutions[j].substituteType(getReturnType(otherMember)));
+      }
+      if (type != null && type != returnType) {
+        // TODO(johnniwinther): Report an error when [type] is null; this
+        // means that nnbd-top-merge was not defined.
+        createStubIfNeeded(forMemberSignature: true);
+        stub.function.returnType = type;
+      }
+    }
     return stub;
   }
 
@@ -299,7 +402,9 @@
   }
 
   /// Creates a forwarding stub based on the given [target].
-  Procedure _createForwardingStub(Substitution substitution, Member target) {
+  Procedure _createForwardingStub(List<TypeParameter> typeParameters,
+      Substitution substitution, Member target,
+      {bool forMemberSignature: false}) {
     VariableDeclaration copyParameter(VariableDeclaration parameter) {
       return new VariableDeclaration(parameter.name,
           type: substitution.substituteType(parameter.type),
@@ -309,21 +414,14 @@
 
     List<TypeParameter> targetTypeParameters =
         target.function?.typeParameters ?? [];
-    List<TypeParameter> typeParameters;
-    if (targetTypeParameters.isNotEmpty) {
-      typeParameters =
-          new List<TypeParameter>.filled(targetTypeParameters.length, null);
+    if (typeParameters != null) {
       Map<TypeParameter, DartType> additionalSubstitution =
           <TypeParameter, DartType>{};
       for (int i = 0; i < targetTypeParameters.length; i++) {
         TypeParameter targetTypeParameter = targetTypeParameters[i];
-        TypeParameter typeParameter = new TypeParameter(
-            targetTypeParameter.name, null)
-          ..isGenericCovariantImpl = targetTypeParameter.isGenericCovariantImpl;
-        typeParameters[i] = typeParameter;
         additionalSubstitution[targetTypeParameter] =
             new TypeParameterType.forAlphaRenaming(
-                targetTypeParameter, typeParameter);
+                targetTypeParameter, typeParameters[i]);
       }
       substitution = Substitution.combine(
           substitution, Substitution.fromMap(additionalSubstitution));
@@ -350,7 +448,8 @@
     }
     return new Procedure(name, kind, function,
         isAbstract: true,
-        isForwardingStub: true,
+        isForwardingStub: !forMemberSignature,
+        isMemberSignature: forMemberSignature,
         fileUri: enclosingClass.fileUri,
         forwardingStubInterfaceTarget: finalTarget)
       ..startFileOffset = enclosingClass.fileOffset
@@ -380,12 +479,27 @@
     }
   }
 
-  Substitution _substitutionFor(Member candidate, Class class_) {
-    return Substitution.fromInterfaceType(hierarchy.getKernelTypeAsInstanceOf(
-        hierarchy.coreTypes
-            .thisInterfaceType(class_, class_.enclosingLibrary.nonNullable),
-        candidate.enclosingClass,
-        class_.enclosingLibrary));
+  Substitution _substitutionFor(
+      List<TypeParameter> stubTypeParameters, Member candidate, Class class_) {
+    Substitution substitution = Substitution.fromInterfaceType(
+        hierarchy.getKernelTypeAsInstanceOf(
+            hierarchy.coreTypes
+                .thisInterfaceType(class_, class_.enclosingLibrary.nonNullable),
+            candidate.enclosingClass,
+            class_.enclosingLibrary));
+    if (stubTypeParameters != null) {
+      // If the stub is generic ensure that type parameters are alpha renamed
+      // to the [stubTypeParameters].
+      Map<TypeParameter, TypeParameterType> map = {};
+      for (int i = 0; i < stubTypeParameters.length; i++) {
+        TypeParameter typeParameter = candidate.function.typeParameters[i];
+        map[typeParameter] = new TypeParameterType.forAlphaRenaming(
+            typeParameter, stubTypeParameters[i]);
+      }
+      substitution =
+          Substitution.combine(substitution, Substitution.fromMap(map));
+    }
+    return substitution;
   }
 
   List<VariableDeclaration> getPositionalParameters(Member member) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
index f6b8941..a437394a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
@@ -8,7 +8,9 @@
 
 import 'package:kernel/ast.dart'
     show DartType, DartTypeVisitor, DartTypeVisitor1, Nullability, Visitor;
+
 import 'package:kernel/src/assumptions.dart';
+import 'package:kernel/src/legacy_erasure.dart';
 
 import '../builder/field_builder.dart';
 
@@ -103,6 +105,13 @@
   }
 
   DartType inferType() {
-    return _targetFieldBuilder.fieldType = _root.inferType();
+    DartType type = _root.inferType();
+    if (_targetFieldBuilder.library.loader.target.enableNonNullable) {
+      if (!_targetFieldBuilder.library.isNonNullableByDefault) {
+        type =
+            legacyErasure(_targetFieldBuilder.library.loader.coreTypes, type);
+      }
+    }
+    return _targetFieldBuilder.fieldType = type;
   }
 }
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 b85cda9..18d1a77 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -5091,7 +5091,14 @@
         result.add(isSetVariable);
       }
 
-      Expression createVariableRead() => new VariableGet(node);
+      Expression createVariableRead({bool needsPromotion: false}) {
+        if (needsPromotion) {
+          return new VariableGet(node, node.type);
+        } else {
+          return new VariableGet(node);
+        }
+      }
+
       Expression createIsSetRead() => new VariableGet(isSetVariable);
       Expression createVariableWrite(Expression value) =>
           new VariableSet(node, value);
diff --git a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
index 3f0a3c4..ca339e3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
@@ -9,7 +9,7 @@
 
 Statement createGetterWithInitializer(
     int fileOffset, String name, DartType type, Expression initializer,
-    {Expression createVariableRead(),
+    {Expression createVariableRead({bool needsPromotion}),
     Expression createVariableWrite(Expression value),
     Expression createIsSetRead(),
     Expression createIsSetWrite(Expression value)}) {
@@ -36,7 +36,11 @@
           ]),
           null)
         ..fileOffset = fileOffset,
-      new ReturnStatement(createVariableRead()..fileOffset = fileOffset)
+      new ReturnStatement(
+          // If [type] is a type variable with undetermined nullability we need
+          // to create a read of the field that is promoted to the type variable
+          // type.
+          createVariableRead(needsPromotion: type.isPotentiallyNonNullable))
         ..fileOffset = fileOffset
     ])
       ..fileOffset = fileOffset;
@@ -45,7 +49,7 @@
     //
     //    return let # = _#field in # == null ? _#field = <init> : #;
     VariableDeclaration variable = new VariableDeclaration.forValue(
-        createVariableRead()..fileOffset = fileOffset,
+        createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
         type: type.withNullability(Nullability.nullable))
       ..fileOffset = fileOffset;
     return new ReturnStatement(
@@ -71,7 +75,8 @@
 
 Statement createGetterBodyWithoutInitializer(CoreTypes coreTypes,
     int fileOffset, String name, DartType type, String variableKindName,
-    {Expression createVariableRead(), Expression createIsSetRead()}) {
+    {Expression createVariableRead({bool needsPromotion}),
+    Expression createIsSetRead()}) {
   Expression exception = new Throw(new ConstructorInvocation(
       coreTypes.lateInitializationErrorConstructor,
       new Arguments(<Expression>[
@@ -87,8 +92,12 @@
     //
     //    return _#isSet#field ? _#field : throw '...';
     return new ReturnStatement(
-        new ConditionalExpression(createIsSetRead()..fileOffset = fileOffset,
-            createVariableRead()..fileOffset = fileOffset, exception, type)
+        new ConditionalExpression(
+            createIsSetRead()..fileOffset = fileOffset,
+            createVariableRead(needsPromotion: type.isPotentiallyNonNullable)
+              ..fileOffset = fileOffset,
+            exception,
+            type)
           ..fileOffset = fileOffset)
       ..fileOffset = fileOffset;
   } else {
diff --git a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
index 5added1..6b88bcd 100644
--- a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
@@ -9,6 +9,7 @@
         DartType,
         Expression,
         ExpressionStatement,
+        Field,
         FunctionNode,
         InvalidExpression,
         Let,
@@ -24,6 +25,21 @@
 
 import 'body_builder.dart' show EnsureLoaded;
 
+/// Name used for a static field holding redirecting factory information.
+const String redirectingName = "_redirecting#";
+
+/// Returns `true` if [member] is synthesized field holding the names of
+/// redirecting factories declared in the same class.
+///
+/// This field should be special-cased by backends.
+bool isRedirectingFactoryField(Member member) {
+  return member is Field &&
+      member.isStatic &&
+      member.name.name == redirectingName;
+}
+
+/// Name used for a synthesized let variable used to encode redirecting factory
+/// information in a factory method body.
 const String letName = "#redirecting_factory";
 
 class RedirectingFactoryBody extends ExpressionStatement {
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index 09fc289..d7cee7f 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -95,8 +95,6 @@
 
 import '../scope.dart';
 
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
 import 'source_library_builder.dart' show SourceLibraryBuilder;
 
 Class initializeClass(
diff --git a/pkg/front_end/lib/src/testing/id_testing_helper.dart b/pkg/front_end/lib/src/testing/id_testing_helper.dart
index e88e95a..63dbae5 100644
--- a/pkg/front_end/lib/src/testing/id_testing_helper.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_helper.dart
@@ -120,9 +120,13 @@
       int offset;
       if (id.className != null) {
         Class cls = lookupClass(library, id.className);
-        member = lookupClassMember(cls, id.memberName);
-        offset = member.fileOffset;
-        if (offset == -1) {
+        member = lookupClassMember(cls, id.memberName, required: false);
+        if (member != null) {
+          offset = member.fileOffset;
+          if (offset == -1) {
+            offset = cls.fileOffset;
+          }
+        } else {
           offset = cls.fileOffset;
         }
       } else {
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index 91d6e0a..b399707 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -505,6 +505,9 @@
       comma = '';
       for (NamedType namedParameter in node.namedParameters) {
         sb.write(comma);
+        if (namedParameter.isRequired) {
+          sb.write('required ');
+        }
         visit(namedParameter.type);
         sb.write(' ');
         sb.write(namedParameter.name);
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 694f491..8600797 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -26,6 +26,8 @@
 AsyncAsIdentifier/example: Fail
 AwaitAsIdentifier/example: Fail
 AwaitNotAsync/example: Fail
+AwaitInLateLocalInitializer/analyzerCode: Fail
+AwaitInLateLocalInitializer/example: Fail
 BuiltInIdentifierAsType/example: Fail
 BuiltInIdentifierInDeclaration/example: Fail
 BytecodeLimitExceededTooManyArguments/analyzerCode: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 035c8e2..e538ddc 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -3768,3 +3768,6 @@
 ValueForRequiredParameterNotProvidedWarning:
   template: "Missing required named parameter '#name'."
   severity: WARNING
+
+AwaitInLateLocalInitializer:
+  template: "`await` expressions are not supported in late local initializers."
diff --git a/pkg/front_end/test/id_tests/inheritance_test.dart b/pkg/front_end/test/id_tests/inheritance_test.dart
index 81f4c90..9bf13d2 100644
--- a/pkg/front_end/test/id_tests/inheritance_test.dart
+++ b/pkg/front_end/test/id_tests/inheritance_test.dart
@@ -3,13 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
-import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
-import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
-    show DataInterpreter, runTests;
+import 'package:_fe_analyzer_shared/src/testing/id.dart';
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:front_end/src/fasta/kernel/kernel_api.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
+import 'package:front_end/src/testing/id_extractor.dart';
 import 'package:kernel/ast.dart';
 
 main(List<String> args) async {
@@ -17,7 +16,7 @@
       .resolve('../../../_fe_analyzer_shared/test/inheritance/data'));
   await runTests<String>(dataDir,
       args: args,
-      supportedMarkers: cfeAnalyzerMarkers,
+      supportedMarkers: [cfeMarker],
       createUriForFileName: createUriForFileName,
       onFailure: onFailure,
       runTest: runTestFor(
@@ -60,10 +59,12 @@
 
 class InheritanceDataExtractor extends CfeDataExtractor<String> {
   final ClassHierarchy _hierarchy;
+  final CoreTypes _coreTypes;
 
   InheritanceDataExtractor(InternalCompilerResult compilerResult,
       Map<Id, ActualData<String>> actualMap)
       : _hierarchy = compilerResult.classHierarchy,
+        _coreTypes = compilerResult.coreTypes,
         super(compilerResult, actualMap);
 
   @override
@@ -72,6 +73,80 @@
   }
 
   @override
+  void computeForClass(Class node) {
+    super.computeForClass(node);
+
+    Set<Name> getters = _hierarchy
+        .getInterfaceMembers(node)
+        .map((Member member) => member.name)
+        .toSet();
+    Set<Name> setters = _hierarchy
+        .getInterfaceMembers(node, setters: true)
+        .where((Member member) =>
+            member is Procedure && member.kind == ProcedureKind.Setter)
+        .map((Member member) => member.name)
+        .toSet();
+
+    void addMember(Name name, {bool setter}) {
+      Member member = _hierarchy.getInterfaceMember(node, name, setter: setter);
+      if (member.enclosingClass == _coreTypes.objectClass) {
+        return;
+      }
+      InterfaceType supertype = _hierarchy.getTypeAsInstanceOf(
+          _coreTypes.thisInterfaceType(node, node.enclosingLibrary.nonNullable),
+          member.enclosingClass,
+          node.enclosingLibrary,
+          _coreTypes);
+      Substitution substitution = Substitution.fromInterfaceType(supertype);
+      DartType type;
+      if (member is Procedure) {
+        if (member.kind == ProcedureKind.Getter) {
+          type = substitution.substituteType(member.function.returnType);
+        } else if (member.kind == ProcedureKind.Setter) {
+          type = substitution
+              .substituteType(member.function.positionalParameters.single.type);
+        } else {
+          type = substitution.substituteType(member.function
+              .computeThisFunctionType(member.enclosingLibrary.nonNullable));
+        }
+      } else if (member is Field) {
+        type = substitution.substituteType(member.type);
+      }
+      if (type == null) {
+        return;
+      }
+
+      String memberName = name.name;
+      if (member is Procedure && member.kind == ProcedureKind.Setter) {
+        memberName += '=';
+      }
+      MemberId id = new MemberId.internal(memberName, className: node.name);
+
+      TreeNode nodeWithOffset;
+      if (member.enclosingClass == node) {
+        nodeWithOffset = computeTreeNodeWithOffset(member);
+      } else {
+        nodeWithOffset = computeTreeNodeWithOffset(node);
+      }
+
+      registerValue(
+          nodeWithOffset?.location?.file,
+          nodeWithOffset?.fileOffset,
+          id,
+          typeToText(type, TypeRepresentation.implicitUndetermined),
+          member);
+    }
+
+    for (Name name in getters) {
+      addMember(name, setter: false);
+    }
+
+    for (Name name in setters) {
+      addMember(name, setter: true);
+    }
+  }
+
+  @override
   String computeClassValue(Id id, Class node) {
     List<String> supertypes = <String>[];
     for (Class superclass in computeAllSuperclasses(node)) {
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 8d05fec..55e557c 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -144,8 +144,11 @@
 clarification
 clashes
 class's
+class2a
+class2b
 class3a
 class3b
+class3c
 class4a
 class4b
 class4c
@@ -532,12 +535,20 @@
 locationd
 logging
 lots
+lp
 lparen
+lq
+lr
 lry
 ls
 lt
+lu
 lub
+lv
 lvalue
+lx
+ly
+lz
 m
 maintaining
 mangled
@@ -555,6 +566,24 @@
 method2b
 method3a
 method3b
+method3c
+method4a
+method4b
+method4c
+method5a
+method5b
+method5c
+method6a
+method6b
+method6c
+method7a
+method7b
+method8a
+method8b
+method9a
+method9b
+method10a
+method10b
 mi
 migration
 mime
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 3872b60..c9e81d4 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -383,6 +383,7 @@
 cascaded
 cascading
 case
+cased
 cases
 casting
 catch
@@ -589,6 +590,7 @@
 constuctor
 consume
 consumed
+consumer
 consuming
 contain
 contained
@@ -1424,6 +1426,7 @@
 inheritable
 inheritance
 inherited
+inheriting
 inherits
 initial
 initialization
@@ -2199,6 +2202,7 @@
 promote
 promoted
 promoter
+promotes
 promotion
 promotions
 propagate
@@ -2647,6 +2651,7 @@
 sorting
 sorts
 sought
+sound
 source
 sources
 space
diff --git a/pkg/front_end/test/static_types/data/from_opt_in/main.dart b/pkg/front_end/test/static_types/data/from_opt_in/main.dart
new file mode 100644
index 0000000..df616be
--- /dev/null
+++ b/pkg/front_end/test/static_types/data/from_opt_in/main.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+/*library: nnbd=false*/
+
+import 'opt_in.dart';
+
+class LegacyClass extends Class implements Interface {
+  int method3() => /*int*/ 0;
+
+  int method4() => /*int*/ 0;
+}
+
+main() {
+  LegacyClass c = new /*LegacyClass*/ LegacyClass();
+  /*LegacyClass*/ c. /*invoke: int*/ method1();
+  /*LegacyClass*/ c. /*invoke: int*/ method2();
+  /*LegacyClass*/ c. /*invoke: int*/ method3();
+  /*LegacyClass*/ c. /*invoke: int*/ method4();
+}
diff --git a/pkg/front_end/test/static_types/data/from_opt_in/opt_in.dart b/pkg/front_end/test/static_types/data/from_opt_in/opt_in.dart
new file mode 100644
index 0000000..a0e60e2
--- /dev/null
+++ b/pkg/front_end/test/static_types/data/from_opt_in/opt_in.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*library: nnbd=true*/
+
+abstract class Interface {
+  int? method1();
+  int method2();
+  int? method3();
+  int method4();
+}
+
+class Class {
+  int method1() => /*int!*/ 0;
+  int? method2() => /*int!*/ 0;
+}
diff --git a/pkg/front_end/test/static_types/data/from_opt_out/main.dart b/pkg/front_end/test/static_types/data/from_opt_out/main.dart
new file mode 100644
index 0000000..13870b0
--- /dev/null
+++ b/pkg/front_end/test/static_types/data/from_opt_out/main.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*library: nnbd=true*/
+
+import 'opt_out.dart';
+
+abstract class Interface {
+  int? method1();
+  int method2();
+  int? method3();
+  int method4();
+}
+
+class Class1 extends LegacyClass {
+  int method1() => /*int!*/ 0;
+  int? method2() => /*int!*/ 0;
+}
+
+class Class2 extends LegacyClass implements Interface {}
+
+main() {
+  Class1 c1 = new /*Class1!*/ Class1();
+  /*Class1!*/ c1. /*invoke: int!*/ method1();
+  /*Class1!*/ c1. /*invoke: int?*/ method2();
+  /*Class1!*/ c1. /*invoke: int*/ method3();
+  /*Class1!*/ c1. /*invoke: int*/ method4();
+  Interface i = new /*Class2!*/ Class2();
+  /*Interface!*/ i. /*invoke: int?*/ method1();
+  /*Interface!*/ i. /*invoke: int!*/ method2();
+  /*Interface!*/ i. /*invoke: int?*/ method3();
+  /*Interface!*/ i. /*invoke: int!*/ method4();
+  Class2 c2 = new /*Class2!*/ Class2();
+  /*Class2!*/ c2. /*invoke: int?*/ method1();
+  /*Class2!*/ c2. /*invoke: int!*/ method2();
+  /*Class2!*/ c2. /*invoke: int?*/ method3();
+  /*Class2!*/ c2. /*invoke: int!*/ method4();
+}
diff --git a/pkg/front_end/test/static_types/data/from_opt_out/opt_out.dart b/pkg/front_end/test/static_types/data/from_opt_out/opt_out.dart
new file mode 100644
index 0000000..988df32
--- /dev/null
+++ b/pkg/front_end/test/static_types/data/from_opt_out/opt_out.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+/*library: nnbd=false*/
+
+class LegacyClass {
+  int method1() => /*int*/ 0;
+
+  int method2() => /*int*/ 0;
+
+  int method3() => /*int*/ 0;
+
+  int method4() => /*int*/ 0;
+}
diff --git a/pkg/front_end/test/static_types/static_type_test.dart b/pkg/front_end/test/static_types/static_type_test.dart
index 7da8681..a20a633 100644
--- a/pkg/front_end/test/static_types/static_type_test.dart
+++ b/pkg/front_end/test/static_types/static_type_test.dart
@@ -21,7 +21,14 @@
       createUriForFileName: createUriForFileName,
       onFailure: onFailure,
       runTest: runTestFor(const StaticTypeDataComputer(),
-          [defaultCfeConfig, cfeNonNullableConfig]));
+          [defaultCfeConfig, cfeNonNullableConfig]),
+      skipMap: {
+        defaultCfeConfig.marker: [
+          // NNBD-only tests.
+          'from_opt_in',
+          'from_opt_out',
+        ]
+      });
 }
 
 class StaticTypeDataComputer extends DataComputer<String> {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.1.expect
index c58b401..30e56b1 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.1.expect
@@ -8,9 +8,9 @@
 }
 
 And 19 platform libraries:
- - dart:vmservice_io
  - dart:_http
  - dart:_builtin
+ - dart:vmservice_io
  - dart:async
  - dart:cli
  - dart:collection
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.2.expect
index ea10dfd..5d64fb9 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/await_in_non_async.yaml.world.2.expect
@@ -15,9 +15,9 @@
 }
 
 And 19 platform libraries:
- - dart:vmservice_io
  - dart:_http
  - dart:_builtin
+ - dart:vmservice_io
  - dart:async
  - dart:cli
  - dart:collection
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.1.expect
index 4e19cd5..9605a7f 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.1.expect
@@ -17,9 +17,9 @@
 }
 
 And 19 platform libraries:
- - dart:vmservice_io
  - dart:_http
  - dart:_builtin
+ - dart:vmservice_io
  - dart:async
  - dart:cli
  - dart:collection
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.2.expect
index 4e19cd5..9605a7f 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/load_from_component_explicitly_import_dart_core.yaml.world.2.expect
@@ -17,9 +17,9 @@
 }
 
 And 19 platform libraries:
- - dart:vmservice_io
  - dart:_http
  - dart:_builtin
+ - dart:vmservice_io
  - dart:async
  - dart:cli
  - dart:collection
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.1.expect
index 62daba9..6c58888 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.1.expect
@@ -7,9 +7,9 @@
 }
 
 And 19 platform libraries:
- - dart:vmservice_io
  - dart:_http
  - dart:_builtin
+ - dart:vmservice_io
  - dart:async
  - dart:cli
  - dart:collection
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.4.expect
index 6a5ad02..ee707d8 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.4.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.4.expect
@@ -15,9 +15,9 @@
 }
 
 And 19 platform libraries:
- - dart:vmservice_io
  - dart:_http
  - dart:_builtin
+ - dart:vmservice_io
  - dart:async
  - dart:cli
  - dart:collection
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.5.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.5.expect
index d78d309..b397a3b 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.5.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/omit_platform_works_3.yaml.world.5.expect
@@ -15,9 +15,9 @@
 }
 
 And 19 platform libraries:
- - dart:vmservice_io
  - dart:_http
  - dart:_builtin
+ - dart:vmservice_io
  - dart:async
  - dart:cli
  - dart:collection
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart
index 896f009..0be2f75 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart
@@ -4,7 +4,7 @@
 
 late int lateTopLevelField1 = 123;
 
-class Class {
+class Class<T> {
   static late int lateStaticField1 = 87;
   static late int lateStaticField2 = 42;
 
@@ -15,15 +15,27 @@
   }
 
   late int lateInstanceField = 16;
+  final T field;
+  late T lateGenericField1 = field;
+  late T lateGenericField2 = field;
 
-  instanceMethod() {
+  Class(this.field);
+
+  instanceMethod(T value) {
     expect(16, lateInstanceField);
     lateInstanceField = 17;
     expect(17, lateInstanceField);
+
+    expect(field, lateGenericField1);
+    lateGenericField1 = value;
+    expect(value, lateGenericField1);
+
+    lateGenericField2 = value;
+    expect(value, lateGenericField2);
   }
 }
 
-extension Extension on Class {
+extension Extension<T> on Class<T> {
   static late int lateExtensionField1 = 87;
   static late int lateExtensionField2 = 42;
 
@@ -44,7 +56,7 @@
   expect(88, Class.lateStaticField1);
 
   Class.staticMethod();
-  new Class().instanceMethod();
+  new Class<int>(0).instanceMethod(42);
 
   expect(87, Extension.lateExtensionField1);
   Extension.lateExtensionField1 = 88;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect
index d47aaf2..a39d7fc 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect
@@ -2,11 +2,16 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1;
   static field core::int? _#lateStaticField2;
   field core::int? _#lateInstanceField;
-  synthetic constructor •() → self::Class
+  final field self::Class::T% field;
+  generic-covariant-impl field self::Class::T? _#lateGenericField1;
+  field core::bool _#lateGenericField1#isSet;
+  generic-covariant-impl field self::Class::T? _#lateGenericField2;
+  field core::bool _#lateGenericField2#isSet;
+  constructor •(self::Class::T% field) → self::Class<self::Class::T%>
     ;
   static get lateStaticField1() → core::int;
   static set lateStaticField1(core::int #t1) → void;
@@ -16,10 +21,14 @@
     ;
   get lateInstanceField() → core::int;
   set lateInstanceField(core::int #t3) → void;
-  method instanceMethod() → dynamic
+  get lateGenericField1() → self::Class::T%;
+  set lateGenericField1(self::Class::T% #t4) → void;
+  get lateGenericField2() → self::Class::T%;
+  set lateGenericField2(self::Class::T% #t5) → void;
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic
     ;
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
@@ -32,11 +41,11 @@
 static field core::int? _#Extension|lateExtensionField1;
 static field core::int? _#Extension|lateExtensionField2;
 static get lateTopLevelField1() → core::int;
-static set lateTopLevelField1(core::int #t4) → void;
+static set lateTopLevelField1(core::int #t6) → void;
 static get Extension|lateExtensionField1() → core::int;
-static set Extension|lateExtensionField1(core::int #t5) → void;
+static set Extension|lateExtensionField1(core::int #t7) → void;
 static get Extension|lateExtensionField2() → core::int;
-static set Extension|lateExtensionField2(core::int #t6) → void;
+static set Extension|lateExtensionField2(core::int #t8) → void;
 static method Extension|staticMethod() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
index b5758c3..d990f22 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
@@ -2,12 +2,17 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  final field self::Class::T% field;
+  generic-covariant-impl field self::Class::T? _#lateGenericField1 = null;
+  field core::bool _#lateGenericField1#isSet = false;
+  generic-covariant-impl field self::Class::T? _#lateGenericField2 = null;
+  field core::bool _#lateGenericField2#isSet = false;
+  constructor •(self::Class::T% field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static get lateStaticField1() → core::int
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} self::Class::_#lateStaticField1 = 87 : #t1{core::int};
@@ -26,13 +31,40 @@
     return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = 16 : #t5{core::int};
   set lateInstanceField(core::int #t6) → void
     this.{self::Class::_#lateInstanceField} = #t6;
-  method instanceMethod() → dynamic {
+  get lateGenericField1() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField1#isSet}) {
+      this.{self::Class::_#lateGenericField1#isSet} = true;
+      this.{self::Class::_#lateGenericField1} = this.{self::Class::field};
+    }
+    return let final self::Class::T? #t7 = this.{self::Class::_#lateGenericField1} in #t7{self::Class::T%};
+  }
+  set lateGenericField1(self::Class::T% #t8) → void {
+    this.{self::Class::_#lateGenericField1#isSet} = true;
+    this.{self::Class::_#lateGenericField1} = #t8;
+  }
+  get lateGenericField2() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField2#isSet}) {
+      this.{self::Class::_#lateGenericField2#isSet} = true;
+      this.{self::Class::_#lateGenericField2} = this.{self::Class::field};
+    }
+    return let final self::Class::T? #t9 = this.{self::Class::_#lateGenericField2} in #t9{self::Class::T%};
+  }
+  set lateGenericField2(self::Class::T% #t10) → void {
+    this.{self::Class::_#lateGenericField2#isSet} = true;
+    this.{self::Class::_#lateGenericField2} = #t10;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField});
     this.{self::Class::lateInstanceField} = 17;
     self::expect(17, this.{self::Class::lateInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericField1});
+    this.{self::Class::lateGenericField1} = value;
+    self::expect(value, this.{self::Class::lateGenericField1});
+    this.{self::Class::lateGenericField2} = value;
+    self::expect(value, this.{self::Class::lateGenericField2});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
@@ -45,17 +77,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField1() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField1 in #t7.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t7{core::int};
-static set lateTopLevelField1(core::int #t8) → void
-  self::_#lateTopLevelField1 = #t8;
+  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t11{core::int};
+static set lateTopLevelField1(core::int #t12) → void
+  self::_#lateTopLevelField1 = #t12;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t9{core::int};
-static set Extension|lateExtensionField1(core::int #t10) → void
-  self::_#Extension|lateExtensionField1 = #t10;
+  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t13{core::int};
+static set Extension|lateExtensionField1(core::int #t14) → void
+  self::_#Extension|lateExtensionField1 = #t14;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t11{core::int};
-static set Extension|lateExtensionField2(core::int #t12) → void
-  self::_#Extension|lateExtensionField2 = #t12;
+  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t15{core::int};
+static set Extension|lateExtensionField2(core::int #t16) → void
+  self::_#Extension|lateExtensionField2 = #t16;
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
   self::Extension|lateExtensionField2 = 43;
@@ -69,7 +101,7 @@
   self::Class::lateStaticField1 = 88;
   self::expect(88, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}(42);
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|lateExtensionField1 = 88;
   self::expect(88, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
index b5758c3..d990f22 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
@@ -2,12 +2,17 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  final field self::Class::T% field;
+  generic-covariant-impl field self::Class::T? _#lateGenericField1 = null;
+  field core::bool _#lateGenericField1#isSet = false;
+  generic-covariant-impl field self::Class::T? _#lateGenericField2 = null;
+  field core::bool _#lateGenericField2#isSet = false;
+  constructor •(self::Class::T% field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static get lateStaticField1() → core::int
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} self::Class::_#lateStaticField1 = 87 : #t1{core::int};
@@ -26,13 +31,40 @@
     return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = 16 : #t5{core::int};
   set lateInstanceField(core::int #t6) → void
     this.{self::Class::_#lateInstanceField} = #t6;
-  method instanceMethod() → dynamic {
+  get lateGenericField1() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField1#isSet}) {
+      this.{self::Class::_#lateGenericField1#isSet} = true;
+      this.{self::Class::_#lateGenericField1} = this.{self::Class::field};
+    }
+    return let final self::Class::T? #t7 = this.{self::Class::_#lateGenericField1} in #t7{self::Class::T%};
+  }
+  set lateGenericField1(self::Class::T% #t8) → void {
+    this.{self::Class::_#lateGenericField1#isSet} = true;
+    this.{self::Class::_#lateGenericField1} = #t8;
+  }
+  get lateGenericField2() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField2#isSet}) {
+      this.{self::Class::_#lateGenericField2#isSet} = true;
+      this.{self::Class::_#lateGenericField2} = this.{self::Class::field};
+    }
+    return let final self::Class::T? #t9 = this.{self::Class::_#lateGenericField2} in #t9{self::Class::T%};
+  }
+  set lateGenericField2(self::Class::T% #t10) → void {
+    this.{self::Class::_#lateGenericField2#isSet} = true;
+    this.{self::Class::_#lateGenericField2} = #t10;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField});
     this.{self::Class::lateInstanceField} = 17;
     self::expect(17, this.{self::Class::lateInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericField1});
+    this.{self::Class::lateGenericField1} = value;
+    self::expect(value, this.{self::Class::lateGenericField1});
+    this.{self::Class::lateGenericField2} = value;
+    self::expect(value, this.{self::Class::lateGenericField2});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
@@ -45,17 +77,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField1() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField1 in #t7.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t7{core::int};
-static set lateTopLevelField1(core::int #t8) → void
-  self::_#lateTopLevelField1 = #t8;
+  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t11{core::int};
+static set lateTopLevelField1(core::int #t12) → void
+  self::_#lateTopLevelField1 = #t12;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t9{core::int};
-static set Extension|lateExtensionField1(core::int #t10) → void
-  self::_#Extension|lateExtensionField1 = #t10;
+  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t13{core::int};
+static set Extension|lateExtensionField1(core::int #t14) → void
+  self::_#Extension|lateExtensionField1 = #t14;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t11{core::int};
-static set Extension|lateExtensionField2(core::int #t12) → void
-  self::_#Extension|lateExtensionField2 = #t12;
+  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t15{core::int};
+static set Extension|lateExtensionField2(core::int #t16) → void
+  self::_#Extension|lateExtensionField2 = #t16;
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
   self::Extension|lateExtensionField2 = 43;
@@ -69,7 +101,7 @@
   self::Class::lateStaticField1 = 88;
   self::expect(88, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}(42);
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|lateExtensionField1 = 88;
   self::expect(88, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
index b5758c3..d990f22 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
@@ -2,12 +2,17 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  final field self::Class::T% field;
+  generic-covariant-impl field self::Class::T? _#lateGenericField1 = null;
+  field core::bool _#lateGenericField1#isSet = false;
+  generic-covariant-impl field self::Class::T? _#lateGenericField2 = null;
+  field core::bool _#lateGenericField2#isSet = false;
+  constructor •(self::Class::T% field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static get lateStaticField1() → core::int
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} self::Class::_#lateStaticField1 = 87 : #t1{core::int};
@@ -26,13 +31,40 @@
     return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = 16 : #t5{core::int};
   set lateInstanceField(core::int #t6) → void
     this.{self::Class::_#lateInstanceField} = #t6;
-  method instanceMethod() → dynamic {
+  get lateGenericField1() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField1#isSet}) {
+      this.{self::Class::_#lateGenericField1#isSet} = true;
+      this.{self::Class::_#lateGenericField1} = this.{self::Class::field};
+    }
+    return let final self::Class::T? #t7 = this.{self::Class::_#lateGenericField1} in #t7{self::Class::T%};
+  }
+  set lateGenericField1(self::Class::T% #t8) → void {
+    this.{self::Class::_#lateGenericField1#isSet} = true;
+    this.{self::Class::_#lateGenericField1} = #t8;
+  }
+  get lateGenericField2() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField2#isSet}) {
+      this.{self::Class::_#lateGenericField2#isSet} = true;
+      this.{self::Class::_#lateGenericField2} = this.{self::Class::field};
+    }
+    return let final self::Class::T? #t9 = this.{self::Class::_#lateGenericField2} in #t9{self::Class::T%};
+  }
+  set lateGenericField2(self::Class::T% #t10) → void {
+    this.{self::Class::_#lateGenericField2#isSet} = true;
+    this.{self::Class::_#lateGenericField2} = #t10;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField});
     this.{self::Class::lateInstanceField} = 17;
     self::expect(17, this.{self::Class::lateInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericField1});
+    this.{self::Class::lateGenericField1} = value;
+    self::expect(value, this.{self::Class::lateGenericField1});
+    this.{self::Class::lateGenericField2} = value;
+    self::expect(value, this.{self::Class::lateGenericField2});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
@@ -45,17 +77,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField1() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField1 in #t7.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t7{core::int};
-static set lateTopLevelField1(core::int #t8) → void
-  self::_#lateTopLevelField1 = #t8;
+  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t11{core::int};
+static set lateTopLevelField1(core::int #t12) → void
+  self::_#lateTopLevelField1 = #t12;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t9{core::int};
-static set Extension|lateExtensionField1(core::int #t10) → void
-  self::_#Extension|lateExtensionField1 = #t10;
+  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t13{core::int};
+static set Extension|lateExtensionField1(core::int #t14) → void
+  self::_#Extension|lateExtensionField1 = #t14;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t11{core::int};
-static set Extension|lateExtensionField2(core::int #t12) → void
-  self::_#Extension|lateExtensionField2 = #t12;
+  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t15{core::int};
+static set Extension|lateExtensionField2(core::int #t16) → void
+  self::_#Extension|lateExtensionField2 = #t16;
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
   self::Extension|lateExtensionField2 = 43;
@@ -69,7 +101,7 @@
   self::Class::lateStaticField1 = 88;
   self::expect(88, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}(42);
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|lateExtensionField1 = 88;
   self::expect(88, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
index b5758c3..d990f22 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
@@ -2,12 +2,17 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  final field self::Class::T% field;
+  generic-covariant-impl field self::Class::T? _#lateGenericField1 = null;
+  field core::bool _#lateGenericField1#isSet = false;
+  generic-covariant-impl field self::Class::T? _#lateGenericField2 = null;
+  field core::bool _#lateGenericField2#isSet = false;
+  constructor •(self::Class::T% field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static get lateStaticField1() → core::int
     return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} self::Class::_#lateStaticField1 = 87 : #t1{core::int};
@@ -26,13 +31,40 @@
     return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = 16 : #t5{core::int};
   set lateInstanceField(core::int #t6) → void
     this.{self::Class::_#lateInstanceField} = #t6;
-  method instanceMethod() → dynamic {
+  get lateGenericField1() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField1#isSet}) {
+      this.{self::Class::_#lateGenericField1#isSet} = true;
+      this.{self::Class::_#lateGenericField1} = this.{self::Class::field};
+    }
+    return let final self::Class::T? #t7 = this.{self::Class::_#lateGenericField1} in #t7{self::Class::T%};
+  }
+  set lateGenericField1(self::Class::T% #t8) → void {
+    this.{self::Class::_#lateGenericField1#isSet} = true;
+    this.{self::Class::_#lateGenericField1} = #t8;
+  }
+  get lateGenericField2() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField2#isSet}) {
+      this.{self::Class::_#lateGenericField2#isSet} = true;
+      this.{self::Class::_#lateGenericField2} = this.{self::Class::field};
+    }
+    return let final self::Class::T? #t9 = this.{self::Class::_#lateGenericField2} in #t9{self::Class::T%};
+  }
+  set lateGenericField2(self::Class::T% #t10) → void {
+    this.{self::Class::_#lateGenericField2#isSet} = true;
+    this.{self::Class::_#lateGenericField2} = #t10;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField});
     this.{self::Class::lateInstanceField} = 17;
     self::expect(17, this.{self::Class::lateInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericField1});
+    this.{self::Class::lateGenericField1} = value;
+    self::expect(value, this.{self::Class::lateGenericField1});
+    this.{self::Class::lateGenericField2} = value;
+    self::expect(value, this.{self::Class::lateGenericField2});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
@@ -45,17 +77,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField1() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField1 in #t7.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t7{core::int};
-static set lateTopLevelField1(core::int #t8) → void
-  self::_#lateTopLevelField1 = #t8;
+  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t11{core::int};
+static set lateTopLevelField1(core::int #t12) → void
+  self::_#lateTopLevelField1 = #t12;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t9{core::int};
-static set Extension|lateExtensionField1(core::int #t10) → void
-  self::_#Extension|lateExtensionField1 = #t10;
+  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t13{core::int};
+static set Extension|lateExtensionField1(core::int #t14) → void
+  self::_#Extension|lateExtensionField1 = #t14;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t11{core::int};
-static set Extension|lateExtensionField2(core::int #t12) → void
-  self::_#Extension|lateExtensionField2 = #t12;
+  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t15{core::int};
+static set Extension|lateExtensionField2(core::int #t16) → void
+  self::_#Extension|lateExtensionField2 = #t16;
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
   self::Extension|lateExtensionField2 = 43;
@@ -69,7 +101,7 @@
   self::Class::lateStaticField1 = 88;
   self::expect(88, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}(42);
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|lateExtensionField1 = 88;
   self::expect(88, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart
index f341089..fc77d31 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart
@@ -4,7 +4,7 @@
 
 late int lateTopLevelField;
 
-class Class {
+class Class<T> {
   static late int lateStaticField1;
   static late int lateStaticField2;
 
@@ -17,15 +17,22 @@
 
   late int lateInstanceField;
 
-  instanceMethod() {
+  late T lateGenericInstanceField;
+
+  instanceMethod(T value) {
     throws(() => lateInstanceField,
         'Read value from uninitialized Class.lateInstanceField');
     lateInstanceField = 16;
     expect(16, lateInstanceField);
+
+    throws(() => lateGenericInstanceField,
+        'Read value from uninitialized Class.lateGenericInstanceField');
+    lateGenericInstanceField = value;
+    expect(value, lateGenericInstanceField);
   }
 }
 
-extension Extension on Class {
+extension Extension<T> on Class<T> {
   static late int lateExtensionField1;
   static late int lateExtensionField2;
 
@@ -49,14 +56,19 @@
   expect(87, Class.lateStaticField1);
 
   Class.staticMethod();
-  new Class().instanceMethod();
+  new Class<int>().instanceMethod(0);
 
-  var c = new Class();
+  var c = new Class<int>();
   throws(() => c.lateInstanceField,
       'Read value from uninitialized Class.lateInstanceField');
   c.lateInstanceField = 16;
   expect(16, c.lateInstanceField);
 
+  throws(() => c.lateGenericInstanceField,
+      'Read value from uninitialized Class.lateGenericInstanceField');
+  c.lateGenericInstanceField = 0;
+  expect(0, c.lateGenericInstanceField);
+
   throws(() => Extension.lateExtensionField1,
       'Read value from uninitialized Extension.lateExtensionField1');
   Extension.lateExtensionField1 = 87;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect
index a48eba7..ffdf14a 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect
@@ -2,11 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1;
   static field core::int? _#lateStaticField2;
   field core::int? _#lateInstanceField;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField;
+  field core::bool _#lateGenericInstanceField#isSet;
+  synthetic constructor •() → self::Class<self::Class::T%>
     ;
   static get lateStaticField1() → core::int;
   static set lateStaticField1(core::int #t1) → void;
@@ -16,10 +18,12 @@
     ;
   get lateInstanceField() → core::int;
   set lateInstanceField(core::int #t3) → void;
-  method instanceMethod() → dynamic
+  get lateGenericInstanceField() → self::Class::T%;
+  set lateGenericInstanceField(self::Class::T% #t4) → void;
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic
     ;
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
@@ -32,11 +36,11 @@
 static field core::int? _#Extension|lateExtensionField1;
 static field core::int? _#Extension|lateExtensionField2;
 static get lateTopLevelField() → core::int;
-static set lateTopLevelField(core::int #t4) → void;
+static set lateTopLevelField(core::int #t5) → void;
 static get Extension|lateExtensionField1() → core::int;
-static set Extension|lateExtensionField1(core::int #t5) → void;
+static set Extension|lateExtensionField1(core::int #t6) → void;
 static get Extension|lateExtensionField2() → core::int;
-static set Extension|lateExtensionField2(core::int #t6) → void;
+static set Extension|lateExtensionField2(core::int #t7) → void;
 static method Extension|staticMethod() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
index 092ce77..61dfded 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
@@ -3,11 +3,13 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int
@@ -27,13 +29,22 @@
     return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.") : #t5{core::int};
   set lateInstanceField(core::int #t6) → void
     this.{self::Class::_#lateInstanceField} = #t6;
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T%
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#lateGenericInstanceField} in #t7{self::Class::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T% #t8) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t8;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
+    self::throws(() → self::Class::T% => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
@@ -46,17 +57,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField in #t7.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t7{core::int};
-static set lateTopLevelField(core::int #t8) → void
-  self::_#lateTopLevelField = #t8;
+  return let final core::int? #t9 = self::_#lateTopLevelField in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t9{core::int};
+static set lateTopLevelField(core::int #t10) → void
+  self::_#lateTopLevelField = #t10;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t9{core::int};
-static set Extension|lateExtensionField1(core::int #t10) → void
-  self::_#Extension|lateExtensionField1 = #t10;
+  return let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t11{core::int};
+static set Extension|lateExtensionField1(core::int #t12) → void
+  self::_#Extension|lateExtensionField1 = #t12;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t11{core::int};
-static set Extension|lateExtensionField2(core::int #t12) → void
-  self::_#Extension|lateExtensionField2 = #t12;
+  return let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t13{core::int};
+static set Extension|lateExtensionField2(core::int #t14) → void
+  self::_#Extension|lateExtensionField2 = #t14;
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
   self::Extension|lateExtensionField2 = 42;
@@ -70,11 +81,14 @@
   self::Class::lateStaticField1 = 87;
   self::expect(87, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
-  self::Class c = new self::Class::•();
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
+  self::Class<core::int> c = new self::Class::•<core::int>();
   self::throws(() → core::int => c.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
   c.{self::Class::lateInstanceField} = 16;
   self::expect(16, c.{self::Class::lateInstanceField});
+  self::throws(() → core::int => c.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+  c.{self::Class::lateGenericInstanceField} = 0;
+  self::expect(0, c.{self::Class::lateGenericInstanceField});
   self::throws(() → core::int => self::Extension|lateExtensionField1, "Read value from uninitialized Extension.lateExtensionField1");
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
index 092ce77..61dfded 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
@@ -3,11 +3,13 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int
@@ -27,13 +29,22 @@
     return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.") : #t5{core::int};
   set lateInstanceField(core::int #t6) → void
     this.{self::Class::_#lateInstanceField} = #t6;
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T%
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#lateGenericInstanceField} in #t7{self::Class::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T% #t8) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t8;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
+    self::throws(() → self::Class::T% => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
@@ -46,17 +57,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField in #t7.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t7{core::int};
-static set lateTopLevelField(core::int #t8) → void
-  self::_#lateTopLevelField = #t8;
+  return let final core::int? #t9 = self::_#lateTopLevelField in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t9{core::int};
+static set lateTopLevelField(core::int #t10) → void
+  self::_#lateTopLevelField = #t10;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t9{core::int};
-static set Extension|lateExtensionField1(core::int #t10) → void
-  self::_#Extension|lateExtensionField1 = #t10;
+  return let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t11{core::int};
+static set Extension|lateExtensionField1(core::int #t12) → void
+  self::_#Extension|lateExtensionField1 = #t12;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t11{core::int};
-static set Extension|lateExtensionField2(core::int #t12) → void
-  self::_#Extension|lateExtensionField2 = #t12;
+  return let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t13{core::int};
+static set Extension|lateExtensionField2(core::int #t14) → void
+  self::_#Extension|lateExtensionField2 = #t14;
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
   self::Extension|lateExtensionField2 = 42;
@@ -70,11 +81,14 @@
   self::Class::lateStaticField1 = 87;
   self::expect(87, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
-  self::Class c = new self::Class::•();
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
+  self::Class<core::int> c = new self::Class::•<core::int>();
   self::throws(() → core::int => c.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
   c.{self::Class::lateInstanceField} = 16;
   self::expect(16, c.{self::Class::lateInstanceField});
+  self::throws(() → core::int => c.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+  c.{self::Class::lateGenericInstanceField} = 0;
+  self::expect(0, c.{self::Class::lateGenericInstanceField});
   self::throws(() → core::int => self::Extension|lateExtensionField1, "Read value from uninitialized Extension.lateExtensionField1");
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
index 092ce77..61dfded 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
@@ -3,11 +3,13 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int
@@ -27,13 +29,22 @@
     return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.") : #t5{core::int};
   set lateInstanceField(core::int #t6) → void
     this.{self::Class::_#lateInstanceField} = #t6;
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T%
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#lateGenericInstanceField} in #t7{self::Class::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T% #t8) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t8;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
+    self::throws(() → self::Class::T% => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
@@ -46,17 +57,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField in #t7.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t7{core::int};
-static set lateTopLevelField(core::int #t8) → void
-  self::_#lateTopLevelField = #t8;
+  return let final core::int? #t9 = self::_#lateTopLevelField in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t9{core::int};
+static set lateTopLevelField(core::int #t10) → void
+  self::_#lateTopLevelField = #t10;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t9{core::int};
-static set Extension|lateExtensionField1(core::int #t10) → void
-  self::_#Extension|lateExtensionField1 = #t10;
+  return let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t11{core::int};
+static set Extension|lateExtensionField1(core::int #t12) → void
+  self::_#Extension|lateExtensionField1 = #t12;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t11{core::int};
-static set Extension|lateExtensionField2(core::int #t12) → void
-  self::_#Extension|lateExtensionField2 = #t12;
+  return let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t13{core::int};
+static set Extension|lateExtensionField2(core::int #t14) → void
+  self::_#Extension|lateExtensionField2 = #t14;
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
   self::Extension|lateExtensionField2 = 42;
@@ -70,11 +81,14 @@
   self::Class::lateStaticField1 = 87;
   self::expect(87, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
-  self::Class c = new self::Class::•();
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
+  self::Class<core::int> c = new self::Class::•<core::int>();
   self::throws(() → core::int => c.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
   c.{self::Class::lateInstanceField} = 16;
   self::expect(16, c.{self::Class::lateInstanceField});
+  self::throws(() → core::int => c.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+  c.{self::Class::lateGenericInstanceField} = 0;
+  self::expect(0, c.{self::Class::lateGenericInstanceField});
   self::throws(() → core::int => self::Extension|lateExtensionField1, "Read value from uninitialized Extension.lateExtensionField1");
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
index 092ce77..61dfded 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
@@ -3,11 +3,13 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int
@@ -27,13 +29,22 @@
     return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.") : #t5{core::int};
   set lateInstanceField(core::int #t6) → void
     this.{self::Class::_#lateInstanceField} = #t6;
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T%
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#lateGenericInstanceField} in #t7{self::Class::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T% #t8) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t8;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
+    self::throws(() → self::Class::T% => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
@@ -46,17 +57,17 @@
 static field core::int? _#Extension|lateExtensionField1 = null;
 static field core::int? _#Extension|lateExtensionField2 = null;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField in #t7.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t7{core::int};
-static set lateTopLevelField(core::int #t8) → void
-  self::_#lateTopLevelField = #t8;
+  return let final core::int? #t9 = self::_#lateTopLevelField in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t9{core::int};
+static set lateTopLevelField(core::int #t10) → void
+  self::_#lateTopLevelField = #t10;
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t9{core::int};
-static set Extension|lateExtensionField1(core::int #t10) → void
-  self::_#Extension|lateExtensionField1 = #t10;
+  return let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t11{core::int};
+static set Extension|lateExtensionField1(core::int #t12) → void
+  self::_#Extension|lateExtensionField1 = #t12;
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t11{core::int};
-static set Extension|lateExtensionField2(core::int #t12) → void
-  self::_#Extension|lateExtensionField2 = #t12;
+  return let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t13{core::int};
+static set Extension|lateExtensionField2(core::int #t14) → void
+  self::_#Extension|lateExtensionField2 = #t14;
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
   self::Extension|lateExtensionField2 = 42;
@@ -70,11 +81,14 @@
   self::Class::lateStaticField1 = 87;
   self::expect(87, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
-  self::Class c = new self::Class::•();
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
+  self::Class<core::int> c = new self::Class::•<core::int>();
   self::throws(() → core::int => c.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
   c.{self::Class::lateInstanceField} = 16;
   self::expect(16, c.{self::Class::lateInstanceField});
+  self::throws(() → core::int => c.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+  c.{self::Class::lateGenericInstanceField} = 0;
+  self::expect(0, c.{self::Class::lateGenericInstanceField});
   self::throws(() → core::int => self::Extension|lateExtensionField1, "Read value from uninitialized Extension.lateExtensionField1");
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart
index dcff292..6a2269e 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart
@@ -9,7 +9,7 @@
 
 late final int lateTopLevelField1 = initLateTopLevelField1(123);
 
-class Class {
+class Class<T> {
   static int? lateStaticField1Init;
   static int initLateStaticField1(int value) {
     return lateStaticField1Init = value;
@@ -37,14 +37,28 @@
 
   late final int lateInstanceField = initLateInstanceField(16);
 
+  T? lateGenericFieldInit;
+  T initLateGenericField(T value) {
+    return lateGenericFieldInit = value;
+  }
+
+  final T field;
+  late final T lateGenericField = initLateGenericField(field);
+
+  Class(this.field);
+
   instanceMethod() {
     expect(null, lateInstanceFieldInit);
     expect(16, lateInstanceField);
     expect(16, lateInstanceFieldInit);
+
+    expect(null, lateGenericFieldInit);
+    expect(field, lateGenericField);
+    expect(field, lateGenericFieldInit);
   }
 }
 
-extension Extension on Class {
+extension Extension<T> on Class<T> {
   static int? lateExtensionField1Init;
   static int initLateExtensionField1(int value) {
     return lateExtensionField1Init = value;
@@ -76,7 +90,7 @@
   expect(87, Class.lateStaticField1Init);
 
   Class.staticMethod();
-  new Class().instanceMethod();
+  new Class<int>(0).instanceMethod();
 
   expect(null, Extension.lateExtensionField1Init);
   expect(87, Extension.lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect
index ffc68c7..cf3a5eb 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect
@@ -2,14 +2,18 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init;
   static field core::int? _#lateStaticField1;
   static field core::int? lateStaticField2Init;
   static field core::int? _#lateStaticField2;
   field core::int? lateInstanceFieldInit;
   field core::int? _#lateInstanceField;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? lateGenericFieldInit;
+  final field self::Class::T% field;
+  field self::Class::T? _#lateGenericField;
+  field core::bool _#lateGenericField#isSet;
+  constructor •(self::Class::T% field) → self::Class<self::Class::T%>
     ;
   static method initLateStaticField1(core::int value) → core::int
     ;
@@ -22,10 +26,13 @@
   method initLateInstanceField(core::int value) → core::int
     ;
   get lateInstanceField() → core::int;
+  method initLateGenericField(generic-covariant-impl self::Class::T% value) → self::Class::T%
+    ;
+  get lateGenericField() → self::Class::T%;
   method instanceMethod() → dynamic
     ;
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect
index 67e2378..6f2bab2 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect
@@ -2,15 +2,19 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init = null;
   static field core::int? _#lateStaticField1 = null;
   static field core::int? lateStaticField2Init = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? lateInstanceFieldInit = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  generic-covariant-impl field self::Class::T? lateGenericFieldInit = null;
+  final field self::Class::T% field;
+  field self::Class::T? _#lateGenericField = null;
+  field core::bool _#lateGenericField#isSet = false;
+  constructor •(self::Class::T% field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method initLateStaticField1(core::int value) → core::int {
     return self::Class::lateStaticField1Init = value;
@@ -32,13 +36,26 @@
   }
   get lateInstanceField() → core::int
     return let final core::int? #t3 = this.{self::Class::_#lateInstanceField} in #t3.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = this.{self::Class::initLateInstanceField}(16) : #t3{core::int};
+  method initLateGenericField(generic-covariant-impl self::Class::T% value) → self::Class::T% {
+    return this.{self::Class::lateGenericFieldInit} = value;
+  }
+  get lateGenericField() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField#isSet}) {
+      this.{self::Class::_#lateGenericField#isSet} = true;
+      this.{self::Class::_#lateGenericField} = this.{self::Class::initLateGenericField}(this.{self::Class::field});
+    }
+    return let final self::Class::T? #t4 = this.{self::Class::_#lateGenericField} in #t4{self::Class::T%};
+  }
   method instanceMethod() → dynamic {
     self::expect(null, this.{self::Class::lateInstanceFieldInit});
     self::expect(16, this.{self::Class::lateInstanceField});
     self::expect(16, this.{self::Class::lateInstanceFieldInit});
+    self::expect(null, this.{self::Class::lateGenericFieldInit});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericFieldInit});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
@@ -59,17 +76,17 @@
   return self::lateTopLevelField1Init = value;
 }
 static get lateTopLevelField1() → core::int
-  return let final core::int? #t4 = self::_#lateTopLevelField1 in #t4.==(null) ?{core::int} self::_#lateTopLevelField1 = self::initLateTopLevelField1(123) : #t4{core::int};
+  return let final core::int? #t5 = self::_#lateTopLevelField1 in #t5.==(null) ?{core::int} self::_#lateTopLevelField1 = self::initLateTopLevelField1(123) : #t5{core::int};
 static method Extension|initLateExtensionField1(core::int value) → core::int {
   return self::Extension|lateExtensionField1Init = value;
 }
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t5 = self::_#Extension|lateExtensionField1 in #t5.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = self::Extension|initLateExtensionField1(87) : #t5{core::int};
+  return let final core::int? #t6 = self::_#Extension|lateExtensionField1 in #t6.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = self::Extension|initLateExtensionField1(87) : #t6{core::int};
 static method Extension|initLateExtensionField2(core::int value) → core::int {
   return self::Extension|lateExtensionField2Init = value;
 }
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t6 = self::_#Extension|lateExtensionField2 in #t6.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = self::Extension|initLateExtensionField2(42) : #t6{core::int};
+  return let final core::int? #t7 = self::_#Extension|lateExtensionField2 in #t7.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = self::Extension|initLateExtensionField2(42) : #t7{core::int};
 static method Extension|staticMethod() → dynamic {
   self::expect(null, self::Extension|lateExtensionField2Init);
   self::expect(42, self::Extension|lateExtensionField2);
@@ -83,7 +100,7 @@
   self::expect(87, self::Class::lateStaticField1);
   self::expect(87, self::Class::lateStaticField1Init);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}();
   self::expect(null, self::Extension|lateExtensionField1Init);
   self::expect(87, self::Extension|lateExtensionField1);
   self::expect(87, self::Extension|lateExtensionField1Init);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.transformed.expect
index 67e2378..6f2bab2 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.transformed.expect
@@ -2,15 +2,19 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init = null;
   static field core::int? _#lateStaticField1 = null;
   static field core::int? lateStaticField2Init = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? lateInstanceFieldInit = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  generic-covariant-impl field self::Class::T? lateGenericFieldInit = null;
+  final field self::Class::T% field;
+  field self::Class::T? _#lateGenericField = null;
+  field core::bool _#lateGenericField#isSet = false;
+  constructor •(self::Class::T% field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method initLateStaticField1(core::int value) → core::int {
     return self::Class::lateStaticField1Init = value;
@@ -32,13 +36,26 @@
   }
   get lateInstanceField() → core::int
     return let final core::int? #t3 = this.{self::Class::_#lateInstanceField} in #t3.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = this.{self::Class::initLateInstanceField}(16) : #t3{core::int};
+  method initLateGenericField(generic-covariant-impl self::Class::T% value) → self::Class::T% {
+    return this.{self::Class::lateGenericFieldInit} = value;
+  }
+  get lateGenericField() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField#isSet}) {
+      this.{self::Class::_#lateGenericField#isSet} = true;
+      this.{self::Class::_#lateGenericField} = this.{self::Class::initLateGenericField}(this.{self::Class::field});
+    }
+    return let final self::Class::T? #t4 = this.{self::Class::_#lateGenericField} in #t4{self::Class::T%};
+  }
   method instanceMethod() → dynamic {
     self::expect(null, this.{self::Class::lateInstanceFieldInit});
     self::expect(16, this.{self::Class::lateInstanceField});
     self::expect(16, this.{self::Class::lateInstanceFieldInit});
+    self::expect(null, this.{self::Class::lateGenericFieldInit});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericFieldInit});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
@@ -59,17 +76,17 @@
   return self::lateTopLevelField1Init = value;
 }
 static get lateTopLevelField1() → core::int
-  return let final core::int? #t4 = self::_#lateTopLevelField1 in #t4.==(null) ?{core::int} self::_#lateTopLevelField1 = self::initLateTopLevelField1(123) : #t4{core::int};
+  return let final core::int? #t5 = self::_#lateTopLevelField1 in #t5.==(null) ?{core::int} self::_#lateTopLevelField1 = self::initLateTopLevelField1(123) : #t5{core::int};
 static method Extension|initLateExtensionField1(core::int value) → core::int {
   return self::Extension|lateExtensionField1Init = value;
 }
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t5 = self::_#Extension|lateExtensionField1 in #t5.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = self::Extension|initLateExtensionField1(87) : #t5{core::int};
+  return let final core::int? #t6 = self::_#Extension|lateExtensionField1 in #t6.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = self::Extension|initLateExtensionField1(87) : #t6{core::int};
 static method Extension|initLateExtensionField2(core::int value) → core::int {
   return self::Extension|lateExtensionField2Init = value;
 }
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t6 = self::_#Extension|lateExtensionField2 in #t6.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = self::Extension|initLateExtensionField2(42) : #t6{core::int};
+  return let final core::int? #t7 = self::_#Extension|lateExtensionField2 in #t7.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = self::Extension|initLateExtensionField2(42) : #t7{core::int};
 static method Extension|staticMethod() → dynamic {
   self::expect(null, self::Extension|lateExtensionField2Init);
   self::expect(42, self::Extension|lateExtensionField2);
@@ -83,7 +100,7 @@
   self::expect(87, self::Class::lateStaticField1);
   self::expect(87, self::Class::lateStaticField1Init);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}();
   self::expect(null, self::Extension|lateExtensionField1Init);
   self::expect(87, self::Extension|lateExtensionField1);
   self::expect(87, self::Extension|lateExtensionField1Init);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect
index 67e2378..6f2bab2 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect
@@ -2,15 +2,19 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init = null;
   static field core::int? _#lateStaticField1 = null;
   static field core::int? lateStaticField2Init = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? lateInstanceFieldInit = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  generic-covariant-impl field self::Class::T? lateGenericFieldInit = null;
+  final field self::Class::T% field;
+  field self::Class::T? _#lateGenericField = null;
+  field core::bool _#lateGenericField#isSet = false;
+  constructor •(self::Class::T% field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method initLateStaticField1(core::int value) → core::int {
     return self::Class::lateStaticField1Init = value;
@@ -32,13 +36,26 @@
   }
   get lateInstanceField() → core::int
     return let final core::int? #t3 = this.{self::Class::_#lateInstanceField} in #t3.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = this.{self::Class::initLateInstanceField}(16) : #t3{core::int};
+  method initLateGenericField(generic-covariant-impl self::Class::T% value) → self::Class::T% {
+    return this.{self::Class::lateGenericFieldInit} = value;
+  }
+  get lateGenericField() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField#isSet}) {
+      this.{self::Class::_#lateGenericField#isSet} = true;
+      this.{self::Class::_#lateGenericField} = this.{self::Class::initLateGenericField}(this.{self::Class::field});
+    }
+    return let final self::Class::T? #t4 = this.{self::Class::_#lateGenericField} in #t4{self::Class::T%};
+  }
   method instanceMethod() → dynamic {
     self::expect(null, this.{self::Class::lateInstanceFieldInit});
     self::expect(16, this.{self::Class::lateInstanceField});
     self::expect(16, this.{self::Class::lateInstanceFieldInit});
+    self::expect(null, this.{self::Class::lateGenericFieldInit});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericFieldInit});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
@@ -59,17 +76,17 @@
   return self::lateTopLevelField1Init = value;
 }
 static get lateTopLevelField1() → core::int
-  return let final core::int? #t4 = self::_#lateTopLevelField1 in #t4.==(null) ?{core::int} self::_#lateTopLevelField1 = self::initLateTopLevelField1(123) : #t4{core::int};
+  return let final core::int? #t5 = self::_#lateTopLevelField1 in #t5.==(null) ?{core::int} self::_#lateTopLevelField1 = self::initLateTopLevelField1(123) : #t5{core::int};
 static method Extension|initLateExtensionField1(core::int value) → core::int {
   return self::Extension|lateExtensionField1Init = value;
 }
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t5 = self::_#Extension|lateExtensionField1 in #t5.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = self::Extension|initLateExtensionField1(87) : #t5{core::int};
+  return let final core::int? #t6 = self::_#Extension|lateExtensionField1 in #t6.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = self::Extension|initLateExtensionField1(87) : #t6{core::int};
 static method Extension|initLateExtensionField2(core::int value) → core::int {
   return self::Extension|lateExtensionField2Init = value;
 }
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t6 = self::_#Extension|lateExtensionField2 in #t6.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = self::Extension|initLateExtensionField2(42) : #t6{core::int};
+  return let final core::int? #t7 = self::_#Extension|lateExtensionField2 in #t7.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = self::Extension|initLateExtensionField2(42) : #t7{core::int};
 static method Extension|staticMethod() → dynamic {
   self::expect(null, self::Extension|lateExtensionField2Init);
   self::expect(42, self::Extension|lateExtensionField2);
@@ -83,7 +100,7 @@
   self::expect(87, self::Class::lateStaticField1);
   self::expect(87, self::Class::lateStaticField1Init);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}();
   self::expect(null, self::Extension|lateExtensionField1Init);
   self::expect(87, self::Extension|lateExtensionField1);
   self::expect(87, self::Extension|lateExtensionField1Init);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect
index 67e2378..6f2bab2 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect
@@ -2,15 +2,19 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init = null;
   static field core::int? _#lateStaticField1 = null;
   static field core::int? lateStaticField2Init = null;
   static field core::int? _#lateStaticField2 = null;
   field core::int? lateInstanceFieldInit = null;
   field core::int? _#lateInstanceField = null;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  generic-covariant-impl field self::Class::T? lateGenericFieldInit = null;
+  final field self::Class::T% field;
+  field self::Class::T? _#lateGenericField = null;
+  field core::bool _#lateGenericField#isSet = false;
+  constructor •(self::Class::T% field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method initLateStaticField1(core::int value) → core::int {
     return self::Class::lateStaticField1Init = value;
@@ -32,13 +36,26 @@
   }
   get lateInstanceField() → core::int
     return let final core::int? #t3 = this.{self::Class::_#lateInstanceField} in #t3.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = this.{self::Class::initLateInstanceField}(16) : #t3{core::int};
+  method initLateGenericField(generic-covariant-impl self::Class::T% value) → self::Class::T% {
+    return this.{self::Class::lateGenericFieldInit} = value;
+  }
+  get lateGenericField() → self::Class::T% {
+    if(!this.{self::Class::_#lateGenericField#isSet}) {
+      this.{self::Class::_#lateGenericField#isSet} = true;
+      this.{self::Class::_#lateGenericField} = this.{self::Class::initLateGenericField}(this.{self::Class::field});
+    }
+    return let final self::Class::T? #t4 = this.{self::Class::_#lateGenericField} in #t4{self::Class::T%};
+  }
   method instanceMethod() → dynamic {
     self::expect(null, this.{self::Class::lateInstanceFieldInit});
     self::expect(16, this.{self::Class::lateInstanceField});
     self::expect(16, this.{self::Class::lateInstanceFieldInit});
+    self::expect(null, this.{self::Class::lateGenericFieldInit});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericFieldInit});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
@@ -59,17 +76,17 @@
   return self::lateTopLevelField1Init = value;
 }
 static get lateTopLevelField1() → core::int
-  return let final core::int? #t4 = self::_#lateTopLevelField1 in #t4.==(null) ?{core::int} self::_#lateTopLevelField1 = self::initLateTopLevelField1(123) : #t4{core::int};
+  return let final core::int? #t5 = self::_#lateTopLevelField1 in #t5.==(null) ?{core::int} self::_#lateTopLevelField1 = self::initLateTopLevelField1(123) : #t5{core::int};
 static method Extension|initLateExtensionField1(core::int value) → core::int {
   return self::Extension|lateExtensionField1Init = value;
 }
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t5 = self::_#Extension|lateExtensionField1 in #t5.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = self::Extension|initLateExtensionField1(87) : #t5{core::int};
+  return let final core::int? #t6 = self::_#Extension|lateExtensionField1 in #t6.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = self::Extension|initLateExtensionField1(87) : #t6{core::int};
 static method Extension|initLateExtensionField2(core::int value) → core::int {
   return self::Extension|lateExtensionField2Init = value;
 }
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t6 = self::_#Extension|lateExtensionField2 in #t6.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = self::Extension|initLateExtensionField2(42) : #t6{core::int};
+  return let final core::int? #t7 = self::_#Extension|lateExtensionField2 in #t7.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = self::Extension|initLateExtensionField2(42) : #t7{core::int};
 static method Extension|staticMethod() → dynamic {
   self::expect(null, self::Extension|lateExtensionField2Init);
   self::expect(42, self::Extension|lateExtensionField2);
@@ -83,7 +100,7 @@
   self::expect(87, self::Class::lateStaticField1);
   self::expect(87, self::Class::lateStaticField1Init);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}();
   self::expect(null, self::Extension|lateExtensionField1Init);
   self::expect(87, self::Extension|lateExtensionField1);
   self::expect(87, self::Extension|lateExtensionField1Init);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart
index d2a2bd7..4cbc166 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart
@@ -13,6 +13,23 @@
   expect(null, lateLocalInit);
   expect(123, lateLocal);
   expect(123, lateLocalInit);
+
+  local<T>(T value) {
+    T? lateGenericLocalInit;
+    T initLateGenericLocal(T value) {
+      return lateGenericLocalInit = value;
+    }
+
+    late final T lateGenericLocal = initLateGenericLocal(value);
+
+    expect(null, lateGenericLocalInit);
+    expect(value, lateGenericLocal);
+    expect(value, lateGenericLocalInit);
+  }
+
+  local<int?>(null);
+  local<int?>(42);
+  local<int>(42);
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect
index 3c9d2c6..3ccf892 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect
@@ -13,6 +13,27 @@
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    T? lateGenericLocalInit;
+    function initLateGenericLocal(T% value) → T% {
+      return lateGenericLocalInit = value;
+    }
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T% {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = initLateGenericLocal.call(value);
+      }
+      return lateGenericLocal{T%};
+    }
+    self::expect(null, lateGenericLocalInit);
+    self::expect(value, #lateGenericLocal#get.call());
+    self::expect(value, lateGenericLocalInit);
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect
index 3c9d2c6..3ccf892 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect
@@ -13,6 +13,27 @@
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    T? lateGenericLocalInit;
+    function initLateGenericLocal(T% value) → T% {
+      return lateGenericLocalInit = value;
+    }
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T% {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = initLateGenericLocal.call(value);
+      }
+      return lateGenericLocal{T%};
+    }
+    self::expect(null, lateGenericLocalInit);
+    self::expect(value, #lateGenericLocal#get.call());
+    self::expect(value, lateGenericLocalInit);
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
index 3c9d2c6..3ccf892 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
@@ -13,6 +13,27 @@
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    T? lateGenericLocalInit;
+    function initLateGenericLocal(T% value) → T% {
+      return lateGenericLocalInit = value;
+    }
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T% {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = initLateGenericLocal.call(value);
+      }
+      return lateGenericLocal{T%};
+    }
+    self::expect(null, lateGenericLocalInit);
+    self::expect(value, #lateGenericLocal#get.call());
+    self::expect(value, lateGenericLocalInit);
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
index 3c9d2c6..3ccf892 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
@@ -13,6 +13,27 @@
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    T? lateGenericLocalInit;
+    function initLateGenericLocal(T% value) → T% {
+      return lateGenericLocalInit = value;
+    }
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T% {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = initLateGenericLocal.call(value);
+      }
+      return lateGenericLocal{T%};
+    }
+    self::expect(null, lateGenericLocalInit);
+    self::expect(value, #lateGenericLocal#get.call());
+    self::expect(value, lateGenericLocalInit);
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart
index 33f43cb..e0d1275 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart
@@ -9,6 +9,21 @@
   expect(123, lateLocal = 123);
   expect(123, lateLocal);
   throws(() => lateLocal = 124, 'Write value to initialized lateLocal');
+
+  local<T>(T value) {
+    late final T lateGenericLocal;
+
+    throws(() => lateGenericLocal,
+        'Read value from uninitialized lateGenericLocal');
+    expect(value, lateGenericLocal = value);
+    expect(value, lateGenericLocal);
+    throws(() => lateGenericLocal = value,
+        'Write value to initialized lateGenericLocal');
+  }
+
+  local<int?>(null);
+  local<int?>(42);
+  local<int>(42);
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
index e918f09..4719f92 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
@@ -16,6 +16,26 @@
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T%
+      return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T% #t3) → dynamic
+      if(#lateGenericLocal#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has already been initialized.");
+      else {
+        #lateGenericLocal#isSet = true;
+        return lateGenericLocal = #t3;
+      }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+    self::throws(() → T% => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
index e918f09..4719f92 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
@@ -16,6 +16,26 @@
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T%
+      return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T% #t3) → dynamic
+      if(#lateGenericLocal#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has already been initialized.");
+      else {
+        #lateGenericLocal#isSet = true;
+        return lateGenericLocal = #t3;
+      }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+    self::throws(() → T% => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
index e918f09..4719f92 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
@@ -16,6 +16,26 @@
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T%
+      return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T% #t3) → dynamic
+      if(#lateGenericLocal#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has already been initialized.");
+      else {
+        #lateGenericLocal#isSet = true;
+        return lateGenericLocal = #t3;
+      }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+    self::throws(() → T% => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
index e918f09..4719f92 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
@@ -16,6 +16,26 @@
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T%
+      return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T% #t3) → dynamic
+      if(#lateGenericLocal#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has already been initialized.");
+      else {
+        #lateGenericLocal#isSet = true;
+        return lateGenericLocal = #t3;
+      }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+    self::throws(() → T% => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart
index 04dbcab..92b4b25 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart
@@ -9,7 +9,7 @@
 
 late final int? lateTopLevelField1 = initLateTopLevelField1(123);
 
-class Class {
+class Class<T> {
   static int? lateStaticField1Init;
   static int? initLateStaticField1(int value) {
     return lateStaticField1Init = value;
@@ -37,14 +37,28 @@
 
   late final int? lateInstanceField = initLateInstanceField(16);
 
+  T? lateGenericInstanceFieldInit;
+  T? initLateGenericInstanceField(T? value) {
+    return lateGenericInstanceFieldInit = value;
+  }
+
+  final T? field;
+  late final T? lateGenericInstanceField = initLateGenericInstanceField(field);
+
+  Class(this.field);
+
   instanceMethod() {
     expect(null, lateInstanceFieldInit);
     expect(16, lateInstanceField);
     expect(16, lateInstanceFieldInit);
+
+    expect(null, lateGenericInstanceFieldInit);
+    expect(field, lateGenericInstanceField);
+    expect(field, lateGenericInstanceFieldInit);
   }
 }
 
-extension Extension on Class {
+extension Extension<T> on Class<T> {
   static int? lateExtensionField1Init;
   static int? initLateExtensionField1(int value) {
     return lateExtensionField1Init = value;
@@ -76,7 +90,9 @@
   expect(87, Class.lateStaticField1Init);
 
   Class.staticMethod();
-  new Class().instanceMethod();
+  new Class<int?>(null).instanceMethod();
+  new Class<int?>(0).instanceMethod();
+  new Class<int>(0).instanceMethod();
 
   expect(null, Extension.lateExtensionField1Init);
   expect(87, Extension.lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.outline.expect
index e6fb499..8938ef7 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.outline.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init;
   static field core::int? _#lateStaticField1;
   static field core::bool _#lateStaticField1#isSet;
@@ -12,7 +12,11 @@
   field core::int? lateInstanceFieldInit;
   field core::int? _#lateInstanceField;
   field core::bool _#lateInstanceField#isSet;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? lateGenericInstanceFieldInit;
+  final field self::Class::T? field;
+  field self::Class::T? _#lateGenericInstanceField;
+  field core::bool _#lateGenericInstanceField#isSet;
+  constructor •(self::Class::T? field) → self::Class<self::Class::T%>
     ;
   static method initLateStaticField1(core::int value) → core::int?
     ;
@@ -25,10 +29,13 @@
   method initLateInstanceField(core::int value) → core::int?
     ;
   get lateInstanceField() → core::int?;
+  method initLateGenericInstanceField(generic-covariant-impl self::Class::T? value) → self::Class::T?
+    ;
+  get lateGenericInstanceField() → self::Class::T?;
   method instanceMethod() → dynamic
     ;
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.expect
index 6bcc89e..92df976 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init = null;
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
@@ -12,8 +12,12 @@
   field core::int? lateInstanceFieldInit = null;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  generic-covariant-impl field self::Class::T? lateGenericInstanceFieldInit = null;
+  final field self::Class::T? field;
+  field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  constructor •(self::Class::T? field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method initLateStaticField1(core::int value) → core::int? {
     return self::Class::lateStaticField1Init = value;
@@ -50,13 +54,26 @@
     }
     return this.{self::Class::_#lateInstanceField};
   }
+  method initLateGenericInstanceField(generic-covariant-impl self::Class::T? value) → self::Class::T? {
+    return this.{self::Class::lateGenericInstanceFieldInit} = value;
+  }
+  get lateGenericInstanceField() → self::Class::T? {
+    if(!this.{self::Class::_#lateGenericInstanceField#isSet}) {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = this.{self::Class::initLateGenericInstanceField}(this.{self::Class::field});
+    }
+    return this.{self::Class::_#lateGenericInstanceField};
+  }
   method instanceMethod() → dynamic {
     self::expect(null, this.{self::Class::lateInstanceFieldInit});
     self::expect(16, this.{self::Class::lateInstanceField});
     self::expect(16, this.{self::Class::lateInstanceFieldInit});
+    self::expect(null, this.{self::Class::lateGenericInstanceFieldInit});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceFieldInit});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
@@ -121,7 +138,9 @@
   self::expect(87, self::Class::lateStaticField1);
   self::expect(87, self::Class::lateStaticField1Init);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(null).{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(0).{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}();
   self::expect(null, self::Extension|lateExtensionField1Init);
   self::expect(87, self::Extension|lateExtensionField1);
   self::expect(87, self::Extension|lateExtensionField1Init);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.transformed.expect
index 6bcc89e..92df976 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init = null;
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
@@ -12,8 +12,12 @@
   field core::int? lateInstanceFieldInit = null;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  generic-covariant-impl field self::Class::T? lateGenericInstanceFieldInit = null;
+  final field self::Class::T? field;
+  field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  constructor •(self::Class::T? field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method initLateStaticField1(core::int value) → core::int? {
     return self::Class::lateStaticField1Init = value;
@@ -50,13 +54,26 @@
     }
     return this.{self::Class::_#lateInstanceField};
   }
+  method initLateGenericInstanceField(generic-covariant-impl self::Class::T? value) → self::Class::T? {
+    return this.{self::Class::lateGenericInstanceFieldInit} = value;
+  }
+  get lateGenericInstanceField() → self::Class::T? {
+    if(!this.{self::Class::_#lateGenericInstanceField#isSet}) {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = this.{self::Class::initLateGenericInstanceField}(this.{self::Class::field});
+    }
+    return this.{self::Class::_#lateGenericInstanceField};
+  }
   method instanceMethod() → dynamic {
     self::expect(null, this.{self::Class::lateInstanceFieldInit});
     self::expect(16, this.{self::Class::lateInstanceField});
     self::expect(16, this.{self::Class::lateInstanceFieldInit});
+    self::expect(null, this.{self::Class::lateGenericInstanceFieldInit});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceFieldInit});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
@@ -121,7 +138,9 @@
   self::expect(87, self::Class::lateStaticField1);
   self::expect(87, self::Class::lateStaticField1Init);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(null).{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(0).{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}();
   self::expect(null, self::Extension|lateExtensionField1Init);
   self::expect(87, self::Extension|lateExtensionField1);
   self::expect(87, self::Extension|lateExtensionField1Init);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.expect
index 6bcc89e..92df976 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init = null;
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
@@ -12,8 +12,12 @@
   field core::int? lateInstanceFieldInit = null;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  generic-covariant-impl field self::Class::T? lateGenericInstanceFieldInit = null;
+  final field self::Class::T? field;
+  field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  constructor •(self::Class::T? field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method initLateStaticField1(core::int value) → core::int? {
     return self::Class::lateStaticField1Init = value;
@@ -50,13 +54,26 @@
     }
     return this.{self::Class::_#lateInstanceField};
   }
+  method initLateGenericInstanceField(generic-covariant-impl self::Class::T? value) → self::Class::T? {
+    return this.{self::Class::lateGenericInstanceFieldInit} = value;
+  }
+  get lateGenericInstanceField() → self::Class::T? {
+    if(!this.{self::Class::_#lateGenericInstanceField#isSet}) {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = this.{self::Class::initLateGenericInstanceField}(this.{self::Class::field});
+    }
+    return this.{self::Class::_#lateGenericInstanceField};
+  }
   method instanceMethod() → dynamic {
     self::expect(null, this.{self::Class::lateInstanceFieldInit});
     self::expect(16, this.{self::Class::lateInstanceField});
     self::expect(16, this.{self::Class::lateInstanceFieldInit});
+    self::expect(null, this.{self::Class::lateGenericInstanceFieldInit});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceFieldInit});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
@@ -121,7 +138,9 @@
   self::expect(87, self::Class::lateStaticField1);
   self::expect(87, self::Class::lateStaticField1Init);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(null).{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(0).{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}();
   self::expect(null, self::Extension|lateExtensionField1Init);
   self::expect(87, self::Extension|lateExtensionField1);
   self::expect(87, self::Extension|lateExtensionField1Init);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.transformed.expect
index 6bcc89e..92df976 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.weak.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init = null;
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
@@ -12,8 +12,12 @@
   field core::int? lateInstanceFieldInit = null;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  generic-covariant-impl field self::Class::T? lateGenericInstanceFieldInit = null;
+  final field self::Class::T? field;
+  field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  constructor •(self::Class::T? field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method initLateStaticField1(core::int value) → core::int? {
     return self::Class::lateStaticField1Init = value;
@@ -50,13 +54,26 @@
     }
     return this.{self::Class::_#lateInstanceField};
   }
+  method initLateGenericInstanceField(generic-covariant-impl self::Class::T? value) → self::Class::T? {
+    return this.{self::Class::lateGenericInstanceFieldInit} = value;
+  }
+  get lateGenericInstanceField() → self::Class::T? {
+    if(!this.{self::Class::_#lateGenericInstanceField#isSet}) {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = this.{self::Class::initLateGenericInstanceField}(this.{self::Class::field});
+    }
+    return this.{self::Class::_#lateGenericInstanceField};
+  }
   method instanceMethod() → dynamic {
     self::expect(null, this.{self::Class::lateInstanceFieldInit});
     self::expect(16, this.{self::Class::lateInstanceField});
     self::expect(16, this.{self::Class::lateInstanceFieldInit});
+    self::expect(null, this.{self::Class::lateGenericInstanceFieldInit});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceFieldInit});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
@@ -121,7 +138,9 @@
   self::expect(87, self::Class::lateStaticField1);
   self::expect(87, self::Class::lateStaticField1Init);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(null).{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(0).{self::Class::instanceMethod}();
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}();
   self::expect(null, self::Extension|lateExtensionField1Init);
   self::expect(87, self::Extension|lateExtensionField1);
   self::expect(87, self::Extension|lateExtensionField1Init);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart
index 1493ede..9967557 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart
@@ -4,7 +4,7 @@
 
 late final int? lateTopLevelField;
 
-class Class {
+class Class<T> {
   static late final int? lateStaticField1;
   static late final int? lateStaticField2;
 
@@ -19,17 +19,26 @@
 
   late final int? lateInstanceField;
 
-  instanceMethod() {
+  late final T? lateGenericInstanceField;
+
+  instanceMethod(T value) {
     throws(() => lateInstanceField,
         'Read value from uninitialized Class.lateInstanceField');
     lateInstanceField = 16;
     expect(16, lateInstanceField);
     throws(() => lateInstanceField = 17,
         'Write value to initialized Class.lateInstanceField');
+
+    throws(() => lateGenericInstanceField,
+        'Read value from uninitialized Class.lateGenericInstanceField');
+    lateGenericInstanceField = value;
+    expect(value, lateGenericInstanceField);
+    throws(() => lateGenericInstanceField = value,
+        'Write value to initialized Class.lateGenericInstanceField');
   }
 }
 
-extension Extension on Class {
+extension Extension<T> on Class<T> {
   static late final int? lateExtensionField1;
   static late final int? lateExtensionField2;
 
@@ -59,7 +68,9 @@
       'Write value to initialized Class.lateStaticField1');
 
   Class.staticMethod();
-  new Class().instanceMethod();
+  new Class<int?>().instanceMethod(null);
+  new Class<int?>().instanceMethod(0);
+  new Class<int>().instanceMethod(0);
 
   throws(() => Extension.lateExtensionField1,
       'Read value from uninitialized Extension.lateExtensionField1');
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.outline.expect
index bc1aaf1..aeb9eb7 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.outline.expect
@@ -2,14 +2,16 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1;
   static field core::bool _#lateStaticField1#isSet;
   static field core::int? _#lateStaticField2;
   static field core::bool _#lateStaticField2#isSet;
   field core::int? _#lateInstanceField;
   field core::bool _#lateInstanceField#isSet;
-  synthetic constructor •() → self::Class
+  field self::Class::T? _#lateGenericInstanceField;
+  field core::bool _#lateGenericInstanceField#isSet;
+  synthetic constructor •() → self::Class<self::Class::T%>
     ;
   static get lateStaticField1() → core::int?;
   static set lateStaticField1(core::int? #t1) → void;
@@ -19,10 +21,12 @@
     ;
   get lateInstanceField() → core::int?;
   set lateInstanceField(core::int? #t3) → void;
-  method instanceMethod() → dynamic
+  get lateGenericInstanceField() → self::Class::T?;
+  set lateGenericInstanceField(self::Class::T? #t4) → void;
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic
     ;
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
@@ -40,11 +44,11 @@
 static field core::int? _#Extension|lateExtensionField2;
 static field core::bool _#Extension|lateExtensionField2#isSet;
 static get lateTopLevelField() → core::int?;
-static set lateTopLevelField(core::int? #t4) → void;
+static set lateTopLevelField(core::int? #t5) → void;
 static get Extension|lateExtensionField1() → core::int?;
-static set Extension|lateExtensionField1(core::int? #t5) → void;
+static set Extension|lateExtensionField1(core::int? #t6) → void;
 static get Extension|lateExtensionField2() → core::int?;
-static set Extension|lateExtensionField2(core::int? #t6) → void;
+static set Extension|lateExtensionField2(core::int? #t7) → void;
 static method Extension|staticMethod() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
index ca3128d..987bda1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
@@ -3,14 +3,16 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
+  field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int?
@@ -46,14 +48,27 @@
       this.{self::Class::_#lateInstanceField#isSet} = true;
       this.{self::Class::_#lateInstanceField} = #t3;
     }
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T?
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T? #t4) → void
+    if(this.{self::Class::_#lateGenericInstanceField#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has already been initialized.");
+    else {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = #t4;
+    }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
     self::throws(() → core::int => this.{self::Class::lateInstanceField} = 17, "Write value to initialized Class.lateInstanceField");
+    self::throws(() → self::Class::T? => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
+    self::throws(() → self::Class::T% => this.{self::Class::lateGenericInstanceField} = value, "Write value to initialized Class.lateGenericInstanceField");
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
@@ -72,30 +87,30 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
-static set lateTopLevelField(core::int? #t4) → void
+static set lateTopLevelField(core::int? #t5) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has already been initialized.");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t4;
+    self::_#lateTopLevelField = #t5;
   }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
-static set Extension|lateExtensionField1(core::int? #t5) → void
+static set Extension|lateExtensionField1(core::int? #t6) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has already been initialized.");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t5;
+    self::_#Extension|lateExtensionField1 = #t6;
   }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
-static set Extension|lateExtensionField2(core::int? #t6) → void
+static set Extension|lateExtensionField2(core::int? #t7) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has already been initialized.");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t6;
+    self::_#Extension|lateExtensionField2 = #t7;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
@@ -113,7 +128,9 @@
   self::expect(87, self::Class::lateStaticField1);
   self::throws(() → core::int => self::Class::lateStaticField1 = 88, "Write value to initialized Class.lateStaticField1");
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
   self::throws(() → core::int? => self::Extension|lateExtensionField1, "Read value from uninitialized Extension.lateExtensionField1");
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
index ca3128d..987bda1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -3,14 +3,16 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
+  field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int?
@@ -46,14 +48,27 @@
       this.{self::Class::_#lateInstanceField#isSet} = true;
       this.{self::Class::_#lateInstanceField} = #t3;
     }
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T?
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T? #t4) → void
+    if(this.{self::Class::_#lateGenericInstanceField#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has already been initialized.");
+    else {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = #t4;
+    }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
     self::throws(() → core::int => this.{self::Class::lateInstanceField} = 17, "Write value to initialized Class.lateInstanceField");
+    self::throws(() → self::Class::T? => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
+    self::throws(() → self::Class::T% => this.{self::Class::lateGenericInstanceField} = value, "Write value to initialized Class.lateGenericInstanceField");
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
@@ -72,30 +87,30 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
-static set lateTopLevelField(core::int? #t4) → void
+static set lateTopLevelField(core::int? #t5) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has already been initialized.");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t4;
+    self::_#lateTopLevelField = #t5;
   }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
-static set Extension|lateExtensionField1(core::int? #t5) → void
+static set Extension|lateExtensionField1(core::int? #t6) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has already been initialized.");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t5;
+    self::_#Extension|lateExtensionField1 = #t6;
   }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
-static set Extension|lateExtensionField2(core::int? #t6) → void
+static set Extension|lateExtensionField2(core::int? #t7) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has already been initialized.");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t6;
+    self::_#Extension|lateExtensionField2 = #t7;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
@@ -113,7 +128,9 @@
   self::expect(87, self::Class::lateStaticField1);
   self::throws(() → core::int => self::Class::lateStaticField1 = 88, "Write value to initialized Class.lateStaticField1");
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
   self::throws(() → core::int? => self::Extension|lateExtensionField1, "Read value from uninitialized Extension.lateExtensionField1");
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
index ca3128d..987bda1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
@@ -3,14 +3,16 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
+  field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int?
@@ -46,14 +48,27 @@
       this.{self::Class::_#lateInstanceField#isSet} = true;
       this.{self::Class::_#lateInstanceField} = #t3;
     }
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T?
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T? #t4) → void
+    if(this.{self::Class::_#lateGenericInstanceField#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has already been initialized.");
+    else {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = #t4;
+    }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
     self::throws(() → core::int => this.{self::Class::lateInstanceField} = 17, "Write value to initialized Class.lateInstanceField");
+    self::throws(() → self::Class::T? => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
+    self::throws(() → self::Class::T% => this.{self::Class::lateGenericInstanceField} = value, "Write value to initialized Class.lateGenericInstanceField");
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
@@ -72,30 +87,30 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
-static set lateTopLevelField(core::int? #t4) → void
+static set lateTopLevelField(core::int? #t5) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has already been initialized.");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t4;
+    self::_#lateTopLevelField = #t5;
   }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
-static set Extension|lateExtensionField1(core::int? #t5) → void
+static set Extension|lateExtensionField1(core::int? #t6) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has already been initialized.");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t5;
+    self::_#Extension|lateExtensionField1 = #t6;
   }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
-static set Extension|lateExtensionField2(core::int? #t6) → void
+static set Extension|lateExtensionField2(core::int? #t7) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has already been initialized.");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t6;
+    self::_#Extension|lateExtensionField2 = #t7;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
@@ -113,7 +128,9 @@
   self::expect(87, self::Class::lateStaticField1);
   self::throws(() → core::int => self::Class::lateStaticField1 = 88, "Write value to initialized Class.lateStaticField1");
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
   self::throws(() → core::int? => self::Extension|lateExtensionField1, "Read value from uninitialized Extension.lateExtensionField1");
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
index ca3128d..987bda1 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -3,14 +3,16 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
+  field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int?
@@ -46,14 +48,27 @@
       this.{self::Class::_#lateInstanceField#isSet} = true;
       this.{self::Class::_#lateInstanceField} = #t3;
     }
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T?
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T? #t4) → void
+    if(this.{self::Class::_#lateGenericInstanceField#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has already been initialized.");
+    else {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = #t4;
+    }
+  method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
     self::throws(() → core::int => this.{self::Class::lateInstanceField} = 17, "Write value to initialized Class.lateInstanceField");
+    self::throws(() → self::Class::T? => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
+    self::throws(() → self::Class::T% => this.{self::Class::lateGenericInstanceField} = value, "Write value to initialized Class.lateGenericInstanceField");
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
@@ -72,30 +87,30 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
-static set lateTopLevelField(core::int? #t4) → void
+static set lateTopLevelField(core::int? #t5) → void
   if(self::_#lateTopLevelField#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has already been initialized.");
   else {
     self::_#lateTopLevelField#isSet = true;
-    self::_#lateTopLevelField = #t4;
+    self::_#lateTopLevelField = #t5;
   }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
-static set Extension|lateExtensionField1(core::int? #t5) → void
+static set Extension|lateExtensionField1(core::int? #t6) → void
   if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has already been initialized.");
   else {
     self::_#Extension|lateExtensionField1#isSet = true;
-    self::_#Extension|lateExtensionField1 = #t5;
+    self::_#Extension|lateExtensionField1 = #t6;
   }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
-static set Extension|lateExtensionField2(core::int? #t6) → void
+static set Extension|lateExtensionField2(core::int? #t7) → void
   if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has already been initialized.");
   else {
     self::_#Extension|lateExtensionField2#isSet = true;
-    self::_#Extension|lateExtensionField2 = #t6;
+    self::_#Extension|lateExtensionField2 = #t7;
   }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
@@ -113,7 +128,9 @@
   self::expect(87, self::Class::lateStaticField1);
   self::throws(() → core::int => self::Class::lateStaticField1 = 88, "Write value to initialized Class.lateStaticField1");
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
   self::throws(() → core::int? => self::Extension|lateExtensionField1, "Read value from uninitialized Extension.lateExtensionField1");
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart
index 778e612..8161ba2 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart
@@ -13,6 +13,23 @@
   expect(null, lateLocalInit);
   expect(123, lateLocal);
   expect(123, lateLocalInit);
+
+  local<T>(T? value) {
+    T? lateGenericLocalInit;
+    T? initLateGenericLocal(T? value) {
+      return lateGenericLocalInit = value;
+    }
+
+    late final T? lateGenericLocal = initLateGenericLocal(value);
+
+    expect(null, lateGenericLocalInit);
+    expect(value, lateGenericLocal);
+    expect(value, lateGenericLocalInit);
+  }
+
+  local<int?>(null);
+  local<int?>(42);
+  local<int>(42);
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect
index f019032..c925621 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect
@@ -19,6 +19,27 @@
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    T? lateGenericLocalInit;
+    function initLateGenericLocal(T? value) → T? {
+      return lateGenericLocalInit = value;
+    }
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T? {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = initLateGenericLocal.call(value);
+      }
+      return lateGenericLocal;
+    }
+    self::expect(null, lateGenericLocalInit);
+    self::expect(value, #lateGenericLocal#get.call());
+    self::expect(value, lateGenericLocalInit);
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect
index f019032..c925621 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect
@@ -19,6 +19,27 @@
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    T? lateGenericLocalInit;
+    function initLateGenericLocal(T? value) → T? {
+      return lateGenericLocalInit = value;
+    }
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T? {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = initLateGenericLocal.call(value);
+      }
+      return lateGenericLocal;
+    }
+    self::expect(null, lateGenericLocalInit);
+    self::expect(value, #lateGenericLocal#get.call());
+    self::expect(value, lateGenericLocalInit);
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect
index f019032..c925621 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.expect
@@ -19,6 +19,27 @@
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    T? lateGenericLocalInit;
+    function initLateGenericLocal(T? value) → T? {
+      return lateGenericLocalInit = value;
+    }
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T? {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = initLateGenericLocal.call(value);
+      }
+      return lateGenericLocal;
+    }
+    self::expect(null, lateGenericLocalInit);
+    self::expect(value, #lateGenericLocal#get.call());
+    self::expect(value, lateGenericLocalInit);
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect
index f019032..c925621 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.weak.transformed.expect
@@ -19,6 +19,27 @@
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    T? lateGenericLocalInit;
+    function initLateGenericLocal(T? value) → T? {
+      return lateGenericLocalInit = value;
+    }
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T? {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = initLateGenericLocal.call(value);
+      }
+      return lateGenericLocal;
+    }
+    self::expect(null, lateGenericLocalInit);
+    self::expect(value, #lateGenericLocal#get.call());
+    self::expect(value, lateGenericLocalInit);
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(42);
+  local.call<core::int>(42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart
index cfa53bc..3ee8c4b 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart
@@ -9,6 +9,22 @@
   expect(123, lateLocal = 123);
   expect(123, lateLocal);
   throws(() => lateLocal = 124, 'Write value to initialized lateLocal');
+
+  local<T>(T? value) {
+    late final T? lateGenericLocal;
+
+    throws(() => lateGenericLocal,
+        'Read value from uninitialized lateGenericLocal');
+    expect(value, lateGenericLocal = value);
+    expect(value, lateGenericLocal);
+    throws(() => lateGenericLocal = value,
+        'Write value to initialized lateGenericLocal');
+  }
+
+  local<int?>(null);
+  local<int?>(0);
+  local<int>(null);
+  local<int>(0);
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
index 268b399..d623c5e 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
@@ -19,6 +19,27 @@
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T?
+      return #lateGenericLocal#isSet ?{T?} lateGenericLocal : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T? #t2) → dynamic
+      if(#lateGenericLocal#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has already been initialized.");
+      else {
+        #lateGenericLocal#isSet = true;
+        return lateGenericLocal = #t2;
+      }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+    self::throws(() → T? => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(null);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
index 268b399..d623c5e 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
@@ -19,6 +19,27 @@
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T?
+      return #lateGenericLocal#isSet ?{T?} lateGenericLocal : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T? #t2) → dynamic
+      if(#lateGenericLocal#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has already been initialized.");
+      else {
+        #lateGenericLocal#isSet = true;
+        return lateGenericLocal = #t2;
+      }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+    self::throws(() → T? => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(null);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
index 268b399..d623c5e 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
@@ -19,6 +19,27 @@
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T?
+      return #lateGenericLocal#isSet ?{T?} lateGenericLocal : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T? #t2) → dynamic
+      if(#lateGenericLocal#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has already been initialized.");
+      else {
+        #lateGenericLocal#isSet = true;
+        return lateGenericLocal = #t2;
+      }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+    self::throws(() → T? => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(null);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
index 268b399..d623c5e 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
@@ -19,6 +19,27 @@
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    final T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T?
+      return #lateGenericLocal#isSet ?{T?} lateGenericLocal : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T? #t2) → dynamic
+      if(#lateGenericLocal#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has already been initialized.");
+      else {
+        #lateGenericLocal#isSet = true;
+        return lateGenericLocal = #t2;
+      }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+    self::throws(() → T? => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(null);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart
index 6363618..489af50 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart
@@ -8,6 +8,18 @@
   expect(123, lateLocal);
   expect(124, lateLocal = 124);
   expect(124, lateLocal);
+
+  local<T>(T value1, T value2) {
+    late T lateGenericLocal = value1;
+
+    expect(value1, lateGenericLocal);
+    expect(value2, lateGenericLocal = value2);
+    expect(value2, lateGenericLocal);
+  }
+
+  local<int?>(null, 0);
+  local<int?>(0, null);
+  local<int>(0, 42);
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect
index 5633dbf..363c922 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect
@@ -11,6 +11,27 @@
   self::expect(123, #lateLocal#get.call());
   self::expect(124, #lateLocal#set.call(124));
   self::expect(124, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T% value1, T% value2) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T% {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = value1;
+      }
+      return lateGenericLocal{T%};
+    }
+    function #lateGenericLocal#set(T% #t3) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t3;
+    }
+    self::expect(value1, #lateGenericLocal#get.call());
+    self::expect(value2, #lateGenericLocal#set.call(value2));
+    self::expect(value2, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null, 0);
+  local.call<core::int?>(0, null);
+  local.call<core::int>(0, 42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect
index 5633dbf..363c922 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect
@@ -11,6 +11,27 @@
   self::expect(123, #lateLocal#get.call());
   self::expect(124, #lateLocal#set.call(124));
   self::expect(124, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T% value1, T% value2) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T% {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = value1;
+      }
+      return lateGenericLocal{T%};
+    }
+    function #lateGenericLocal#set(T% #t3) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t3;
+    }
+    self::expect(value1, #lateGenericLocal#get.call());
+    self::expect(value2, #lateGenericLocal#set.call(value2));
+    self::expect(value2, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null, 0);
+  local.call<core::int?>(0, null);
+  local.call<core::int>(0, 42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
index 5633dbf..363c922 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
@@ -11,6 +11,27 @@
   self::expect(123, #lateLocal#get.call());
   self::expect(124, #lateLocal#set.call(124));
   self::expect(124, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T% value1, T% value2) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T% {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = value1;
+      }
+      return lateGenericLocal{T%};
+    }
+    function #lateGenericLocal#set(T% #t3) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t3;
+    }
+    self::expect(value1, #lateGenericLocal#get.call());
+    self::expect(value2, #lateGenericLocal#set.call(value2));
+    self::expect(value2, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null, 0);
+  local.call<core::int?>(0, null);
+  local.call<core::int>(0, 42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
index 5633dbf..363c922 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
@@ -11,6 +11,27 @@
   self::expect(123, #lateLocal#get.call());
   self::expect(124, #lateLocal#set.call(124));
   self::expect(124, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T% value1, T% value2) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T% {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = value1;
+      }
+      return lateGenericLocal{T%};
+    }
+    function #lateGenericLocal#set(T% #t3) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t3;
+    }
+    self::expect(value1, #lateGenericLocal#get.call());
+    self::expect(value2, #lateGenericLocal#set.call(value2));
+    self::expect(value2, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null, 0);
+  local.call<core::int?>(0, null);
+  local.call<core::int>(0, 42);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart
index 0cb0e98..819dc30 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart
@@ -7,6 +7,18 @@
   throws(() => lateLocal, 'Read value from uninitialized lateLocal');
   expect(123, lateLocal = 123);
   expect(123, lateLocal);
+
+  local<T>(T value) {
+    late T lateGenericLocal;
+    throws(() => lateGenericLocal,
+        'Read value from uninitialized lateGenericLocal');
+    expect(value, lateGenericLocal = value);
+    expect(value, lateGenericLocal);
+  }
+
+  local<int?>(null);
+  local<int?>(0);
+  local<int>(0);
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
index 26d533b..353612c 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
@@ -12,6 +12,22 @@
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T%
+      return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T% #t3) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t3;
+    }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
index 26d533b..353612c 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
@@ -12,6 +12,22 @@
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T%
+      return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T% #t3) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t3;
+    }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
index 26d533b..353612c 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
@@ -12,6 +12,22 @@
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T%
+      return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T% #t3) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t3;
+    }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
index 26d533b..353612c 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
@@ -12,6 +12,22 @@
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T% value) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T%
+      return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T% #t3) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t3;
+    }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart
index 9c90916..7d83dfe 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart
@@ -5,7 +5,7 @@
 int? lateTopLevelField1Init() => 123;
 late int? lateTopLevelField1 = lateTopLevelField1Init();
 
-class Class {
+class Class<T> {
   static int? lateStaticField1Init() => 87;
   static late int? lateStaticField1 = lateStaticField1Init();
   static int? lateStaticField2Init() => 42;
@@ -20,14 +20,24 @@
   int? lateInstanceFieldInit() => 16;
   late int? lateInstanceField = lateInstanceFieldInit();
 
-  instanceMethod() {
+  final T? field;
+  T? lateGenericInstanceFieldInit() => field;
+  late T? lateGenericInstanceField = lateGenericInstanceFieldInit();
+
+  Class(this.field);
+
+  instanceMethod(T? value) {
     expect(16, lateInstanceField);
     lateInstanceField = 17;
     expect(17, lateInstanceField);
+
+    expect(field, lateGenericInstanceField);
+    lateGenericInstanceField = value;
+    expect(value, lateGenericInstanceField);
   }
 }
 
-extension Extension on Class {
+extension Extension<T> on Class<T> {
   static int? lateExtensionField1Init() => 87;
   static late int? lateExtensionField1 = lateExtensionField1Init();
   static int? lateExtensionField2Init() => 42;
@@ -50,7 +60,10 @@
   expect(88, Class.lateStaticField1);
 
   Class.staticMethod();
-  new Class().instanceMethod();
+  new Class<int?>(null).instanceMethod(0);
+  new Class<int?>(0).instanceMethod(null);
+  new Class<int>(null).instanceMethod(0);
+  new Class<int>(0).instanceMethod(null);
 
   expect(87, Extension.lateExtensionField1);
   Extension.lateExtensionField1 = 88;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect
index 0e2d5ce..42a5d1b 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect
@@ -2,14 +2,17 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1;
   static field core::bool _#lateStaticField1#isSet;
   static field core::int? _#lateStaticField2;
   static field core::bool _#lateStaticField2#isSet;
   field core::int? _#lateInstanceField;
   field core::bool _#lateInstanceField#isSet;
-  synthetic constructor •() → self::Class
+  final field self::Class::T? field;
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField;
+  field core::bool _#lateGenericInstanceField#isSet;
+  constructor •(self::Class::T? field) → self::Class<self::Class::T%>
     ;
   static method lateStaticField1Init() → core::int?
     ;
@@ -25,10 +28,14 @@
     ;
   get lateInstanceField() → core::int?;
   set lateInstanceField(core::int? #t3) → void;
-  method instanceMethod() → dynamic
+  method lateGenericInstanceFieldInit() → self::Class::T?
+    ;
+  get lateGenericInstanceField() → self::Class::T?;
+  set lateGenericInstanceField(self::Class::T? #t4) → void;
+  method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic
     ;
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static method lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
@@ -50,15 +57,15 @@
 static method lateTopLevelField1Init() → core::int?
   ;
 static get lateTopLevelField1() → core::int?;
-static set lateTopLevelField1(core::int? #t4) → void;
+static set lateTopLevelField1(core::int? #t5) → void;
 static method Extension|lateExtensionField1Init() → core::int?
   ;
 static get Extension|lateExtensionField1() → core::int?;
-static set Extension|lateExtensionField1(core::int? #t5) → void;
+static set Extension|lateExtensionField1(core::int? #t6) → void;
 static method Extension|lateExtensionField2Init() → core::int?
   ;
 static get Extension|lateExtensionField2() → core::int?;
-static set Extension|lateExtensionField2(core::int? #t6) → void;
+static set Extension|lateExtensionField2(core::int? #t7) → void;
 static method Extension|staticMethod() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
index 9ee88bb..a90900a 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
@@ -2,15 +2,18 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  final field self::Class::T? field;
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  constructor •(self::Class::T? field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method lateStaticField1Init() → core::int?
     return 87;
@@ -56,13 +59,29 @@
     this.{self::Class::_#lateInstanceField#isSet} = true;
     this.{self::Class::_#lateInstanceField} = #t3;
   }
-  method instanceMethod() → dynamic {
+  method lateGenericInstanceFieldInit() → self::Class::T?
+    return this.{self::Class::field};
+  get lateGenericInstanceField() → self::Class::T? {
+    if(!this.{self::Class::_#lateGenericInstanceField#isSet}) {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = this.{self::Class::lateGenericInstanceFieldInit}();
+    }
+    return this.{self::Class::_#lateGenericInstanceField};
+  }
+  set lateGenericInstanceField(self::Class::T? #t4) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t4;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField});
     this.{self::Class::lateInstanceField} = 17;
     self::expect(17, this.{self::Class::lateInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceField});
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static method lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
@@ -90,9 +109,9 @@
   }
   return self::_#lateTopLevelField1;
 }
-static set lateTopLevelField1(core::int? #t4) → void {
+static set lateTopLevelField1(core::int? #t5) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t4;
+  self::_#lateTopLevelField1 = #t5;
 }
 static method Extension|lateExtensionField1Init() → core::int?
   return 87;
@@ -103,9 +122,9 @@
   }
   return self::_#Extension|lateExtensionField1;
 }
-static set Extension|lateExtensionField1(core::int? #t5) → void {
+static set Extension|lateExtensionField1(core::int? #t6) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t5;
+  self::_#Extension|lateExtensionField1 = #t6;
 }
 static method Extension|lateExtensionField2Init() → core::int?
   return 42;
@@ -116,9 +135,9 @@
   }
   return self::_#Extension|lateExtensionField2;
 }
-static set Extension|lateExtensionField2(core::int? #t6) → void {
+static set Extension|lateExtensionField2(core::int? #t7) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t6;
+  self::_#Extension|lateExtensionField2 = #t7;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
@@ -133,7 +152,10 @@
   self::Class::lateStaticField1 = 88;
   self::expect(88, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(null).{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int?>(0).{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int>(null).{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}(null);
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|lateExtensionField1 = 88;
   self::expect(88, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
index 9ee88bb..a90900a 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
@@ -2,15 +2,18 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  final field self::Class::T? field;
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  constructor •(self::Class::T? field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method lateStaticField1Init() → core::int?
     return 87;
@@ -56,13 +59,29 @@
     this.{self::Class::_#lateInstanceField#isSet} = true;
     this.{self::Class::_#lateInstanceField} = #t3;
   }
-  method instanceMethod() → dynamic {
+  method lateGenericInstanceFieldInit() → self::Class::T?
+    return this.{self::Class::field};
+  get lateGenericInstanceField() → self::Class::T? {
+    if(!this.{self::Class::_#lateGenericInstanceField#isSet}) {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = this.{self::Class::lateGenericInstanceFieldInit}();
+    }
+    return this.{self::Class::_#lateGenericInstanceField};
+  }
+  set lateGenericInstanceField(self::Class::T? #t4) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t4;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField});
     this.{self::Class::lateInstanceField} = 17;
     self::expect(17, this.{self::Class::lateInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceField});
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static method lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
@@ -90,9 +109,9 @@
   }
   return self::_#lateTopLevelField1;
 }
-static set lateTopLevelField1(core::int? #t4) → void {
+static set lateTopLevelField1(core::int? #t5) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t4;
+  self::_#lateTopLevelField1 = #t5;
 }
 static method Extension|lateExtensionField1Init() → core::int?
   return 87;
@@ -103,9 +122,9 @@
   }
   return self::_#Extension|lateExtensionField1;
 }
-static set Extension|lateExtensionField1(core::int? #t5) → void {
+static set Extension|lateExtensionField1(core::int? #t6) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t5;
+  self::_#Extension|lateExtensionField1 = #t6;
 }
 static method Extension|lateExtensionField2Init() → core::int?
   return 42;
@@ -116,9 +135,9 @@
   }
   return self::_#Extension|lateExtensionField2;
 }
-static set Extension|lateExtensionField2(core::int? #t6) → void {
+static set Extension|lateExtensionField2(core::int? #t7) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t6;
+  self::_#Extension|lateExtensionField2 = #t7;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
@@ -133,7 +152,10 @@
   self::Class::lateStaticField1 = 88;
   self::expect(88, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(null).{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int?>(0).{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int>(null).{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}(null);
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|lateExtensionField1 = 88;
   self::expect(88, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
index 9ee88bb..a90900a 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
@@ -2,15 +2,18 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  final field self::Class::T? field;
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  constructor •(self::Class::T? field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method lateStaticField1Init() → core::int?
     return 87;
@@ -56,13 +59,29 @@
     this.{self::Class::_#lateInstanceField#isSet} = true;
     this.{self::Class::_#lateInstanceField} = #t3;
   }
-  method instanceMethod() → dynamic {
+  method lateGenericInstanceFieldInit() → self::Class::T?
+    return this.{self::Class::field};
+  get lateGenericInstanceField() → self::Class::T? {
+    if(!this.{self::Class::_#lateGenericInstanceField#isSet}) {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = this.{self::Class::lateGenericInstanceFieldInit}();
+    }
+    return this.{self::Class::_#lateGenericInstanceField};
+  }
+  set lateGenericInstanceField(self::Class::T? #t4) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t4;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField});
     this.{self::Class::lateInstanceField} = 17;
     self::expect(17, this.{self::Class::lateInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceField});
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static method lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
@@ -90,9 +109,9 @@
   }
   return self::_#lateTopLevelField1;
 }
-static set lateTopLevelField1(core::int? #t4) → void {
+static set lateTopLevelField1(core::int? #t5) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t4;
+  self::_#lateTopLevelField1 = #t5;
 }
 static method Extension|lateExtensionField1Init() → core::int?
   return 87;
@@ -103,9 +122,9 @@
   }
   return self::_#Extension|lateExtensionField1;
 }
-static set Extension|lateExtensionField1(core::int? #t5) → void {
+static set Extension|lateExtensionField1(core::int? #t6) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t5;
+  self::_#Extension|lateExtensionField1 = #t6;
 }
 static method Extension|lateExtensionField2Init() → core::int?
   return 42;
@@ -116,9 +135,9 @@
   }
   return self::_#Extension|lateExtensionField2;
 }
-static set Extension|lateExtensionField2(core::int? #t6) → void {
+static set Extension|lateExtensionField2(core::int? #t7) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t6;
+  self::_#Extension|lateExtensionField2 = #t7;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
@@ -133,7 +152,10 @@
   self::Class::lateStaticField1 = 88;
   self::expect(88, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(null).{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int?>(0).{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int>(null).{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}(null);
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|lateExtensionField1 = 88;
   self::expect(88, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
index 9ee88bb..a90900a 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
@@ -2,15 +2,18 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
-    : super core::Object::•()
+  final field self::Class::T? field;
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  constructor •(self::Class::T? field) → self::Class<self::Class::T%>
+    : self::Class::field = field, super core::Object::•()
     ;
   static method lateStaticField1Init() → core::int?
     return 87;
@@ -56,13 +59,29 @@
     this.{self::Class::_#lateInstanceField#isSet} = true;
     this.{self::Class::_#lateInstanceField} = #t3;
   }
-  method instanceMethod() → dynamic {
+  method lateGenericInstanceFieldInit() → self::Class::T?
+    return this.{self::Class::field};
+  get lateGenericInstanceField() → self::Class::T? {
+    if(!this.{self::Class::_#lateGenericInstanceField#isSet}) {
+      this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+      this.{self::Class::_#lateGenericInstanceField} = this.{self::Class::lateGenericInstanceFieldInit}();
+    }
+    return this.{self::Class::_#lateGenericInstanceField};
+  }
+  set lateGenericInstanceField(self::Class::T? #t4) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t4;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic {
     self::expect(16, this.{self::Class::lateInstanceField});
     this.{self::Class::lateInstanceField} = 17;
     self::expect(17, this.{self::Class::lateInstanceField});
+    self::expect(this.{self::Class::field}, this.{self::Class::lateGenericInstanceField});
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static method lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
@@ -90,9 +109,9 @@
   }
   return self::_#lateTopLevelField1;
 }
-static set lateTopLevelField1(core::int? #t4) → void {
+static set lateTopLevelField1(core::int? #t5) → void {
   self::_#lateTopLevelField1#isSet = true;
-  self::_#lateTopLevelField1 = #t4;
+  self::_#lateTopLevelField1 = #t5;
 }
 static method Extension|lateExtensionField1Init() → core::int?
   return 87;
@@ -103,9 +122,9 @@
   }
   return self::_#Extension|lateExtensionField1;
 }
-static set Extension|lateExtensionField1(core::int? #t5) → void {
+static set Extension|lateExtensionField1(core::int? #t6) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t5;
+  self::_#Extension|lateExtensionField1 = #t6;
 }
 static method Extension|lateExtensionField2Init() → core::int?
   return 42;
@@ -116,9 +135,9 @@
   }
   return self::_#Extension|lateExtensionField2;
 }
-static set Extension|lateExtensionField2(core::int? #t6) → void {
+static set Extension|lateExtensionField2(core::int? #t7) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t6;
+  self::_#Extension|lateExtensionField2 = #t7;
 }
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
@@ -133,7 +152,10 @@
   self::Class::lateStaticField1 = 88;
   self::expect(88, self::Class::lateStaticField1);
   self::Class::staticMethod();
-  new self::Class::•().{self::Class::instanceMethod}();
+  new self::Class::•<core::int?>(null).{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int?>(0).{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int>(null).{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>(0).{self::Class::instanceMethod}(null);
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|lateExtensionField1 = 88;
   self::expect(88, self::Extension|lateExtensionField1);
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart
index d036884..0d7df55 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart
@@ -4,7 +4,7 @@
 
 late int? lateTopLevelField;
 
-class Class {
+class Class<T> {
   static late int? lateStaticField1;
   static late int? lateStaticField2;
 
@@ -17,15 +17,22 @@
 
   late int? lateInstanceField;
 
-  instanceMethod() {
+  late T? lateGenericInstanceField;
+
+  instanceMethod(T? value) {
     throws(() => lateInstanceField,
         'Read value from uninitialized Class.lateInstanceField');
     lateInstanceField = 16;
     expect(16, lateInstanceField);
+
+    throws(() => lateGenericInstanceField,
+        'Read value from uninitialized Class.lateGenericInstanceField');
+    lateGenericInstanceField = value;
+    expect(value, lateGenericInstanceField);
   }
 }
 
-extension Extension on Class {
+extension Extension<T> on Class<T> {
   static late int? lateExtensionField1;
   static late int? lateExtensionField2;
 
@@ -56,6 +63,11 @@
   expect(87, Extension.lateExtensionField1);
 
   Extension.staticMethod();
+
+  new Class<int?>().instanceMethod(null);
+  new Class<int?>().instanceMethod(0);
+  new Class<int>().instanceMethod(null);
+  new Class<int>().instanceMethod(0);
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect
index bc1aaf1..9d6eba5 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect
@@ -2,14 +2,16 @@
 import self as self;
 import "dart:core" as core;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1;
   static field core::bool _#lateStaticField1#isSet;
   static field core::int? _#lateStaticField2;
   static field core::bool _#lateStaticField2#isSet;
   field core::int? _#lateInstanceField;
   field core::bool _#lateInstanceField#isSet;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField;
+  field core::bool _#lateGenericInstanceField#isSet;
+  synthetic constructor •() → self::Class<self::Class::T%>
     ;
   static get lateStaticField1() → core::int?;
   static set lateStaticField1(core::int? #t1) → void;
@@ -19,10 +21,12 @@
     ;
   get lateInstanceField() → core::int?;
   set lateInstanceField(core::int? #t3) → void;
-  method instanceMethod() → dynamic
+  get lateGenericInstanceField() → self::Class::T?;
+  set lateGenericInstanceField(self::Class::T? #t4) → void;
+  method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic
     ;
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
@@ -40,11 +44,11 @@
 static field core::int? _#Extension|lateExtensionField2;
 static field core::bool _#Extension|lateExtensionField2#isSet;
 static get lateTopLevelField() → core::int?;
-static set lateTopLevelField(core::int? #t4) → void;
+static set lateTopLevelField(core::int? #t5) → void;
 static get Extension|lateExtensionField1() → core::int?;
-static set Extension|lateExtensionField1(core::int? #t5) → void;
+static set Extension|lateExtensionField1(core::int? #t6) → void;
 static get Extension|lateExtensionField2() → core::int?;
-static set Extension|lateExtensionField2(core::int? #t6) → void;
+static set Extension|lateExtensionField2(core::int? #t7) → void;
 static method Extension|staticMethod() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
index e5753c8..95cb961 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
@@ -3,14 +3,16 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int?
@@ -36,13 +38,22 @@
     this.{self::Class::_#lateInstanceField#isSet} = true;
     this.{self::Class::_#lateInstanceField} = #t3;
   }
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T?
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T? #t4) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t4;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
+    self::throws(() → self::Class::T? => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
@@ -61,21 +72,21 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
-static set lateTopLevelField(core::int? #t4) → void {
+static set lateTopLevelField(core::int? #t5) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t4;
+  self::_#lateTopLevelField = #t5;
 }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
-static set Extension|lateExtensionField1(core::int? #t5) → void {
+static set Extension|lateExtensionField1(core::int? #t6) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t5;
+  self::_#Extension|lateExtensionField1 = #t6;
 }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
-static set Extension|lateExtensionField2(core::int? #t6) → void {
+static set Extension|lateExtensionField2(core::int? #t7) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t6;
+  self::_#Extension|lateExtensionField2 = #t7;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
@@ -94,6 +105,10 @@
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|staticMethod();
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
index e5753c8..95cb961 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -3,14 +3,16 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int?
@@ -36,13 +38,22 @@
     this.{self::Class::_#lateInstanceField#isSet} = true;
     this.{self::Class::_#lateInstanceField} = #t3;
   }
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T?
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T? #t4) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t4;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
+    self::throws(() → self::Class::T? => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
@@ -61,21 +72,21 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
-static set lateTopLevelField(core::int? #t4) → void {
+static set lateTopLevelField(core::int? #t5) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t4;
+  self::_#lateTopLevelField = #t5;
 }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
-static set Extension|lateExtensionField1(core::int? #t5) → void {
+static set Extension|lateExtensionField1(core::int? #t6) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t5;
+  self::_#Extension|lateExtensionField1 = #t6;
 }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
-static set Extension|lateExtensionField2(core::int? #t6) → void {
+static set Extension|lateExtensionField2(core::int? #t7) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t6;
+  self::_#Extension|lateExtensionField2 = #t7;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
@@ -94,6 +105,10 @@
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|staticMethod();
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
index e5753c8..95cb961 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
@@ -3,14 +3,16 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int?
@@ -36,13 +38,22 @@
     this.{self::Class::_#lateInstanceField#isSet} = true;
     this.{self::Class::_#lateInstanceField} = #t3;
   }
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T?
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T? #t4) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t4;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
+    self::throws(() → self::Class::T? => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
@@ -61,21 +72,21 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
-static set lateTopLevelField(core::int? #t4) → void {
+static set lateTopLevelField(core::int? #t5) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t4;
+  self::_#lateTopLevelField = #t5;
 }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
-static set Extension|lateExtensionField1(core::int? #t5) → void {
+static set Extension|lateExtensionField1(core::int? #t6) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t5;
+  self::_#Extension|lateExtensionField1 = #t6;
 }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
-static set Extension|lateExtensionField2(core::int? #t6) → void {
+static set Extension|lateExtensionField2(core::int? #t7) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t6;
+  self::_#Extension|lateExtensionField2 = #t7;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
@@ -94,6 +105,10 @@
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|staticMethod();
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
index e5753c8..95cb961 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -3,14 +3,16 @@
 import "dart:core" as core;
 import "dart:_internal" as _in;
 
-class Class extends core::Object {
+class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
   static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
   static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#lateInstanceField = null;
   field core::bool _#lateInstanceField#isSet = false;
-  synthetic constructor •() → self::Class
+  generic-covariant-impl field self::Class::T? _#lateGenericInstanceField = null;
+  field core::bool _#lateGenericInstanceField#isSet = false;
+  synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int?
@@ -36,13 +38,22 @@
     this.{self::Class::_#lateInstanceField#isSet} = true;
     this.{self::Class::_#lateInstanceField} = #t3;
   }
-  method instanceMethod() → dynamic {
+  get lateGenericInstanceField() → self::Class::T?
+    return this.{self::Class::_#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
+  set lateGenericInstanceField(self::Class::T? #t4) → void {
+    this.{self::Class::_#lateGenericInstanceField#isSet} = true;
+    this.{self::Class::_#lateGenericInstanceField} = #t4;
+  }
+  method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic {
     self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
     self::expect(16, this.{self::Class::lateInstanceField});
+    self::throws(() → self::Class::T? => this.{self::Class::lateGenericInstanceField}, "Read value from uninitialized Class.lateGenericInstanceField");
+    this.{self::Class::lateGenericInstanceField} = value;
+    self::expect(value, this.{self::Class::lateGenericInstanceField});
   }
 }
-extension Extension on self::Class {
+extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
@@ -61,21 +72,21 @@
 static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int?
   return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
-static set lateTopLevelField(core::int? #t4) → void {
+static set lateTopLevelField(core::int? #t5) → void {
   self::_#lateTopLevelField#isSet = true;
-  self::_#lateTopLevelField = #t4;
+  self::_#lateTopLevelField = #t5;
 }
 static get Extension|lateExtensionField1() → core::int?
   return self::_#Extension|lateExtensionField1#isSet ?{core::int?} self::_#Extension|lateExtensionField1 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
-static set Extension|lateExtensionField1(core::int? #t5) → void {
+static set Extension|lateExtensionField1(core::int? #t6) → void {
   self::_#Extension|lateExtensionField1#isSet = true;
-  self::_#Extension|lateExtensionField1 = #t5;
+  self::_#Extension|lateExtensionField1 = #t6;
 }
 static get Extension|lateExtensionField2() → core::int?
   return self::_#Extension|lateExtensionField2#isSet ?{core::int?} self::_#Extension|lateExtensionField2 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
-static set Extension|lateExtensionField2(core::int? #t6) → void {
+static set Extension|lateExtensionField2(core::int? #t7) → void {
   self::_#Extension|lateExtensionField2#isSet = true;
-  self::_#Extension|lateExtensionField2 = #t6;
+  self::_#Extension|lateExtensionField2 = #t7;
 }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int? => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
@@ -94,6 +105,10 @@
   self::Extension|lateExtensionField1 = 87;
   self::expect(87, self::Extension|lateExtensionField1);
   self::Extension|staticMethod();
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int?>().{self::Class::instanceMethod}(0);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(null);
+  new self::Class::•<core::int>().{self::Class::instanceMethod}(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart
index a59e3f2..93ce4fa 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart
@@ -10,6 +10,19 @@
   expect(123, lateLocal);
   expect(124, lateLocal = 124);
   expect(124, lateLocal);
+
+  local<T>(T? value1, T? value2) {
+    late T? lateGenericLocal = value1;
+
+    expect(value1, lateGenericLocal);
+    expect(value2, lateGenericLocal = value2);
+    expect(value2, lateGenericLocal);
+  }
+
+  local<int?>(null, 0);
+  local<int?>(0, null);
+  local<int>(null, 0);
+  local<int>(0, null);
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect
index 850613c..9363ab8 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect
@@ -21,6 +21,28 @@
   self::expect(123, #lateLocal#get.call());
   self::expect(124, #lateLocal#set.call(124));
   self::expect(124, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T? value1, T? value2) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T? {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = value1;
+      }
+      return lateGenericLocal;
+    }
+    function #lateGenericLocal#set(T? #t2) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t2;
+    }
+    self::expect(value1, #lateGenericLocal#get.call());
+    self::expect(value2, #lateGenericLocal#set.call(value2));
+    self::expect(value2, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null, 0);
+  local.call<core::int?>(0, null);
+  local.call<core::int>(null, 0);
+  local.call<core::int>(0, null);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect
index 850613c..9363ab8 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect
@@ -21,6 +21,28 @@
   self::expect(123, #lateLocal#get.call());
   self::expect(124, #lateLocal#set.call(124));
   self::expect(124, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T? value1, T? value2) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T? {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = value1;
+      }
+      return lateGenericLocal;
+    }
+    function #lateGenericLocal#set(T? #t2) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t2;
+    }
+    self::expect(value1, #lateGenericLocal#get.call());
+    self::expect(value2, #lateGenericLocal#set.call(value2));
+    self::expect(value2, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null, 0);
+  local.call<core::int?>(0, null);
+  local.call<core::int>(null, 0);
+  local.call<core::int>(0, null);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect
index 850613c..9363ab8 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.expect
@@ -21,6 +21,28 @@
   self::expect(123, #lateLocal#get.call());
   self::expect(124, #lateLocal#set.call(124));
   self::expect(124, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T? value1, T? value2) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T? {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = value1;
+      }
+      return lateGenericLocal;
+    }
+    function #lateGenericLocal#set(T? #t2) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t2;
+    }
+    self::expect(value1, #lateGenericLocal#get.call());
+    self::expect(value2, #lateGenericLocal#set.call(value2));
+    self::expect(value2, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null, 0);
+  local.call<core::int?>(0, null);
+  local.call<core::int>(null, 0);
+  local.call<core::int>(0, null);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect
index 850613c..9363ab8 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.weak.transformed.expect
@@ -21,6 +21,28 @@
   self::expect(123, #lateLocal#get.call());
   self::expect(124, #lateLocal#set.call(124));
   self::expect(124, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T? value1, T? value2) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T? {
+      if(!#lateGenericLocal#isSet) {
+        #lateGenericLocal#isSet = true;
+        lateGenericLocal = value1;
+      }
+      return lateGenericLocal;
+    }
+    function #lateGenericLocal#set(T? #t2) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t2;
+    }
+    self::expect(value1, #lateGenericLocal#get.call());
+    self::expect(value2, #lateGenericLocal#set.call(value2));
+    self::expect(value2, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null, 0);
+  local.call<core::int?>(0, null);
+  local.call<core::int>(null, 0);
+  local.call<core::int>(0, null);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart
index d23214d..70b36f7 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart
@@ -7,6 +7,19 @@
   throws(() => lateLocal, 'Read value from uninitialized lateLocal');
   expect(123, lateLocal = 123);
   expect(123, lateLocal);
+
+  local<T>(T? value) {
+    late T? lateGenericLocal;
+    throws(() => lateGenericLocal,
+        'Read value from uninitialized lateGenericLocal');
+    expect(value, lateGenericLocal = value);
+    expect(value, lateGenericLocal);
+  }
+
+  local<int?>(null);
+  local<int?>(0);
+  local<int>(null);
+  local<int>(0);
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
index 1ce4c50..29c9282 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
@@ -15,6 +15,23 @@
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T?
+      return #lateGenericLocal#isSet ?{T?} lateGenericLocal : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T? #t2) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t2;
+    }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(null);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
index 1ce4c50..29c9282 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
@@ -15,6 +15,23 @@
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T?
+      return #lateGenericLocal#isSet ?{T?} lateGenericLocal : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T? #t2) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t2;
+    }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(null);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
index 1ce4c50..29c9282 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
@@ -15,6 +15,23 @@
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T?
+      return #lateGenericLocal#isSet ?{T?} lateGenericLocal : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T? #t2) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t2;
+    }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(null);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
index 1ce4c50..29c9282 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
@@ -15,6 +15,23 @@
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
+  function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
+    T? lateGenericLocal;
+    core::bool #lateGenericLocal#isSet = false;
+    function #lateGenericLocal#get() → T?
+      return #lateGenericLocal#isSet ?{T?} lateGenericLocal : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
+    function #lateGenericLocal#set(T? #t2) → dynamic {
+      #lateGenericLocal#isSet = true;
+      return lateGenericLocal = #t2;
+    }
+    self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
+    self::expect(value, #lateGenericLocal#set.call(value));
+    self::expect(value, #lateGenericLocal#get.call());
+  }
+  local.call<core::int?>(null);
+  local.call<core::int?>(0);
+  local.call<core::int>(null);
+  local.call<core::int>(0);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual))
diff --git a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart
new file mode 100644
index 0000000..3114c78
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test checks for compile-time errors related to definite assignment and
+// completion.
+
+int foo() {
+  int x;
+  return x;
+}
+
+int bar() {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.outline.expect b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.outline.expect
new file mode 100644
index 0000000..7dc40d1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.outline.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int
+  ;
+static method bar() → core::int
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.expect b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.expect
new file mode 100644
index 0000000..c56d12d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+  core::int x;
+  return x;
+}
+static method bar() → core::int {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.transformed.expect
new file mode 100644
index 0000000..c56d12d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.strong.transformed.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+  core::int x;
+  return x;
+}
+static method bar() → core::int {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.expect b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.expect
new file mode 100644
index 0000000..c56d12d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+  core::int x;
+  return x;
+}
+static method bar() → core::int {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.transformed.expect
new file mode 100644
index 0000000..c56d12d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/definite_assignment_and_completion.dart.weak.transformed.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+  core::int x;
+  return x;
+}
+static method bar() → core::int {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart b/pkg/front_end/testcases/nnbd/forbidden_supers.dart
new file mode 100644
index 0000000..80fde61
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart
@@ -0,0 +1,21 @@
+// 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.
+
+// This test checks for compile-time errors in cases when either Never or T? is
+// extended, implemented, or mixed in, where T is a type.
+
+class A {}
+
+class B {}
+
+class C extends B with A? {}
+class C1 extends B with Never {}
+
+class D extends A? {}
+class D1 extends Never {}
+
+class E implements B? {}
+class E1 implements Never {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.outline.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.outline.expect
new file mode 100644
index 0000000..14fa9bf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.outline.expect
@@ -0,0 +1,75 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:13:7: Error: The type 'Never' can't be mixed in.
+// class C1 extends B with Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:13:7: Error: The type 'Never' can't be used as supertype.
+// class C1 extends B with Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:16:7: Error: The type 'Never' can't be used as supertype.
+// class D1 extends Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:19:7: Error: The type 'Never' can't be used as supertype.
+// class E1 implements Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:16:7: Error: The type 'Never' can't be used in an 'extends' clause.
+// class D1 extends Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:19:7: Error: The type 'Never' can't be used in an 'implements' clause.
+// class E1 implements Never {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    ;
+}
+abstract class _C&B&A = self::B with self::A {
+  synthetic constructor •() → self::_C&B&A
+    : super self::B::•()
+    ;
+}
+class C extends self::_C&B&A {
+  synthetic constructor •() → self::C
+    ;
+}
+abstract class _C1&B&Never extends self::B {
+  synthetic constructor •() → self::_C1&B&Never
+    : super self::B::•()
+    ;
+}
+class C1 extends self::_C1&B&Never {
+  synthetic constructor •() → self::C1
+    ;
+}
+class D extends self::A {
+  synthetic constructor •() → self::D
+    ;
+}
+class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    ;
+}
+class E extends core::Object implements self::B {
+  synthetic constructor •() → self::E
+    ;
+}
+class E1 extends core::Object {
+  synthetic constructor •() → self::E1
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.expect
new file mode 100644
index 0000000..a7be0e3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.expect
@@ -0,0 +1,82 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:13:7: Error: The type 'Never' can't be mixed in.
+// class C1 extends B with Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:13:7: Error: The type 'Never' can't be used as supertype.
+// class C1 extends B with Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:16:7: Error: The type 'Never' can't be used as supertype.
+// class D1 extends Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:19:7: Error: The type 'Never' can't be used as supertype.
+// class E1 implements Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:16:7: Error: The type 'Never' can't be used in an 'extends' clause.
+// class D1 extends Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:19:7: Error: The type 'Never' can't be used in an 'implements' clause.
+// class E1 implements Never {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+abstract class _C&B&A = self::B with self::A {
+  synthetic constructor •() → self::_C&B&A
+    : super self::B::•()
+    ;
+}
+class C extends self::_C&B&A {
+  synthetic constructor •() → self::C
+    : super self::_C&B&A::•()
+    ;
+}
+abstract class _C1&B&Never extends self::B {
+  synthetic constructor •() → self::_C1&B&Never
+    : super self::B::•()
+    ;
+}
+class C1 extends self::_C1&B&Never {
+  synthetic constructor •() → self::C1
+    : super self::_C1&B&Never::•()
+    ;
+}
+class D extends self::A {
+  synthetic constructor •() → self::D
+    : super self::A::•()
+    ;
+}
+class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+}
+class E extends core::Object implements self::B {
+  synthetic constructor •() → self::E
+    : super core::Object::•()
+    ;
+}
+class E1 extends core::Object {
+  synthetic constructor •() → self::E1
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.transformed.expect
new file mode 100644
index 0000000..de6ba93
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.transformed.expect
@@ -0,0 +1,82 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:13:7: Error: The type 'Never' can't be mixed in.
+// class C1 extends B with Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:13:7: Error: The type 'Never' can't be used as supertype.
+// class C1 extends B with Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:16:7: Error: The type 'Never' can't be used as supertype.
+// class D1 extends Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:19:7: Error: The type 'Never' can't be used as supertype.
+// class E1 implements Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:16:7: Error: The type 'Never' can't be used in an 'extends' clause.
+// class D1 extends Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:19:7: Error: The type 'Never' can't be used in an 'implements' clause.
+// class E1 implements Never {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+abstract class _C&B&A extends self::B implements self::A {
+  synthetic constructor •() → self::_C&B&A
+    : super self::B::•()
+    ;
+}
+class C extends self::_C&B&A {
+  synthetic constructor •() → self::C
+    : super self::_C&B&A::•()
+    ;
+}
+abstract class _C1&B&Never extends self::B {
+  synthetic constructor •() → self::_C1&B&Never
+    : super self::B::•()
+    ;
+}
+class C1 extends self::_C1&B&Never {
+  synthetic constructor •() → self::C1
+    : super self::_C1&B&Never::•()
+    ;
+}
+class D extends self::A {
+  synthetic constructor •() → self::D
+    : super self::A::•()
+    ;
+}
+class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+}
+class E extends core::Object implements self::B {
+  synthetic constructor •() → self::E
+    : super core::Object::•()
+    ;
+}
+class E1 extends core::Object {
+  synthetic constructor •() → self::E1
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.expect
new file mode 100644
index 0000000..a7be0e3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.expect
@@ -0,0 +1,82 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:13:7: Error: The type 'Never' can't be mixed in.
+// class C1 extends B with Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:13:7: Error: The type 'Never' can't be used as supertype.
+// class C1 extends B with Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:16:7: Error: The type 'Never' can't be used as supertype.
+// class D1 extends Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:19:7: Error: The type 'Never' can't be used as supertype.
+// class E1 implements Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:16:7: Error: The type 'Never' can't be used in an 'extends' clause.
+// class D1 extends Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:19:7: Error: The type 'Never' can't be used in an 'implements' clause.
+// class E1 implements Never {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+abstract class _C&B&A = self::B with self::A {
+  synthetic constructor •() → self::_C&B&A
+    : super self::B::•()
+    ;
+}
+class C extends self::_C&B&A {
+  synthetic constructor •() → self::C
+    : super self::_C&B&A::•()
+    ;
+}
+abstract class _C1&B&Never extends self::B {
+  synthetic constructor •() → self::_C1&B&Never
+    : super self::B::•()
+    ;
+}
+class C1 extends self::_C1&B&Never {
+  synthetic constructor •() → self::C1
+    : super self::_C1&B&Never::•()
+    ;
+}
+class D extends self::A {
+  synthetic constructor •() → self::D
+    : super self::A::•()
+    ;
+}
+class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+}
+class E extends core::Object implements self::B {
+  synthetic constructor •() → self::E
+    : super core::Object::•()
+    ;
+}
+class E1 extends core::Object {
+  synthetic constructor •() → self::E1
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.transformed.expect
new file mode 100644
index 0000000..de6ba93
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.transformed.expect
@@ -0,0 +1,82 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:13:7: Error: The type 'Never' can't be mixed in.
+// class C1 extends B with Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:13:7: Error: The type 'Never' can't be used as supertype.
+// class C1 extends B with Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:16:7: Error: The type 'Never' can't be used as supertype.
+// class D1 extends Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:19:7: Error: The type 'Never' can't be used as supertype.
+// class E1 implements Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:16:7: Error: The type 'Never' can't be used in an 'extends' clause.
+// class D1 extends Never {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/forbidden_supers.dart:19:7: Error: The type 'Never' can't be used in an 'implements' clause.
+// class E1 implements Never {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+abstract class _C&B&A extends self::B implements self::A {
+  synthetic constructor •() → self::_C&B&A
+    : super self::B::•()
+    ;
+}
+class C extends self::_C&B&A {
+  synthetic constructor •() → self::C
+    : super self::_C&B&A::•()
+    ;
+}
+abstract class _C1&B&Never extends self::B {
+  synthetic constructor •() → self::_C1&B&Never
+    : super self::B::•()
+    ;
+}
+class C1 extends self::_C1&B&Never {
+  synthetic constructor •() → self::C1
+    : super self::_C1&B&Never::•()
+    ;
+}
+class D extends self::A {
+  synthetic constructor •() → self::D
+    : super self::A::•()
+    ;
+}
+class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+}
+class E extends core::Object implements self::B {
+  synthetic constructor •() → self::E
+    : super core::Object::•()
+    ;
+}
+class E1 extends core::Object {
+  synthetic constructor •() → self::E1
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/forin.dart b/pkg/front_end/testcases/nnbd/forin.dart
new file mode 100644
index 0000000..05b3a79
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forin.dart
@@ -0,0 +1,33 @@
+// 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.
+
+// The test checks that only subtypes of Iterable<dynamic> and "dynamic" are
+// allowed as the iterable in a for-in loop.
+
+error(Iterable<int>? i2, List<int>? l2, Object o1, Object? o2) {
+  for (int x in i2) x;
+  [for (int x in i2) x];
+
+  for (int x in l2) x;
+  [for (int x in l2) x];
+
+  for (int x in o1) x;
+  [for (int x in o1) x];
+
+  for (int x in o2) x;
+  [for (int x in o2) x];
+}
+
+ok(Iterable<int> i1, List<int> l1, dynamic d) {
+  for (int x in i1) x;
+  [for (int x in i1) x];
+
+  for (int x in l1) x;
+  [for (int x in l1) x];
+
+  for (int x in d) x;
+  [for (int x in d) x];
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.outline.expect b/pkg/front_end/testcases/nnbd/forin.dart.outline.expect
new file mode 100644
index 0000000..33cd4d6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forin.dart.outline.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method error(core::Iterable<core::int>? i2, core::List<core::int>? l2, core::Object o1, core::Object? o2) → dynamic
+  ;
+static method ok(core::Iterable<core::int> i1, core::List<core::int> l1, dynamic d) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.strong.expect b/pkg/front_end/testcases/nnbd/forin.dart.strong.expect
new file mode 100644
index 0000000..dc3ec6b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forin.dart.strong.expect
@@ -0,0 +1,149 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/forin.dart:9:17: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in i2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:10:18: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in i2) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:12:17: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'List' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in l2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:13:18: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'List' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in l2) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:15:17: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in o1) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:16:18: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in o1) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:18:17: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in o2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:19:18: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in o2) x];
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method error(core::Iterable<core::int>? i2, core::List<core::int>? l2, core::Object o1, core::Object? o2) → dynamic {
+  for (core::int x in let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:9:17: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Iterable' is from 'dart:core'.
+  for (int x in i2) x;
+                ^" in i2 as{TypeError} core::Iterable<dynamic>)
+    x;
+  block {
+    final core::List<core::int> #t2 = <core::int>[];
+    for (core::int x in let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:10:18: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Iterable' is from 'dart:core'.
+  [for (int x in i2) x];
+                 ^" in i2 as{TypeError} core::Iterable<dynamic>)
+      #t2.{core::List::add}(x);
+  } =>#t2;
+  for (core::int x in let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:12:17: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'List' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  for (int x in l2) x;
+                ^" in l2 as{TypeError} core::Iterable<dynamic>)
+    x;
+  block {
+    final core::List<core::int> #t5 = <core::int>[];
+    for (core::int x in let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:13:18: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'List' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  [for (int x in l2) x];
+                 ^" in l2 as{TypeError} core::Iterable<dynamic>)
+      #t5.{core::List::add}(x);
+  } =>#t5;
+  for (final dynamic #t7 in let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:15:17: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Object' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  for (int x in o1) x;
+                ^" in o1 as{TypeError} core::Iterable<dynamic>) {
+    core::int x = #t7 as{TypeError} core::int;
+    x;
+  }
+  block {
+    final core::List<core::int> #t9 = <core::int>[];
+    for (final dynamic #t10 in let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:16:18: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Object' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  [for (int x in o1) x];
+                 ^" in o1 as{TypeError} core::Iterable<dynamic>) {
+      core::int x = #t10 as{TypeError} core::int;
+      #t9.{core::List::add}(x);
+    }
+  } =>#t9;
+  for (final dynamic #t12 in let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:18:17: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Object' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  for (int x in o2) x;
+                ^" in o2 as{TypeError} core::Iterable<dynamic>) {
+    core::int x = #t12 as{TypeError} core::int;
+    x;
+  }
+  block {
+    final core::List<core::int> #t14 = <core::int>[];
+    for (final dynamic #t15 in let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:19:18: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Object' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  [for (int x in o2) x];
+                 ^" in o2 as{TypeError} core::Iterable<dynamic>) {
+      core::int x = #t15 as{TypeError} core::int;
+      #t14.{core::List::add}(x);
+    }
+  } =>#t14;
+}
+static method ok(core::Iterable<core::int> i1, core::List<core::int> l1, dynamic d) → dynamic {
+  for (core::int x in i1)
+    x;
+  block {
+    final core::List<core::int> #t17 = <core::int>[];
+    for (core::int x in i1)
+      #t17.{core::List::add}(x);
+  } =>#t17;
+  for (core::int x in l1)
+    x;
+  block {
+    final core::List<core::int> #t18 = <core::int>[];
+    for (core::int x in l1)
+      #t18.{core::List::add}(x);
+  } =>#t18;
+  for (final dynamic #t19 in d as{TypeError} core::Iterable<dynamic>) {
+    core::int x = #t19 as{TypeError} core::int;
+    x;
+  }
+  block {
+    final core::List<core::int> #t20 = <core::int>[];
+    for (final dynamic #t21 in d as{TypeError} core::Iterable<dynamic>) {
+      core::int x = #t21 as{TypeError} core::int;
+      #t20.{core::List::add}(x);
+    }
+  } =>#t20;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect
new file mode 100644
index 0000000..04b46d0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect
@@ -0,0 +1,226 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/forin.dart:9:17: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in i2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:10:18: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in i2) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:12:17: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'List' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in l2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:13:18: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'List' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in l2) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:15:17: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in o1) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:16:18: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in o1) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:18:17: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in o2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:19:18: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in o2) x];
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method error(core::Iterable<core::int>? i2, core::List<core::int>? l2, core::Object o1, core::Object? o2) → dynamic {
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:9:17: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Iterable' is from 'dart:core'.
+  for (int x in i2) x;
+                ^" in i2 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::int x = :sync-for-iterator.{core::Iterator::current};
+      x;
+    }
+  }
+  block {
+    final core::List<core::int> #t2 = <core::int>[];
+    {
+      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:10:18: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Iterable' is from 'dart:core'.
+  [for (int x in i2) x];
+                 ^" in i2 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        core::int x = :sync-for-iterator.{core::Iterator::current};
+        #t2.{core::List::add}(x);
+      }
+    }
+  } =>#t2;
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:12:17: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'List' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  for (int x in l2) x;
+                ^" in l2 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::int x = :sync-for-iterator.{core::Iterator::current};
+      x;
+    }
+  }
+  block {
+    final core::List<core::int> #t5 = <core::int>[];
+    {
+      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:13:18: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'List' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  [for (int x in l2) x];
+                 ^" in l2 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        core::int x = :sync-for-iterator.{core::Iterator::current};
+        #t5.{core::List::add}(x);
+      }
+    }
+  } =>#t5;
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:15:17: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Object' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  for (int x in o1) x;
+                ^" in o1 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      final dynamic #t8 = :sync-for-iterator.{core::Iterator::current};
+      {
+        core::int x = #t8 as{TypeError} core::int;
+        x;
+      }
+    }
+  }
+  block {
+    final core::List<core::int> #t9 = <core::int>[];
+    {
+      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:16:18: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Object' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  [for (int x in o1) x];
+                 ^" in o1 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t11 = :sync-for-iterator.{core::Iterator::current};
+        {
+          core::int x = #t11 as{TypeError} core::int;
+          #t9.{core::List::add}(x);
+        }
+      }
+    }
+  } =>#t9;
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:18:17: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Object' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  for (int x in o2) x;
+                ^" in o2 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      final dynamic #t13 = :sync-for-iterator.{core::Iterator::current};
+      {
+        core::int x = #t13 as{TypeError} core::int;
+        x;
+      }
+    }
+  }
+  block {
+    final core::List<core::int> #t14 = <core::int>[];
+    {
+      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:19:18: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
+ - 'Object' is from 'dart:core'.
+ - 'Iterable' is from 'dart:core'.
+  [for (int x in o2) x];
+                 ^" in o2 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t16 = :sync-for-iterator.{core::Iterator::current};
+        {
+          core::int x = #t16 as{TypeError} core::int;
+          #t14.{core::List::add}(x);
+        }
+      }
+    }
+  } =>#t14;
+}
+static method ok(core::Iterable<core::int> i1, core::List<core::int> l1, dynamic d) → dynamic {
+  {
+    core::Iterator<core::int>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int>*>(i1).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::int x = :sync-for-iterator.{core::Iterator::current};
+      x;
+    }
+  }
+  block {
+    final core::List<core::int> #t17 = <core::int>[];
+    {
+      core::Iterator<core::int>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int>*>(i1).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        core::int x = :sync-for-iterator.{core::Iterator::current};
+        #t17.{core::List::add}(x);
+      }
+    }
+  } =>#t17;
+  {
+    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(l1).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::int x = :sync-for-iterator.{core::Iterator::current};
+      x;
+    }
+  }
+  block {
+    final core::List<core::int> #t18 = <core::int>[];
+    {
+      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(l1).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        core::int x = :sync-for-iterator.{core::Iterator::current};
+        #t18.{core::List::add}(x);
+      }
+    }
+  } =>#t18;
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(d as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      final dynamic #t19 = :sync-for-iterator.{core::Iterator::current};
+      {
+        core::int x = #t19 as{TypeError} core::int;
+        x;
+      }
+    }
+  }
+  block {
+    final core::List<core::int> #t20 = <core::int>[];
+    {
+      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(d as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t21 = :sync-for-iterator.{core::Iterator::current};
+        {
+          core::int x = #t21 as{TypeError} core::int;
+          #t20.{core::List::add}(x);
+        }
+      }
+    }
+  } =>#t20;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.weak.expect b/pkg/front_end/testcases/nnbd/forin.dart.weak.expect
new file mode 100644
index 0000000..12c0f2c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forin.dart.weak.expect
@@ -0,0 +1,119 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/forin.dart:9:17: Warning: Assigning value of type 'Iterable<int>?' to a variable of type 'Iterable<dynamic>'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in i2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:10:18: Warning: Assigning value of type 'Iterable<int>?' to a variable of type 'Iterable<dynamic>'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in i2) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:12:17: Warning: Assigning value of type 'List<int>?' to a variable of type 'Iterable<dynamic>'.
+//  - 'List' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in l2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:13:18: Warning: Assigning value of type 'List<int>?' to a variable of type 'Iterable<dynamic>'.
+//  - 'List' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in l2) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:15:17: Warning: Assigning value of type 'Object' to a variable of type 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in o1) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:16:18: Warning: Assigning value of type 'Object' to a variable of type 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in o1) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:18:17: Warning: Assigning value of type 'Object?' to a variable of type 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in o2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:19:18: Warning: Assigning value of type 'Object?' to a variable of type 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in o2) x];
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method error(core::Iterable<core::int>? i2, core::List<core::int>? l2, core::Object o1, core::Object? o2) → dynamic {
+  for (core::int x in i2)
+    x;
+  block {
+    final core::List<core::int> #t1 = <core::int>[];
+    for (core::int x in i2)
+      #t1.{core::List::add}(x);
+  } =>#t1;
+  for (core::int x in l2)
+    x;
+  block {
+    final core::List<core::int> #t2 = <core::int>[];
+    for (core::int x in l2)
+      #t2.{core::List::add}(x);
+  } =>#t2;
+  for (final dynamic #t3 in o1 as{TypeError} core::Iterable<dynamic>) {
+    core::int x = #t3 as{TypeError} core::int;
+    x;
+  }
+  block {
+    final core::List<core::int> #t4 = <core::int>[];
+    for (final dynamic #t5 in o1 as{TypeError} core::Iterable<dynamic>) {
+      core::int x = #t5 as{TypeError} core::int;
+      #t4.{core::List::add}(x);
+    }
+  } =>#t4;
+  for (final dynamic #t6 in o2 as{TypeError} core::Iterable<dynamic>) {
+    core::int x = #t6 as{TypeError} core::int;
+    x;
+  }
+  block {
+    final core::List<core::int> #t7 = <core::int>[];
+    for (final dynamic #t8 in o2 as{TypeError} core::Iterable<dynamic>) {
+      core::int x = #t8 as{TypeError} core::int;
+      #t7.{core::List::add}(x);
+    }
+  } =>#t7;
+}
+static method ok(core::Iterable<core::int> i1, core::List<core::int> l1, dynamic d) → dynamic {
+  for (core::int x in i1)
+    x;
+  block {
+    final core::List<core::int> #t9 = <core::int>[];
+    for (core::int x in i1)
+      #t9.{core::List::add}(x);
+  } =>#t9;
+  for (core::int x in l1)
+    x;
+  block {
+    final core::List<core::int> #t10 = <core::int>[];
+    for (core::int x in l1)
+      #t10.{core::List::add}(x);
+  } =>#t10;
+  for (final dynamic #t11 in d as{TypeError} core::Iterable<dynamic>) {
+    core::int x = #t11 as{TypeError} core::int;
+    x;
+  }
+  block {
+    final core::List<core::int> #t12 = <core::int>[];
+    for (final dynamic #t13 in d as{TypeError} core::Iterable<dynamic>) {
+      core::int x = #t13 as{TypeError} core::int;
+      #t12.{core::List::add}(x);
+    }
+  } =>#t12;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect
new file mode 100644
index 0000000..1cf6aaf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect
@@ -0,0 +1,196 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/forin.dart:9:17: Warning: Assigning value of type 'Iterable<int>?' to a variable of type 'Iterable<dynamic>'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in i2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:10:18: Warning: Assigning value of type 'Iterable<int>?' to a variable of type 'Iterable<dynamic>'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in i2) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:12:17: Warning: Assigning value of type 'List<int>?' to a variable of type 'Iterable<dynamic>'.
+//  - 'List' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in l2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:13:18: Warning: Assigning value of type 'List<int>?' to a variable of type 'Iterable<dynamic>'.
+//  - 'List' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in l2) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:15:17: Warning: Assigning value of type 'Object' to a variable of type 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in o1) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:16:18: Warning: Assigning value of type 'Object' to a variable of type 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in o1) x];
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:18:17: Warning: Assigning value of type 'Object?' to a variable of type 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   for (int x in o2) x;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/forin.dart:19:18: Warning: Assigning value of type 'Object?' to a variable of type 'Iterable<dynamic>'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Iterable' is from 'dart:core'.
+//   [for (int x in o2) x];
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method error(core::Iterable<core::int>? i2, core::List<core::int>? l2, core::Object o1, core::Object? o2) → dynamic {
+  {
+    core::Iterator<core::int>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int>*>(i2).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::int x = :sync-for-iterator.{core::Iterator::current};
+      x;
+    }
+  }
+  block {
+    final core::List<core::int> #t1 = <core::int>[];
+    {
+      core::Iterator<core::int>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int>*>(i2).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        core::int x = :sync-for-iterator.{core::Iterator::current};
+        #t1.{core::List::add}(x);
+      }
+    }
+  } =>#t1;
+  {
+    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(l2).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::int x = :sync-for-iterator.{core::Iterator::current};
+      x;
+    }
+  }
+  block {
+    final core::List<core::int> #t2 = <core::int>[];
+    {
+      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(l2).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        core::int x = :sync-for-iterator.{core::Iterator::current};
+        #t2.{core::List::add}(x);
+      }
+    }
+  } =>#t2;
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(o1 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      final dynamic #t3 = :sync-for-iterator.{core::Iterator::current};
+      {
+        core::int x = #t3 as{TypeError} core::int;
+        x;
+      }
+    }
+  }
+  block {
+    final core::List<core::int> #t4 = <core::int>[];
+    {
+      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(o1 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t5 = :sync-for-iterator.{core::Iterator::current};
+        {
+          core::int x = #t5 as{TypeError} core::int;
+          #t4.{core::List::add}(x);
+        }
+      }
+    }
+  } =>#t4;
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(o2 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      final dynamic #t6 = :sync-for-iterator.{core::Iterator::current};
+      {
+        core::int x = #t6 as{TypeError} core::int;
+        x;
+      }
+    }
+  }
+  block {
+    final core::List<core::int> #t7 = <core::int>[];
+    {
+      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(o2 as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t8 = :sync-for-iterator.{core::Iterator::current};
+        {
+          core::int x = #t8 as{TypeError} core::int;
+          #t7.{core::List::add}(x);
+        }
+      }
+    }
+  } =>#t7;
+}
+static method ok(core::Iterable<core::int> i1, core::List<core::int> l1, dynamic d) → dynamic {
+  {
+    core::Iterator<core::int>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int>*>(i1).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::int x = :sync-for-iterator.{core::Iterator::current};
+      x;
+    }
+  }
+  block {
+    final core::List<core::int> #t9 = <core::int>[];
+    {
+      core::Iterator<core::int>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int>*>(i1).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        core::int x = :sync-for-iterator.{core::Iterator::current};
+        #t9.{core::List::add}(x);
+      }
+    }
+  } =>#t9;
+  {
+    core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(l1).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::int x = :sync-for-iterator.{core::Iterator::current};
+      x;
+    }
+  }
+  block {
+    final core::List<core::int> #t10 = <core::int>[];
+    {
+      core::Iterator<core::int*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::int*>*>(l1).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        core::int x = :sync-for-iterator.{core::Iterator::current};
+        #t10.{core::List::add}(x);
+      }
+    }
+  } =>#t10;
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(d as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      final dynamic #t11 = :sync-for-iterator.{core::Iterator::current};
+      {
+        core::int x = #t11 as{TypeError} core::int;
+        x;
+      }
+    }
+  }
+  block {
+    final core::List<core::int> #t12 = <core::int>[];
+    {
+      core::Iterator<dynamic>* :sync-for-iterator = _in::unsafeCast<core::Iterable<dynamic>*>(d as{TypeError} core::Iterable<dynamic>).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t13 = :sync-for-iterator.{core::Iterator::current};
+        {
+          core::int x = #t13 as{TypeError} core::int;
+          #t12.{core::List::add}(x);
+        }
+      }
+    }
+  } =>#t12;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/later.dart b/pkg/front_end/testcases/nnbd/later.dart
new file mode 100644
index 0000000..c43f4b5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/later.dart
@@ -0,0 +1,57 @@
+// 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.
+
+// This test checks for compile-time errors and their absence for some use cases
+// of late fields and variables.
+
+class A {
+  int a = 42;
+  late int b = (this.a * 2) >> 1; // Ok.
+
+  foo(late int x) {}
+}
+
+bar(late int x) {}
+
+baz() {
+  try {
+    throw "baz";
+  } on dynamic catch (late e, late t) {}
+  for (late int i = 0; i < 10; ++i) {
+    print("baz");
+  }
+  for (late String s in ["baz"]) {
+    print(s);
+  }
+  [for (late int i = 0; i < 10; ++i) i];
+}
+
+hest() async {
+  await for (late String s in new Stream.fromIterable(["hest"])) {
+    print(s);
+  }
+  return "hest";
+}
+
+fisk() async {
+  late String s1 = await hest();
+  late String s2 = '${fisk}${await hest()}${fisk}';
+  late Function f = () async => await hest();
+}
+
+class B {
+  late final int x = 42;
+
+  const B();
+}
+
+class C {
+  late final int x;
+
+  initVars() {
+    x = 42; // Ok: [x] doesn't have an initializer.
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/later.dart.outline.expect b/pkg/front_end/testcases/nnbd/later.dart.outline.expect
new file mode 100644
index 0000000..c3b7544
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/later.dart.outline.expect
@@ -0,0 +1,48 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/later.dart:12:7: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   foo(late int x) {}
+//       ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:15:5: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+// bar(late int x) {}
+//     ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a;
+  late field core::int b;
+  synthetic constructor •() → self::A
+    ;
+  method foo(core::int x) → dynamic
+    ;
+}
+class B extends core::Object {
+  late final field core::int x = 42;
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  late final field core::int x;
+  synthetic constructor •() → self::C
+    ;
+  method initVars() → dynamic
+    ;
+}
+static method bar(core::int x) → dynamic
+  ;
+static method baz() → dynamic
+  ;
+static method hest() → dynamic
+  ;
+static method fisk() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
new file mode 100644
index 0000000..723db80
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
@@ -0,0 +1,131 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/later.dart:12:7: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   foo(late int x) {}
+//       ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:15:5: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+// bar(late int x) {}
+//     ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:28: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+// No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+//   } on dynamic catch (late e, late t) {}
+//                            ^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:31: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   } on dynamic catch (late e, late t) {}
+//                               ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:36: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+// No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+//   } on dynamic catch (late e, late t) {}
+//                                    ^
+//
+// pkg/front_end/testcases/nnbd/later.dart:21:8: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   for (late int i = 0; i < 10; ++i) {
+//        ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:24:8: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   for (late String s in ["baz"]) {
+//        ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:27:9: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   [for (late int i = 0; i < 10; ++i) i];
+//         ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:31:14: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   await for (late String s in new Stream.fromIterable(["hest"])) {
+//              ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
+//   late String s1 = await hest();
+//                    ^^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
+//   late String s2 = '${fisk}${await hest()}${fisk}';
+//                              ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class A extends core::Object {
+  field core::int a = 42;
+  late field core::int b = this.{self::A::a}.{core::num::*}(2).{core::int::>>}(1);
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo(core::int x) → dynamic {}
+}
+class B extends core::Object {
+  late final field core::int x = 42;
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  late final field core::int x;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  method initVars() → dynamic {
+    this.{self::C::x} = 42;
+  }
+}
+static method bar(core::int x) → dynamic {}
+static method baz() → dynamic {
+  {
+    {
+      invalid-expression "pkg/front_end/testcases/nnbd/later.dart:20:36: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+  } on dynamic catch (late e, late t) {}
+                                   ^";
+    }
+    try {
+      throw "baz";
+    }
+    on dynamic catch(final dynamic late, final core::StackTrace e) {
+    }
+  }
+  for (late core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
+    core::print("baz");
+  }
+  for (late core::String s in <core::String>["baz"]) {
+    core::print(s);
+  }
+  block {
+    final core::List<core::int> #t1 = <core::int>[];
+    for (late core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1))
+      #t1.{core::List::add}(i);
+  } =>#t1;
+}
+static method hest() → dynamic async {
+  await for (late core::String s in asy::Stream::fromIterable<core::String>(<core::String*>["hest"])) {
+    core::print(s);
+  }
+  return "hest";
+}
+static method fisk() → dynamic async {
+  late core::String s1 = invalid-expression "pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
+  late String s1 = await hest();
+                   ^^^^^" as{TypeError} core::String;
+  late core::String s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
+  late String s2 = '\${fisk}\${await hest()}\${fisk}';
+                             ^^^^^"}${#C1}";
+  late core::Function f = () → asy::Future<dynamic> async => await self::hest();
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = tearoff self::fisk
+}
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
new file mode 100644
index 0000000..0973de4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
@@ -0,0 +1,248 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/later.dart:12:7: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   foo(late int x) {}
+//       ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:15:5: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+// bar(late int x) {}
+//     ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:28: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+// No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+//   } on dynamic catch (late e, late t) {}
+//                            ^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:31: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   } on dynamic catch (late e, late t) {}
+//                               ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:36: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+// No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+//   } on dynamic catch (late e, late t) {}
+//                                    ^
+//
+// pkg/front_end/testcases/nnbd/later.dart:21:8: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   for (late int i = 0; i < 10; ++i) {
+//        ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:24:8: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   for (late String s in ["baz"]) {
+//        ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:27:9: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   [for (late int i = 0; i < 10; ++i) i];
+//         ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:31:14: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   await for (late String s in new Stream.fromIterable(["hest"])) {
+//              ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
+//   late String s1 = await hest();
+//                    ^^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
+//   late String s2 = '${fisk}${await hest()}${fisk}';
+//                              ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+import "dart:async" as asy;
+
+class A extends core::Object {
+  field core::int a = 42;
+  late field core::int b = this.{self::A::a}.{core::num::*}(2).{core::int::>>}(1);
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo(core::int x) → dynamic {}
+}
+class B extends core::Object {
+  late final field core::int x = 42;
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  late final field core::int x;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  method initVars() → dynamic {
+    this.{self::C::x} = 42;
+  }
+}
+static method bar(core::int x) → dynamic {}
+static method baz() → dynamic {
+  {
+    {
+      invalid-expression "pkg/front_end/testcases/nnbd/later.dart:20:36: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+  } on dynamic catch (late e, late t) {}
+                                   ^";
+    }
+    try {
+      throw "baz";
+    }
+    on dynamic catch(final dynamic late, final core::StackTrace e) {
+    }
+  }
+  for (late core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
+    core::print("baz");
+  }
+  {
+    core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(<core::String>["baz"]).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      function #s#initializer() → core::String
+        return :sync-for-iterator.{core::Iterator::current};
+      late core::String s = #s#initializer.call();
+      {
+        core::print(s);
+      }
+    }
+  }
+  block {
+    final core::List<core::int> #t1 = <core::int>[];
+    for (late core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1))
+      #t1.{core::List::add}(i);
+  } =>#t1;
+}
+static method hest() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  asy::FutureOr<dynamic>? :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        {
+          dynamic :stream = asy::Stream::fromIterable<core::String>(<core::String*>["hest"]);
+          asy::_asyncStarListenHelper(:stream, :async_op);
+          asy::_StreamIterator<core::String>? :for-iterator = new asy::_StreamIterator::•<core::String>(:stream);
+          try
+            #L2:
+            while (true) {
+              dynamic #t2 = asy::_asyncStarMoveNextHelper(:stream);
+              [yield] let dynamic #t3 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
+              if(_in::unsafeCast<core::bool*>(:result)) {
+                function #s#initializer() → core::String
+                  return :for-iterator.{asy::_StreamIterator::current};
+                late core::String s = #s#initializer.call();
+                {
+                  core::print(s);
+                }
+              }
+              else
+                break #L2;
+            }
+          finally
+            if(!:for-iterator.{asy::_StreamIterator::_subscription}.{core::Object::==}(null)) {
+              [yield] let dynamic #t4 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(), :async_op_then, :async_op_error, :async_op) in null;
+              :result;
+            }
+        }
+        :return_value = "hest";
+        break #L1;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.start(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method fisk() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  asy::FutureOr<dynamic>? :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        function #s1#initializer() → core::String
+          return invalid-expression "pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
+  late String s1 = await hest();
+                   ^^^^^" as{TypeError} core::String;
+        late core::String s1 = #s1#initializer.call();
+        function #s2#initializer() → core::String
+          return "${#C1}${invalid-expression "pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
+  late String s2 = '\${fisk}\${await hest()}\${fisk}';
+                             ^^^^^"}${#C1}";
+        late core::String s2 = #s2#initializer.call();
+        function #f#initializer() → core::Function
+          return () → asy::Future<dynamic> /* originally async */ {
+            final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+            asy::FutureOr<dynamic>? :return_value;
+            dynamic :async_stack_trace;
+            dynamic :async_op_then;
+            dynamic :async_op_error;
+            core::int :await_jump_var = 0;
+            dynamic :await_ctx_var;
+            dynamic :saved_try_context_var0;
+            function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+              try {
+                #L4:
+                {
+                  [yield] let dynamic #t5 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                  :return_value = :result;
+                  break #L4;
+                }
+                asy::_completeOnAsyncReturn(:async_completer, :return_value);
+                return;
+              }
+              on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+              }
+            :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+            :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+            :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+            :async_completer.start(:async_op);
+            return :async_completer.{asy::Completer::future};
+          };
+        late core::Function f = #f#initializer.call();
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.start(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = tearoff self::fisk
+}
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
new file mode 100644
index 0000000..723db80
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
@@ -0,0 +1,131 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/later.dart:12:7: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   foo(late int x) {}
+//       ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:15:5: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+// bar(late int x) {}
+//     ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:28: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+// No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+//   } on dynamic catch (late e, late t) {}
+//                            ^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:31: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   } on dynamic catch (late e, late t) {}
+//                               ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:36: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+// No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+//   } on dynamic catch (late e, late t) {}
+//                                    ^
+//
+// pkg/front_end/testcases/nnbd/later.dart:21:8: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   for (late int i = 0; i < 10; ++i) {
+//        ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:24:8: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   for (late String s in ["baz"]) {
+//        ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:27:9: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   [for (late int i = 0; i < 10; ++i) i];
+//         ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:31:14: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   await for (late String s in new Stream.fromIterable(["hest"])) {
+//              ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
+//   late String s1 = await hest();
+//                    ^^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
+//   late String s2 = '${fisk}${await hest()}${fisk}';
+//                              ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class A extends core::Object {
+  field core::int a = 42;
+  late field core::int b = this.{self::A::a}.{core::num::*}(2).{core::int::>>}(1);
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo(core::int x) → dynamic {}
+}
+class B extends core::Object {
+  late final field core::int x = 42;
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  late final field core::int x;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  method initVars() → dynamic {
+    this.{self::C::x} = 42;
+  }
+}
+static method bar(core::int x) → dynamic {}
+static method baz() → dynamic {
+  {
+    {
+      invalid-expression "pkg/front_end/testcases/nnbd/later.dart:20:36: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+  } on dynamic catch (late e, late t) {}
+                                   ^";
+    }
+    try {
+      throw "baz";
+    }
+    on dynamic catch(final dynamic late, final core::StackTrace e) {
+    }
+  }
+  for (late core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
+    core::print("baz");
+  }
+  for (late core::String s in <core::String>["baz"]) {
+    core::print(s);
+  }
+  block {
+    final core::List<core::int> #t1 = <core::int>[];
+    for (late core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1))
+      #t1.{core::List::add}(i);
+  } =>#t1;
+}
+static method hest() → dynamic async {
+  await for (late core::String s in asy::Stream::fromIterable<core::String>(<core::String*>["hest"])) {
+    core::print(s);
+  }
+  return "hest";
+}
+static method fisk() → dynamic async {
+  late core::String s1 = invalid-expression "pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
+  late String s1 = await hest();
+                   ^^^^^" as{TypeError} core::String;
+  late core::String s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
+  late String s2 = '\${fisk}\${await hest()}\${fisk}';
+                             ^^^^^"}${#C1}";
+  late core::Function f = () → asy::Future<dynamic> async => await self::hest();
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = tearoff self::fisk
+}
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
new file mode 100644
index 0000000..0973de4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
@@ -0,0 +1,248 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/later.dart:12:7: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   foo(late int x) {}
+//       ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:15:5: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+// bar(late int x) {}
+//     ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:28: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+// No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+//   } on dynamic catch (late e, late t) {}
+//                            ^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:31: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   } on dynamic catch (late e, late t) {}
+//                               ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:20:36: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+// No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+//   } on dynamic catch (late e, late t) {}
+//                                    ^
+//
+// pkg/front_end/testcases/nnbd/later.dart:21:8: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   for (late int i = 0; i < 10; ++i) {
+//        ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:24:8: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   for (late String s in ["baz"]) {
+//        ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:27:9: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   [for (late int i = 0; i < 10; ++i) i];
+//         ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:31:14: Error: Can't have modifier 'late' here.
+// Try removing 'late'.
+//   await for (late String s in new Stream.fromIterable(["hest"])) {
+//              ^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
+//   late String s1 = await hest();
+//                    ^^^^^
+//
+// pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
+//   late String s2 = '${fisk}${await hest()}${fisk}';
+//                              ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+import "dart:async" as asy;
+
+class A extends core::Object {
+  field core::int a = 42;
+  late field core::int b = this.{self::A::a}.{core::num::*}(2).{core::int::>>}(1);
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo(core::int x) → dynamic {}
+}
+class B extends core::Object {
+  late final field core::int x = 42;
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object {
+  late final field core::int x;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  method initVars() → dynamic {
+    this.{self::C::x} = 42;
+  }
+}
+static method bar(core::int x) → dynamic {}
+static method baz() → dynamic {
+  {
+    {
+      invalid-expression "pkg/front_end/testcases/nnbd/later.dart:20:36: Error: 'catch' must be followed by '(identifier)' or '(identifier, identifier)'.
+No types are needed, the first is given by 'on', the second is always 'StackTrace'.
+  } on dynamic catch (late e, late t) {}
+                                   ^";
+    }
+    try {
+      throw "baz";
+    }
+    on dynamic catch(final dynamic late, final core::StackTrace e) {
+    }
+  }
+  for (late core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
+    core::print("baz");
+  }
+  {
+    core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(<core::String>["baz"]).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      function #s#initializer() → core::String
+        return :sync-for-iterator.{core::Iterator::current};
+      late core::String s = #s#initializer.call();
+      {
+        core::print(s);
+      }
+    }
+  }
+  block {
+    final core::List<core::int> #t1 = <core::int>[];
+    for (late core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1))
+      #t1.{core::List::add}(i);
+  } =>#t1;
+}
+static method hest() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  asy::FutureOr<dynamic>? :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        {
+          dynamic :stream = asy::Stream::fromIterable<core::String>(<core::String*>["hest"]);
+          asy::_asyncStarListenHelper(:stream, :async_op);
+          asy::_StreamIterator<core::String>? :for-iterator = new asy::_StreamIterator::•<core::String>(:stream);
+          try
+            #L2:
+            while (true) {
+              dynamic #t2 = asy::_asyncStarMoveNextHelper(:stream);
+              [yield] let dynamic #t3 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
+              if(_in::unsafeCast<core::bool*>(:result)) {
+                function #s#initializer() → core::String
+                  return :for-iterator.{asy::_StreamIterator::current};
+                late core::String s = #s#initializer.call();
+                {
+                  core::print(s);
+                }
+              }
+              else
+                break #L2;
+            }
+          finally
+            if(!:for-iterator.{asy::_StreamIterator::_subscription}.{core::Object::==}(null)) {
+              [yield] let dynamic #t4 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(), :async_op_then, :async_op_error, :async_op) in null;
+              :result;
+            }
+        }
+        :return_value = "hest";
+        break #L1;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.start(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method fisk() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  asy::FutureOr<dynamic>? :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  core::int :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        function #s1#initializer() → core::String
+          return invalid-expression "pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
+  late String s1 = await hest();
+                   ^^^^^" as{TypeError} core::String;
+        late core::String s1 = #s1#initializer.call();
+        function #s2#initializer() → core::String
+          return "${#C1}${invalid-expression "pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
+  late String s2 = '\${fisk}\${await hest()}\${fisk}';
+                             ^^^^^"}${#C1}";
+        late core::String s2 = #s2#initializer.call();
+        function #f#initializer() → core::Function
+          return () → asy::Future<dynamic> /* originally async */ {
+            final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+            asy::FutureOr<dynamic>? :return_value;
+            dynamic :async_stack_trace;
+            dynamic :async_op_then;
+            dynamic :async_op_error;
+            core::int :await_jump_var = 0;
+            dynamic :await_ctx_var;
+            dynamic :saved_try_context_var0;
+            function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+              try {
+                #L4:
+                {
+                  [yield] let dynamic #t5 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                  :return_value = :result;
+                  break #L4;
+                }
+                asy::_completeOnAsyncReturn(:async_completer, :return_value);
+                return;
+              }
+              on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+                :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+              }
+            :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+            :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+            :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+            :async_completer.start(:async_op);
+            return :async_completer.{asy::Completer::future};
+          };
+        late core::Function f = #f#initializer.call();
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.start(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = tearoff self::fisk
+}
diff --git a/pkg/front_end/testcases/nnbd/list_constructor.dart b/pkg/front_end/testcases/nnbd/list_constructor.dart
new file mode 100644
index 0000000..95543ad
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/list_constructor.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.
+
+// The test checks that it's an error to invoke the default constructor of List
+// with potentially non-nullable type argument and specify the length.
+
+foo<T extends Object?>() {
+  new List<T>(42);
+  new List<int?>(42);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/list_constructor.dart.outline.expect b/pkg/front_end/testcases/nnbd/list_constructor.dart.outline.expect
new file mode 100644
index 0000000..00f17da
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/list_constructor.dart.outline.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo<T extends core::Object? = core::Object?>() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.expect b/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.expect
new file mode 100644
index 0000000..638b5be
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo<T extends core::Object? = core::Object?>() → dynamic {
+  core::List::•<self::foo::T%>(42);
+  core::List::•<core::int?>(42);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.transformed.expect
new file mode 100644
index 0000000..1f48f90
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/list_constructor.dart.strong.transformed.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo<T extends core::Object? = core::Object?>() → dynamic {
+  core::_List::•<self::foo::T%>(42);
+  core::_List::•<core::int?>(42);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.expect b/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.expect
new file mode 100644
index 0000000..638b5be
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo<T extends core::Object? = core::Object?>() → dynamic {
+  core::List::•<self::foo::T%>(42);
+  core::List::•<core::int?>(42);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.transformed.expect
new file mode 100644
index 0000000..1f48f90
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/list_constructor.dart.weak.transformed.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo<T extends core::Object? = core::Object?>() → dynamic {
+  core::_List::•<self::foo::T%>(42);
+  core::_List::•<core::int?>(42);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart
new file mode 100644
index 0000000..9db578a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+/*cfe.library: nnbd=false*/
+
+import 'member_inheritance_from_opt_in_lib.dart';
+
+class LegacyClass extends Class implements Interface {
+  int method3() => 0;
+
+  int method4() => 0;
+
+  int method6a(int a, int b) => 0;
+
+  int method6b(int a, [int b]) => 0;
+
+  int method6c([int a, int b]) => 0;
+
+  int method8a(int a, {int b: 0}) => 0;
+
+  int method8b({int a, int b: 0}) => 0;
+
+  int method10a(int a, {int b}) => 0;
+
+  int method10b({int a, int b}) => 0;
+
+  int get getter3 => 0;
+
+  int get getter4 => 0;
+
+  void set setter3(int value) {}
+
+  void set setter4(int value) {}
+
+  int field3;
+
+  int field4;
+
+  int get property3 => 0;
+
+  void set property3(int value) {}
+
+  int get property4 => 0;
+
+  void set property4(int value) {}
+
+  int property7;
+
+  int property8;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.outline.expect
new file mode 100644
index 0000000..dcd675f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.outline.expect
@@ -0,0 +1,173 @@
+library;
+import self as self;
+import "member_inheritance_from_opt_in_lib.dart" as mem;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///member_inheritance_from_opt_in_lib.dart";
+
+class LegacyClass extends mem::Class implements mem::Interface {
+  field core::int* field3;
+  field core::int* field4;
+  field core::int* property7;
+  field core::int* property8;
+  synthetic constructor •() → self::LegacyClass*
+    ;
+  method method3() → core::int*
+    ;
+  method method4() → core::int*
+    ;
+  method method6a(core::int* a, core::int* b) → core::int*
+    ;
+  method method6b(core::int* a, [core::int* b]) → core::int*
+    ;
+  method method6c([core::int* a, core::int* b]) → core::int*
+    ;
+  method method8a(core::int* a, {core::int* b = 0}) → core::int*
+    ;
+  method method8b({core::int* a, core::int* b = 0}) → core::int*
+    ;
+  method method10a(core::int* a, {core::int* b}) → core::int*
+    ;
+  method method10b({core::int* a, core::int* b}) → core::int*
+    ;
+  get getter3() → core::int*
+    ;
+  get getter4() → core::int*
+    ;
+  set setter3(core::int* value) → void
+    ;
+  set setter4(core::int* value) → void
+    ;
+  get property3() → core::int*
+    ;
+  set property3(core::int* value) → void
+    ;
+  get property4() → core::int*
+    ;
+  set property4(core::int* value) → void
+    ;
+  abstract member-signature get property6() → core::int*;
+  abstract member-signature get getter1() → core::int*;
+  abstract member-signature get field1() → core::int*;
+  abstract member-signature get field2() → core::int*;
+  abstract member-signature get getter2() → core::int*;
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
+  abstract member-signature method method9a(core::int* a, {core::int* b}) → core::int*;
+  abstract member-signature method method5c([core::int* a, core::int* b]) → core::int*;
+  abstract member-signature get property5() → core::int*;
+  abstract member-signature method method2() → core::int*;
+  abstract member-signature method method7a(core::int* a, {core::int* b}) → core::int*;
+  abstract member-signature method method5b(core::int* a, [core::int* b]) → core::int*;
+  abstract member-signature method method9b({core::int* a, core::int* b}) → core::int*;
+  abstract member-signature method method1() → core::int*;
+  abstract member-signature get property1() → core::int*;
+  abstract member-signature get property2() → core::int*;
+  abstract member-signature method method7b({core::int* a, core::int* b}) → core::int*;
+  abstract member-signature set setter1(core::int* value) → void;
+  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature set field1(core::int* _) → void;
+  abstract member-signature set field2(core::int* _) → void;
+  abstract member-signature set property5(core::int* _) → void;
+  abstract member-signature set setter2(core::int* value) → void;
+  abstract member-signature set property1(core::int* value) → void;
+  abstract member-signature set property2(core::int* value) → void;
+}
+static method main() → dynamic
+  ;
+
+library;
+import self as mem;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  field core::int? field1;
+  field core::int field2;
+  field core::int field3;
+  field core::int? field4;
+  synthetic constructor •() → mem::Interface
+    ;
+  abstract method method1() → core::int?;
+  abstract method method2() → core::int;
+  abstract method method3() → core::int;
+  abstract method method4() → core::int?;
+  abstract method method5a(core::int a, core::int? b) → core::int;
+  abstract method method5b(core::int a, [core::int? b]) → core::int;
+  abstract method method5c([core::int a = 0, core::int? b]) → core::int;
+  abstract method method6a(core::int? a, core::int b) → core::int?;
+  abstract method method6b(core::int? a, [core::int b = 0]) → core::int?;
+  abstract method method6c([core::int? a, core::int b = 0]) → core::int?;
+  abstract method method7a(core::int a, {core::int? b}) → core::int;
+  abstract method method7b({core::int a = 0, core::int? b}) → core::int;
+  abstract method method8a(core::int? a, {core::int b = 0}) → core::int?;
+  abstract method method8b({core::int? a, core::int b = 0}) → core::int?;
+  abstract method method9a(core::int a, {required core::int? b}) → core::int;
+  abstract method method9b({required core::int a, required core::int? b}) → core::int;
+  abstract method method10a(core::int? a, {required core::int b}) → core::int?;
+  abstract method method10b({required core::int? a, required core::int b}) → core::int?;
+  abstract get getter1() → core::int?;
+  abstract get getter2() → core::int;
+  abstract get getter3() → core::int;
+  abstract get getter4() → core::int?;
+  abstract set setter1(core::int? value) → void;
+  abstract set setter2(core::int value) → void;
+  abstract set setter3(core::int value) → void;
+  abstract set setter4(core::int? value) → void;
+  abstract get property1() → core::int?;
+  abstract set property1(core::int? value) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int value) → void;
+  abstract get property3() → core::int;
+  abstract set property3(core::int value) → void;
+  abstract get property4() → core::int?;
+  abstract set property4(core::int? value) → void;
+  abstract get property5() → core::int?;
+  abstract set property5(core::int? value) → void;
+  abstract get property6() → core::int;
+  abstract set property6(core::int value) → void;
+  abstract get property7() → core::int;
+  abstract set property7(core::int value) → void;
+  abstract get property8() → core::int?;
+  abstract set property8(core::int? value) → void;
+}
+class Class extends core::Object {
+  field core::int field1;
+  field core::int? field2;
+  field core::int property5;
+  field core::int? property6;
+  synthetic constructor •() → mem::Class
+    ;
+  method method1() → core::int
+    ;
+  method method2() → core::int?
+    ;
+  method method5a(core::int a, core::int? b) → core::int
+    ;
+  method method5b(core::int a, [core::int? b]) → core::int
+    ;
+  method method5c([core::int a = 0, core::int? b]) → core::int
+    ;
+  method method7a(core::int a, {core::int? b}) → core::int
+    ;
+  method method7b({core::int a = 0, core::int? b}) → core::int
+    ;
+  method method9a(core::int a, {required core::int? b}) → core::int
+    ;
+  method method9b({required core::int a, required core::int? b}) → core::int
+    ;
+  get getter1() → core::int
+    ;
+  get getter2() → core::int?
+    ;
+  set setter1(core::int value) → void
+    ;
+  set setter2(core::int? value) → void
+    ;
+  get property1() → core::int
+    ;
+  set property1(core::int value) → void
+    ;
+  get property2() → core::int?
+    ;
+  set property2(core::int? value) → void
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.expect
new file mode 100644
index 0000000..c6a3171
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.expect
@@ -0,0 +1,172 @@
+library;
+import self as self;
+import "member_inheritance_from_opt_in_lib.dart" as mem;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///member_inheritance_from_opt_in_lib.dart";
+
+class LegacyClass extends mem::Class implements mem::Interface {
+  field core::int* field3 = null;
+  field core::int* field4 = null;
+  field core::int* property7 = null;
+  field core::int* property8 = null;
+  synthetic constructor •() → self::LegacyClass*
+    : super mem::Class::•()
+    ;
+  method method3() → core::int*
+    return 0;
+  method method4() → core::int*
+    return 0;
+  method method6a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method6b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method6c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method8a(core::int* a, {core::int* b = #C2}) → core::int*
+    return 0;
+  method method8b({core::int* a = #C1, core::int* b = #C2}) → core::int*
+    return 0;
+  method method10a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method10b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  get getter3() → core::int*
+    return 0;
+  get getter4() → core::int*
+    return 0;
+  set setter3(core::int* value) → void {}
+  set setter4(core::int* value) → void {}
+  get property3() → core::int*
+    return 0;
+  set property3(core::int* value) → void {}
+  get property4() → core::int*
+    return 0;
+  set property4(core::int* value) → void {}
+  abstract member-signature get property6() → core::int*;
+  abstract member-signature get getter1() → core::int*;
+  abstract member-signature get field1() → core::int*;
+  abstract member-signature get field2() → core::int*;
+  abstract member-signature get getter2() → core::int*;
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
+  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
+  abstract member-signature get property5() → core::int*;
+  abstract member-signature method method2() → core::int*;
+  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
+  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
+  abstract member-signature method method1() → core::int*;
+  abstract member-signature get property1() → core::int*;
+  abstract member-signature get property2() → core::int*;
+  abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*;
+  abstract member-signature set setter1(core::int* value) → void;
+  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature set field1(core::int* _) → void;
+  abstract member-signature set field2(core::int* _) → void;
+  abstract member-signature set property5(core::int* _) → void;
+  abstract member-signature set setter2(core::int* value) → void;
+  abstract member-signature set property1(core::int* value) → void;
+  abstract member-signature set property2(core::int* value) → void;
+}
+static method main() → dynamic {}
+
+library;
+import self as mem;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  field core::int? field1 = null;
+  field core::int field2 = 0;
+  field core::int field3 = 0;
+  field core::int? field4 = null;
+  synthetic constructor •() → mem::Interface
+    : super core::Object::•()
+    ;
+  abstract method method1() → core::int?;
+  abstract method method2() → core::int;
+  abstract method method3() → core::int;
+  abstract method method4() → core::int?;
+  abstract method method5a(core::int a, core::int? b) → core::int;
+  abstract method method5b(core::int a, [core::int? b = #C1]) → core::int;
+  abstract method method5c([core::int a = #C2, core::int? b = #C1]) → core::int;
+  abstract method method6a(core::int? a, core::int b) → core::int?;
+  abstract method method6b(core::int? a, [core::int b = #C2]) → core::int?;
+  abstract method method6c([core::int? a = #C1, core::int b = #C2]) → core::int?;
+  abstract method method7a(core::int a, {core::int? b = #C1}) → core::int;
+  abstract method method7b({core::int a = #C2, core::int? b = #C1}) → core::int;
+  abstract method method8a(core::int? a, {core::int b = #C2}) → core::int?;
+  abstract method method8b({core::int? a = #C1, core::int b = #C2}) → core::int?;
+  abstract method method9a(core::int a, {required core::int? b = #C1}) → core::int;
+  abstract method method9b({required core::int a = #C1, required core::int? b = #C1}) → core::int;
+  abstract method method10a(core::int? a, {required core::int b = #C1}) → core::int?;
+  abstract method method10b({required core::int? a = #C1, required core::int b = #C1}) → core::int?;
+  abstract get getter1() → core::int?;
+  abstract get getter2() → core::int;
+  abstract get getter3() → core::int;
+  abstract get getter4() → core::int?;
+  abstract set setter1(core::int? value) → void;
+  abstract set setter2(core::int value) → void;
+  abstract set setter3(core::int value) → void;
+  abstract set setter4(core::int? value) → void;
+  abstract get property1() → core::int?;
+  abstract set property1(core::int? value) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int value) → void;
+  abstract get property3() → core::int;
+  abstract set property3(core::int value) → void;
+  abstract get property4() → core::int?;
+  abstract set property4(core::int? value) → void;
+  abstract get property5() → core::int?;
+  abstract set property5(core::int? value) → void;
+  abstract get property6() → core::int;
+  abstract set property6(core::int value) → void;
+  abstract get property7() → core::int;
+  abstract set property7(core::int value) → void;
+  abstract get property8() → core::int?;
+  abstract set property8(core::int? value) → void;
+}
+class Class extends core::Object {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property5 = 0;
+  field core::int? property6 = null;
+  synthetic constructor •() → mem::Class
+    : super core::Object::•()
+    ;
+  method method1() → core::int
+    return 0;
+  method method2() → core::int?
+    return 0;
+  method method5a(core::int a, core::int? b) → core::int
+    return 0;
+  method method5b(core::int a, [core::int? b = #C1]) → core::int
+    return 0;
+  method method5c([core::int a = #C2, core::int? b = #C1]) → core::int
+    return 0;
+  method method7a(core::int a, {core::int? b = #C1}) → core::int
+    return 0;
+  method method7b({core::int a = #C2, core::int? b = #C1}) → core::int
+    return 0;
+  method method9a(core::int a, {required core::int? b = #C1}) → core::int
+    return 0;
+  method method9b({required core::int a = #C1, required core::int? b = #C1}) → core::int
+    return 0;
+  get getter1() → core::int
+    return 0;
+  get getter2() → core::int?
+    return 0;
+  set setter1(core::int value) → void {}
+  set setter2(core::int? value) → void {}
+  get property1() → core::int
+    return 0;
+  set property1(core::int value) → void {}
+  get property2() → core::int?
+    return 0;
+  set property2(core::int? value) → void {}
+}
+
+constants  {
+  #C1 = null
+  #C2 = 0
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.transformed.expect
new file mode 100644
index 0000000..c6a3171
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.transformed.expect
@@ -0,0 +1,172 @@
+library;
+import self as self;
+import "member_inheritance_from_opt_in_lib.dart" as mem;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///member_inheritance_from_opt_in_lib.dart";
+
+class LegacyClass extends mem::Class implements mem::Interface {
+  field core::int* field3 = null;
+  field core::int* field4 = null;
+  field core::int* property7 = null;
+  field core::int* property8 = null;
+  synthetic constructor •() → self::LegacyClass*
+    : super mem::Class::•()
+    ;
+  method method3() → core::int*
+    return 0;
+  method method4() → core::int*
+    return 0;
+  method method6a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method6b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method6c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method8a(core::int* a, {core::int* b = #C2}) → core::int*
+    return 0;
+  method method8b({core::int* a = #C1, core::int* b = #C2}) → core::int*
+    return 0;
+  method method10a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method10b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  get getter3() → core::int*
+    return 0;
+  get getter4() → core::int*
+    return 0;
+  set setter3(core::int* value) → void {}
+  set setter4(core::int* value) → void {}
+  get property3() → core::int*
+    return 0;
+  set property3(core::int* value) → void {}
+  get property4() → core::int*
+    return 0;
+  set property4(core::int* value) → void {}
+  abstract member-signature get property6() → core::int*;
+  abstract member-signature get getter1() → core::int*;
+  abstract member-signature get field1() → core::int*;
+  abstract member-signature get field2() → core::int*;
+  abstract member-signature get getter2() → core::int*;
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
+  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
+  abstract member-signature get property5() → core::int*;
+  abstract member-signature method method2() → core::int*;
+  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
+  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
+  abstract member-signature method method1() → core::int*;
+  abstract member-signature get property1() → core::int*;
+  abstract member-signature get property2() → core::int*;
+  abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*;
+  abstract member-signature set setter1(core::int* value) → void;
+  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature set field1(core::int* _) → void;
+  abstract member-signature set field2(core::int* _) → void;
+  abstract member-signature set property5(core::int* _) → void;
+  abstract member-signature set setter2(core::int* value) → void;
+  abstract member-signature set property1(core::int* value) → void;
+  abstract member-signature set property2(core::int* value) → void;
+}
+static method main() → dynamic {}
+
+library;
+import self as mem;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  field core::int? field1 = null;
+  field core::int field2 = 0;
+  field core::int field3 = 0;
+  field core::int? field4 = null;
+  synthetic constructor •() → mem::Interface
+    : super core::Object::•()
+    ;
+  abstract method method1() → core::int?;
+  abstract method method2() → core::int;
+  abstract method method3() → core::int;
+  abstract method method4() → core::int?;
+  abstract method method5a(core::int a, core::int? b) → core::int;
+  abstract method method5b(core::int a, [core::int? b = #C1]) → core::int;
+  abstract method method5c([core::int a = #C2, core::int? b = #C1]) → core::int;
+  abstract method method6a(core::int? a, core::int b) → core::int?;
+  abstract method method6b(core::int? a, [core::int b = #C2]) → core::int?;
+  abstract method method6c([core::int? a = #C1, core::int b = #C2]) → core::int?;
+  abstract method method7a(core::int a, {core::int? b = #C1}) → core::int;
+  abstract method method7b({core::int a = #C2, core::int? b = #C1}) → core::int;
+  abstract method method8a(core::int? a, {core::int b = #C2}) → core::int?;
+  abstract method method8b({core::int? a = #C1, core::int b = #C2}) → core::int?;
+  abstract method method9a(core::int a, {required core::int? b = #C1}) → core::int;
+  abstract method method9b({required core::int a = #C1, required core::int? b = #C1}) → core::int;
+  abstract method method10a(core::int? a, {required core::int b = #C1}) → core::int?;
+  abstract method method10b({required core::int? a = #C1, required core::int b = #C1}) → core::int?;
+  abstract get getter1() → core::int?;
+  abstract get getter2() → core::int;
+  abstract get getter3() → core::int;
+  abstract get getter4() → core::int?;
+  abstract set setter1(core::int? value) → void;
+  abstract set setter2(core::int value) → void;
+  abstract set setter3(core::int value) → void;
+  abstract set setter4(core::int? value) → void;
+  abstract get property1() → core::int?;
+  abstract set property1(core::int? value) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int value) → void;
+  abstract get property3() → core::int;
+  abstract set property3(core::int value) → void;
+  abstract get property4() → core::int?;
+  abstract set property4(core::int? value) → void;
+  abstract get property5() → core::int?;
+  abstract set property5(core::int? value) → void;
+  abstract get property6() → core::int;
+  abstract set property6(core::int value) → void;
+  abstract get property7() → core::int;
+  abstract set property7(core::int value) → void;
+  abstract get property8() → core::int?;
+  abstract set property8(core::int? value) → void;
+}
+class Class extends core::Object {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property5 = 0;
+  field core::int? property6 = null;
+  synthetic constructor •() → mem::Class
+    : super core::Object::•()
+    ;
+  method method1() → core::int
+    return 0;
+  method method2() → core::int?
+    return 0;
+  method method5a(core::int a, core::int? b) → core::int
+    return 0;
+  method method5b(core::int a, [core::int? b = #C1]) → core::int
+    return 0;
+  method method5c([core::int a = #C2, core::int? b = #C1]) → core::int
+    return 0;
+  method method7a(core::int a, {core::int? b = #C1}) → core::int
+    return 0;
+  method method7b({core::int a = #C2, core::int? b = #C1}) → core::int
+    return 0;
+  method method9a(core::int a, {required core::int? b = #C1}) → core::int
+    return 0;
+  method method9b({required core::int a = #C1, required core::int? b = #C1}) → core::int
+    return 0;
+  get getter1() → core::int
+    return 0;
+  get getter2() → core::int?
+    return 0;
+  set setter1(core::int value) → void {}
+  set setter2(core::int? value) → void {}
+  get property1() → core::int
+    return 0;
+  set property1(core::int value) → void {}
+  get property2() → core::int?
+    return 0;
+  set property2(core::int? value) → void {}
+}
+
+constants  {
+  #C1 = null
+  #C2 = 0
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.expect
new file mode 100644
index 0000000..c6a3171
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.expect
@@ -0,0 +1,172 @@
+library;
+import self as self;
+import "member_inheritance_from_opt_in_lib.dart" as mem;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///member_inheritance_from_opt_in_lib.dart";
+
+class LegacyClass extends mem::Class implements mem::Interface {
+  field core::int* field3 = null;
+  field core::int* field4 = null;
+  field core::int* property7 = null;
+  field core::int* property8 = null;
+  synthetic constructor •() → self::LegacyClass*
+    : super mem::Class::•()
+    ;
+  method method3() → core::int*
+    return 0;
+  method method4() → core::int*
+    return 0;
+  method method6a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method6b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method6c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method8a(core::int* a, {core::int* b = #C2}) → core::int*
+    return 0;
+  method method8b({core::int* a = #C1, core::int* b = #C2}) → core::int*
+    return 0;
+  method method10a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method10b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  get getter3() → core::int*
+    return 0;
+  get getter4() → core::int*
+    return 0;
+  set setter3(core::int* value) → void {}
+  set setter4(core::int* value) → void {}
+  get property3() → core::int*
+    return 0;
+  set property3(core::int* value) → void {}
+  get property4() → core::int*
+    return 0;
+  set property4(core::int* value) → void {}
+  abstract member-signature get property6() → core::int*;
+  abstract member-signature get getter1() → core::int*;
+  abstract member-signature get field1() → core::int*;
+  abstract member-signature get field2() → core::int*;
+  abstract member-signature get getter2() → core::int*;
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
+  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
+  abstract member-signature get property5() → core::int*;
+  abstract member-signature method method2() → core::int*;
+  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
+  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
+  abstract member-signature method method1() → core::int*;
+  abstract member-signature get property1() → core::int*;
+  abstract member-signature get property2() → core::int*;
+  abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*;
+  abstract member-signature set setter1(core::int* value) → void;
+  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature set field1(core::int* _) → void;
+  abstract member-signature set field2(core::int* _) → void;
+  abstract member-signature set property5(core::int* _) → void;
+  abstract member-signature set setter2(core::int* value) → void;
+  abstract member-signature set property1(core::int* value) → void;
+  abstract member-signature set property2(core::int* value) → void;
+}
+static method main() → dynamic {}
+
+library;
+import self as mem;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  field core::int? field1 = null;
+  field core::int field2 = 0;
+  field core::int field3 = 0;
+  field core::int? field4 = null;
+  synthetic constructor •() → mem::Interface
+    : super core::Object::•()
+    ;
+  abstract method method1() → core::int?;
+  abstract method method2() → core::int;
+  abstract method method3() → core::int;
+  abstract method method4() → core::int?;
+  abstract method method5a(core::int a, core::int? b) → core::int;
+  abstract method method5b(core::int a, [core::int? b = #C1]) → core::int;
+  abstract method method5c([core::int a = #C2, core::int? b = #C1]) → core::int;
+  abstract method method6a(core::int? a, core::int b) → core::int?;
+  abstract method method6b(core::int? a, [core::int b = #C2]) → core::int?;
+  abstract method method6c([core::int? a = #C1, core::int b = #C2]) → core::int?;
+  abstract method method7a(core::int a, {core::int? b = #C1}) → core::int;
+  abstract method method7b({core::int a = #C2, core::int? b = #C1}) → core::int;
+  abstract method method8a(core::int? a, {core::int b = #C2}) → core::int?;
+  abstract method method8b({core::int? a = #C1, core::int b = #C2}) → core::int?;
+  abstract method method9a(core::int a, {required core::int? b = #C1}) → core::int;
+  abstract method method9b({required core::int a = #C1, required core::int? b = #C1}) → core::int;
+  abstract method method10a(core::int? a, {required core::int b = #C1}) → core::int?;
+  abstract method method10b({required core::int? a = #C1, required core::int b = #C1}) → core::int?;
+  abstract get getter1() → core::int?;
+  abstract get getter2() → core::int;
+  abstract get getter3() → core::int;
+  abstract get getter4() → core::int?;
+  abstract set setter1(core::int? value) → void;
+  abstract set setter2(core::int value) → void;
+  abstract set setter3(core::int value) → void;
+  abstract set setter4(core::int? value) → void;
+  abstract get property1() → core::int?;
+  abstract set property1(core::int? value) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int value) → void;
+  abstract get property3() → core::int;
+  abstract set property3(core::int value) → void;
+  abstract get property4() → core::int?;
+  abstract set property4(core::int? value) → void;
+  abstract get property5() → core::int?;
+  abstract set property5(core::int? value) → void;
+  abstract get property6() → core::int;
+  abstract set property6(core::int value) → void;
+  abstract get property7() → core::int;
+  abstract set property7(core::int value) → void;
+  abstract get property8() → core::int?;
+  abstract set property8(core::int? value) → void;
+}
+class Class extends core::Object {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property5 = 0;
+  field core::int? property6 = null;
+  synthetic constructor •() → mem::Class
+    : super core::Object::•()
+    ;
+  method method1() → core::int
+    return 0;
+  method method2() → core::int?
+    return 0;
+  method method5a(core::int a, core::int? b) → core::int
+    return 0;
+  method method5b(core::int a, [core::int? b = #C1]) → core::int
+    return 0;
+  method method5c([core::int a = #C2, core::int? b = #C1]) → core::int
+    return 0;
+  method method7a(core::int a, {core::int? b = #C1}) → core::int
+    return 0;
+  method method7b({core::int a = #C2, core::int? b = #C1}) → core::int
+    return 0;
+  method method9a(core::int a, {required core::int? b = #C1}) → core::int
+    return 0;
+  method method9b({required core::int a = #C1, required core::int? b = #C1}) → core::int
+    return 0;
+  get getter1() → core::int
+    return 0;
+  get getter2() → core::int?
+    return 0;
+  set setter1(core::int value) → void {}
+  set setter2(core::int? value) → void {}
+  get property1() → core::int
+    return 0;
+  set property1(core::int value) → void {}
+  get property2() → core::int?
+    return 0;
+  set property2(core::int? value) → void {}
+}
+
+constants  {
+  #C1 = null
+  #C2 = 0
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.transformed.expect
new file mode 100644
index 0000000..c6a3171
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.transformed.expect
@@ -0,0 +1,172 @@
+library;
+import self as self;
+import "member_inheritance_from_opt_in_lib.dart" as mem;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///member_inheritance_from_opt_in_lib.dart";
+
+class LegacyClass extends mem::Class implements mem::Interface {
+  field core::int* field3 = null;
+  field core::int* field4 = null;
+  field core::int* property7 = null;
+  field core::int* property8 = null;
+  synthetic constructor •() → self::LegacyClass*
+    : super mem::Class::•()
+    ;
+  method method3() → core::int*
+    return 0;
+  method method4() → core::int*
+    return 0;
+  method method6a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method6b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method6c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method8a(core::int* a, {core::int* b = #C2}) → core::int*
+    return 0;
+  method method8b({core::int* a = #C1, core::int* b = #C2}) → core::int*
+    return 0;
+  method method10a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method10b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  get getter3() → core::int*
+    return 0;
+  get getter4() → core::int*
+    return 0;
+  set setter3(core::int* value) → void {}
+  set setter4(core::int* value) → void {}
+  get property3() → core::int*
+    return 0;
+  set property3(core::int* value) → void {}
+  get property4() → core::int*
+    return 0;
+  set property4(core::int* value) → void {}
+  abstract member-signature get property6() → core::int*;
+  abstract member-signature get getter1() → core::int*;
+  abstract member-signature get field1() → core::int*;
+  abstract member-signature get field2() → core::int*;
+  abstract member-signature get getter2() → core::int*;
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
+  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
+  abstract member-signature get property5() → core::int*;
+  abstract member-signature method method2() → core::int*;
+  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
+  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
+  abstract member-signature method method1() → core::int*;
+  abstract member-signature get property1() → core::int*;
+  abstract member-signature get property2() → core::int*;
+  abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*;
+  abstract member-signature set setter1(core::int* value) → void;
+  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature set field1(core::int* _) → void;
+  abstract member-signature set field2(core::int* _) → void;
+  abstract member-signature set property5(core::int* _) → void;
+  abstract member-signature set setter2(core::int* value) → void;
+  abstract member-signature set property1(core::int* value) → void;
+  abstract member-signature set property2(core::int* value) → void;
+}
+static method main() → dynamic {}
+
+library;
+import self as mem;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  field core::int? field1 = null;
+  field core::int field2 = 0;
+  field core::int field3 = 0;
+  field core::int? field4 = null;
+  synthetic constructor •() → mem::Interface
+    : super core::Object::•()
+    ;
+  abstract method method1() → core::int?;
+  abstract method method2() → core::int;
+  abstract method method3() → core::int;
+  abstract method method4() → core::int?;
+  abstract method method5a(core::int a, core::int? b) → core::int;
+  abstract method method5b(core::int a, [core::int? b = #C1]) → core::int;
+  abstract method method5c([core::int a = #C2, core::int? b = #C1]) → core::int;
+  abstract method method6a(core::int? a, core::int b) → core::int?;
+  abstract method method6b(core::int? a, [core::int b = #C2]) → core::int?;
+  abstract method method6c([core::int? a = #C1, core::int b = #C2]) → core::int?;
+  abstract method method7a(core::int a, {core::int? b = #C1}) → core::int;
+  abstract method method7b({core::int a = #C2, core::int? b = #C1}) → core::int;
+  abstract method method8a(core::int? a, {core::int b = #C2}) → core::int?;
+  abstract method method8b({core::int? a = #C1, core::int b = #C2}) → core::int?;
+  abstract method method9a(core::int a, {required core::int? b = #C1}) → core::int;
+  abstract method method9b({required core::int a = #C1, required core::int? b = #C1}) → core::int;
+  abstract method method10a(core::int? a, {required core::int b = #C1}) → core::int?;
+  abstract method method10b({required core::int? a = #C1, required core::int b = #C1}) → core::int?;
+  abstract get getter1() → core::int?;
+  abstract get getter2() → core::int;
+  abstract get getter3() → core::int;
+  abstract get getter4() → core::int?;
+  abstract set setter1(core::int? value) → void;
+  abstract set setter2(core::int value) → void;
+  abstract set setter3(core::int value) → void;
+  abstract set setter4(core::int? value) → void;
+  abstract get property1() → core::int?;
+  abstract set property1(core::int? value) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int value) → void;
+  abstract get property3() → core::int;
+  abstract set property3(core::int value) → void;
+  abstract get property4() → core::int?;
+  abstract set property4(core::int? value) → void;
+  abstract get property5() → core::int?;
+  abstract set property5(core::int? value) → void;
+  abstract get property6() → core::int;
+  abstract set property6(core::int value) → void;
+  abstract get property7() → core::int;
+  abstract set property7(core::int value) → void;
+  abstract get property8() → core::int?;
+  abstract set property8(core::int? value) → void;
+}
+class Class extends core::Object {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property5 = 0;
+  field core::int? property6 = null;
+  synthetic constructor •() → mem::Class
+    : super core::Object::•()
+    ;
+  method method1() → core::int
+    return 0;
+  method method2() → core::int?
+    return 0;
+  method method5a(core::int a, core::int? b) → core::int
+    return 0;
+  method method5b(core::int a, [core::int? b = #C1]) → core::int
+    return 0;
+  method method5c([core::int a = #C2, core::int? b = #C1]) → core::int
+    return 0;
+  method method7a(core::int a, {core::int? b = #C1}) → core::int
+    return 0;
+  method method7b({core::int a = #C2, core::int? b = #C1}) → core::int
+    return 0;
+  method method9a(core::int a, {required core::int? b = #C1}) → core::int
+    return 0;
+  method method9b({required core::int a = #C1, required core::int? b = #C1}) → core::int
+    return 0;
+  get getter1() → core::int
+    return 0;
+  get getter2() → core::int?
+    return 0;
+  set setter1(core::int value) → void {}
+  set setter2(core::int? value) → void {}
+  get property1() → core::int
+    return 0;
+  set property1(core::int value) → void {}
+  get property2() → core::int?
+    return 0;
+  set property2(core::int? value) → void {}
+}
+
+constants  {
+  #C1 = null
+  #C2 = 0
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in_lib.dart b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in_lib.dart
new file mode 100644
index 0000000..596f43a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in_lib.dart
@@ -0,0 +1,141 @@
+// 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.
+
+abstract class Interface {
+  int? method1();
+
+  int method2();
+
+  int method3();
+
+  int? method4();
+
+  int method5a(int a, int? b);
+
+  int method5b(int a, [int? b]);
+
+  int method5c([int a = 0, int? b]);
+
+  int? method6a(int? a, int b);
+
+  int? method6b(int? a, [int b = 0]);
+
+  int? method6c([int? a, int b = 0]);
+
+  int method7a(int a, {int? b});
+
+  int method7b({int a: 0, int? b});
+
+  int? method8a(int? a, {int b: 0});
+
+  int? method8b({int? a, int b: 0});
+
+  int method9a(int a, {required int? b});
+
+  int method9b({required int a, required int? b});
+
+  int? method10a(int? a, {required int b});
+
+  int? method10b({required int? a, required int b});
+
+  int? get getter1;
+
+  int get getter2;
+
+  int get getter3;
+
+  int? get getter4;
+
+  void set setter1(int? value);
+
+  void set setter2(int value);
+
+  void set setter3(int value);
+
+  void set setter4(int? value);
+
+  int? field1;
+
+  int field2 = 0;
+
+  int field3 = 0;
+
+  int? field4;
+
+  int? get property1;
+
+  void set property1(int? value);
+
+  int get property2;
+
+  void set property2(int value);
+
+  int get property3;
+
+  void set property3(int value);
+
+  int? get property4;
+
+  void set property4(int? value);
+
+  int? get property5;
+
+  void set property5(int? value);
+
+  int get property6;
+
+  void set property6(int value);
+
+  int get property7;
+
+  void set property7(int value);
+
+  int? get property8;
+
+  void set property8(int? value);
+}
+
+class Class {
+  int method1() => 0;
+
+  int? method2() => 0;
+
+  int method5a(int a, int? b) => 0;
+
+  int method5b(int a, [int? b]) => 0;
+
+  int method5c([int a = 0, int? b]) => 0;
+
+  int method7a(int a, {int? b}) => 0;
+
+  int method7b({int a = 0, int? b}) => 0;
+
+  int method9a(int a, {required int? b}) => 0;
+
+  int method9b({required int a, required int? b}) => 0;
+
+  int get getter1 => 0;
+
+  int? get getter2 => 0;
+
+  void set setter1(int value) {}
+
+  void set setter2(int? value) {}
+
+  int field1 = 0;
+
+  int? field2;
+
+  int get property1 => 0;
+
+  void set property1(int value) {}
+
+  int? get property2 => 0;
+
+  void set property2(int? value) {}
+
+  int property5 = 0;
+
+  int? property6;
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart
new file mode 100644
index 0000000..cd4a076
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart
@@ -0,0 +1,143 @@
+// 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 main;
+
+import 'member_inheritance_from_opt_out_lib.dart';
+
+abstract class Interface {
+  int method1();
+
+  int? method2();
+
+  int method3a(int a, int b);
+
+  int method3b(int a, [int b]);
+
+  int method3c([int a, int b]);
+
+  int? method4a(int? a, int? b);
+
+  int? method4b(int? a, [int? b]);
+
+  int? method4c([int? a, int? b]);
+
+  int method5a(int a, {int b: 0});
+
+  int method5b({int a: 0, int b: 0});
+
+  int method5c({required int a, required int b});
+
+  int? method6a(int? a, {int? b});
+
+  int? method6b({int? a, int? b});
+
+  int? method6c({required int? a, required int? b});
+
+  int get getter1;
+
+  int? get getter2;
+
+  void set setter1(int value);
+
+  void set setter2(int? value);
+
+  int field1 = 0;
+
+  int? field2;
+
+  int get field3;
+
+  void set field3(int value);
+
+  int? get field4;
+
+  void set field4(int? value);
+
+  int get property1;
+
+  void set property1(int value);
+
+  int? get property2;
+
+  void set property2(int? value);
+
+  int property3 = 0;
+
+  int? property4;
+}
+
+class Class1 extends LegacyClass {}
+
+class Class2a extends LegacyClass implements Interface {}
+
+class Class2b extends LegacyClass implements Interface {
+  int method1() => 0;
+
+  int? method2() => 0;
+
+  int method3a(int a, int b) => 0;
+
+  int method3b(int a, [int b]) => 0;
+
+  int method3c([int a, int b]) => 0;
+
+  int? method4a(int? a, int? b) => 0;
+
+  int? method4b(int? a, [int? b]) => 0;
+
+  int? method4c([int? a, int? b]) => 0;
+
+  int method5a(int a, {int b: 0}) => 0;
+
+  int method5b({int a: 0, int b: 0}) => 0;
+
+  int method5c({required int a, required int b}) => 0;
+
+  int? method6a(int? a, {int? b}) => 0;
+
+  int? method6b({int? a, int? b}) => 0;
+
+  int? method6c({required int? a, required int? b}) => 0;
+
+  int get getter1 => 0;
+
+  int? get getter2 => 0;
+
+  void set setter1(int value) {}
+
+  void set setter2(int? value) {}
+
+  int field1 = 0;
+
+  int? field2;
+
+  int get field3 => 0;
+
+  void set field3(int value) {}
+
+  int? get field4 => 0;
+
+  void set field4(int? value) {}
+
+  int get property1 => 0;
+
+  void set property1(int value) {}
+
+  int? get property2 => 0;
+
+  void set property2(int? value) {}
+
+  int property3 = 0;
+
+  int? property4;
+}
+
+class Class3a extends GenericLegacyClass<int> {}
+
+class Class3b extends GenericLegacyClass<int?> {}
+
+class Class3c<S> extends GenericLegacyClass<S> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.outline.expect
new file mode 100644
index 0000000..ea1d831
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.outline.expect
@@ -0,0 +1,228 @@
+library main;
+import self as self;
+import "dart:core" as core;
+import "member_inheritance_from_opt_out_lib.dart" as opt;
+
+import "org-dartlang-testcase:///member_inheritance_from_opt_out_lib.dart";
+
+abstract class Interface extends core::Object {
+  field core::int field1;
+  field core::int? field2;
+  field core::int property3;
+  field core::int? property4;
+  synthetic constructor •() → self::Interface
+    ;
+  abstract method method1() → core::int;
+  abstract method method2() → core::int?;
+  abstract method method3a(core::int a, core::int b) → core::int;
+  abstract method method3b(core::int a, [core::int b]) → core::int;
+  abstract method method3c([core::int a, core::int b]) → core::int;
+  abstract method method4a(core::int? a, core::int? b) → core::int?;
+  abstract method method4b(core::int? a, [core::int? b]) → core::int?;
+  abstract method method4c([core::int? a, core::int? b]) → core::int?;
+  abstract method method5a(core::int a, {core::int b = 0}) → core::int;
+  abstract method method5b({core::int a = 0, core::int b = 0}) → core::int;
+  abstract method method5c({required core::int a, required core::int b}) → core::int;
+  abstract method method6a(core::int? a, {core::int? b}) → core::int?;
+  abstract method method6b({core::int? a, core::int? b}) → core::int?;
+  abstract method method6c({required core::int? a, required core::int? b}) → core::int?;
+  abstract get getter1() → core::int;
+  abstract get getter2() → core::int?;
+  abstract set setter1(core::int value) → void;
+  abstract set setter2(core::int? value) → void;
+  abstract get field3() → core::int;
+  abstract set field3(core::int value) → void;
+  abstract get field4() → core::int?;
+  abstract set field4(core::int? value) → void;
+  abstract get property1() → core::int;
+  abstract set property1(core::int value) → void;
+  abstract get property2() → core::int?;
+  abstract set property2(core::int? value) → void;
+}
+class Class1 extends opt::LegacyClass {
+  synthetic constructor •() → self::Class1
+    ;
+}
+class Class2a extends opt::LegacyClass implements self::Interface {
+  synthetic constructor •() → self::Class2a
+    ;
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
+  abstract member-signature method method4c([core::int? a, core::int? b]) → core::int?;
+  abstract member-signature get getter1() → core::int;
+  abstract member-signature get field1() → core::int;
+  abstract member-signature method method3a(core::int a, core::int b) → core::int;
+  abstract member-signature get field4() → core::int?;
+  abstract member-signature get property3() → core::int;
+  abstract member-signature get field2() → core::int?;
+  abstract member-signature method method6a(core::int? a, {core::int? b}) → core::int?;
+  abstract member-signature get getter2() → core::int?;
+  abstract member-signature method method5a(core::int a, {core::int b}) → core::int;
+  abstract member-signature method method5c({core::int a, core::int b}) → core::int;
+  abstract member-signature get property4() → core::int?;
+  abstract member-signature method method6b({core::int? a, core::int? b}) → core::int?;
+  abstract member-signature method method6c({core::int? a, core::int? b}) → core::int?;
+  abstract member-signature method method2() → core::int?;
+  abstract member-signature method method5b({core::int a, core::int b}) → core::int;
+  abstract member-signature method method4b(core::int? a, [core::int? b]) → core::int?;
+  abstract member-signature get field3() → core::int;
+  abstract member-signature method method3c([core::int a, core::int b]) → core::int;
+  abstract member-signature method method1() → core::int;
+  abstract member-signature get property1() → core::int;
+  abstract member-signature get property2() → core::int?;
+  abstract member-signature method method3b(core::int a, [core::int b]) → core::int;
+  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature set field1(core::int _) → void;
+  abstract member-signature set field4(core::int? _) → void;
+  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature set field2(core::int? _) → void;
+  abstract member-signature set property4(core::int? value) → void;
+  abstract member-signature set setter2(core::int? value) → void;
+  abstract member-signature set field3(core::int _) → void;
+  abstract member-signature set property1(core::int value) → void;
+  abstract member-signature set property2(core::int? value) → void;
+}
+class Class2b extends opt::LegacyClass implements self::Interface {
+  field core::int field1;
+  field core::int? field2;
+  field core::int property3;
+  field core::int? property4;
+  synthetic constructor •() → self::Class2b
+    ;
+  method method1() → core::int
+    ;
+  method method2() → core::int?
+    ;
+  method method3a(core::int a, core::int b) → core::int
+    ;
+  method method3b(core::int a, [core::int b]) → core::int
+    ;
+  method method3c([core::int a, core::int b]) → core::int
+    ;
+  method method4a(core::int? a, core::int? b) → core::int?
+    ;
+  method method4b(core::int? a, [core::int? b]) → core::int?
+    ;
+  method method4c([core::int? a, core::int? b]) → core::int?
+    ;
+  method method5a(core::int a, {core::int b = 0}) → core::int
+    ;
+  method method5b({core::int a = 0, core::int b = 0}) → core::int
+    ;
+  method method5c({required core::int a, required core::int b}) → core::int
+    ;
+  method method6a(core::int? a, {core::int? b}) → core::int?
+    ;
+  method method6b({core::int? a, core::int? b}) → core::int?
+    ;
+  method method6c({required core::int? a, required core::int? b}) → core::int?
+    ;
+  get getter1() → core::int
+    ;
+  get getter2() → core::int?
+    ;
+  set setter1(core::int value) → void
+    ;
+  set setter2(core::int? value) → void
+    ;
+  get field3() → core::int
+    ;
+  set field3(core::int value) → void
+    ;
+  get field4() → core::int?
+    ;
+  set field4(core::int? value) → void
+    ;
+  get property1() → core::int
+    ;
+  set property1(core::int value) → void
+    ;
+  get property2() → core::int?
+    ;
+  set property2(core::int? value) → void
+    ;
+}
+class Class3a extends opt::GenericLegacyClass<core::int> {
+  synthetic constructor •() → self::Class3a
+    ;
+}
+class Class3b extends opt::GenericLegacyClass<core::int?> {
+  synthetic constructor •() → self::Class3b
+    ;
+}
+class Class3c<S extends core::Object? = dynamic> extends opt::GenericLegacyClass<self::Class3c::S%> {
+  synthetic constructor •() → self::Class3c<self::Class3c::S%>
+    ;
+}
+static method main() → dynamic
+  ;
+
+library opt_out;
+import self as opt;
+import "dart:core" as core;
+
+class LegacyClass extends core::Object {
+  field core::int* field1;
+  field core::int* field2;
+  field core::int* field3;
+  field core::int* field4;
+  synthetic constructor •() → opt::LegacyClass*
+    ;
+  method method1() → core::int*
+    ;
+  method method2() → core::int*
+    ;
+  method method3a(core::int* a, core::int* b) → core::int*
+    ;
+  method method3b(core::int* a, [core::int* b]) → core::int*
+    ;
+  method method3c([core::int* a, core::int* b]) → core::int*
+    ;
+  method method4a(core::int* a, core::int* b) → core::int*
+    ;
+  method method4b(core::int* a, [core::int* b]) → core::int*
+    ;
+  method method4c([core::int* a, core::int* b]) → core::int*
+    ;
+  method method5a(core::int* a, {core::int* b}) → core::int*
+    ;
+  method method5b({core::int* a, core::int* b}) → core::int*
+    ;
+  method method5c({core::int* a, core::int* b}) → core::int*
+    ;
+  method method6a(core::int* a, {core::int* b}) → core::int*
+    ;
+  method method6b({core::int* a, core::int* b}) → core::int*
+    ;
+  method method6c({core::int* a, core::int* b}) → core::int*
+    ;
+  get getter1() → core::int*
+    ;
+  get getter2() → core::int*
+    ;
+  set setter1(core::int* value) → void
+    ;
+  set setter2(core::int* value) → void
+    ;
+  get property1() → core::int*
+    ;
+  set property1(core::int* value) → void
+    ;
+  get property2() → core::int*
+    ;
+  set property2(core::int* value) → void
+    ;
+  get property3() → core::int*
+    ;
+  set property3(core::int* value) → void
+    ;
+  get property4() → core::int*
+    ;
+  set property4(core::int* value) → void
+    ;
+}
+class GenericLegacyClass<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → opt::GenericLegacyClass<opt::GenericLegacyClass::T*>*
+    ;
+  method method1() → opt::GenericLegacyClass::T*
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.expect
new file mode 100644
index 0000000..0f04f45
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.expect
@@ -0,0 +1,229 @@
+library main;
+import self as self;
+import "dart:core" as core;
+import "member_inheritance_from_opt_out_lib.dart" as opt;
+
+import "org-dartlang-testcase:///member_inheritance_from_opt_out_lib.dart";
+
+abstract class Interface extends core::Object {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property3 = 0;
+  field core::int? property4 = null;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract method method1() → core::int;
+  abstract method method2() → core::int?;
+  abstract method method3a(core::int a, core::int b) → core::int;
+  abstract method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract method method4a(core::int? a, core::int? b) → core::int?;
+  abstract method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
+  abstract method method5a(core::int a, {core::int b = #C2}) → core::int;
+  abstract method method5b({core::int a = #C2, core::int b = #C2}) → core::int;
+  abstract method method5c({required core::int a = #C1, required core::int b = #C1}) → core::int;
+  abstract method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
+  abstract method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract method method6c({required core::int? a = #C1, required core::int? b = #C1}) → core::int?;
+  abstract get getter1() → core::int;
+  abstract get getter2() → core::int?;
+  abstract set setter1(core::int value) → void;
+  abstract set setter2(core::int? value) → void;
+  abstract get field3() → core::int;
+  abstract set field3(core::int value) → void;
+  abstract get field4() → core::int?;
+  abstract set field4(core::int? value) → void;
+  abstract get property1() → core::int;
+  abstract set property1(core::int value) → void;
+  abstract get property2() → core::int?;
+  abstract set property2(core::int? value) → void;
+}
+class Class1 extends opt::LegacyClass {
+  synthetic constructor •() → self::Class1
+    : super opt::LegacyClass::•()
+    ;
+}
+class Class2a extends opt::LegacyClass implements self::Interface {
+  synthetic constructor •() → self::Class2a
+    : super opt::LegacyClass::•()
+    ;
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
+  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
+  abstract member-signature get getter1() → core::int;
+  abstract member-signature get field1() → core::int;
+  abstract member-signature method method3a(core::int a, core::int b) → core::int;
+  abstract member-signature get field4() → core::int?;
+  abstract member-signature get property3() → core::int;
+  abstract member-signature get field2() → core::int?;
+  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
+  abstract member-signature get getter2() → core::int?;
+  abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int;
+  abstract member-signature method method5c({core::int a = #C1, core::int b = #C1}) → core::int;
+  abstract member-signature get property4() → core::int?;
+  abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract member-signature method method6c({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract member-signature method method2() → core::int?;
+  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
+  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract member-signature get field3() → core::int;
+  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract member-signature method method1() → core::int;
+  abstract member-signature get property1() → core::int;
+  abstract member-signature get property2() → core::int?;
+  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature set field1(core::int _) → void;
+  abstract member-signature set field4(core::int? _) → void;
+  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature set field2(core::int? _) → void;
+  abstract member-signature set property4(core::int? value) → void;
+  abstract member-signature set setter2(core::int? value) → void;
+  abstract member-signature set field3(core::int _) → void;
+  abstract member-signature set property1(core::int value) → void;
+  abstract member-signature set property2(core::int? value) → void;
+}
+class Class2b extends opt::LegacyClass implements self::Interface {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property3 = 0;
+  field core::int? property4 = null;
+  synthetic constructor •() → self::Class2b
+    : super opt::LegacyClass::•()
+    ;
+  method method1() → core::int
+    return 0;
+  method method2() → core::int?
+    return 0;
+  method method3a(core::int a, core::int b) → core::int
+    return 0;
+  method method3b(core::int a, [core::int b = #C1]) → core::int
+    return 0;
+  method method3c([core::int a = #C1, core::int b = #C1]) → core::int
+    return 0;
+  method method4a(core::int? a, core::int? b) → core::int?
+    return 0;
+  method method4b(core::int? a, [core::int? b = #C1]) → core::int?
+    return 0;
+  method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?
+    return 0;
+  method method5a(core::int a, {core::int b = #C2}) → core::int
+    return 0;
+  method method5b({core::int a = #C2, core::int b = #C2}) → core::int
+    return 0;
+  method method5c({required core::int a = #C1, required core::int b = #C1}) → core::int
+    return 0;
+  method method6a(core::int? a, {core::int? b = #C1}) → core::int?
+    return 0;
+  method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?
+    return 0;
+  method method6c({required core::int? a = #C1, required core::int? b = #C1}) → core::int?
+    return 0;
+  get getter1() → core::int
+    return 0;
+  get getter2() → core::int?
+    return 0;
+  set setter1(core::int value) → void {}
+  set setter2(core::int? value) → void {}
+  get field3() → core::int
+    return 0;
+  set field3(core::int value) → void {}
+  get field4() → core::int?
+    return 0;
+  set field4(core::int? value) → void {}
+  get property1() → core::int
+    return 0;
+  set property1(core::int value) → void {}
+  get property2() → core::int?
+    return 0;
+  set property2(core::int? value) → void {}
+}
+class Class3a extends opt::GenericLegacyClass<core::int> {
+  synthetic constructor •() → self::Class3a
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+class Class3b extends opt::GenericLegacyClass<core::int?> {
+  synthetic constructor •() → self::Class3b
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+class Class3c<S extends core::Object? = dynamic> extends opt::GenericLegacyClass<self::Class3c::S%> {
+  synthetic constructor •() → self::Class3c<self::Class3c::S%>
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+static method main() → dynamic {}
+
+library opt_out;
+import self as opt;
+import "dart:core" as core;
+
+class LegacyClass extends core::Object {
+  field core::int* field1 = null;
+  field core::int* field2 = null;
+  field core::int* field3 = null;
+  field core::int* field4 = null;
+  synthetic constructor •() → opt::LegacyClass*
+    : super core::Object::•()
+    ;
+  method method1() → core::int*
+    return 0;
+  method method2() → core::int*
+    return 0;
+  method method3a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method3b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method3c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method4a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method4b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method4c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method5a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method5b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method5c({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method6a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method6b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method6c({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  get getter1() → core::int*
+    return 0;
+  get getter2() → core::int*
+    return 0;
+  set setter1(core::int* value) → void {}
+  set setter2(core::int* value) → void {}
+  get property1() → core::int*
+    return 0;
+  set property1(core::int* value) → void {}
+  get property2() → core::int*
+    return 0;
+  set property2(core::int* value) → void {}
+  get property3() → core::int*
+    return 0;
+  set property3(core::int* value) → void {}
+  get property4() → core::int*
+    return 0;
+  set property4(core::int* value) → void {}
+}
+class GenericLegacyClass<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → opt::GenericLegacyClass<opt::GenericLegacyClass::T*>*
+    : super core::Object::•()
+    ;
+  method method1() → opt::GenericLegacyClass::T*
+    return null;
+}
+
+constants  {
+  #C1 = null
+  #C2 = 0
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.transformed.expect
new file mode 100644
index 0000000..0f04f45
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.transformed.expect
@@ -0,0 +1,229 @@
+library main;
+import self as self;
+import "dart:core" as core;
+import "member_inheritance_from_opt_out_lib.dart" as opt;
+
+import "org-dartlang-testcase:///member_inheritance_from_opt_out_lib.dart";
+
+abstract class Interface extends core::Object {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property3 = 0;
+  field core::int? property4 = null;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract method method1() → core::int;
+  abstract method method2() → core::int?;
+  abstract method method3a(core::int a, core::int b) → core::int;
+  abstract method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract method method4a(core::int? a, core::int? b) → core::int?;
+  abstract method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
+  abstract method method5a(core::int a, {core::int b = #C2}) → core::int;
+  abstract method method5b({core::int a = #C2, core::int b = #C2}) → core::int;
+  abstract method method5c({required core::int a = #C1, required core::int b = #C1}) → core::int;
+  abstract method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
+  abstract method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract method method6c({required core::int? a = #C1, required core::int? b = #C1}) → core::int?;
+  abstract get getter1() → core::int;
+  abstract get getter2() → core::int?;
+  abstract set setter1(core::int value) → void;
+  abstract set setter2(core::int? value) → void;
+  abstract get field3() → core::int;
+  abstract set field3(core::int value) → void;
+  abstract get field4() → core::int?;
+  abstract set field4(core::int? value) → void;
+  abstract get property1() → core::int;
+  abstract set property1(core::int value) → void;
+  abstract get property2() → core::int?;
+  abstract set property2(core::int? value) → void;
+}
+class Class1 extends opt::LegacyClass {
+  synthetic constructor •() → self::Class1
+    : super opt::LegacyClass::•()
+    ;
+}
+class Class2a extends opt::LegacyClass implements self::Interface {
+  synthetic constructor •() → self::Class2a
+    : super opt::LegacyClass::•()
+    ;
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
+  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
+  abstract member-signature get getter1() → core::int;
+  abstract member-signature get field1() → core::int;
+  abstract member-signature method method3a(core::int a, core::int b) → core::int;
+  abstract member-signature get field4() → core::int?;
+  abstract member-signature get property3() → core::int;
+  abstract member-signature get field2() → core::int?;
+  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
+  abstract member-signature get getter2() → core::int?;
+  abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int;
+  abstract member-signature method method5c({core::int a = #C1, core::int b = #C1}) → core::int;
+  abstract member-signature get property4() → core::int?;
+  abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract member-signature method method6c({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract member-signature method method2() → core::int?;
+  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
+  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract member-signature get field3() → core::int;
+  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract member-signature method method1() → core::int;
+  abstract member-signature get property1() → core::int;
+  abstract member-signature get property2() → core::int?;
+  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature set field1(core::int _) → void;
+  abstract member-signature set field4(core::int? _) → void;
+  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature set field2(core::int? _) → void;
+  abstract member-signature set property4(core::int? value) → void;
+  abstract member-signature set setter2(core::int? value) → void;
+  abstract member-signature set field3(core::int _) → void;
+  abstract member-signature set property1(core::int value) → void;
+  abstract member-signature set property2(core::int? value) → void;
+}
+class Class2b extends opt::LegacyClass implements self::Interface {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property3 = 0;
+  field core::int? property4 = null;
+  synthetic constructor •() → self::Class2b
+    : super opt::LegacyClass::•()
+    ;
+  method method1() → core::int
+    return 0;
+  method method2() → core::int?
+    return 0;
+  method method3a(core::int a, core::int b) → core::int
+    return 0;
+  method method3b(core::int a, [core::int b = #C1]) → core::int
+    return 0;
+  method method3c([core::int a = #C1, core::int b = #C1]) → core::int
+    return 0;
+  method method4a(core::int? a, core::int? b) → core::int?
+    return 0;
+  method method4b(core::int? a, [core::int? b = #C1]) → core::int?
+    return 0;
+  method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?
+    return 0;
+  method method5a(core::int a, {core::int b = #C2}) → core::int
+    return 0;
+  method method5b({core::int a = #C2, core::int b = #C2}) → core::int
+    return 0;
+  method method5c({required core::int a = #C1, required core::int b = #C1}) → core::int
+    return 0;
+  method method6a(core::int? a, {core::int? b = #C1}) → core::int?
+    return 0;
+  method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?
+    return 0;
+  method method6c({required core::int? a = #C1, required core::int? b = #C1}) → core::int?
+    return 0;
+  get getter1() → core::int
+    return 0;
+  get getter2() → core::int?
+    return 0;
+  set setter1(core::int value) → void {}
+  set setter2(core::int? value) → void {}
+  get field3() → core::int
+    return 0;
+  set field3(core::int value) → void {}
+  get field4() → core::int?
+    return 0;
+  set field4(core::int? value) → void {}
+  get property1() → core::int
+    return 0;
+  set property1(core::int value) → void {}
+  get property2() → core::int?
+    return 0;
+  set property2(core::int? value) → void {}
+}
+class Class3a extends opt::GenericLegacyClass<core::int> {
+  synthetic constructor •() → self::Class3a
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+class Class3b extends opt::GenericLegacyClass<core::int?> {
+  synthetic constructor •() → self::Class3b
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+class Class3c<S extends core::Object? = dynamic> extends opt::GenericLegacyClass<self::Class3c::S%> {
+  synthetic constructor •() → self::Class3c<self::Class3c::S%>
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+static method main() → dynamic {}
+
+library opt_out;
+import self as opt;
+import "dart:core" as core;
+
+class LegacyClass extends core::Object {
+  field core::int* field1 = null;
+  field core::int* field2 = null;
+  field core::int* field3 = null;
+  field core::int* field4 = null;
+  synthetic constructor •() → opt::LegacyClass*
+    : super core::Object::•()
+    ;
+  method method1() → core::int*
+    return 0;
+  method method2() → core::int*
+    return 0;
+  method method3a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method3b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method3c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method4a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method4b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method4c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method5a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method5b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method5c({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method6a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method6b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method6c({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  get getter1() → core::int*
+    return 0;
+  get getter2() → core::int*
+    return 0;
+  set setter1(core::int* value) → void {}
+  set setter2(core::int* value) → void {}
+  get property1() → core::int*
+    return 0;
+  set property1(core::int* value) → void {}
+  get property2() → core::int*
+    return 0;
+  set property2(core::int* value) → void {}
+  get property3() → core::int*
+    return 0;
+  set property3(core::int* value) → void {}
+  get property4() → core::int*
+    return 0;
+  set property4(core::int* value) → void {}
+}
+class GenericLegacyClass<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → opt::GenericLegacyClass<opt::GenericLegacyClass::T*>*
+    : super core::Object::•()
+    ;
+  method method1() → opt::GenericLegacyClass::T*
+    return null;
+}
+
+constants  {
+  #C1 = null
+  #C2 = 0
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.expect
new file mode 100644
index 0000000..0f04f45
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.expect
@@ -0,0 +1,229 @@
+library main;
+import self as self;
+import "dart:core" as core;
+import "member_inheritance_from_opt_out_lib.dart" as opt;
+
+import "org-dartlang-testcase:///member_inheritance_from_opt_out_lib.dart";
+
+abstract class Interface extends core::Object {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property3 = 0;
+  field core::int? property4 = null;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract method method1() → core::int;
+  abstract method method2() → core::int?;
+  abstract method method3a(core::int a, core::int b) → core::int;
+  abstract method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract method method4a(core::int? a, core::int? b) → core::int?;
+  abstract method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
+  abstract method method5a(core::int a, {core::int b = #C2}) → core::int;
+  abstract method method5b({core::int a = #C2, core::int b = #C2}) → core::int;
+  abstract method method5c({required core::int a = #C1, required core::int b = #C1}) → core::int;
+  abstract method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
+  abstract method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract method method6c({required core::int? a = #C1, required core::int? b = #C1}) → core::int?;
+  abstract get getter1() → core::int;
+  abstract get getter2() → core::int?;
+  abstract set setter1(core::int value) → void;
+  abstract set setter2(core::int? value) → void;
+  abstract get field3() → core::int;
+  abstract set field3(core::int value) → void;
+  abstract get field4() → core::int?;
+  abstract set field4(core::int? value) → void;
+  abstract get property1() → core::int;
+  abstract set property1(core::int value) → void;
+  abstract get property2() → core::int?;
+  abstract set property2(core::int? value) → void;
+}
+class Class1 extends opt::LegacyClass {
+  synthetic constructor •() → self::Class1
+    : super opt::LegacyClass::•()
+    ;
+}
+class Class2a extends opt::LegacyClass implements self::Interface {
+  synthetic constructor •() → self::Class2a
+    : super opt::LegacyClass::•()
+    ;
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
+  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
+  abstract member-signature get getter1() → core::int;
+  abstract member-signature get field1() → core::int;
+  abstract member-signature method method3a(core::int a, core::int b) → core::int;
+  abstract member-signature get field4() → core::int?;
+  abstract member-signature get property3() → core::int;
+  abstract member-signature get field2() → core::int?;
+  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
+  abstract member-signature get getter2() → core::int?;
+  abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int;
+  abstract member-signature method method5c({core::int a = #C1, core::int b = #C1}) → core::int;
+  abstract member-signature get property4() → core::int?;
+  abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract member-signature method method6c({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract member-signature method method2() → core::int?;
+  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
+  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract member-signature get field3() → core::int;
+  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract member-signature method method1() → core::int;
+  abstract member-signature get property1() → core::int;
+  abstract member-signature get property2() → core::int?;
+  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature set field1(core::int _) → void;
+  abstract member-signature set field4(core::int? _) → void;
+  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature set field2(core::int? _) → void;
+  abstract member-signature set property4(core::int? value) → void;
+  abstract member-signature set setter2(core::int? value) → void;
+  abstract member-signature set field3(core::int _) → void;
+  abstract member-signature set property1(core::int value) → void;
+  abstract member-signature set property2(core::int? value) → void;
+}
+class Class2b extends opt::LegacyClass implements self::Interface {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property3 = 0;
+  field core::int? property4 = null;
+  synthetic constructor •() → self::Class2b
+    : super opt::LegacyClass::•()
+    ;
+  method method1() → core::int
+    return 0;
+  method method2() → core::int?
+    return 0;
+  method method3a(core::int a, core::int b) → core::int
+    return 0;
+  method method3b(core::int a, [core::int b = #C1]) → core::int
+    return 0;
+  method method3c([core::int a = #C1, core::int b = #C1]) → core::int
+    return 0;
+  method method4a(core::int? a, core::int? b) → core::int?
+    return 0;
+  method method4b(core::int? a, [core::int? b = #C1]) → core::int?
+    return 0;
+  method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?
+    return 0;
+  method method5a(core::int a, {core::int b = #C2}) → core::int
+    return 0;
+  method method5b({core::int a = #C2, core::int b = #C2}) → core::int
+    return 0;
+  method method5c({required core::int a = #C1, required core::int b = #C1}) → core::int
+    return 0;
+  method method6a(core::int? a, {core::int? b = #C1}) → core::int?
+    return 0;
+  method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?
+    return 0;
+  method method6c({required core::int? a = #C1, required core::int? b = #C1}) → core::int?
+    return 0;
+  get getter1() → core::int
+    return 0;
+  get getter2() → core::int?
+    return 0;
+  set setter1(core::int value) → void {}
+  set setter2(core::int? value) → void {}
+  get field3() → core::int
+    return 0;
+  set field3(core::int value) → void {}
+  get field4() → core::int?
+    return 0;
+  set field4(core::int? value) → void {}
+  get property1() → core::int
+    return 0;
+  set property1(core::int value) → void {}
+  get property2() → core::int?
+    return 0;
+  set property2(core::int? value) → void {}
+}
+class Class3a extends opt::GenericLegacyClass<core::int> {
+  synthetic constructor •() → self::Class3a
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+class Class3b extends opt::GenericLegacyClass<core::int?> {
+  synthetic constructor •() → self::Class3b
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+class Class3c<S extends core::Object? = dynamic> extends opt::GenericLegacyClass<self::Class3c::S%> {
+  synthetic constructor •() → self::Class3c<self::Class3c::S%>
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+static method main() → dynamic {}
+
+library opt_out;
+import self as opt;
+import "dart:core" as core;
+
+class LegacyClass extends core::Object {
+  field core::int* field1 = null;
+  field core::int* field2 = null;
+  field core::int* field3 = null;
+  field core::int* field4 = null;
+  synthetic constructor •() → opt::LegacyClass*
+    : super core::Object::•()
+    ;
+  method method1() → core::int*
+    return 0;
+  method method2() → core::int*
+    return 0;
+  method method3a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method3b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method3c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method4a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method4b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method4c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method5a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method5b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method5c({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method6a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method6b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method6c({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  get getter1() → core::int*
+    return 0;
+  get getter2() → core::int*
+    return 0;
+  set setter1(core::int* value) → void {}
+  set setter2(core::int* value) → void {}
+  get property1() → core::int*
+    return 0;
+  set property1(core::int* value) → void {}
+  get property2() → core::int*
+    return 0;
+  set property2(core::int* value) → void {}
+  get property3() → core::int*
+    return 0;
+  set property3(core::int* value) → void {}
+  get property4() → core::int*
+    return 0;
+  set property4(core::int* value) → void {}
+}
+class GenericLegacyClass<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → opt::GenericLegacyClass<opt::GenericLegacyClass::T*>*
+    : super core::Object::•()
+    ;
+  method method1() → opt::GenericLegacyClass::T*
+    return null;
+}
+
+constants  {
+  #C1 = null
+  #C2 = 0
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.transformed.expect
new file mode 100644
index 0000000..0f04f45
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.transformed.expect
@@ -0,0 +1,229 @@
+library main;
+import self as self;
+import "dart:core" as core;
+import "member_inheritance_from_opt_out_lib.dart" as opt;
+
+import "org-dartlang-testcase:///member_inheritance_from_opt_out_lib.dart";
+
+abstract class Interface extends core::Object {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property3 = 0;
+  field core::int? property4 = null;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract method method1() → core::int;
+  abstract method method2() → core::int?;
+  abstract method method3a(core::int a, core::int b) → core::int;
+  abstract method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract method method4a(core::int? a, core::int? b) → core::int?;
+  abstract method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
+  abstract method method5a(core::int a, {core::int b = #C2}) → core::int;
+  abstract method method5b({core::int a = #C2, core::int b = #C2}) → core::int;
+  abstract method method5c({required core::int a = #C1, required core::int b = #C1}) → core::int;
+  abstract method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
+  abstract method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract method method6c({required core::int? a = #C1, required core::int? b = #C1}) → core::int?;
+  abstract get getter1() → core::int;
+  abstract get getter2() → core::int?;
+  abstract set setter1(core::int value) → void;
+  abstract set setter2(core::int? value) → void;
+  abstract get field3() → core::int;
+  abstract set field3(core::int value) → void;
+  abstract get field4() → core::int?;
+  abstract set field4(core::int? value) → void;
+  abstract get property1() → core::int;
+  abstract set property1(core::int value) → void;
+  abstract get property2() → core::int?;
+  abstract set property2(core::int? value) → void;
+}
+class Class1 extends opt::LegacyClass {
+  synthetic constructor •() → self::Class1
+    : super opt::LegacyClass::•()
+    ;
+}
+class Class2a extends opt::LegacyClass implements self::Interface {
+  synthetic constructor •() → self::Class2a
+    : super opt::LegacyClass::•()
+    ;
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
+  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
+  abstract member-signature get getter1() → core::int;
+  abstract member-signature get field1() → core::int;
+  abstract member-signature method method3a(core::int a, core::int b) → core::int;
+  abstract member-signature get field4() → core::int?;
+  abstract member-signature get property3() → core::int;
+  abstract member-signature get field2() → core::int?;
+  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
+  abstract member-signature get getter2() → core::int?;
+  abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int;
+  abstract member-signature method method5c({core::int a = #C1, core::int b = #C1}) → core::int;
+  abstract member-signature get property4() → core::int?;
+  abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract member-signature method method6c({core::int? a = #C1, core::int? b = #C1}) → core::int?;
+  abstract member-signature method method2() → core::int?;
+  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
+  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract member-signature get field3() → core::int;
+  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract member-signature method method1() → core::int;
+  abstract member-signature get property1() → core::int;
+  abstract member-signature get property2() → core::int?;
+  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature set field1(core::int _) → void;
+  abstract member-signature set field4(core::int? _) → void;
+  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature set field2(core::int? _) → void;
+  abstract member-signature set property4(core::int? value) → void;
+  abstract member-signature set setter2(core::int? value) → void;
+  abstract member-signature set field3(core::int _) → void;
+  abstract member-signature set property1(core::int value) → void;
+  abstract member-signature set property2(core::int? value) → void;
+}
+class Class2b extends opt::LegacyClass implements self::Interface {
+  field core::int field1 = 0;
+  field core::int? field2 = null;
+  field core::int property3 = 0;
+  field core::int? property4 = null;
+  synthetic constructor •() → self::Class2b
+    : super opt::LegacyClass::•()
+    ;
+  method method1() → core::int
+    return 0;
+  method method2() → core::int?
+    return 0;
+  method method3a(core::int a, core::int b) → core::int
+    return 0;
+  method method3b(core::int a, [core::int b = #C1]) → core::int
+    return 0;
+  method method3c([core::int a = #C1, core::int b = #C1]) → core::int
+    return 0;
+  method method4a(core::int? a, core::int? b) → core::int?
+    return 0;
+  method method4b(core::int? a, [core::int? b = #C1]) → core::int?
+    return 0;
+  method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?
+    return 0;
+  method method5a(core::int a, {core::int b = #C2}) → core::int
+    return 0;
+  method method5b({core::int a = #C2, core::int b = #C2}) → core::int
+    return 0;
+  method method5c({required core::int a = #C1, required core::int b = #C1}) → core::int
+    return 0;
+  method method6a(core::int? a, {core::int? b = #C1}) → core::int?
+    return 0;
+  method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?
+    return 0;
+  method method6c({required core::int? a = #C1, required core::int? b = #C1}) → core::int?
+    return 0;
+  get getter1() → core::int
+    return 0;
+  get getter2() → core::int?
+    return 0;
+  set setter1(core::int value) → void {}
+  set setter2(core::int? value) → void {}
+  get field3() → core::int
+    return 0;
+  set field3(core::int value) → void {}
+  get field4() → core::int?
+    return 0;
+  set field4(core::int? value) → void {}
+  get property1() → core::int
+    return 0;
+  set property1(core::int value) → void {}
+  get property2() → core::int?
+    return 0;
+  set property2(core::int? value) → void {}
+}
+class Class3a extends opt::GenericLegacyClass<core::int> {
+  synthetic constructor •() → self::Class3a
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+class Class3b extends opt::GenericLegacyClass<core::int?> {
+  synthetic constructor •() → self::Class3b
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+class Class3c<S extends core::Object? = dynamic> extends opt::GenericLegacyClass<self::Class3c::S%> {
+  synthetic constructor •() → self::Class3c<self::Class3c::S%>
+    : super opt::GenericLegacyClass::•()
+    ;
+}
+static method main() → dynamic {}
+
+library opt_out;
+import self as opt;
+import "dart:core" as core;
+
+class LegacyClass extends core::Object {
+  field core::int* field1 = null;
+  field core::int* field2 = null;
+  field core::int* field3 = null;
+  field core::int* field4 = null;
+  synthetic constructor •() → opt::LegacyClass*
+    : super core::Object::•()
+    ;
+  method method1() → core::int*
+    return 0;
+  method method2() → core::int*
+    return 0;
+  method method3a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method3b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method3c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method4a(core::int* a, core::int* b) → core::int*
+    return 0;
+  method method4b(core::int* a, [core::int* b = #C1]) → core::int*
+    return 0;
+  method method4c([core::int* a = #C1, core::int* b = #C1]) → core::int*
+    return 0;
+  method method5a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method5b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method5c({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method6a(core::int* a, {core::int* b = #C1}) → core::int*
+    return 0;
+  method method6b({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  method method6c({core::int* a = #C1, core::int* b = #C1}) → core::int*
+    return 0;
+  get getter1() → core::int*
+    return 0;
+  get getter2() → core::int*
+    return 0;
+  set setter1(core::int* value) → void {}
+  set setter2(core::int* value) → void {}
+  get property1() → core::int*
+    return 0;
+  set property1(core::int* value) → void {}
+  get property2() → core::int*
+    return 0;
+  set property2(core::int* value) → void {}
+  get property3() → core::int*
+    return 0;
+  set property3(core::int* value) → void {}
+  get property4() → core::int*
+    return 0;
+  set property4(core::int* value) → void {}
+}
+class GenericLegacyClass<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → opt::GenericLegacyClass<opt::GenericLegacyClass::T*>*
+    : super core::Object::•()
+    ;
+  method method1() → opt::GenericLegacyClass::T*
+    return null;
+}
+
+constants  {
+  #C1 = null
+  #C2 = 0
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out_lib.dart b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out_lib.dart
new file mode 100644
index 0000000..d7d4f9f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out_lib.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+library opt_out;
+
+class LegacyClass {
+  int method1() => 0;
+
+  int method2() => 0;
+
+  int method3a(int a, int b) => 0;
+
+  int method3b(int a, [int b]) => 0;
+
+  int method3c([int a, int b]) => 0;
+
+  int method4a(int a, int b) => 0;
+
+  int method4b(int a, [int b]) => 0;
+
+  int method4c([int a, int b]) => 0;
+
+  int method5a(int a, {int b}) => 0;
+
+  int method5b({int a, int b}) => 0;
+
+  int method5c({int a, int b}) => 0;
+
+  int method6a(int a, {int b}) => 0;
+
+  int method6b({int a, int b}) => 0;
+
+  int method6c({int a, int b}) => 0;
+
+  int get getter1 => 0;
+
+  int get getter2 => 0;
+
+  void set setter1(int value) {}
+
+  void set setter2(int value) {}
+
+  int field1;
+
+  int field2;
+
+  int field3;
+
+  int field4;
+
+  int get property1 => 0;
+
+  void set property1(int value) {}
+
+  int get property2 => 0;
+
+  void set property2(int value) {}
+
+  int get property3 => 0;
+
+  void set property3(int value) {}
+
+  int get property4 => 0;
+
+  void set property4(int value) {}
+}
+
+class GenericLegacyClass<T> {
+  T method1() => null;
+}
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart b/pkg/front_end/testcases/nnbd/nullable_receiver.dart
new file mode 100644
index 0000000..98c3f88
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.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.
+
+// The test checks for compile-time errors or their absence for cases involving
+// nullable receiver.
+
+class A {
+  foo() {}
+  int get bar => 42;
+  void set baz(int value) {}
+  void call() {}
+}
+
+error(String? s, A? a) {
+  s.length;
+  s.substring(1, 1);
+
+  a.foo();
+  a.bar;
+  a.baz = 42;
+  a();
+
+  Function f1 = a;
+  void Function() f2 = a;
+  void Function()? f3 = a;
+}
+
+// It's ok to invoke members of Object on nullable types.
+ok(String? s, A? a, Invocation i) {
+  s == s;
+  a == a;
+
+  s.hashCode;
+  a.hashCode;
+
+  s.toString();
+  a.toString();
+
+  try { s.noSuchMethod(i); } catch (e, t) {}
+  try { a.noSuchMethod(i); } catch (e, t) {}
+
+  s.runtimeType;
+  a.runtimeType;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.outline.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.outline.expect
new file mode 100644
index 0000000..65602b3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.outline.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  method foo() → dynamic
+    ;
+  get bar() → core::int
+    ;
+  set baz(core::int value) → void
+    ;
+  method call() → void
+    ;
+}
+static method error(core::String? s, self::A? a) → dynamic
+  ;
+static method ok(core::String? s, self::A? a, core::Invocation i) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect
new file mode 100644
index 0000000..c298044
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.expect
@@ -0,0 +1,117 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:16:5: Error: Property 'length' cannot be accessed on 'String?' because it is potentially null.
+// Try accessing using ?. instead.
+//   s.length;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:20:5: Error: Property 'bar' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.bar;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:24:12: Error: A value of type 'void Function()?' can't be assigned to a variable of type 'Function'.
+//  - 'Function' is from 'dart:core'.
+//   Function f1 = a;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:25:19: Error: A value of type 'void Function()?' can't be assigned to a variable of type 'void Function()'.
+//   void Function() f2 = a;
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:34:5: Error: Property 'hashCode' cannot be accessed on 'String?' because it is potentially null.
+// Try accessing using ?. instead.
+//   s.hashCode;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:35:5: Error: Property 'hashCode' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.hashCode;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:43:5: Error: Property 'runtimeType' cannot be accessed on 'String?' because it is potentially null.
+// Try accessing using ?. instead.
+//   s.runtimeType;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:44:5: Error: Property 'runtimeType' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.runtimeType;
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+  get bar() → core::int
+    return 42;
+  set baz(core::int value) → void {}
+  method call() → void {}
+}
+static method error(core::String? s, self::A? a) → dynamic {
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:16:5: Error: Property 'length' cannot be accessed on 'String?' because it is potentially null.
+Try accessing using ?. instead.
+  s.length;
+    ^" in s.{core::String::length};
+  s.{core::String::substring}(1, 1);
+  a.{self::A::foo}();
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:20:5: Error: Property 'bar' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+Try accessing using ?. instead.
+  a.bar;
+    ^" in a.{self::A::bar};
+  a.{self::A::baz} = 42;
+  a.{self::A::call}();
+  core::Function f1 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:24:12: Error: A value of type 'void Function()?' can't be assigned to a variable of type 'Function'.
+ - 'Function' is from 'dart:core'.
+  Function f1 = a;
+           ^" in (let final self::A? #t4 = a in #t4.==(null) ?{() →? void} null : #t4.{self::A::call}) as{TypeError} core::Function;
+  () → void f2 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:25:19: Error: A value of type 'void Function()?' can't be assigned to a variable of type 'void Function()'.
+  void Function() f2 = a;
+                  ^" in (let final self::A? #t6 = a in #t6.==(null) ?{() →? void} null : #t6.{self::A::call}) as{TypeError} () → void;
+  () →? void f3 = let final self::A? #t7 = a in #t7.==(null) ?{() →? void} null : #t7.{self::A::call};
+}
+static method ok(core::String? s, self::A? a, core::Invocation i) → dynamic {
+  s.{core::String::==}(s);
+  a.{core::Object::==}(a);
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:34:5: Error: Property 'hashCode' cannot be accessed on 'String?' because it is potentially null.
+Try accessing using ?. instead.
+  s.hashCode;
+    ^" in s.{core::String::hashCode};
+  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:35:5: Error: Property 'hashCode' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+Try accessing using ?. instead.
+  a.hashCode;
+    ^" in a.{core::Object::hashCode};
+  s.{core::Object::toString}();
+  a.{core::Object::toString}();
+  try {
+    s.{core::Object::noSuchMethod}(i);
+  }
+  on dynamic catch(final dynamic e, final core::StackTrace t) {
+  }
+  try {
+    a.{core::Object::noSuchMethod}(i);
+  }
+  on dynamic catch(final dynamic e, final core::StackTrace t) {
+  }
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:43:5: Error: Property 'runtimeType' cannot be accessed on 'String?' because it is potentially null.
+Try accessing using ?. instead.
+  s.runtimeType;
+    ^" in s.{core::Object::runtimeType};
+  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:44:5: Error: Property 'runtimeType' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+Try accessing using ?. instead.
+  a.runtimeType;
+    ^" in a.{core::Object::runtimeType};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.transformed.expect
new file mode 100644
index 0000000..c298044
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.strong.transformed.expect
@@ -0,0 +1,117 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:16:5: Error: Property 'length' cannot be accessed on 'String?' because it is potentially null.
+// Try accessing using ?. instead.
+//   s.length;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:20:5: Error: Property 'bar' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.bar;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:24:12: Error: A value of type 'void Function()?' can't be assigned to a variable of type 'Function'.
+//  - 'Function' is from 'dart:core'.
+//   Function f1 = a;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:25:19: Error: A value of type 'void Function()?' can't be assigned to a variable of type 'void Function()'.
+//   void Function() f2 = a;
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:34:5: Error: Property 'hashCode' cannot be accessed on 'String?' because it is potentially null.
+// Try accessing using ?. instead.
+//   s.hashCode;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:35:5: Error: Property 'hashCode' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.hashCode;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:43:5: Error: Property 'runtimeType' cannot be accessed on 'String?' because it is potentially null.
+// Try accessing using ?. instead.
+//   s.runtimeType;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:44:5: Error: Property 'runtimeType' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.runtimeType;
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+  get bar() → core::int
+    return 42;
+  set baz(core::int value) → void {}
+  method call() → void {}
+}
+static method error(core::String? s, self::A? a) → dynamic {
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:16:5: Error: Property 'length' cannot be accessed on 'String?' because it is potentially null.
+Try accessing using ?. instead.
+  s.length;
+    ^" in s.{core::String::length};
+  s.{core::String::substring}(1, 1);
+  a.{self::A::foo}();
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:20:5: Error: Property 'bar' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+Try accessing using ?. instead.
+  a.bar;
+    ^" in a.{self::A::bar};
+  a.{self::A::baz} = 42;
+  a.{self::A::call}();
+  core::Function f1 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:24:12: Error: A value of type 'void Function()?' can't be assigned to a variable of type 'Function'.
+ - 'Function' is from 'dart:core'.
+  Function f1 = a;
+           ^" in (let final self::A? #t4 = a in #t4.==(null) ?{() →? void} null : #t4.{self::A::call}) as{TypeError} core::Function;
+  () → void f2 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:25:19: Error: A value of type 'void Function()?' can't be assigned to a variable of type 'void Function()'.
+  void Function() f2 = a;
+                  ^" in (let final self::A? #t6 = a in #t6.==(null) ?{() →? void} null : #t6.{self::A::call}) as{TypeError} () → void;
+  () →? void f3 = let final self::A? #t7 = a in #t7.==(null) ?{() →? void} null : #t7.{self::A::call};
+}
+static method ok(core::String? s, self::A? a, core::Invocation i) → dynamic {
+  s.{core::String::==}(s);
+  a.{core::Object::==}(a);
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:34:5: Error: Property 'hashCode' cannot be accessed on 'String?' because it is potentially null.
+Try accessing using ?. instead.
+  s.hashCode;
+    ^" in s.{core::String::hashCode};
+  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:35:5: Error: Property 'hashCode' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+Try accessing using ?. instead.
+  a.hashCode;
+    ^" in a.{core::Object::hashCode};
+  s.{core::Object::toString}();
+  a.{core::Object::toString}();
+  try {
+    s.{core::Object::noSuchMethod}(i);
+  }
+  on dynamic catch(final dynamic e, final core::StackTrace t) {
+  }
+  try {
+    a.{core::Object::noSuchMethod}(i);
+  }
+  on dynamic catch(final dynamic e, final core::StackTrace t) {
+  }
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:43:5: Error: Property 'runtimeType' cannot be accessed on 'String?' because it is potentially null.
+Try accessing using ?. instead.
+  s.runtimeType;
+    ^" in s.{core::Object::runtimeType};
+  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/nullable_receiver.dart:44:5: Error: Property 'runtimeType' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+Try accessing using ?. instead.
+  a.runtimeType;
+    ^" in a.{core::Object::runtimeType};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect
new file mode 100644
index 0000000..5d3c3c6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.expect
@@ -0,0 +1,91 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:16:5: Warning: Property 'length' is accessed on 'String?' which is potentially null.
+// Try accessing using ?. instead.
+//   s.length;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:20:5: Warning: Property 'bar' is accessed on 'A?' which is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.bar;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:24:12: Warning: Assigning value of type 'void Function()?' to a variable of type 'Function'.
+//  - 'Function' is from 'dart:core'.
+//   Function f1 = a;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:25:19: Warning: Assigning value of type 'void Function()?' to a variable of type 'void Function()'.
+//   void Function() f2 = a;
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:34:5: Warning: Property 'hashCode' is accessed on 'String?' which is potentially null.
+// Try accessing using ?. instead.
+//   s.hashCode;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:35:5: Warning: Property 'hashCode' is accessed on 'A?' which is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.hashCode;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:43:5: Warning: Property 'runtimeType' is accessed on 'String?' which is potentially null.
+// Try accessing using ?. instead.
+//   s.runtimeType;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:44:5: Warning: Property 'runtimeType' is accessed on 'A?' which is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.runtimeType;
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+  get bar() → core::int
+    return 42;
+  set baz(core::int value) → void {}
+  method call() → void {}
+}
+static method error(core::String? s, self::A? a) → dynamic {
+  s.{core::String::length};
+  s.{core::String::substring}(1, 1);
+  a.{self::A::foo}();
+  a.{self::A::bar};
+  a.{self::A::baz} = 42;
+  a.{self::A::call}();
+  core::Function f1 = let final self::A? #t1 = a in #t1.==(null) ?{() →? void} null : #t1.{self::A::call};
+  () → void f2 = let final self::A? #t2 = a in #t2.==(null) ?{() →? void} null : #t2.{self::A::call};
+  () →? void f3 = let final self::A? #t3 = a in #t3.==(null) ?{() →? void} null : #t3.{self::A::call};
+}
+static method ok(core::String? s, self::A? a, core::Invocation i) → dynamic {
+  s.{core::String::==}(s);
+  a.{core::Object::==}(a);
+  s.{core::String::hashCode};
+  a.{core::Object::hashCode};
+  s.{core::Object::toString}();
+  a.{core::Object::toString}();
+  try {
+    s.{core::Object::noSuchMethod}(i);
+  }
+  on dynamic catch(final dynamic e, final core::StackTrace t) {
+  }
+  try {
+    a.{core::Object::noSuchMethod}(i);
+  }
+  on dynamic catch(final dynamic e, final core::StackTrace t) {
+  }
+  s.{core::Object::runtimeType};
+  a.{core::Object::runtimeType};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.transformed.expect
new file mode 100644
index 0000000..5d3c3c6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_receiver.dart.weak.transformed.expect
@@ -0,0 +1,91 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:16:5: Warning: Property 'length' is accessed on 'String?' which is potentially null.
+// Try accessing using ?. instead.
+//   s.length;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:20:5: Warning: Property 'bar' is accessed on 'A?' which is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.bar;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:24:12: Warning: Assigning value of type 'void Function()?' to a variable of type 'Function'.
+//  - 'Function' is from 'dart:core'.
+//   Function f1 = a;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:25:19: Warning: Assigning value of type 'void Function()?' to a variable of type 'void Function()'.
+//   void Function() f2 = a;
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:34:5: Warning: Property 'hashCode' is accessed on 'String?' which is potentially null.
+// Try accessing using ?. instead.
+//   s.hashCode;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:35:5: Warning: Property 'hashCode' is accessed on 'A?' which is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.hashCode;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:43:5: Warning: Property 'runtimeType' is accessed on 'String?' which is potentially null.
+// Try accessing using ?. instead.
+//   s.runtimeType;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/nullable_receiver.dart:44:5: Warning: Property 'runtimeType' is accessed on 'A?' which is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/nullable_receiver.dart'.
+// Try accessing using ?. instead.
+//   a.runtimeType;
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+  get bar() → core::int
+    return 42;
+  set baz(core::int value) → void {}
+  method call() → void {}
+}
+static method error(core::String? s, self::A? a) → dynamic {
+  s.{core::String::length};
+  s.{core::String::substring}(1, 1);
+  a.{self::A::foo}();
+  a.{self::A::bar};
+  a.{self::A::baz} = 42;
+  a.{self::A::call}();
+  core::Function f1 = let final self::A? #t1 = a in #t1.==(null) ?{() →? void} null : #t1.{self::A::call};
+  () → void f2 = let final self::A? #t2 = a in #t2.==(null) ?{() →? void} null : #t2.{self::A::call};
+  () →? void f3 = let final self::A? #t3 = a in #t3.==(null) ?{() →? void} null : #t3.{self::A::call};
+}
+static method ok(core::String? s, self::A? a, core::Invocation i) → dynamic {
+  s.{core::String::==}(s);
+  a.{core::Object::==}(a);
+  s.{core::String::hashCode};
+  a.{core::Object::hashCode};
+  s.{core::Object::toString}();
+  a.{core::Object::toString}();
+  try {
+    s.{core::Object::noSuchMethod}(i);
+  }
+  on dynamic catch(final dynamic e, final core::StackTrace t) {
+  }
+  try {
+    a.{core::Object::noSuchMethod}(i);
+  }
+  on dynamic catch(final dynamic e, final core::StackTrace t) {
+  }
+  s.{core::Object::runtimeType};
+  a.{core::Object::runtimeType};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart
new file mode 100644
index 0000000..ae83e07
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart
@@ -0,0 +1,32 @@
+// 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.
+
+// The test checks for compile-time errors and their absence for cases involving
+// fields of potentially non-nullable types.
+
+int x;
+int? y; // Ok: it's nullable.
+late int z; // Ok: it's late.
+
+class A<T extends Object?> {
+  static int x;
+  static int? y; // Ok: it's nullable.
+  static late int z; // Ok: it's late. 
+
+  int lx;
+  int? ly; // Ok: it's nullable.
+  late int? lz; // Ok: it's late.
+  int lv; // Ok: initialized in an initializing formal.
+  int lu; // Ok: initialized in an initializer list entry.
+
+  T lt;
+  T? ls; // Ok: it's nullable.
+  late T lr; // Ok: it's late.
+  T lp; // Ok: initialized in an initializing formal.
+  T lq; // Ok: initialized in an initializer list entry.
+
+  A(this.lv, this.lp, T t) : this.lu = 42, this.lq = t;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.outline.expect b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.outline.expect
new file mode 100644
index 0000000..153b9bb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.outline.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = core::Object?> extends core::Object {
+  static field core::int x;
+  static field core::int? y;
+  late static field core::int z;
+  field core::int lx;
+  field core::int? ly;
+  late field core::int? lz;
+  field core::int lv;
+  field core::int lu;
+  generic-covariant-impl field self::A::T% lt;
+  generic-covariant-impl field self::A::T? ls;
+  late generic-covariant-impl field self::A::T% lr;
+  generic-covariant-impl field self::A::T% lp;
+  generic-covariant-impl field self::A::T% lq;
+  constructor •(core::int lv, self::A::T% lp, self::A::T% t) → self::A<self::A::T%>
+    ;
+}
+static field core::int x;
+static field core::int? y;
+late static field core::int z;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.expect b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.expect
new file mode 100644
index 0000000..80be9f2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = core::Object?> extends core::Object {
+  static field core::int x = null;
+  static field core::int? y = null;
+  late static field core::int z;
+  field core::int lx = null;
+  field core::int? ly = null;
+  late field core::int? lz;
+  field core::int lv;
+  field core::int lu;
+  generic-covariant-impl field self::A::T% lt = null;
+  generic-covariant-impl field self::A::T? ls = null;
+  late generic-covariant-impl field self::A::T% lr;
+  generic-covariant-impl field self::A::T% lp;
+  generic-covariant-impl field self::A::T% lq;
+  constructor •(core::int lv, self::A::T% lp, self::A::T% t) → self::A<self::A::T%>
+    : self::A::lv = lv, self::A::lp = lp, self::A::lu = 42, self::A::lq = t, super core::Object::•()
+    ;
+}
+static field core::int x;
+static field core::int? y;
+late static field core::int z;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.transformed.expect
new file mode 100644
index 0000000..80be9f2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = core::Object?> extends core::Object {
+  static field core::int x = null;
+  static field core::int? y = null;
+  late static field core::int z;
+  field core::int lx = null;
+  field core::int? ly = null;
+  late field core::int? lz;
+  field core::int lv;
+  field core::int lu;
+  generic-covariant-impl field self::A::T% lt = null;
+  generic-covariant-impl field self::A::T? ls = null;
+  late generic-covariant-impl field self::A::T% lr;
+  generic-covariant-impl field self::A::T% lp;
+  generic-covariant-impl field self::A::T% lq;
+  constructor •(core::int lv, self::A::T% lp, self::A::T% t) → self::A<self::A::T%>
+    : self::A::lv = lv, self::A::lp = lp, self::A::lu = 42, self::A::lq = t, super core::Object::•()
+    ;
+}
+static field core::int x;
+static field core::int? y;
+late static field core::int z;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.expect b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.expect
new file mode 100644
index 0000000..80be9f2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = core::Object?> extends core::Object {
+  static field core::int x = null;
+  static field core::int? y = null;
+  late static field core::int z;
+  field core::int lx = null;
+  field core::int? ly = null;
+  late field core::int? lz;
+  field core::int lv;
+  field core::int lu;
+  generic-covariant-impl field self::A::T% lt = null;
+  generic-covariant-impl field self::A::T? ls = null;
+  late generic-covariant-impl field self::A::T% lr;
+  generic-covariant-impl field self::A::T% lp;
+  generic-covariant-impl field self::A::T% lq;
+  constructor •(core::int lv, self::A::T% lp, self::A::T% t) → self::A<self::A::T%>
+    : self::A::lv = lv, self::A::lp = lp, self::A::lu = 42, self::A::lq = t, super core::Object::•()
+    ;
+}
+static field core::int x;
+static field core::int? y;
+late static field core::int z;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..80be9f2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.weak.transformed.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = core::Object?> extends core::Object {
+  static field core::int x = null;
+  static field core::int? y = null;
+  late static field core::int z;
+  field core::int lx = null;
+  field core::int? ly = null;
+  late field core::int? lz;
+  field core::int lv;
+  field core::int lu;
+  generic-covariant-impl field self::A::T% lt = null;
+  generic-covariant-impl field self::A::T? ls = null;
+  late generic-covariant-impl field self::A::T% lr;
+  generic-covariant-impl field self::A::T% lp;
+  generic-covariant-impl field self::A::T% lq;
+  constructor •(core::int lv, self::A::T% lp, self::A::T% t) → self::A<self::A::T%>
+    : self::A::lv = lv, self::A::lp = lp, self::A::lu = 42, self::A::lq = t, super core::Object::•()
+    ;
+}
+static field core::int x;
+static field core::int? y;
+late static field core::int z;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/required_named_parameter.dart b/pkg/front_end/testcases/nnbd/required_named_parameter.dart
index 49a509e..97f1ba3 100644
--- a/pkg/front_end/testcases/nnbd/required_named_parameter.dart
+++ b/pkg/front_end/testcases/nnbd/required_named_parameter.dart
@@ -4,8 +4,10 @@
 
 // Should be a compile-time error / warning.
 foo({required int parameter = 42}) {}
+foo2({int parameter}) {}
 
 // Should be ok.
 bar({required int parameter}) {}
+bar2({int parameter = 42}) {}
 
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.outline.expect b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.outline.expect
index 385108f..a0fc817 100644
--- a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.outline.expect
@@ -11,7 +11,11 @@
 
 static method foo({required core::int parameter}) → dynamic
   ;
+static method foo2({core::int parameter}) → dynamic
+  ;
 static method bar({required core::int parameter}) → dynamic
   ;
+static method bar2({core::int parameter}) → dynamic
+  ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.expect b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.expect
index b865c67..ff04da2 100644
--- a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.expect
@@ -10,7 +10,9 @@
 import "dart:core" as core;
 
 static method foo({required core::int parameter = #C1}) → dynamic {}
+static method foo2({core::int parameter = #C2}) → dynamic {}
 static method bar({required core::int parameter = #C2}) → dynamic {}
+static method bar2({core::int parameter = #C1}) → dynamic {}
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.transformed.expect
index b865c67..ff04da2 100644
--- a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.strong.transformed.expect
@@ -10,7 +10,9 @@
 import "dart:core" as core;
 
 static method foo({required core::int parameter = #C1}) → dynamic {}
+static method foo2({core::int parameter = #C2}) → dynamic {}
 static method bar({required core::int parameter = #C2}) → dynamic {}
+static method bar2({core::int parameter = #C1}) → dynamic {}
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.expect b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.expect
index 0ccf7a2d..1686682 100644
--- a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.expect
@@ -10,7 +10,9 @@
 import "dart:core" as core;
 
 static method foo({required core::int parameter = #C1}) → dynamic {}
+static method foo2({core::int parameter = #C2}) → dynamic {}
 static method bar({required core::int parameter = #C2}) → dynamic {}
+static method bar2({core::int parameter = #C1}) → dynamic {}
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.transformed.expect
index 0ccf7a2d..1686682 100644
--- a/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/required_named_parameter.dart.weak.transformed.expect
@@ -10,7 +10,9 @@
 import "dart:core" as core;
 
 static method foo({required core::int parameter = #C1}) → dynamic {}
+static method foo2({core::int parameter = #C2}) → dynamic {}
 static method bar({required core::int parameter = #C2}) → dynamic {}
+static method bar2({core::int parameter = #C1}) → dynamic {}
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/nnbd/sink_hierarchy.dart b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart
new file mode 100644
index 0000000..963e45f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart
@@ -0,0 +1,23 @@
+// 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
+
+abstract class Sink<T> {
+  void close();
+}
+
+abstract class EventSink<T> implements Sink<T> {
+  void close();
+}
+
+abstract class StreamConsumer<S> {
+  Future close();
+}
+
+abstract class StreamSink<S> implements EventSink<S>, StreamConsumer<S> {
+  Future close();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.outline.expect b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.outline.expect
new file mode 100644
index 0000000..b423e94
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.outline.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+abstract class Sink<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Sink<self::Sink::T*>*
+    ;
+  abstract method close() → void;
+}
+abstract class EventSink<T extends core::Object* = dynamic> extends core::Object implements self::Sink<self::EventSink::T*> {
+  synthetic constructor •() → self::EventSink<self::EventSink::T*>*
+    ;
+  abstract method close() → void;
+}
+abstract class StreamConsumer<S extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::StreamConsumer<self::StreamConsumer::S*>*
+    ;
+  abstract method close() → asy::Future<dynamic>*;
+}
+abstract class StreamSink<S extends core::Object* = dynamic> extends core::Object implements self::EventSink<self::StreamSink::S*>, self::StreamConsumer<self::StreamSink::S*> {
+  synthetic constructor •() → self::StreamSink<self::StreamSink::S*>*
+    ;
+  abstract method close() → asy::Future<dynamic>*;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.strong.expect b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.strong.expect
new file mode 100644
index 0000000..bd5a1e5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.strong.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+abstract class Sink<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Sink<self::Sink::T*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → void;
+}
+abstract class EventSink<T extends core::Object* = dynamic> extends core::Object implements self::Sink<self::EventSink::T*> {
+  synthetic constructor •() → self::EventSink<self::EventSink::T*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → void;
+}
+abstract class StreamConsumer<S extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::StreamConsumer<self::StreamConsumer::S*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → asy::Future<dynamic>*;
+}
+abstract class StreamSink<S extends core::Object* = dynamic> extends core::Object implements self::EventSink<self::StreamSink::S*>, self::StreamConsumer<self::StreamSink::S*> {
+  synthetic constructor •() → self::StreamSink<self::StreamSink::S*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → asy::Future<dynamic>*;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.strong.transformed.expect
new file mode 100644
index 0000000..bd5a1e5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.strong.transformed.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+abstract class Sink<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Sink<self::Sink::T*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → void;
+}
+abstract class EventSink<T extends core::Object* = dynamic> extends core::Object implements self::Sink<self::EventSink::T*> {
+  synthetic constructor •() → self::EventSink<self::EventSink::T*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → void;
+}
+abstract class StreamConsumer<S extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::StreamConsumer<self::StreamConsumer::S*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → asy::Future<dynamic>*;
+}
+abstract class StreamSink<S extends core::Object* = dynamic> extends core::Object implements self::EventSink<self::StreamSink::S*>, self::StreamConsumer<self::StreamSink::S*> {
+  synthetic constructor •() → self::StreamSink<self::StreamSink::S*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → asy::Future<dynamic>*;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.weak.expect b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.weak.expect
new file mode 100644
index 0000000..bd5a1e5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.weak.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+abstract class Sink<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Sink<self::Sink::T*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → void;
+}
+abstract class EventSink<T extends core::Object* = dynamic> extends core::Object implements self::Sink<self::EventSink::T*> {
+  synthetic constructor •() → self::EventSink<self::EventSink::T*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → void;
+}
+abstract class StreamConsumer<S extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::StreamConsumer<self::StreamConsumer::S*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → asy::Future<dynamic>*;
+}
+abstract class StreamSink<S extends core::Object* = dynamic> extends core::Object implements self::EventSink<self::StreamSink::S*>, self::StreamConsumer<self::StreamSink::S*> {
+  synthetic constructor •() → self::StreamSink<self::StreamSink::S*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → asy::Future<dynamic>*;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.weak.transformed.expect
new file mode 100644
index 0000000..bd5a1e5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/sink_hierarchy.dart.weak.transformed.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+abstract class Sink<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Sink<self::Sink::T*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → void;
+}
+abstract class EventSink<T extends core::Object* = dynamic> extends core::Object implements self::Sink<self::EventSink::T*> {
+  synthetic constructor •() → self::EventSink<self::EventSink::T*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → void;
+}
+abstract class StreamConsumer<S extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::StreamConsumer<self::StreamConsumer::S*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → asy::Future<dynamic>*;
+}
+abstract class StreamSink<S extends core::Object* = dynamic> extends core::Object implements self::EventSink<self::StreamSink::S*>, self::StreamConsumer<self::StreamSink::S*> {
+  synthetic constructor •() → self::StreamSink<self::StreamSink::S*>*
+    : super core::Object::•()
+    ;
+  abstract method close() → asy::Future<dynamic>*;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart
new file mode 100644
index 0000000..89fe8b0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The test checks for compile-time warnings about expressions of strictly
+// non-nullable types being used in positions typically occupied by those of
+// nullable types, that is, in various null-aware expressions.
+
+warning(String s, List<String> l) {
+  s?.length;
+  s?..length;
+  s ?? "foo";
+  s ??= "foo";
+  [...?l];
+  s!;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.outline.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.outline.expect
new file mode 100644
index 0000000..f2afe48
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.outline.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method warning(core::String s, core::List<core::String> l) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.expect
new file mode 100644
index 0000000..7bac66b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method warning(core::String s, core::List<core::String> l) → dynamic {
+  let final core::String #t1 = s in #t1.{core::String::==}(null) ?{core::int*} null : #t1.{core::String::length};
+  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::String} null : let final void #t3 = #t2.{core::String::length} in #t2;
+  let final core::String #t4 = s in #t4.{core::String::==}(null) ?{core::String} "foo" : #t4;
+  s.{core::String::==}(null) ?{core::String} s = "foo" : null;
+  block {
+    final core::List<core::String*> #t5 = <core::String*>[];
+    final core::Iterable<core::String*>? #t6 = l;
+    if(!#t6.{core::Object::==}(null))
+      for (final core::String* #t7 in #t6{core::Iterable<core::String*>})
+        #t5.{core::List::add}(#t7);
+  } =>#t5;
+  s!;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.transformed.expect
new file mode 100644
index 0000000..ec3449a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method warning(core::String s, core::List<core::String> l) → dynamic {
+  let final core::String #t1 = s in #t1.{core::String::==}(null) ?{core::int*} null : #t1.{core::String::length};
+  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::String} null : let final void #t3 = #t2.{core::String::length} in #t2;
+  let final core::String #t4 = s in #t4.{core::String::==}(null) ?{core::String} "foo" : #t4;
+  s.{core::String::==}(null) ?{core::String} s = "foo" : null;
+  block {
+    final core::List<core::String*> #t5 = <core::String*>[];
+    final core::Iterable<core::String*>? #t6 = l;
+    if(!#t6.{core::Object::==}(null)) {
+      core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(#t6{core::Iterable<core::String*>}).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final core::String* #t7 = :sync-for-iterator.{core::Iterator::current};
+        #t5.{core::List::add}(#t7);
+      }
+    }
+  } =>#t5;
+  s!;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.expect
new file mode 100644
index 0000000..7bac66b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method warning(core::String s, core::List<core::String> l) → dynamic {
+  let final core::String #t1 = s in #t1.{core::String::==}(null) ?{core::int*} null : #t1.{core::String::length};
+  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::String} null : let final void #t3 = #t2.{core::String::length} in #t2;
+  let final core::String #t4 = s in #t4.{core::String::==}(null) ?{core::String} "foo" : #t4;
+  s.{core::String::==}(null) ?{core::String} s = "foo" : null;
+  block {
+    final core::List<core::String*> #t5 = <core::String*>[];
+    final core::Iterable<core::String*>? #t6 = l;
+    if(!#t6.{core::Object::==}(null))
+      for (final core::String* #t7 in #t6{core::Iterable<core::String*>})
+        #t5.{core::List::add}(#t7);
+  } =>#t5;
+  s!;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.transformed.expect
new file mode 100644
index 0000000..ec3449a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.transformed.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method warning(core::String s, core::List<core::String> l) → dynamic {
+  let final core::String #t1 = s in #t1.{core::String::==}(null) ?{core::int*} null : #t1.{core::String::length};
+  let final core::String #t2 = s in #t2.{core::String::==}(null) ?{core::String} null : let final void #t3 = #t2.{core::String::length} in #t2;
+  let final core::String #t4 = s in #t4.{core::String::==}(null) ?{core::String} "foo" : #t4;
+  s.{core::String::==}(null) ?{core::String} s = "foo" : null;
+  block {
+    final core::List<core::String*> #t5 = <core::String*>[];
+    final core::Iterable<core::String*>? #t6 = l;
+    if(!#t6.{core::Object::==}(null)) {
+      core::Iterator<core::String*>* :sync-for-iterator = _in::unsafeCast<core::Iterable<core::String*>*>(#t6{core::Iterable<core::String*>}).{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final core::String* #t7 = :sync-for-iterator.{core::Iterator::current};
+        #t5.{core::List::add}(#t7);
+      }
+    }
+  } =>#t5;
+  s!;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index d96b9d1..17d8d69 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -928,6 +928,10 @@
 late_lowering/late_nullable_local_without_initializer: TextSerializationFailure
 new_const_insertion/simple: TextSerializationFailure # Was: Pass
 nnbd/assignability: TextSerializationFailure
+nnbd/definite_assignment_and_completion
+nnbd/definite_assignment_and_completion: TextSerializationFailure
+nnbd/forbidden_supers: TextSerializationFailure
+nnbd/forin: TextSerializationFailure
 nnbd/function_types: TextSerializationFailure
 nnbd/infer_if_null: TextSerializationFailure
 nnbd/inheritance_from_opt_in: TypeCheckError
@@ -938,6 +942,10 @@
 nnbd/issue_39286: TextSerializationFailure
 nnbd/issue_39286_2: TextSerializationFailure
 nnbd/late: TextSerializationFailure
+nnbd/later: TextSerializationFailure
+nnbd/list_constructor: TextSerializationFailure
+nnbd/member_inheritance_from_opt_in: TextSerializationFailure
+nnbd/member_inheritance_from_opt_out: TextSerializationFailure
 nnbd/messages_with_types_opt_in: TypeCheckError
 nnbd/messages_with_types_opt_out: TypeCheckError
 nnbd/missing_required_named_parameter: TextSerializationFailure
@@ -954,11 +962,15 @@
 nnbd/nullable_access: TextSerializationFailure
 nnbd/nullable_null: TextSerializationFailure
 nnbd/nullable_param: TextSerializationFailure
+nnbd/nullable_receiver: TextSerializationFailure
 nnbd/opt_out: TextSerializationFailure
+nnbd/potentially_non_nullable_field: TextSerializationFailure
 nnbd/regress_null_aware: TextSerializationFailure
 nnbd/required: TextSerializationFailure
 nnbd/required_named_parameter: TextSerializationFailure
 nnbd/simple_never: TextSerializationFailure
+nnbd/sink_hierarchy: TextSerializationFailure
+nnbd/strictly_non_nullable_warnings: TextSerializationFailure
 nnbd/substitution_in_inference: TextSerializationFailure
 nnbd/type_parameter_types: TextSerializationFailure
 no_such_method_forwarders/abstract_accessors_from_field: TextSerializationFailure # Was: Pass
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index dfecc60..82cbcc1 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -434,12 +434,8 @@
       "test/extensions/data/",
       "test/id_testing/data/",
       "test/language_versioning/data/",
-      "test/flow_analysis/assigned_variables/data/",
-      "test/flow_analysis/definite_assignment/data/",
-      "test/flow_analysis/nullability/data/",
-      "test/flow_analysis/reachability/data/",
-      "test/flow_analysis/type_promotion/data/",
-      "test/patching/data"
+      "test/patching/data",
+      "test/static_types/data/"
     ]
   }
 }
diff --git a/pkg/front_end/testing_with_lints.json b/pkg/front_end/testing_with_lints.json
index 8f65ff9..78fdd07 100644
--- a/pkg/front_end/testing_with_lints.json
+++ b/pkg/front_end/testing_with_lints.json
@@ -15,12 +15,8 @@
       "test/extensions/data/",
       "test/id_testing/data/",
       "test/language_versioning/data/",
-      "test/flow_analysis/assigned_variables/data/",
-      "test/flow_analysis/definite_assignment/data/",
-      "test/flow_analysis/nullability/data/",
-      "test/flow_analysis/reachability/data/",
-      "test/flow_analysis/type_promotion/data/",
-      "test/patching/data/"
+      "test/patching/data/",
+      "test/static_types/data/"
     ]
   }
 }
diff --git a/pkg/front_end/tool/perf.dart b/pkg/front_end/tool/perf.dart
index 2c6fd5b..edec99c 100644
--- a/pkg/front_end/tool/perf.dart
+++ b/pkg/front_end/tool/perf.dart
@@ -23,16 +23,15 @@
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/file_system/physical_file_system.dart'
-    show PhysicalResourceProvider;
-import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/file_system/file_system.dart' show Folder;
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk;
 import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/source/package_map_resolver.dart';
-import 'package:package_config/discovery.dart';
 import 'package:path/path.dart' as path;
 
 main(List<String> args) async {
@@ -45,7 +44,7 @@
   var bench = args[0];
   var entryUri = Uri.base.resolve(args[1]);
 
-  await setup(entryUri);
+  await setup(path.fromUri(entryUri));
 
   Set<Source> files = scanReachableFiles(entryUri);
   var handlers = {
@@ -196,10 +195,19 @@
 
 /// Sets up analyzer to be able to load and resolve app, packages, and sdk
 /// sources.
-Future setup(Uri entryUri) async {
+Future setup(String path) async {
   var provider = PhysicalResourceProvider.INSTANCE;
-  var packageMap = ContextBuilder.convertPackagesToMap(
-      provider, await findPackages(entryUri));
+
+  var packages = findPackagesFrom(
+    provider,
+    provider.getResource(path),
+  );
+
+  var packageMap = <String, List<Folder>>{};
+  for (var package in packages.packages) {
+    packageMap[package.name] = [package.libFolder];
+  }
+
   sources = new SourceFactory([
     new ResourceUriResolver(provider),
     new PackageMapUriResolver(provider, packageMap),
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 55e003a..12f3b1f 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -143,7 +143,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 36;
+  UInt32 formatVersion = 37;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
   UriSource sourceMap;
@@ -409,7 +409,7 @@
   Byte kind; // Index into the ProcedureKind enum above.
   UInt flags (isStatic, isAbstract, isExternal, isConst, isForwardingStub,
               isForwardingSemiStub, isRedirectingFactoryConstructor,
-              isNoSuchMethodForwarder, isExtensionMember);
+              isNoSuchMethodForwarder, isExtensionMember, isMemberSignature);
   Name name;
   List<Expression> annotations;
   // Only present if the 'isForwardingStub' flag is set.
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index c68657b..4cb08a9 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -2018,6 +2018,7 @@
       bool isConst: false,
       bool isForwardingStub: false,
       bool isForwardingSemiStub: false,
+      bool isMemberSignature: false,
       bool isExtensionMember: false,
       int transformerFlags: 0,
       Uri fileUri,
@@ -2030,6 +2031,7 @@
             isExternal: isExternal,
             isConst: isConst,
             isForwardingStub: isForwardingStub,
+            isMemberSignature: isMemberSignature,
             isForwardingSemiStub: isForwardingSemiStub,
             isExtensionMember: isExtensionMember,
             transformerFlags: transformerFlags,
@@ -2047,6 +2049,7 @@
       bool isConst: false,
       bool isForwardingStub: false,
       bool isForwardingSemiStub: false,
+      bool isMemberSignature: false,
       bool isExtensionMember: false,
       int transformerFlags: 0,
       Uri fileUri,
@@ -2061,6 +2064,7 @@
     this.isConst = isConst;
     this.isForwardingStub = isForwardingStub;
     this.isForwardingSemiStub = isForwardingSemiStub;
+    this.isMemberSignature = isMemberSignature;
     this.isExtensionMember = isExtensionMember;
     this.transformerFlags = transformerFlags;
   }
@@ -2075,6 +2079,7 @@
   static const int FlagRedirectingFactoryConstructor = 1 << 6;
   static const int FlagNoSuchMethodForwarder = 1 << 7;
   static const int FlagExtensionMember = 1 << 8;
+  static const int FlagMemberSignature = 1 << 9;
 
   bool get isStatic => flags & FlagStatic != 0;
   bool get isAbstract => flags & FlagAbstract != 0;
@@ -2098,6 +2103,15 @@
   /// stub, it was present in the original source as an abstract method.
   bool get isForwardingSemiStub => flags & FlagForwardingSemiStub != 0;
 
+  /// If set, this method is a class member added to show the type of an
+  /// inherited member.
+  ///
+  /// This is used when the type of the inherited member cannot be computed
+  /// directly from the member(s) in the supertypes. For instance in case of
+  /// an nnbd opt-out class inheriting from an nnbd opt-in class; here all nnbd-
+  /// aware types are replaced with legacy types in the inherited signature.
+  bool get isMemberSignature => flags & FlagMemberSignature != 0;
+
   // Indicates if this [Procedure] represents a redirecting factory constructor
   // and doesn't have a runnable body.
   bool get isRedirectingFactoryConstructor {
@@ -2141,6 +2155,11 @@
         : (flags & ~FlagForwardingSemiStub);
   }
 
+  void set isMemberSignature(bool value) {
+    flags =
+        value ? (flags | FlagMemberSignature) : (flags & ~FlagMemberSignature);
+  }
+
   void set isRedirectingFactoryConstructor(bool value) {
     flags = value
         ? (flags | FlagRedirectingFactoryConstructor)
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 00e609f..9ed4051 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -149,7 +149,7 @@
   /// Internal version of kernel binary format.
   /// Bump it when making incompatible changes in kernel binaries.
   /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
-  static const int BinaryFormatVersion = 36;
+  static const int BinaryFormatVersion = 37;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 39b6ac1..4ac5d73 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -259,6 +259,7 @@
   /// Compares members by name, using the same sort order as
   /// [getDeclaredMembers] and [getInterfaceMembers].
   static int compareMembers(Member first, Member second) {
+    if (first == second) return 0;
     return compareNames(first.name, second.name);
   }
 
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 5ae2df6..015b3b8 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1088,6 +1088,7 @@
     writeModifier(node.isAbstract, 'abstract');
     writeModifier(node.isForwardingStub, 'forwarding-stub');
     writeModifier(node.isForwardingSemiStub, 'forwarding-semi-stub');
+    writeModifier(node.isMemberSignature, 'member-signature');
     writeModifier(node.isNoSuchMethodForwarder, 'no-such-method-forwarder');
     writeWord(procedureKindToString(node.kind));
     if ((node.enclosingClass == null &&
diff --git a/pkg/nnbd_migration/lib/src/conditional_discard.dart b/pkg/nnbd_migration/lib/src/conditional_discard.dart
index 8495d47..dfddc9b 100644
--- a/pkg/nnbd_migration/lib/src/conditional_discard.dart
+++ b/pkg/nnbd_migration/lib/src/conditional_discard.dart
@@ -11,6 +11,9 @@
 /// This information will be associated with an Expression in the input program
 /// whose boolean value influences control flow (e.g. the condition of an `if`
 /// statement).
+///
+/// TODO(paulberry): simplify this once PotentialModification is no longer
+/// needed.
 class ConditionalDiscard {
   /// Nullability node that will be `nullable` if the code path that results
   /// from the condition evaluating to `true` will be reachable after
diff --git a/pkg/nnbd_migration/lib/src/edit_plan.dart b/pkg/nnbd_migration/lib/src/edit_plan.dart
index e93001c..c6464d8 100644
--- a/pkg/nnbd_migration/lib/src/edit_plan.dart
+++ b/pkg/nnbd_migration/lib/src/edit_plan.dart
@@ -6,9 +6,43 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/precedence.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:meta/meta.dart';
+import 'package:nnbd_migration/instrumentation.dart';
+
+Map<int, List<AtomicEdit>> _removeCode(
+    int offset, int end, _RemovalStyle removalStyle) {
+  if (offset < end) {
+    // TODO(paulberry): handle preexisting comments?
+    switch (removalStyle) {
+      case _RemovalStyle.commentSpace:
+        return {
+          offset: [AtomicEdit.insert('/* ')],
+          end: [AtomicEdit.insert('*/ ')]
+        };
+      case _RemovalStyle.delete:
+        return {
+          offset: [AtomicEdit.delete(end - offset)]
+        };
+      case _RemovalStyle.spaceComment:
+        return {
+          offset: [AtomicEdit.insert(' /*')],
+          end: [AtomicEdit.insert(' */')]
+        };
+      case _RemovalStyle.spaceInsideComment:
+        return {
+          offset: [AtomicEdit.insert('/* ')],
+          end: [AtomicEdit.insert(' */')]
+        };
+    }
+    throw StateError('Null value for removalStyle');
+  } else {
+    return null;
+  }
+}
 
 /// A single atomic change to a source file, decoupled from the location at
 /// which the change is made. The [EditPlan] class performs its duties by
@@ -66,6 +100,26 @@
   }
 }
 
+/// An atomic edit that has a reason associated with it.
+class AtomicEditWithReason extends AtomicEdit {
+  /// The reason for the edit.
+  final FixReasonInfo fixReason;
+
+  /// Initialize an edit to delete [length] characters.
+  const AtomicEditWithReason.delete(int length, this.fixReason)
+      : super.delete(length);
+
+  /// Initialize an edit to insert the [replacement] characters.
+  const AtomicEditWithReason.insert(String replacement, this.fixReason)
+      : super.insert(replacement);
+
+  /// Initialize an edit to replace [length] characters with the [replacement]
+  /// characters.
+  const AtomicEditWithReason.replace(
+      int length, String replacement, this.fixReason)
+      : super.replace(length, replacement);
+}
+
 /// An [EditPlan] is a builder capable of accumulating a set of edits to be
 /// applied to a given [AstNode].
 ///
@@ -88,20 +142,6 @@
   /// AST node being replaced.  For edit plans that insert or delete AST nodes,
   /// this is the parent of the AST nodes that will be inserted or deleted.
   AstNode get parentNode;
-
-  /// Returns a new [EditPlan] that replicates this [EditPlan], but may
-  /// incorporate relevant information obtained from the parent of [sourceNode].
-  /// For example, if this [EditPlan] would produce an expression that might or
-  /// might not need parentheses, and the parent of [sourceNode] is a
-  /// [ParenthesizedExpression], then an [EditPlan] is produced that will either
-  /// preserve the existing parentheses, or remove them, as appropriate.
-  ///
-  /// May return `this`, if no information needs to be incorporated from the
-  /// parent.
-  ///
-  /// This method is used when composing and finalizing plans, to ensure that
-  /// parentheses are removed when they are no longer needed.
-  NodeProducingEditPlan _incorporateParent();
 }
 
 /// Factory class for creating [EditPlan]s.
@@ -111,7 +151,25 @@
   /// that is removed.
   final bool removeViaComments;
 
-  EditPlanner({this.removeViaComments = false});
+  /// The line info for the source file being edited.  This is used when
+  /// removing statements that fill one or more lines, so that we can remove
+  /// the indentation as well as the statement, and avoid leaving behind ugly
+  /// whitespace.
+  final LineInfo lineInfo;
+
+  /// The text of the source file being edited.  This is used when removing
+  /// code, so that we can figure out if it is safe to remove adjoining
+  /// whitespace.
+  final String sourceText;
+
+  EditPlanner(this.lineInfo, this.sourceText, {this.removeViaComments = false});
+
+  /// Creates a [_PassThroughBuilder] object based around [node].
+  ///
+  /// Exposed so that we can substitute a mock class in unit tests.
+  @visibleForTesting
+  PassThroughBuilder createPassThroughBuilder(AstNode node) =>
+      _PassThroughBuilderImpl(node);
 
   /// Creates a new edit plan that consists of executing [innerPlan], and then
   /// removing from the source code any code that is in [sourceNode] but not in
@@ -126,8 +184,9 @@
   /// caller.
   NodeProducingEditPlan extract(
       AstNode sourceNode, NodeProducingEditPlan innerPlan) {
-    if (!identical(innerPlan.sourceNode.parent, sourceNode)) {
-      innerPlan = innerPlan._incorporateParent();
+    var parent = innerPlan.sourceNode.parent;
+    if (!identical(parent, sourceNode) && parent is ParenthesizedExpression) {
+      innerPlan = _ProvisionalParenEditPlan(parent, innerPlan);
     }
     return _ExtractEditPlan(sourceNode, innerPlan, this);
   }
@@ -139,25 +198,118 @@
   /// Finalizing an [EditPlan] is a destructive operation; it should not be used
   /// again after it is finalized.
   Map<int, List<AtomicEdit>> finalize(EditPlan plan) {
-    var incorporatedPlan = plan._incorporateParent();
-    return incorporatedPlan
-        ._getChanges(incorporatedPlan.parensNeededFromContext(null));
+    // Convert to a plan for the top level CompilationUnit.
+    var parent = plan.parentNode;
+    if (parent != null) {
+      var unit = parent.thisOrAncestorOfType<CompilationUnit>();
+      plan = passThrough(unit, innerPlans: [plan]);
+    }
+    // The plan for a compilation unit should always be a NodeProducingEditPlan.
+    // So we can just ask it for its changes.
+    return (plan as NodeProducingEditPlan)._getChanges(false);
   }
 
   /// Creates a new edit plan that makes no changes to [node], but may make
   /// changes to some of its descendants (specified via [innerPlans]).
   ///
+  /// Note that the [innerPlans] must be specified in document order.
+  ///
   /// All plans in [innerPlans] will be finalized as a side effect (either
   /// immediately or when the newly created plan is finalized), so they should
   /// not be re-used by the caller.
   NodeProducingEditPlan passThrough(AstNode node,
       {Iterable<EditPlan> innerPlans = const []}) {
-    if (node is ParenthesizedExpression) {
-      return _ProvisionalParenEditPlan(
-          node, _PassThroughEditPlan(node.expression, innerPlans: innerPlans));
-    } else {
-      return _PassThroughEditPlan(node, innerPlans: innerPlans);
+    // It's possible that some of the inner plans are nested more deeply within
+    // [node] than others.  We want to group these inner plans together into
+    // pass through plans at each level in the AST until we bubble up to [node].
+    // To do so, we form a stack of [_PassThroughBuilder] objects to handle each
+    // level of AST depth, where the first entry in the stack corresponds to
+    // [node], and each subsequent entry will correspond to a child of the
+    // previous.
+    var builderStack = [createPassThroughBuilder(node)];
+    var ancestryPath = <AstNode>[];
+    for (var plan in innerPlans) {
+      // Compute the ancestryPath (the path from `plan.parentNode` up to
+      // `node`).  Note that whereas builderStack walks stepwise down the AST,
+      // ancestryStack will walk stepwise up the AST, with the last entry of
+      // ancestryStack corresponding to the first entry of builderStack.  We
+      // re-use the same list for each loop iteration to reduce GC load.
+      ancestryPath.clear();
+      for (var parent = plan.parentNode;
+          !identical(parent, node);
+          parent = parent.parent) {
+        ancestryPath.add(parent);
+      }
+      ancestryPath.add(node);
+      // Find the deepest entry in builderStack that's on the ancestryPath.
+      var builderIndex = _findMatchingBuilder(builderStack, ancestryPath);
+      // We're finished with all builders beyond that entry.
+      while (builderStack.length > builderIndex + 1) {
+        var passThrough = builderStack.removeLast().finish(this);
+        builderStack.last.add(passThrough);
+      }
+      // And we may need to add new builders to make our way down to
+      // `plan.parentNode`.
+      while (builderStack.length < ancestryPath.length) {
+        // Since builderStack and ancestryPath walk in different directions
+        // through the AST, when building entry builderIndex, we need to count
+        // backwards from the end of ancestryPath to figure out which node to
+        // associate the builder with.
+        builderStack.add(createPassThroughBuilder(
+            ancestryPath[ancestryPath.length - builderStack.length - 1]));
+      }
+      // Now the deepest entry in the builderStack corresponds to
+      // `plan.parentNode`, so we can add the plan to it.
+      builderStack.last.add(plan);
     }
+    // We're now finished with all builders.
+    while (true) {
+      var passThrough = builderStack.removeLast().finish(this);
+      if (builderStack.isEmpty) return passThrough;
+      builderStack.last.add(passThrough);
+    }
+  }
+
+  /// Creates a new edit plan that removes [node] from the AST.
+  ///
+  /// [node] must be one element of a variable length sequence maintained by
+  /// [node]'s parent (for example, a statement in a block, an element in a
+  /// list, a declaration in a class, etc.)
+  EditPlan removeNode(AstNode sourceNode) {
+    var parent = sourceNode.parent;
+    var sequenceNodes = _computeSequenceNodes(parent);
+    if (sequenceNodes == null) {
+      throw StateError(
+          'Cannot remove node whose parent is of type ${parent.runtimeType}');
+    }
+    var index = sequenceNodes.indexOf(sourceNode);
+    assert(index != -1);
+    return _RemoveEditPlan(parent, index, index);
+  }
+
+  /// Creates a new edit plan that removes a sequence of adjacent nodes from
+  /// the AST, starting with [firstSourceNode] and ending with [lastSourceNode].
+  ///
+  /// [firstSourceNode] and [lastSourceNode] must be elements of a variable
+  /// length sequence maintained by their (common) parent (for example,
+  /// statements in a block, elements in a list, declarations in a class, etc.)
+  /// [lastSourceNode] must come after [firstSourceNode].
+  ///
+  /// If [firstSourceNode] and [lastSourceNode] are the same node, then the
+  /// behavior is identical to [removeNode] (i.e. just the one node is removed).
+  EditPlan removeNodes(AstNode firstSourceNode, AstNode lastSourceNode) {
+    var parent = firstSourceNode.parent;
+    assert(identical(lastSourceNode.parent, parent));
+    var sequenceNodes = _computeSequenceNodes(parent);
+    if (sequenceNodes == null) {
+      throw StateError(
+          'Cannot remove node whose parent is of type ${parent.runtimeType}');
+    }
+    var firstIndex = sequenceNodes.indexOf(firstSourceNode);
+    assert(firstIndex != -1);
+    var lastIndex = sequenceNodes.indexOf(lastSourceNode, firstIndex);
+    assert(lastIndex >= firstIndex);
+    return _RemoveEditPlan(parent, firstIndex, lastIndex);
   }
 
   /// Creates a new edit plan that consists of executing [innerPlan], and then
@@ -210,6 +362,124 @@
             : endsInCascade,
         innerChanges);
   }
+
+  /// Walks backward through the source text, starting at [offset] and stopping
+  /// before passing any non-whitespace character.
+  ///
+  /// Does not walk further than [limit] (which should be less than or equal to
+  /// [offset]).
+  int _backAcrossWhitespace(int offset, int limit) {
+    assert(limit <= offset);
+    return limit + sourceText.substring(limit, offset).trimRight().length;
+  }
+
+  /// Walks backward through the source text, starting at [offset] and stopping
+  /// when the beginning of the line is reached.
+  ///
+  /// If [offset] is at the beginning of the line, it is returned unchanged.
+  int _backToLineStart(int offset) {
+    var lineNumber = lineInfo.getLocation(offset).lineNumber;
+    // lineNumber is one-based, but lineInfo.lineStarts expects a zero-based
+    // index, so we need `lineInfo.lineStarts[lineNumber - 1]`.
+    return lineInfo.lineStarts[lineNumber - 1];
+  }
+
+  /// Finds the deepest entry in [builderStack] that matches an entry in
+  /// [ancestryStack], taking advantage of the fact that [builderStack] walks
+  /// stepwise down the AST, and [ancestryStack] walks stepwise up the AST, with
+  /// the last entry of [ancestryStack] corresponding to the first entry of
+  /// [builderStack].
+  int _findMatchingBuilder(
+      List<PassThroughBuilder> builderStack, List<AstNode> ancestryStack) {
+    var builderIndex = builderStack.length - 1;
+    while (builderIndex > 0) {
+      var ancestryIndex = ancestryStack.length - builderIndex - 1;
+      if (ancestryIndex >= 0 &&
+          identical(
+              builderStack[builderIndex].node, ancestryStack[ancestryIndex])) {
+        break;
+      }
+      --builderIndex;
+    }
+    return builderIndex;
+  }
+
+  /// Walks forward through the source text, starting at [offset] and stopping
+  /// before passing any non-whitespace character.
+  ///
+  /// Does not walk further than [limit] (which should be greater than or equal
+  /// to [offset]).
+  int _forwardAcrossWhitespace(int offset, int limit) {
+    return limit - sourceText.substring(offset, limit).trimLeft().length;
+  }
+
+  /// Walks forward through the source text, starting at [offset] and stopping
+  /// at the beginning of the next line (or at the end of the document, if this
+  /// line is the last line).
+  int _forwardToLineEnd(int offset) {
+    int lineNumber = lineInfo.getLocation(offset).lineNumber;
+    // lineNumber is one-based, so if it is equal to
+    // `lineInfo.lineStarts.length`, then we are on the last line.
+    if (lineNumber >= lineInfo.lineStarts.length) {
+      return sourceText.length;
+    }
+    // lineInfo.lineStarts expects a zero-based index, so
+    // `lineInfo.lineStarts[lineNumber]` gives us the beginning of the next
+    // line.
+    return lineInfo.lineStarts[lineNumber];
+  }
+
+  /// Determines whether the given source [offset] comes just after an opener
+  /// ('(', '[', or '{').
+  bool _isJustAfterOpener(int offset) =>
+      offset > 0 && const ['(', '[', '{'].contains(sourceText[offset - 1]);
+
+  /// Determines whether the given source [end] comes just before a closer
+  /// (')', ']', or '}').
+  bool _isJustBeforeCloser(int end) =>
+      end < sourceText.length &&
+      const [')', ']', '}'].contains(sourceText[end]);
+
+  /// Determines if the characters between [offset] and [end] in the source text
+  /// are all whitespace characters.
+  bool _isWhitespaceRange(int offset, int end) {
+    return sourceText.substring(offset, end).trimRight().isEmpty;
+  }
+
+  /// If the given [node] maintains a variable-length sequence of child nodes,
+  /// returns a list containing those child nodes, otherwise returns `null`.
+  ///
+  /// The returned list may or may not be the exact list used by the node to
+  /// maintain its child nodes.  For example, [CompilationUnit] maintains its
+  /// directives and declarations in separate lists, so the returned list is
+  /// a new list containing both directives and declarations.
+  static List<AstNode> _computeSequenceNodes(AstNode node) {
+    if (node is Block) {
+      return node.statements;
+    } else if (node is ListLiteral) {
+      return node.elements;
+    } else if (node is SetOrMapLiteral) {
+      return node.elements;
+    } else if (node is ArgumentList) {
+      return node.arguments;
+    } else if (node is FormalParameterList) {
+      return node.parameters;
+    } else if (node is VariableDeclarationList) {
+      return node.variables;
+    } else if (node is TypeArgumentList) {
+      return node.arguments;
+    } else if (node is TypeParameterList) {
+      return node.typeParameters;
+    } else if (node is EnumDeclaration) {
+      return node.constants;
+    } else if (node is ClassDeclaration) {
+      return node.members;
+    } else if (node is CompilationUnit) {
+      return [...node.directives, ...node.declarations];
+    } else {
+      return null;
+    }
+  }
 }
 
 /// Specialization of [EditPlan] for the situation where the text being produced
@@ -266,16 +536,6 @@
   /// finalized.
   Map<int, List<AtomicEdit>> _getChanges(bool parens);
 
-  @override
-  NodeProducingEditPlan _incorporateParent() {
-    var parent = sourceNode.parent;
-    if (parent is ParenthesizedExpression) {
-      return _ProvisionalParenEditPlan(parent, this);
-    } else {
-      return this;
-    }
-  }
-
   /// Determines if the text that would be produced by [EditPlan] needs to be
   /// surrounded by parens, based on the context in which it will be used.
   bool _parensNeeded(
@@ -284,6 +544,22 @@
       bool allowCascade = false});
 }
 
+/// Data structure that accumulates together a set of [EditPlans] sharing a
+/// common parent node, and groups them together into an [EditPlan] with a
+/// parent node one level up the AST.
+@visibleForTesting
+abstract class PassThroughBuilder {
+  /// The AST node that is the parent of all the [EditPlan]s being accumulated.
+  AstNode get node;
+
+  /// Accumulate another edit plan.
+  void add(EditPlan innerPlan);
+
+  /// Called when no more edit plans need to be added.  Returns the final
+  /// [EditPlan].
+  NodeProducingEditPlan finish(EditPlanner planner);
+}
+
 /// Visitor that determines whether a given [AstNode] ends in a cascade.
 class _EndsInCascadeVisitor extends UnifyingAstVisitor<void> {
   bool endsInCascade = false;
@@ -343,32 +619,6 @@
     }
     return changes;
   }
-
-  static Map<int, List<AtomicEdit>> _removeCode(
-      int offset, int end, _RemovalStyle removalStyle) {
-    if (offset < end) {
-      // TODO(paulberry): handle preexisting comments?
-      switch (removalStyle) {
-        case _RemovalStyle.commentSpace:
-          return {
-            offset: [AtomicEdit.insert('/* ')],
-            end: [AtomicEdit.insert('*/ ')]
-          };
-        case _RemovalStyle.delete:
-          return {
-            offset: [AtomicEdit.delete(end - offset)]
-          };
-        case _RemovalStyle.spaceComment:
-          return {
-            offset: [AtomicEdit.insert(' /*')],
-            end: [AtomicEdit.insert(' */')]
-          };
-      }
-      throw StateError('Null value for removalStyle');
-    } else {
-      return null;
-    }
-  }
 }
 
 /// [EditPlan] representing additional edits performed on the result of a
@@ -607,36 +857,72 @@
   }
 }
 
-/// [EditPlan] representing an AstNode that is not to be changed, but may have
-/// some changes applied to some of its descendants.
-class _PassThroughEditPlan extends _SimpleEditPlan {
-  factory _PassThroughEditPlan(AstNode node,
-      {Iterable<EditPlan> innerPlans = const []}) {
-    bool /*?*/ endsInCascade = node is CascadeExpression ? true : null;
-    Map<int, List<AtomicEdit>> changes;
-    for (var innerPlan in innerPlans) {
-      if (!identical(innerPlan.parentNode, node)) {
-        innerPlan = innerPlan._incorporateParent();
-      }
+class _PassThroughBuilderImpl implements PassThroughBuilder {
+  @override
+  final AstNode node;
+
+  /// The [EditPlan]s accumulated so far.
+  final List<EditPlan> innerPlans = [];
+
+  /// The [EditPlanner] currently being used to create this
+  /// [_PassThroughEditPlan].
+  EditPlanner planner;
+
+  /// Determination of whether the resulting [EditPlan] will end in a cascade,
+  /// or `null` if it is not yet known.
+  bool endsInCascade;
+
+  /// The set of changes aggregated together so far.
+  Map<int, List<AtomicEdit>> changes;
+
+  /// Index into [innerPlans] of the plan to process next.
+  int planIndex = 0;
+
+  /// If [node] is a sequence, the list of its child nodes.  Otherwise `null`.
+  List<AstNode> sequenceNodes;
+
+  /// If [node] is a sequence that uses separators (e.g. a list literal, which
+  /// uses comma separators), a list of its separators.  Otherwise `null`.
+  List<Token> separators;
+
+  /// If [separators] is non-null, and nodes are being removed from the
+  /// sequence, this boolean indicates whether each node should be removed along
+  /// with the separator that *precedes* it.
+  ///
+  /// `false` indicates that each node should be removed along with the
+  /// separator that *follows* it.
+  bool removeLeadingSeparators = false;
+
+  _PassThroughBuilderImpl(this.node);
+
+  @override
+  void add(EditPlan innerPlan) {
+    assert(identical(innerPlan.parentNode, node));
+    innerPlans.add(innerPlan);
+  }
+
+  @override
+  NodeProducingEditPlan finish(EditPlanner planner) {
+    this.planner = planner;
+    var node = this.node;
+    if (node is ParenthesizedExpression) {
+      assert(innerPlans.length <= 1);
+      var innerPlan = innerPlans.isEmpty
+          ? planner.passThrough(node.expression)
+          : innerPlans[0];
       if (innerPlan is NodeProducingEditPlan) {
-        var parensNeeded = innerPlan.parensNeededFromContext(node);
-        assert(_checkParenLogic(innerPlan, parensNeeded));
-        if (!parensNeeded && innerPlan is _ProvisionalParenEditPlan) {
-          var innerInnerPlan = innerPlan.innerPlan;
-          if (innerInnerPlan is _PassThroughEditPlan) {
-            // Input source code had redundant parens, so keep them.
-            parensNeeded = true;
-          }
-        }
-        changes += innerPlan._getChanges(parensNeeded);
-        if (endsInCascade == null && innerPlan.sourceNode.end == node.end) {
-          endsInCascade = !parensNeeded && innerPlan.endsInCascade;
-        }
-      } else {
-        // TODO(paulberry): handle this case.
-        throw UnimplementedError('Inner plan is not node-producing');
+        return _ProvisionalParenEditPlan(node, innerPlan);
       }
     }
+
+    // Make a provisional determination of whether the result will end in a
+    // cascade.
+    // TODO(paulberry): can we make some of these computations lazy?
+    endsInCascade = node is CascadeExpression ? true : null;
+    sequenceNodes = EditPlanner._computeSequenceNodes(node);
+    separators =
+        sequenceNodes == null ? null : _computeSeparators(node, sequenceNodes);
+    _processPlans();
     return _PassThroughEditPlan._(
         node,
         node is Expression ? node.precedence : Precedence.primary,
@@ -644,9 +930,173 @@
         changes);
   }
 
-  _PassThroughEditPlan._(AstNode node, Precedence precedence,
-      bool endsInCascade, Map<int, List<AtomicEdit>> innerChanges)
-      : super(node, precedence, endsInCascade, innerChanges);
+  /// Starting at index [planIndex] of [innerPlans] (whose value is [plan]),
+  /// scans forward to see if there is a range of inner plans that remove a
+  /// contiguous range of AST nodes.
+  ///
+  /// Returns the index into [innerPlans] of the last such contiguous plan, or
+  /// [planIndex] if a contiguous range of removals wasn't found.
+  int _findConsecutiveRemovals(int planIndex, _RemoveEditPlan plan) {
+    assert(identical(innerPlans[planIndex], plan));
+    var lastRemovePlanIndex = planIndex;
+    var lastRemoveEditPlan = plan;
+    while (lastRemovePlanIndex + 1 < innerPlans.length) {
+      var nextPlan = innerPlans[lastRemovePlanIndex + 1];
+      if (nextPlan is _RemoveEditPlan) {
+        if (nextPlan.firstChildIndex == lastRemoveEditPlan.lastChildIndex + 1) {
+          // Removals are consecutive.  Slurp up.
+          lastRemovePlanIndex++;
+          lastRemoveEditPlan = nextPlan;
+          continue;
+        }
+      }
+      break;
+    }
+    return lastRemovePlanIndex;
+  }
+
+  /// Processes an inner plan of type [NodeProducingEditPlan], and updates
+  /// [planIndex] to point to the next inner plan.
+  void _handleNodeProducingEditPlan(NodeProducingEditPlan innerPlan) {
+    var parensNeeded = innerPlan.parensNeededFromContext(node);
+    assert(_checkParenLogic(innerPlan, parensNeeded));
+    if (!parensNeeded && innerPlan is _ProvisionalParenEditPlan) {
+      var innerInnerPlan = innerPlan.innerPlan;
+      if (innerInnerPlan is _PassThroughEditPlan) {
+        // Input source code had redundant parens, so keep them.
+        parensNeeded = true;
+      }
+    }
+    changes += innerPlan._getChanges(parensNeeded);
+    if (endsInCascade == null && innerPlan.sourceNode.end == node.end) {
+      endsInCascade = !parensNeeded && innerPlan.endsInCascade;
+    }
+    planIndex++;
+  }
+
+  /// Processes one or more inner plans of type [_RemoveEditPlan], and updates
+  /// [planIndex] to point to the next inner plan.
+  void _handleRemoveEditPlans(_RemoveEditPlan firstPlan) {
+    assert(identical(firstPlan.parentNode, node));
+    var firstPlanIndex = planIndex;
+    var lastPlanIndex = _findConsecutiveRemovals(firstPlanIndex, firstPlan);
+    var lastPlan = innerPlans[lastPlanIndex] as _RemoveEditPlan;
+    int lastRemovalEnd;
+    int nextRemovalOffset;
+    removeLeadingSeparators = separators != null &&
+        firstPlan.firstChildIndex != 0 &&
+        lastPlan.lastChildIndex >= separators.length;
+    if (planner.removeViaComments) {
+      nextRemovalOffset = _removalOffset(firstPlan);
+      lastRemovalEnd = _removalEnd(lastPlan);
+    } else {
+      var firstRemovalOffset = _removalOffset(firstPlan);
+      var firstLineStart = planner._backToLineStart(firstRemovalOffset);
+      var startsOnLineBoundary =
+          planner._isWhitespaceRange(firstLineStart, firstRemovalOffset);
+      lastRemovalEnd = _removalEnd(lastPlan);
+      var lastLineEnd = planner._forwardToLineEnd(lastRemovalEnd);
+      var endsOnLineBoundary =
+          planner._isWhitespaceRange(lastRemovalEnd, lastLineEnd);
+      if (!endsOnLineBoundary) {
+        // E.g. removing B and C, and possibly A, from `A; B; C; D;`.  Want to
+        // remove the whitespace after `C;`.
+        lastRemovalEnd =
+            planner._forwardAcrossWhitespace(lastRemovalEnd, lastLineEnd);
+      } else if (!startsOnLineBoundary) {
+        // E.g. removing B and C from `A; B; C;`.  Want to remove the whitespace
+        // before `B`.
+        firstRemovalOffset =
+            planner._backAcrossWhitespace(firstRemovalOffset, firstLineStart);
+      } else {
+        // Removing whole lines.
+        firstRemovalOffset = firstLineStart;
+        lastRemovalEnd = lastLineEnd;
+      }
+      if (firstPlanIndex == 0 && lastPlanIndex == sequenceNodes.length - 1) {
+        // We're removing everything.  Try to remove additional whitespace so
+        // that we're left with just `()`, `{}`, or `[]`.
+        var candidateFirstRemovalOffset =
+            planner._backAcrossWhitespace(firstRemovalOffset, node.offset);
+        if (planner._isJustAfterOpener(candidateFirstRemovalOffset)) {
+          var candidateLastRemovalEnd =
+              planner._forwardAcrossWhitespace(lastRemovalEnd, node.end);
+          if (planner._isJustBeforeCloser(candidateLastRemovalEnd)) {
+            firstRemovalOffset = candidateFirstRemovalOffset;
+            lastRemovalEnd = candidateLastRemovalEnd;
+          }
+        }
+      }
+      nextRemovalOffset = firstRemovalOffset;
+    }
+
+    for (; planIndex <= lastPlanIndex; planIndex++) {
+      var offset = nextRemovalOffset;
+      int end;
+      if (planIndex == lastPlanIndex) {
+        end = lastRemovalEnd;
+      } else {
+        var innerPlan = innerPlans[planIndex + 1] as _RemoveEditPlan;
+        assert(identical(innerPlan.parentNode, node));
+        nextRemovalOffset = _removalOffset(innerPlan);
+        if (planner.removeViaComments) {
+          end = _removalEnd(innerPlans[planIndex] as _RemoveEditPlan);
+        } else {
+          var lineStart = planner._backToLineStart(nextRemovalOffset);
+          if (planner._isWhitespaceRange(lineStart, nextRemovalOffset)) {
+            // The next node to remove starts at the beginning of a line
+            // (possibly with whitespace before it).  Consider the removal of
+            // the whitespace to be part of removing the next node.
+            nextRemovalOffset = lineStart;
+          }
+          end = nextRemovalOffset;
+        }
+      }
+      changes += _removeCode(
+          offset,
+          end,
+          planner.removeViaComments
+              ? _RemovalStyle.spaceInsideComment
+              : _RemovalStyle.delete);
+    }
+  }
+
+  /// Walks through the plans in [innerPlans], adjusting them as necessary and
+  /// collecting their changes in [changes].
+  void _processPlans() {
+    while (planIndex < innerPlans.length) {
+      var innerPlan = innerPlans[planIndex];
+      if (innerPlan is NodeProducingEditPlan) {
+        _handleNodeProducingEditPlan(innerPlan);
+      } else if (innerPlan is _RemoveEditPlan) {
+        _handleRemoveEditPlans(innerPlan);
+      } else {
+        throw UnimplementedError('Unrecognized inner plan type');
+      }
+    }
+  }
+
+  /// Computes the end for the text that should be removed by the given
+  /// [innerPlan].
+  int _removalEnd(_RemoveEditPlan innerPlan) {
+    if (separators != null &&
+        !removeLeadingSeparators &&
+        innerPlan.lastChildIndex < separators.length) {
+      return separators[innerPlan.lastChildIndex].end;
+    } else {
+      return sequenceNodes[innerPlan.lastChildIndex].end;
+    }
+  }
+
+  /// Computes the offset for the text that should be removed by the given
+  /// [innerPlan].
+  int _removalOffset(_RemoveEditPlan innerPlan) {
+    if (separators != null && removeLeadingSeparators) {
+      return separators[innerPlan.firstChildIndex - 1].offset;
+    } else {
+      return sequenceNodes[innerPlan.firstChildIndex].offset;
+    }
+  }
 
   static bool _checkParenLogic(EditPlan innerPlan, bool parensNeeded) {
     if (innerPlan is _SimpleEditPlan && innerPlan._innerChanges == null) {
@@ -657,6 +1107,37 @@
     }
     return true;
   }
+
+  /// Compute the set of tokens used by the given [parent] node to separate its
+  /// [childNodes].
+  static List<Token> _computeSeparators(
+      AstNode parent, List<AstNode> childNodes) {
+    if (parent is Block ||
+        parent is ClassDeclaration ||
+        parent is CompilationUnit) {
+      // These parent types don't use separators.
+      return null;
+    } else {
+      var result = <Token>[];
+      for (var child in childNodes) {
+        var separator = child.endToken.next;
+        if (separator != null && separator.type == TokenType.COMMA) {
+          result.add(separator);
+        }
+      }
+      assert(result.length == childNodes.length ||
+          result.length == childNodes.length - 1);
+      return result;
+    }
+  }
+}
+
+/// [EditPlan] representing an AstNode that is not to be changed, but may have
+/// some changes applied to some of its descendants.
+class _PassThroughEditPlan extends _SimpleEditPlan {
+  _PassThroughEditPlan._(AstNode node, Precedence precedence,
+      bool endsInCascade, Map<int, List<AtomicEdit>> innerChanges)
+      : super(node, precedence, endsInCascade, innerChanges);
 }
 
 /// [EditPlan] applying to a [ParenthesizedExpression].  Unlike the normal
@@ -701,6 +1182,30 @@
   /// Code should be removed by commenting it out.  Inserted comment delimiters
   /// should be a space followed by a comment delimiter (i.e. ` /*` and ` */`).
   spaceComment,
+
+  /// Code should be removed by commenting it out.  Inserted comment delimiters
+  /// should have a space inside the comment.
+  spaceInsideComment,
+}
+
+/// [EditPlan] representing one or more AstNodes that are to be removed from
+/// their (common) parent, which must be an AST node that stores a list of
+/// sub-nodes.
+///
+/// If more than one node is to be removed by this [EditPlan], they must be
+/// contiguous.
+class _RemoveEditPlan extends EditPlan {
+  @override
+  final AstNode parentNode;
+
+  /// Index of the node to be removed within the parent.
+  final int firstChildIndex;
+
+  /// Index of the node to be removed within the parent.
+  final int lastChildIndex;
+
+  _RemoveEditPlan(this.parentNode, this.firstChildIndex, this.lastChildIndex)
+      : super._();
 }
 
 /// Implementation of [EditPlan] underlying simple cases where no computation
diff --git a/pkg/nnbd_migration/lib/src/fix_aggregator.dart b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
index ffdd042..76c403d 100644
--- a/pkg/nnbd_migration/lib/src/fix_aggregator.dart
+++ b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/precedence.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:nnbd_migration/src/decorated_type.dart';
 import 'package:nnbd_migration/src/edit_plan.dart';
 
 /// Implementation of [NodeChange] representing the addition of the keyword
@@ -25,6 +26,60 @@
   }
 }
 
+/// Implementation of [NodeChange] representing the removal of a dead branch
+/// because the conditional expression in an if statement, if element, or
+/// conditional expression has been determined to always evaluate to either
+/// `true` or `false`.
+///
+/// TODO(paulberry): store additional information necessary to include in the
+/// preview.
+class EliminateDeadIf extends NodeChange {
+  /// The value that the conditional expression has been determined to always
+  /// evaluate to
+  final bool conditionValue;
+
+  const EliminateDeadIf(this.conditionValue);
+
+  @override
+  EditPlan apply(AstNode node, FixAggregator aggregator) {
+    // TODO(paulberry): do we need to detect whether the condition has side
+    // effects?  For now, assuming no.
+    AstNode nodeToKeep;
+    if (node is IfStatement) {
+      nodeToKeep = conditionValue ? node.thenStatement : node.elseStatement;
+    } else if (node is ConditionalExpression) {
+      nodeToKeep = conditionValue ? node.thenExpression : node.elseExpression;
+    } else if (node is IfElement) {
+      nodeToKeep = conditionValue ? node.thenElement : node.elseElement;
+    } else {
+      throw StateError(
+          "EliminateDeadIf applied to an AST node that's not an if");
+    }
+    if (nodeToKeep == null) {
+      return aggregator.planner.removeNode(node);
+    }
+    if (nodeToKeep is Block) {
+      if (nodeToKeep.statements.isEmpty) {
+        return aggregator.planner.removeNode(node);
+      } else if (nodeToKeep.statements.length == 1) {
+        var singleStatement = nodeToKeep.statements[0];
+        if (singleStatement is VariableDeclarationStatement) {
+          // It's not safe to eliminate the {} because it increases the scope of
+          // the variable declarations
+        } else {
+          return aggregator.planner.extract(node,
+              aggregator.planner.passThrough(nodeToKeep.statements.single));
+        }
+      }
+    }
+    return aggregator.planner
+        .extract(node, aggregator.planner.passThrough(nodeToKeep));
+  }
+
+  @override
+  String toString() => 'EliminateDeadIf($conditionValue)';
+}
+
 /// Visitor that combines together the changes produced by [FixBuilder] into a
 /// concrete set of source code edits using the infrastructure of [EditPlan].
 class FixAggregator extends UnifyingAstVisitor<void> {
@@ -41,12 +96,17 @@
 
   /// Gathers all the changes to nodes descended from [node] into a single
   /// [EditPlan].
-  NodeProducingEditPlan innerPlanForNode(AstNode node) {
+  NodeProducingEditPlan innerPlanForNode(AstNode node) =>
+      planner.passThrough(node, innerPlans: innerPlansForNode(node));
+
+  /// Gathers all the changes to nodes descended from [node] into a list of
+  /// [EditPlan]s, one for each change.
+  List<EditPlan> innerPlansForNode(AstNode node) {
     var previousPlans = _plans;
     try {
       _plans = [];
       node.visitChildren(this);
-      return planner.passThrough(node, innerPlans: _plans);
+      return _plans;
     } finally {
       _plans = previousPlans;
     }
@@ -67,8 +127,10 @@
 
   /// Runs the [FixAggregator] on a [unit] and returns the resulting edits.
   static Map<int, List<AtomicEdit>> run(
-      CompilationUnit unit, Map<AstNode, NodeChange> changes) {
-    var planner = EditPlanner();
+      CompilationUnit unit, String sourceText, Map<AstNode, NodeChange> changes,
+      {bool removeViaComments: false}) {
+    var planner = EditPlanner(unit.lineInfo, sourceText,
+        removeViaComments: removeViaComments);
     var aggregator = FixAggregator._(planner, changes);
     unit.accept(aggregator);
     if (aggregator._plans.isEmpty) return {};
@@ -107,19 +169,19 @@
 
 /// Implementation of [NodeChange] representing the addition of a trailing `?`
 /// to a type.
-///
-/// TODO(paulberry): store additional information necessary to include in the
-/// preview.
 class MakeNullable extends _NestableChange {
-  const MakeNullable(
+  /// The decorated type to which a question mark is being added.
+  final DecoratedType decoratedType;
+
+  const MakeNullable(this.decoratedType,
       [NodeChange<NodeProducingEditPlan> inner = const NoChange()])
       : super(inner);
 
   @override
   EditPlan apply(AstNode node, FixAggregator aggregator) {
     var innerPlan = _inner.apply(node, aggregator);
-    return aggregator.planner
-        .surround(innerPlan, suffix: [const AtomicEdit.insert('?')]);
+    return aggregator.planner.surround(innerPlan,
+        suffix: [AtomicEditWithReason.insert('?', decoratedType.node)]);
   }
 }
 
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 2097229..a64053f 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -198,6 +198,23 @@
   MigrationResolutionHooksImpl(this._fixBuilder);
 
   @override
+  bool getConditionalKnownValue(AstNode node) {
+    // TODO(paulberry): handle things other than IfStatement.
+    var conditionalDiscard =
+        _fixBuilder._variables.getConditionalDiscard(_fixBuilder.source, node);
+    if (conditionalDiscard == null) {
+      return null;
+    } else {
+      if (conditionalDiscard.keepTrue && conditionalDiscard.keepFalse) {
+        return null;
+      }
+      var conditionValue = conditionalDiscard.keepTrue;
+      _fixBuilder._addChange(node, EliminateDeadIf(conditionValue));
+      return conditionValue;
+    }
+  }
+
+  @override
   List<ParameterElement> getExecutableParameters(ExecutableElement element) =>
       getExecutableType(element).parameters;
 
@@ -285,7 +302,9 @@
         _fixBuilder._variables.decoratedTypeAnnotation(source, node);
     var type = decoratedType.type;
     if (!type.isDynamic && !type.isVoid && decoratedType.node.isNullable) {
-      _fixBuilder._addChange(node, MakeNullable());
+      var decoratedType =
+          _fixBuilder._variables.decoratedTypeAnnotation(source, node);
+      _fixBuilder._addChange(node, MakeNullable(decoratedType));
     }
     if (node is TypeName) {
       var typeArguments = node.typeArguments;
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index cff8c09..3a7646b 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -43,6 +43,11 @@
   /// Currently defaults to `false`.
   final bool useFixBuilder;
 
+  /// Indicates whether code removed by the migration engine should be removed
+  /// by commenting it out.  A value of `false` means to actually delete the
+  /// code that is removed.
+  final bool removeViaComments;
+
   /// Prepares to perform nullability migration.
   ///
   /// If [permissive] is `true`, exception handling logic will try to proceed
@@ -57,17 +62,16 @@
   ///
   /// Optional parameter [removeViaComments] indicates whether dead code should
   /// be removed in its entirety (the default) or removed by commenting it out.
-  /// TODO(paulberry): wire this up.
   NullabilityMigrationImpl(NullabilityMigrationListener listener,
       {bool permissive: false,
       NullabilityMigrationInstrumentation instrumentation,
       bool useFixBuilder: false,
       bool removeViaComments = false})
       : this._(listener, NullabilityGraph(instrumentation: instrumentation),
-            permissive, instrumentation, useFixBuilder);
+            permissive, instrumentation, useFixBuilder, removeViaComments);
 
   NullabilityMigrationImpl._(this.listener, this._graph, this._permissive,
-      this._instrumentation, this.useFixBuilder) {
+      this._instrumentation, this.useFixBuilder, this.removeViaComments) {
     _instrumentation?.immutableNodes(_graph.never, _graph.always);
   }
 
@@ -90,15 +94,20 @@
         _variables,
         library);
     fixBuilder.visitAll(unit);
-    var changes = FixAggregator.run(unit, fixBuilder.changes);
+    var changes = FixAggregator.run(unit, result.content, fixBuilder.changes,
+        removeViaComments: removeViaComments);
     for (var entry in changes.entries) {
       final lineInfo = LineInfo.fromContent(source.contents.data);
       var fix = _SingleNullabilityFix(
           source, const _DummyPotentialModification(), lineInfo);
       listener.addFix(fix);
-      // TODO(paulberry): don't pass null to instrumentation.
-      _instrumentation?.fix(fix, null);
-      listener.addEdit(fix, entry.value.toSourceEdit(entry.key));
+      var edits = entry.value;
+      _instrumentation?.fix(
+          fix,
+          edits
+              .whereType<AtomicEditWithReason>()
+              .map((edit) => edit.fixReason));
+      listener.addEdit(fix, edits.toSourceEdit(entry.key));
     }
   }
 
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index d190727..8db150a 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -22,6 +22,8 @@
 class Variables implements VariableRecorder, VariableRepository {
   final NullabilityGraph _graph;
 
+  final _conditionalDiscards = <Source, Map<int, ConditionalDiscard>>{};
+
   final _decoratedElementTypes = <Element, DecoratedType>{};
 
   final _decoratedTypeParameterBounds = <Element, DecoratedType>{};
@@ -104,12 +106,16 @@
     }
   }
 
+  ConditionalDiscard getConditionalDiscard(Source source, AstNode node) =>
+      (_conditionalDiscards[source] ?? {})[node.offset];
+
   Map<Source, List<PotentialModification>> getPotentialModifications() =>
       _potentialModifications;
 
   @override
   void recordConditionalDiscard(
       Source source, AstNode node, ConditionalDiscard conditionalDiscard) {
+    (_conditionalDiscards[source] ??= {})[node.offset] = conditionalDiscard;
     _addPotentialModification(
         source, ConditionalModification(node, conditionalDiscard));
   }
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 8aaf324..54aa90b 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -2075,6 +2075,7 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38472')
   Future<void> test_ifStatement_nullCheck_noElse() async {
     var content = '''
 int f(int x) {
@@ -2084,7 +2085,6 @@
 ''';
     var expected = '''
 int f(int x) {
-  if (x == null) return 0;
   return x;
 }
 ''';
@@ -3854,11 +3854,6 @@
 
   @override
   @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38472')
-  Future<void> test_discard_simple_condition() =>
-      super.test_discard_simple_condition();
-
-  @override
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38472')
   Future<void> test_downcast_dynamic_function_to_functionType() =>
       super.test_downcast_dynamic_function_to_functionType();
 
@@ -3883,11 +3878,6 @@
 
   @override
   @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/40023')
-  Future<void> test_extension_nullableOnType_typeArgument() =>
-      super.test_extension_nullableOnType_typeArgument();
-
-  @override
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/40023')
   Future<void> test_extension_nullableOnType_viaImplicitInvocation() =>
       super.test_extension_nullableOnType_viaImplicitInvocation();
 
@@ -3898,25 +3888,6 @@
 
   @override
   @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38472')
-  Future<void> test_field_initializer_untyped_list_literal() =>
-      super.test_field_initializer_untyped_list_literal();
-
-  @override
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38472')
-  Future<void> test_field_initializer_untyped_map_literal() =>
-      super.test_field_initializer_untyped_map_literal();
-
-  @override
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38472')
-  Future<void> test_field_initializer_untyped_set_literal() =>
-      super.test_field_initializer_untyped_set_literal();
-
-  @override
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38472')
-  Future<void> test_for_each_basic() => super.test_for_each_basic();
-
-  @override
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38472')
   Future<void> test_generic_exact_propagation() =>
       super.test_generic_exact_propagation();
 
@@ -3925,6 +3896,11 @@
   Future<void> test_generic_exact_propagation_premigratedListClass() =>
       super.test_generic_exact_propagation_premigratedListClass();
 
+  /// Test fails under the pre-FixBuilder implementation; passes now.
+  @override
+  Future<void> test_ifStatement_nullCheck_noElse() =>
+      super.test_ifStatement_nullCheck_noElse();
+
   @override
   @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38472')
   Future<void> test_instance_creation_generic() =>
diff --git a/pkg/nnbd_migration/test/edit_plan_test.dart b/pkg/nnbd_migration/test/edit_plan_test.dart
index 8287884..5990bb9 100644
--- a/pkg/nnbd_migration/test/edit_plan_test.dart
+++ b/pkg/nnbd_migration/test/edit_plan_test.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/precedence.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/source/line_info.dart';
 import 'package:nnbd_migration/src/edit_plan.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -23,15 +24,27 @@
 class EditPlanTest extends AbstractSingleUnitTest {
   String code;
 
-  var planner = EditPlanner();
+  EditPlanner _planner;
+
+  EditPlanner get planner {
+    if (_planner == null) createPlanner();
+    return _planner;
+  }
 
   Future<void> analyze(String code) async {
     this.code = code;
     await resolveTestUnit(code);
   }
 
-  void checkPlan(EditPlan plan, String expected) {
-    expect(planner.finalize(plan).applyTo(code), expected);
+  Map<int, List<AtomicEdit>> checkPlan(EditPlan plan, String expected) {
+    var changes = planner.finalize(plan);
+    expect(changes.applyTo(code), expected);
+    return changes;
+  }
+
+  void createPlanner({bool removeViaComments: false}) {
+    _planner = EditPlanner(testUnit.lineInfo, code,
+        removeViaComments: removeViaComments);
   }
 
   NodeProducingEditPlan extract(AstNode inner, AstNode outer) =>
@@ -74,7 +87,7 @@
       // We can tell that the parens have been finalized because `endsInCascade`
       // returns false now.
       expect(plan.endsInCascade, false);
-      checkPlan(plan, 'f(a, c) => a..b = c = (1..isEven);');
+      checkPlan(plan, 'f(a, c) => a..b = (c = 1..isEven);');
     }
   }
 
@@ -126,23 +139,38 @@
         'var x = 1 + 2 << 4;');
   }
 
+  Future<void> test_extract_remove_redundant_parens() async {
+    await analyze('var x = (1 * 2) + 3;');
+    var times = findNode.binary('*');
+    checkPlan(extract(times, times.parent), 'var x = 1 * 2 + 3;');
+  }
+
+  Future<void> test_extract_try_to_remove_necessary_parens() async {
+    // This is a weird corner case.  We try to extract the expression `1 + 2`
+    // from `( 1 + 2 )`, meaning we should remove parens.  But the parens are
+    // necessary.  So we create fresh ones (without the spaces).
+    await analyze('var x = ( 1 + 2 ) * 3;');
+    var plus = findNode.binary('+');
+    checkPlan(extract(plus, plus.parent), 'var x = (1 + 2) * 3;');
+  }
+
   Future<void> test_extract_using_comments_inner() async {
-    planner = EditPlanner(removeViaComments: true);
     await analyze('var x = 1 + 2 * 3;');
+    createPlanner(removeViaComments: true);
     checkPlan(extract(findNode.integerLiteral('2'), findNode.binary('+')),
         'var x = /* 1 + */ 2 /* * 3 */;');
   }
 
   Future<void> test_extract_using_comments_left() async {
-    planner = EditPlanner(removeViaComments: true);
     await analyze('var x = 1 + 2;');
+    createPlanner(removeViaComments: true);
     checkPlan(extract(findNode.integerLiteral('1'), findNode.binary('+')),
         'var x = 1 /* + 2 */;');
   }
 
   Future<void> test_extract_using_comments_right() async {
-    planner = EditPlanner(removeViaComments: true);
     await analyze('var x = 1 + 2;');
+    createPlanner(removeViaComments: true);
     checkPlan(extract(findNode.integerLiteral('2'), findNode.binary('+')),
         'var x = /* 1 + */ 2;');
   }
@@ -158,6 +186,574 @@
         'var x = 0; var y = 0;');
   }
 
+  Future<void> test_passThrough_remove_statement() async {
+    await analyze('''
+void f() {
+  var x = () {
+    1;
+    2;
+    3;
+  };
+}
+''');
+    var innerPlan = planner.removeNode(findNode.statement('2'));
+    var outerPlan = planner.passThrough(findNode.variableDeclaration('x'),
+        innerPlans: [innerPlan]);
+    checkPlan(outerPlan, '''
+void f() {
+  var x = () {
+    1;
+    3;
+  };
+}
+''');
+  }
+
+  Future<void> test_remove_argument() async {
+    await analyze('f(dynamic d) => d(1, 2, 3);');
+    var i2 = findNode.integerLiteral('2');
+    var changes = checkPlan(planner.removeNode(i2), 'f(dynamic d) => d(1, 3);');
+    expect(changes.keys, [i2.offset]);
+  }
+
+  Future<void> test_remove_class_member() async {
+    await analyze('''
+class C {
+  int x;
+  int y;
+  int z;
+}
+''');
+    var declaration = findNode.fieldDeclaration('y');
+    var changes = checkPlan(planner.removeNode(declaration), '''
+class C {
+  int x;
+  int z;
+}
+''');
+    expect(changes.keys, [declaration.offset - 2]);
+  }
+
+  Future<void>
+      test_remove_elements_of_related_lists_at_different_levels() async {
+    await analyze('var x = [[1, 2], 3, 4];');
+    var i2 = findNode.integerLiteral('2');
+    var i3 = findNode.integerLiteral('3');
+    checkPlan(
+        planner.passThrough(testUnit,
+            innerPlans: [planner.removeNode(i2), planner.removeNode(i3)]),
+        'var x = [[1], 4];');
+  }
+
+  Future<void>
+      test_remove_elements_of_sibling_lists_passThrough_container() async {
+    await analyze('var x = [[1, 2], [3, 4]];');
+    var i2 = findNode.integerLiteral('2');
+    var i3 = findNode.integerLiteral('3');
+    checkPlan(
+        planner.passThrough(i2.parent.parent,
+            innerPlans: [planner.removeNode(i2), planner.removeNode(i3)]),
+        'var x = [[1], [4]];');
+  }
+
+  Future<void> test_remove_elements_of_sibling_lists_passThrough_unit() async {
+    await analyze('var x = [[1, 2], [3, 4]];');
+    var i2 = findNode.integerLiteral('2');
+    var i3 = findNode.integerLiteral('3');
+    checkPlan(
+        planner.passThrough(testUnit,
+            innerPlans: [planner.removeNode(i2), planner.removeNode(i3)]),
+        'var x = [[1], [4]];');
+  }
+
+  Future<void> test_remove_enum_constant() async {
+    await analyze('''
+enum E {
+  A,
+  B,
+  C
+}
+''');
+    var enumConstant = findNode.simple('B').parent;
+    var changes = checkPlan(planner.removeNode(enumConstant), '''
+enum E {
+  A,
+  C
+}
+''');
+    expect(changes.keys, [enumConstant.offset - 2]);
+  }
+
+  Future<void> test_remove_field_declaration() async {
+    await analyze('''
+class C {
+  int x, y, z;
+}
+''');
+    var declaration = findNode.simple('y').parent;
+    var changes = checkPlan(planner.removeNode(declaration), '''
+class C {
+  int x, z;
+}
+''');
+    expect(changes.keys, [declaration.offset]);
+  }
+
+  Future<void> test_remove_list_element() async {
+    await analyze('var x = [1, 2, 3];');
+    var i2 = findNode.integerLiteral('2');
+    var changes = checkPlan(planner.removeNode(i2), 'var x = [1, 3];');
+    expect(changes.keys, [i2.offset]);
+  }
+
+  Future<void> test_remove_list_element_at_list_end() async {
+    await analyze('var x = [1, 2, 3];');
+    var i2 = findNode.integerLiteral('2');
+    var i3 = findNode.integerLiteral('3');
+    var changes = checkPlan(planner.removeNode(i3), 'var x = [1, 2];');
+    expect(changes.keys, [i2.end]);
+  }
+
+  Future<void> test_remove_list_element_singleton() async {
+    await analyze('var x = [1];');
+    var i1 = findNode.integerLiteral('1');
+    checkPlan(planner.removeNode(i1), 'var x = [];');
+  }
+
+  Future<void> test_remove_list_element_with_trailing_separator() async {
+    await analyze('var x = [1, 2, 3, ];');
+    var i3 = findNode.integerLiteral('3');
+    checkPlan(planner.removeNode(i3), 'var x = [1, 2, ];');
+  }
+
+  Future<void> test_remove_list_elements() async {
+    await analyze('var x = [1, 2, 3, 4, 5];');
+    var i2 = findNode.integerLiteral('2');
+    var i4 = findNode.integerLiteral('4');
+    var changes = checkPlan(
+        planner.passThrough(i2.parent,
+            innerPlans: [planner.removeNode(i2), planner.removeNode(i4)]),
+        'var x = [1, 3, 5];');
+    expect(changes.keys, unorderedEquals([i2.offset, i4.offset]));
+  }
+
+  Future<void> test_remove_list_elements_all() async {
+    await analyze('var x = [1, 2];');
+    var i1 = findNode.integerLiteral('1');
+    var i2 = findNode.integerLiteral('2');
+    checkPlan(
+        planner.passThrough(i1.parent,
+            innerPlans: [planner.removeNode(i1), planner.removeNode(i2)]),
+        'var x = [];');
+  }
+
+  Future<void> test_remove_list_elements_all_asUnit() async {
+    await analyze('var x = [1, 2];');
+    var i1 = findNode.integerLiteral('1');
+    var i2 = findNode.integerLiteral('2');
+    checkPlan(planner.removeNodes(i1, i2), 'var x = [];');
+  }
+
+  Future<void> test_remove_list_elements_all_passThrough_unit() async {
+    await analyze('var x = [1, 2];');
+    var i1 = findNode.integerLiteral('1');
+    var i2 = findNode.integerLiteral('2');
+    checkPlan(
+        planner.passThrough(testUnit,
+            innerPlans: [planner.removeNode(i1), planner.removeNode(i2)]),
+        'var x = [];');
+  }
+
+  Future<void> test_remove_list_elements_at_list_end() async {
+    await analyze('var x = [1, 2, 3];');
+    var i1 = findNode.integerLiteral('1');
+    var i2 = findNode.integerLiteral('2');
+    var i3 = findNode.integerLiteral('3');
+    var changes = checkPlan(
+        planner.passThrough(i2.parent,
+            innerPlans: [planner.removeNode(i2), planner.removeNode(i3)]),
+        'var x = [1];');
+    expect(changes.keys, unorderedEquals([i1.end, i2.end]));
+  }
+
+  Future<void> test_remove_list_elements_at_list_end_asUnit() async {
+    await analyze('var x = [1, 2, 3];');
+    var i1 = findNode.integerLiteral('1');
+    var i2 = findNode.integerLiteral('2');
+    var i3 = findNode.integerLiteral('3');
+    var changes = checkPlan(planner.removeNodes(i2, i3), 'var x = [1];');
+    expect(changes.keys, [i1.end]);
+  }
+
+  Future<void> test_remove_list_elements_consecutive_asUnit() async {
+    await analyze('var x = [1, 2, 3, 4];');
+    var i2 = findNode.integerLiteral('2');
+    var i3 = findNode.integerLiteral('3');
+    var changes = checkPlan(planner.removeNodes(i2, i3), 'var x = [1, 4];');
+    expect(changes.keys, [i2.offset]);
+  }
+
+  Future<void>
+      test_remove_list_elements_consecutive_at_list_end_using_comments() async {
+    await analyze('var x = [1, 2, 3];');
+    var i2 = findNode.integerLiteral('2');
+    var i3 = findNode.integerLiteral('3');
+    createPlanner(removeViaComments: true);
+    checkPlan(
+        planner.passThrough(i2.parent,
+            innerPlans: [planner.removeNode(i2), planner.removeNode(i3)]),
+        'var x = [1/* , 2 *//* , 3 */];');
+  }
+
+  Future<void> test_remove_list_elements_consecutive_using_comments() async {
+    await analyze('var x = [1, 2, 3, 4];');
+    var i2 = findNode.integerLiteral('2');
+    var i3 = findNode.integerLiteral('3');
+    createPlanner(removeViaComments: true);
+    checkPlan(
+        planner.passThrough(i2.parent,
+            innerPlans: [planner.removeNode(i2), planner.removeNode(i3)]),
+        'var x = [1, /* 2, */ /* 3, */ 4];');
+  }
+
+  Future<void> test_remove_list_elements_using_comments() async {
+    await analyze('var x = [1, 2, 3, 4, 5];');
+    var i2 = findNode.integerLiteral('2');
+    var i4 = findNode.integerLiteral('4');
+    createPlanner(removeViaComments: true);
+    checkPlan(
+        planner.passThrough(i2.parent,
+            innerPlans: [planner.removeNode(i2), planner.removeNode(i4)]),
+        'var x = [1, /* 2, */ 3, /* 4, */ 5];');
+  }
+
+  Future<void> test_remove_map_element() async {
+    await analyze('var x = {1: 2, 3: 4, 5: 6};');
+    var entry = findNode.integerLiteral('3').parent;
+    var changes = checkPlan(planner.removeNode(entry), 'var x = {1: 2, 5: 6};');
+    expect(changes.keys, [entry.offset]);
+  }
+
+  Future<void> test_remove_parameter() async {
+    await analyze('f(int x, int y, int z) => null;');
+    var parameter = findNode.simple('y').parent;
+    var changes =
+        checkPlan(planner.removeNode(parameter), 'f(int x, int z) => null;');
+    expect(changes.keys, [parameter.offset]);
+  }
+
+  Future<void> test_remove_set_element() async {
+    await analyze('var x = {1, 2, 3};');
+    var i2 = findNode.integerLiteral('2');
+    var changes = checkPlan(planner.removeNode(i2), 'var x = {1, 3};');
+    expect(changes.keys, [i2.offset]);
+  }
+
+  Future<void> test_remove_statement() async {
+    await analyze('''
+void f() {
+  1;
+  2;
+  3;
+}
+''');
+    checkPlan(planner.removeNode(findNode.statement('2')), '''
+void f() {
+  1;
+  3;
+}
+''');
+  }
+
+  Future<void> test_remove_statement_first_of_many_on_line() async {
+    await analyze('''
+void f() {
+  1;
+  2; 3;
+  4;
+}
+''');
+    checkPlan(planner.removeNode(findNode.statement('2')), '''
+void f() {
+  1;
+  3;
+  4;
+}
+''');
+  }
+
+  Future<void> test_remove_statement_last_of_many_on_line() async {
+    await analyze('''
+void f() {
+  1;
+  2; 3;
+  4;
+}
+''');
+    checkPlan(planner.removeNode(findNode.statement('3')), '''
+void f() {
+  1;
+  2;
+  4;
+}
+''');
+  }
+
+  Future<void> test_remove_statement_middle_of_many_on_line() async {
+    await analyze('''
+void f() {
+  1;
+  2; 3; 4;
+  5;
+}
+''');
+    checkPlan(planner.removeNode(findNode.statement('3')), '''
+void f() {
+  1;
+  2; 4;
+  5;
+}
+''');
+  }
+
+  Future<void> test_remove_statement_using_comments() async {
+    await analyze('''
+void f() {
+  1;
+  2;
+  3;
+}
+''');
+    createPlanner(removeViaComments: true);
+    checkPlan(planner.removeNode(findNode.statement('2')), '''
+void f() {
+  1;
+  /* 2; */
+  3;
+}
+''');
+  }
+
+  Future<void> test_remove_statements_asUnit() async {
+    await analyze('''
+void f() {
+  1;
+  2;
+
+  3;
+  4;
+}
+''');
+    var s2 = findNode.statement('2');
+    var s3 = findNode.statement('3');
+    var changes = checkPlan(planner.removeNodes(s2, s3), '''
+void f() {
+  1;
+  4;
+}
+''');
+    expect(changes, hasLength(1));
+  }
+
+  Future<void> test_remove_statements_consecutive_three() async {
+    await analyze('''
+void f() {
+  1;
+  2;
+
+  3;
+
+  4;
+  5;
+}
+''');
+    var s2 = findNode.statement('2');
+    var s3 = findNode.statement('3');
+    var s4 = findNode.statement('4');
+    var changes = checkPlan(
+        planner.passThrough(s2.parent, innerPlans: [
+          planner.removeNode(s2),
+          planner.removeNode(s3),
+          planner.removeNode(s4)
+        ]),
+        '''
+void f() {
+  1;
+  5;
+}
+''');
+    expect(changes.keys,
+        unorderedEquals([s2.offset - 2, s3.offset - 2, s4.offset - 2]));
+  }
+
+  Future<void> test_remove_statements_consecutive_two() async {
+    await analyze('''
+void f() {
+  1;
+  2;
+
+  3;
+  4;
+}
+''');
+    var s2 = findNode.statement('2');
+    var s3 = findNode.statement('3');
+    var changes = checkPlan(
+        planner.passThrough(s2.parent,
+            innerPlans: [planner.removeNode(s2), planner.removeNode(s3)]),
+        '''
+void f() {
+  1;
+  4;
+}
+''');
+    expect(changes.keys, unorderedEquals([s2.offset - 2, s3.offset - 2]));
+  }
+
+  Future<void> test_remove_statements_nonconsecutive() async {
+    await analyze('''
+void f() {
+  1;
+  2;
+  3;
+  4;
+  5;
+}
+''');
+    var s2 = findNode.statement('2');
+    var s4 = findNode.statement('4');
+    var changes = checkPlan(
+        planner.passThrough(s2.parent,
+            innerPlans: [planner.removeNode(s2), planner.removeNode(s4)]),
+        '''
+void f() {
+  1;
+  3;
+  5;
+}
+''');
+    expect(changes, hasLength(2));
+  }
+
+  Future<void> test_remove_statements_singleton() async {
+    await analyze('''
+void f() {
+  1;
+}
+''');
+    checkPlan(planner.removeNode(findNode.statement('1')), '''
+void f() {}
+''');
+  }
+
+  Future<void> test_remove_statements_singleton_with_following_comment() async {
+    await analyze('''
+void f() {
+  1;
+  // Foo
+}
+''');
+    checkPlan(planner.removeNode(findNode.statement('1')), '''
+void f() {
+  // Foo
+}
+''');
+  }
+
+  Future<void> test_remove_statements_singleton_with_preceding_comment() async {
+    await analyze('''
+void f() {
+  // Foo
+  1;
+}
+''');
+    checkPlan(planner.removeNode(findNode.statement('1')), '''
+void f() {
+  // Foo
+}
+''');
+  }
+
+  Future<void> test_remove_statements_using_comments() async {
+    await analyze('''
+void f() {
+  1;
+  2;
+  3;
+  4;
+}
+''');
+    createPlanner(removeViaComments: true);
+    var s2 = findNode.statement('2');
+    var s3 = findNode.statement('3');
+    checkPlan(
+        planner.passThrough(s2.parent,
+            innerPlans: [planner.removeNode(s2), planner.removeNode(s3)]),
+        '''
+void f() {
+  1;
+  /* 2; */
+  /* 3; */
+  4;
+}
+''');
+  }
+
+  Future<void> test_remove_top_level_declaration() async {
+    await analyze('''
+class C {}
+class D {}
+class E {}
+''');
+    var declaration = findNode.classDeclaration('D');
+    var changes = checkPlan(planner.removeNode(declaration), '''
+class C {}
+class E {}
+''');
+    expect(changes.keys, [declaration.offset]);
+  }
+
+  Future<void> test_remove_top_level_directive() async {
+    await analyze('''
+import 'dart:io';
+import 'dart:async';
+import 'dart:math';
+''');
+    var directive = findNode.import('async');
+    var changes = checkPlan(planner.removeNode(directive), '''
+import 'dart:io';
+import 'dart:math';
+''');
+    expect(changes.keys, [directive.offset]);
+  }
+
+  Future<void> test_remove_type_argument() async {
+    await analyze('''
+class C<T, U, V> {}
+C<int, double, String> c;
+''');
+    var typeArgument = findNode.simple('double').parent;
+    var changes = checkPlan(planner.removeNode(typeArgument), '''
+class C<T, U, V> {}
+C<int, String> c;
+''');
+    expect(changes.keys, [typeArgument.offset]);
+  }
+
+  Future<void> test_remove_type_parameter() async {
+    await analyze('class C<T, U, V> {}');
+    var parameter = findNode.simple('U').parent;
+    var changes = checkPlan(planner.removeNode(parameter), 'class C<T, V> {}');
+    expect(changes.keys, [parameter.offset]);
+  }
+
+  Future<void> test_remove_variable_declaration() async {
+    await analyze('int x, y, z;');
+    var declaration = findNode.simple('y').parent;
+    var changes = checkPlan(planner.removeNode(declaration), 'int x, z;');
+    expect(changes.keys, [declaration.offset]);
+  }
+
   Future<void> test_surround_allowCascade() async {
     await analyze('f(x) => 1..isEven;');
     checkPlan(
@@ -273,6 +869,24 @@
         'var x = 1..isEven;');
   }
 
+  Future<void> test_surround_suffix_parenthesized() async {
+    await analyze('var x = (1);');
+    checkPlan(
+        planner.surround(planner.passThrough(findNode.integerLiteral('1')),
+            suffix: [AtomicEdit.insert('..isEven')]),
+        'var x = 1..isEven;');
+  }
+
+  Future<void> test_surround_suffix_parenthesized_passThrough_unit() async {
+    await analyze('var x = (1);');
+    checkPlan(
+        planner.passThrough(testUnit, innerPlans: [
+          planner.surround(planner.passThrough(findNode.integerLiteral('1')),
+              suffix: [AtomicEdit.insert('..isEven')])
+        ]),
+        'var x = 1..isEven;');
+  }
+
   Future<void> test_surround_threshold() async {
     await analyze('var x = 1 < 2;');
     checkPlan(
@@ -323,7 +937,7 @@
 class PrecedenceTest extends AbstractSingleUnitTest {
   Future<void> checkPrecedence(String content) async {
     await resolveTestUnit(content);
-    testUnit.accept(_PrecedenceChecker());
+    testUnit.accept(_PrecedenceChecker(testUnit.lineInfo, testCode));
   }
 
   Future<void> test_precedence_as() async {
@@ -436,13 +1050,17 @@
 
   Future<void> test_precedenceChecker_detects_unnecessary_paren() async {
     await resolveTestUnit('var x = (1);');
-    expect(() => testUnit.accept(_PrecedenceChecker()),
+    expect(
+        () => testUnit.accept(_PrecedenceChecker(testUnit.lineInfo, testCode)),
         throwsA(TypeMatcher<TestFailure>()));
   }
 }
 
 class _PrecedenceChecker extends UnifyingAstVisitor<void> {
-  final planner = EditPlanner();
+  final EditPlanner planner;
+
+  _PrecedenceChecker(LineInfo lineInfo, String sourceText)
+      : planner = EditPlanner(lineInfo, sourceText);
 
   @override
   void visitNode(AstNode node) {
diff --git a/pkg/nnbd_migration/test/edit_planner_pass_through_merging_test.dart b/pkg/nnbd_migration/test/edit_planner_pass_through_merging_test.dart
new file mode 100644
index 0000000..1bc5d2a
--- /dev/null
+++ b/pkg/nnbd_migration/test/edit_planner_pass_through_merging_test.dart
@@ -0,0 +1,115 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/source/line_info.dart';
+import 'package:nnbd_migration/src/edit_plan.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'abstract_single_unit.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(PassThroughMergingTest);
+  });
+}
+
+/// Tests to make sure the algorithm used by [EditPlaner.passThrough] is
+/// correct.
+@reflectiveTest
+class PassThroughMergingTest extends AbstractSingleUnitTest {
+  Future<void> test_creates_pass_through_plans_stepwise() async {
+    await resolveTestUnit('var x = [[[1]]];');
+    var plan = _EditPlannerForTesting(testCode).passThrough(
+        findNode.listLiteral('[[['),
+        innerPlans: [_MockPlan(findNode.integerLiteral('1'))]);
+    expect(plan.toString(),
+        'plan([[[1]]], [plan([[1]], [plan([1], [plan(1)])])])');
+  }
+
+  Future<void> test_merge_plans_at_lower_level() async {
+    await resolveTestUnit('var x = [[1, 2]];');
+    var plan = _EditPlannerForTesting(testCode)
+        .passThrough(findNode.listLiteral('[['), innerPlans: [
+      _MockPlan(findNode.integerLiteral('1')),
+      _MockPlan(findNode.integerLiteral('2'))
+    ]);
+    expect(
+        plan.toString(), 'plan([[1, 2]], [plan([1, 2], [plan(1), plan(2)])])');
+  }
+
+  Future<void> test_merge_plans_at_top_level() async {
+    await resolveTestUnit('var x = [[1], [2]];');
+    var plan = _EditPlannerForTesting(testCode)
+        .passThrough(findNode.listLiteral('[['), innerPlans: [
+      _MockPlan(findNode.integerLiteral('1')),
+      _MockPlan(findNode.integerLiteral('2'))
+    ]);
+    expect(plan.toString(),
+        'plan([[1], [2]], [plan([1], [plan(1)]), plan([2], [plan(2)])])');
+  }
+
+  Future<void> test_merge_plans_at_varying_levels() async {
+    await resolveTestUnit('var x = [1, [2, 3], 4];');
+    var plan = _EditPlannerForTesting(testCode)
+        .passThrough(findNode.listLiteral('[1'), innerPlans: [
+      _MockPlan(findNode.integerLiteral('1')),
+      _MockPlan(findNode.integerLiteral('2')),
+      _MockPlan(findNode.integerLiteral('3')),
+      _MockPlan(findNode.integerLiteral('4'))
+    ]);
+    expect(
+        plan.toString(),
+        'plan([1, [2, 3], 4], [plan(1), plan([2, 3], [plan(2), plan(3)]), '
+        'plan(4)])');
+  }
+}
+
+class _EditPlannerForTesting extends EditPlanner {
+  _EditPlannerForTesting(String content)
+      : super(LineInfo.fromContent(content), content);
+
+  @override
+  PassThroughBuilder createPassThroughBuilder(AstNode node) =>
+      _MockPassThroughBuilder(node);
+}
+
+class _MockPassThroughBuilder implements PassThroughBuilder {
+  final List<EditPlan> _innerPlans = [];
+
+  @override
+  final AstNode node;
+
+  _MockPassThroughBuilder(this.node);
+
+  @override
+  void add(EditPlan innerPlan) {
+    _innerPlans.add(innerPlan);
+  }
+
+  @override
+  NodeProducingEditPlan finish(EditPlanner planner) {
+    return _MockPlan(node, _innerPlans);
+  }
+}
+
+class _MockPlan implements NodeProducingEditPlan {
+  final AstNode _node;
+
+  final List<EditPlan> _innerPlans;
+
+  _MockPlan(this._node, [List<EditPlan> innerPlans = const []])
+      : _innerPlans = innerPlans;
+
+  @override
+  AstNode get parentNode => _node.parent;
+
+  @override
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+
+  @override
+  String toString() =>
+      _innerPlans.isEmpty ? 'plan($_node)' : 'plan($_node, $_innerPlans)';
+}
diff --git a/pkg/nnbd_migration/test/fix_aggregator_test.dart b/pkg/nnbd_migration/test/fix_aggregator_test.dart
index 3d5009e..35ebd36 100644
--- a/pkg/nnbd_migration/test/fix_aggregator_test.dart
+++ b/pkg/nnbd_migration/test/fix_aggregator_test.dart
@@ -3,8 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:nnbd_migration/src/decorated_type.dart';
 import 'package:nnbd_migration/src/edit_plan.dart';
 import 'package:nnbd_migration/src/fix_aggregator.dart';
+import 'package:nnbd_migration/src/nullability_node.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -37,6 +39,215 @@
     expect(previewInfo.applyTo(code), 'f(a, b) => (a! + b!)!;');
   }
 
+  Future<void> test_eliminateDeadIf_element_delete_drop_completely() async {
+    await analyze('''
+List<int> f(int i) {
+  return [if (i == null) null];
+}
+''');
+    var previewInfo = run({findNode.ifElement('=='): EliminateDeadIf(false)});
+    expect(previewInfo.applyTo(code), '''
+List<int> f(int i) {
+  return [];
+}
+''');
+  }
+
+  Future<void> test_eliminateDeadIf_element_delete_keep_else() async {
+    await analyze('''
+List<int> f(int i) {
+  return [if (i == null) null else i + 1];
+}
+''');
+    var previewInfo = run({findNode.ifElement('=='): EliminateDeadIf(false)});
+    expect(previewInfo.applyTo(code), '''
+List<int> f(int i) {
+  return [i + 1];
+}
+''');
+  }
+
+  Future<void> test_eliminateDeadIf_element_delete_keep_then() async {
+    await analyze('''
+List<int> f(int i) {
+  return [if (i == null) null else i + 1];
+}
+''');
+    var previewInfo = run({findNode.ifElement('=='): EliminateDeadIf(true)});
+    expect(previewInfo.applyTo(code), '''
+List<int> f(int i) {
+  return [null];
+}
+''');
+  }
+
+  Future<void> test_eliminateDeadIf_expression_delete_keep_else() async {
+    await analyze('''
+int f(int i) {
+  return i == null ? null : i + 1;
+}
+''');
+    var previewInfo =
+        run({findNode.conditionalExpression('=='): EliminateDeadIf(false)});
+    expect(previewInfo.applyTo(code), '''
+int f(int i) {
+  return i + 1;
+}
+''');
+  }
+
+  Future<void> test_eliminateDeadIf_expression_delete_keep_then() async {
+    await analyze('''
+int f(int i) {
+  return i == null ? null : i + 1;
+}
+''');
+    var previewInfo =
+        run({findNode.conditionalExpression('=='): EliminateDeadIf(true)});
+    expect(previewInfo.applyTo(code), '''
+int f(int i) {
+  return null;
+}
+''');
+  }
+
+  Future<void> test_eliminateDeadIf_statement_comment_keep_else() async {
+    await analyze('''
+int f(int i) {
+  if (i == null) {
+    return null;
+  } else {
+    return i + 1;
+  }
+}
+''');
+    var previewInfo = run({findNode.statement('if'): EliminateDeadIf(false)},
+        removeViaComments: true);
+    expect(previewInfo.applyTo(code), '''
+int f(int i) {
+  /* if (i == null) {
+    return null;
+  } else {
+    */ return i + 1; /*
+  } */
+}
+''');
+  }
+
+  Future<void> test_eliminateDeadIf_statement_comment_keep_then() async {
+    await analyze('''
+int f(int i) {
+  if (i == null) {
+    return null;
+  } else {
+    return i + 1;
+  }
+}
+''');
+    var previewInfo = run({findNode.statement('if'): EliminateDeadIf(true)},
+        removeViaComments: true);
+    expect(previewInfo.applyTo(code), '''
+int f(int i) {
+  /* if (i == null) {
+    */ return null; /*
+  } else {
+    return i + 1;
+  } */
+}
+''');
+  }
+
+  Future<void>
+      test_eliminateDeadIf_statement_delete_drop_completely_false() async {
+    await analyze('''
+void f(int i) {
+  if (i == null) {
+    print('null');
+  }
+}
+''');
+    var previewInfo = run({findNode.statement('if'): EliminateDeadIf(false)});
+    expect(previewInfo.applyTo(code), '''
+void f(int i) {}
+''');
+  }
+
+  Future<void>
+      test_eliminateDeadIf_statement_delete_drop_completely_true() async {
+    await analyze('''
+void f(int i) {
+  if (i != null) {} else {
+    print('null');
+  }
+}
+''');
+    var previewInfo = run({findNode.statement('if'): EliminateDeadIf(true)});
+    expect(previewInfo.applyTo(code), '''
+void f(int i) {}
+''');
+  }
+
+  Future<void> test_eliminateDeadIf_statement_delete_keep_else() async {
+    await analyze('''
+int f(int i) {
+  if (i == null) {
+    return null;
+  } else {
+    return i + 1;
+  }
+}
+''');
+    var previewInfo = run({findNode.statement('if'): EliminateDeadIf(false)});
+    expect(previewInfo.applyTo(code), '''
+int f(int i) {
+  return i + 1;
+}
+''');
+  }
+
+  Future<void> test_eliminateDeadIf_statement_delete_keep_then() async {
+    await analyze('''
+int f(int i) {
+  if (i != null) {
+    return i + 1;
+  } else {
+    return null;
+  }
+}
+''');
+    var previewInfo = run({findNode.statement('if'): EliminateDeadIf(true)});
+    expect(previewInfo.applyTo(code), '''
+int f(int i) {
+  return i + 1;
+}
+''');
+  }
+
+  Future<void>
+      test_eliminateDeadIf_statement_delete_keep_then_declaration() async {
+    await analyze('''
+void f(int i, String callback()) {
+  if (i != null) {
+    var i = callback();
+  } else {
+    return;
+  }
+  print(i);
+}
+''');
+    // In this case we have to keep the block so that the scope of `var i`
+    // doesn't widen.
+    var previewInfo = run({findNode.statement('if'): EliminateDeadIf(true)});
+    expect(previewInfo.applyTo(code), '''
+void f(int i, String callback()) {
+  {
+    var i = callback();
+  }
+  print(i);
+}
+''');
+  }
+
   Future<void> test_introduceAs_distant_parens_no_longer_needed() async {
     // Note: in principle it would be nice to delete the outer parens, but it's
     // difficult to see that they used to be necessary and aren't anymore, so we
@@ -71,7 +282,7 @@
   Future<void> test_makeNullable() async {
     await analyze('f(int x) {}');
     var typeName = findNode.typeName('int');
-    var previewInfo = run({typeName: const MakeNullable()});
+    var previewInfo = run({typeName: MakeNullable(MockDecoratedType())});
     expect(previewInfo.applyTo(code), 'f(int? x) {}');
   }
 
@@ -142,13 +353,21 @@
   }
 
   Future<void> test_removeAs_parens_needed_due_to_cascade() async {
-    // Note: spaces around parens to verify that we don't remove the old parens
-    // and create new ones.
-    await analyze('f(a, c) => a..b = throw ( c..d ) as int;');
+    // Note: parens are needed, and they could either be around `c..d` or around
+    // `throw c..d`.  In an ideal world, we would see that we can just keep the
+    // parens we have, but this is difficult because we don't see that the
+    // parens are needed until we walk far enough up the AST to see that we're
+    // inside a casade expression.  So we drop the parens and then create new
+    // ones surrounding `throw c..d`.
+    //
+    // Strictly speaking the code we produce is correct, it's just making a
+    // slightly larger edit than necessary.  This is presumably a really rare
+    // corner case so for now we're not worrying about it.
+    await analyze('f(a, c) => a..b = throw (c..d) as int;');
     var cd = findNode.cascade('c..d');
     var cast = cd.parent.parent;
     var previewInfo = run({cast: const RemoveAs()});
-    expect(previewInfo.applyTo(code), 'f(a, c) => a..b = throw ( c..d );');
+    expect(previewInfo.applyTo(code), 'f(a, c) => a..b = (throw c..d);');
   }
 
   Future<void>
@@ -199,7 +418,19 @@
     await resolveTestUnit(code);
   }
 
-  Map<int, List<AtomicEdit>> run(Map<AstNode, NodeChange> changes) {
-    return FixAggregator.run(testUnit, changes);
+  Map<int, List<AtomicEdit>> run(Map<AstNode, NodeChange> changes,
+      {bool removeViaComments: false}) {
+    return FixAggregator.run(testUnit, testCode, changes,
+        removeViaComments: removeViaComments);
+  }
+}
+
+class MockDecoratedType implements DecoratedType {
+  @override
+  NullabilityNode get node => NullabilityNode.forTypeAnnotation(0);
+
+  @override
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
   }
 }
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index ee03cff..19ad529 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -1110,6 +1110,36 @@
         changes: {findNode.propertyAccess('c.f'): isNullCheck});
   }
 
+  Future<void> test_ifStatement_dead_else() async {
+    await analyze('''
+_f(int x, int/*?*/ y) {
+  if (x != null) {
+    print(x + 1);
+  } else {
+    print(y + 1);
+  }
+}
+''');
+    var ifStatement = findNode.statement('if');
+    visitStatement(ifStatement,
+        changes: {ifStatement: isEliminateDeadIf(true)});
+  }
+
+  Future<void> test_ifStatement_dead_then() async {
+    await analyze('''
+_f(int x, int/*?*/ y) {
+  if (x == null) {
+    print(y + 1);
+  } else {
+    print(x + 1);
+  }
+}
+''');
+    var ifStatement = findNode.statement('if');
+    visitStatement(ifStatement,
+        changes: {ifStatement: isEliminateDeadIf(false)});
+  }
+
   Future<void> test_ifStatement_flow_promote_in_else() async {
     await analyze('''
 _f(int/*?*/ x) {
@@ -1226,6 +1256,11 @@
     visitSubexpression(findNode.integerLiteral('1'), 'int');
   }
 
+  Future<void> test_list_unchanged() async {
+    await analyze('_f(int x) => [x];');
+    visitSubexpression(findNode.listLiteral('['), 'List<int>');
+  }
+
   Future<void> test_listLiteral_typed() async {
     await analyze('''
 _f() => <int>[];
@@ -2278,4 +2313,8 @@
             .thisOrAncestorMatching((ancestor) => identical(ancestor, scope)) !=
         null;
   }
+
+  static Matcher isEliminateDeadIf(bool knownValue) =>
+      TypeMatcher<EliminateDeadIf>()
+          .having((c) => c.conditionValue, 'conditionValue', knownValue);
 }
diff --git a/pkg/nnbd_migration/test/test_all.dart b/pkg/nnbd_migration/test/test_all.dart
index f5e2719..0267b31 100644
--- a/pkg/nnbd_migration/test/test_all.dart
+++ b/pkg/nnbd_migration/test/test_all.dart
@@ -13,6 +13,8 @@
     as edge_builder_flow_analysis_test;
 import 'edge_builder_test.dart' as edge_builder_test;
 import 'edit_plan_test.dart' as edit_plan_test;
+import 'edit_planner_pass_through_merging_test.dart'
+    as edit_planner_pass_through_merging_test;
 import 'fix_aggregator_test.dart' as fix_aggregator_test;
 import 'fix_builder_test.dart' as fix_builder_test;
 import 'instrumentation_test.dart' as instrumentation_test;
@@ -31,6 +33,7 @@
     edge_builder_flow_analysis_test.main();
     edge_builder_test.main();
     edit_plan_test.main();
+    edit_planner_pass_through_merging_test.main();
     fix_aggregator_test.main();
     fix_builder_test.main();
     instrumentation_test.main();
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 05ba2426..c0d2628 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -8,6 +8,7 @@
     show
         CompilerContext,
         Severity,
+        isRedirectingFactoryField,
         messageBytecodeLimitExceededTooManyArguments,
         noLength,
         templateIllegalRecursiveType;
@@ -957,7 +958,7 @@
       // contain incorrect kernel AST, e.g. StaticGet which takes tear-off
       // of a constructor. Do not generate bytecode for them, as they should
       // never be used.
-      if (member.isStatic && member.name.name == "_redirecting#") {
+      if (isRedirectingFactoryField(member)) {
         return false;
       }
       return hasInitializerCode(member);
diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc
index 0f52f7c..583c603 100644
--- a/runtime/bin/ffi_test/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions.cc
@@ -186,6 +186,28 @@
   return retval;
 }
 
+// Sums many ints.
+// Used for testing calling conventions. With small integers on stack slots we
+// test stack alignment.
+DART_EXPORT int16_t SumManySmallInts(int8_t a,
+                                     int16_t b,
+                                     int8_t c,
+                                     int16_t d,
+                                     int8_t e,
+                                     int16_t f,
+                                     int8_t g,
+                                     int16_t h,
+                                     int8_t i,
+                                     int16_t j) {
+  std::cout << "SumManySmallInts(" << static_cast<int>(a) << ", " << b << ", "
+            << static_cast<int>(c) << ", " << d << ", " << static_cast<int>(e)
+            << ", " << f << ", " << static_cast<int>(g) << ", " << h << ", "
+            << static_cast<int>(i) << ", " << j << ")\n";
+  int16_t retval = a + b + c + d + e + f + g + h + i + j;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
 // Sums an odd number of ints.
 // Used for testing calling conventions. With so many arguments, and an odd
 // number of arguments, we are testing stack alignment on various architectures.
diff --git a/runtime/bin/vmservice/.gitignore b/runtime/bin/vmservice/.gitignore
deleted file mode 100644
index b183031..0000000
--- a/runtime/bin/vmservice/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.buildlog
-pubspec.lock
diff --git a/runtime/bin/vmservice/vmservice_sources.gni b/runtime/bin/vmservice/vmservice_sources.gni
deleted file mode 100644
index d326c2a..0000000
--- a/runtime/bin/vmservice/vmservice_sources.gni
+++ /dev/null
@@ -1,10 +0,0 @@
-# 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.
-
-# This file contains all Dart sources for the dart:io implementation of
-# the VM Service server.
-vmservice_sources = [
-  "server.dart",
-  "vmservice_io.dart",
-]
diff --git a/runtime/observatory/lib/object_graph.dart b/runtime/observatory/lib/object_graph.dart
index 1bf79ca..18426bb 100644
--- a/runtime/observatory/lib/object_graph.dart
+++ b/runtime/observatory/lib/object_graph.dart
@@ -335,15 +335,9 @@
   _VerticesIterator(this._graph);
 
   bool moveNext() {
-    while (_nextId <= _graph._N) {
-      // A retained size of zero means the object was unreachable.
-      if (_graph._retainedSizes[_nextId] != 0) {
-        current = new _SnapshotObject._(_nextId++, _graph, "");
-        return true;
-      }
-      _nextId++;
-    }
-    return false;
+    if (_nextId == _graph._N) return false;
+    current = new _SnapshotObject._(_nextId++, _graph, "");
+    return true;
   }
 }
 
@@ -366,10 +360,8 @@
   _InstancesIterator(this._graph, this._cid);
 
   bool moveNext() {
-    while (_nextId <= _graph._N) {
-      // A retained size of zero means the object was unreachable.
-      if (_graph._cids[_nextId] == _cid &&
-          _graph._retainedSizes[_nextId] != 0) {
+    while (_nextId < _graph._N) {
+      if (_graph._cids[_nextId] == _cid) {
         current = new _SnapshotObject._(_nextId++, _graph, "");
         return true;
       }
@@ -1185,13 +1177,10 @@
       cls.liveInstanceCount++;
     }
 
-    // Start with retained size as shallow size + external size. For reachable
-    // objects only; leave unreachable objects with a retained size of 0 so
-    // they can be filtered during graph iterations.
+    // Start with retained size as shallow size + external size.
     var retainedSizes = new Uint32List(N + 1);
-    for (var i = 0; i <= Nconnected; i++) {
-      var v = vertex[i];
-      retainedSizes[v] = internalSizes[v] + externalSizes[v];
+    for (var i = 0; i < N + 1; i++) {
+      retainedSizes[i] = internalSizes[i] + externalSizes[i];
     }
 
     // In post order (bottom up), add retained size to dominator's retained
diff --git a/runtime/observatory/tests/service/object_graph_vm_test.dart b/runtime/observatory/tests/service/object_graph_vm_test.dart
index 5458b49..dd4b936 100644
--- a/runtime/observatory/tests/service/object_graph_vm_test.dart
+++ b/runtime/observatory/tests/service/object_graph_vm_test.dart
@@ -82,69 +82,6 @@
     // Check that the short list retains more than the long list inside.
     // and specifically, that it retains exactly itself + the long one.
     expect(first.retainedSize, equals(first.shallowSize + second.shallowSize));
-
-    // Verify sizes of classes are the appropriates sums of their instances.
-    // This also verifies that the class instance iterators are visiting the
-    // correct set of objects (e.g., not including dead objects).
-    for (SnapshotClass klass in graph.classes) {
-      int shallowSum = 0;
-      int internalSum = 0;
-      int externalSum = 0;
-      for (SnapshotObject instance in klass.instances) {
-        if (instance == graph.root) {
-          // The root may have 0 self size.
-          expect(instance.internalSize, greaterThanOrEqualTo(0));
-          expect(instance.externalSize, greaterThanOrEqualTo(0));
-          expect(instance.shallowSize, greaterThanOrEqualTo(0));
-        } else {
-          // All other objects are heap objects with positive size.
-          expect(instance.internalSize, greaterThan(0));
-          expect(instance.externalSize, greaterThanOrEqualTo(0));
-          expect(instance.shallowSize, greaterThan(0));
-        }
-        expect(instance.retainedSize, greaterThan(0));
-        expect(instance.shallowSize,
-            equals(instance.internalSize + instance.externalSize));
-        shallowSum += instance.shallowSize;
-        internalSum += instance.internalSize;
-        externalSum += instance.externalSize;
-      }
-      expect(shallowSum, equals(klass.shallowSize));
-      expect(internalSum, equals(klass.internalSize));
-      expect(externalSum, equals(klass.externalSize));
-      expect(
-          klass.shallowSize, equals(klass.internalSize + klass.externalSize));
-    }
-
-    // Verify sizes of the overall graph are the appropriates sums of all
-    // instances. This also verifies that the all instances iterator is visiting
-    // the correct set of objects (e.g., not including dead objects).
-    int shallowSum = 0;
-    int internalSum = 0;
-    int externalSum = 0;
-    for (SnapshotObject instance in graph.objects) {
-      if (instance == graph.root) {
-        // The root may have 0 self size.
-        expect(instance.internalSize, greaterThanOrEqualTo(0));
-        expect(instance.externalSize, greaterThanOrEqualTo(0));
-        expect(instance.shallowSize, greaterThanOrEqualTo(0));
-      } else {
-        // All other objects are heap objects with positive size.
-        expect(instance.internalSize, greaterThan(0));
-        expect(instance.externalSize, greaterThanOrEqualTo(0));
-        expect(instance.shallowSize, greaterThan(0));
-      }
-      expect(instance.retainedSize, greaterThan(0));
-      expect(instance.shallowSize,
-          equals(instance.internalSize + instance.externalSize));
-      shallowSum += instance.shallowSize;
-      internalSum += instance.internalSize;
-      externalSum += instance.externalSize;
-    }
-    expect(shallowSum, equals(graph.size));
-    expect(internalSum, equals(graph.internalSize));
-    expect(externalSum, equals(graph.externalSize));
-    expect(graph.size, equals(graph.internalSize + graph.externalSize));
   },
 ];
 
diff --git a/runtime/observatory/tests/service/verify_http_timeline_test.dart b/runtime/observatory/tests/service/verify_http_timeline_test.dart
index 9b41df0..dfd6ad8 100644
--- a/runtime/observatory/tests/service/verify_http_timeline_test.dart
+++ b/runtime/observatory/tests/service/verify_http_timeline_test.dart
@@ -44,7 +44,7 @@
         .then((_) async {
       try {
         await f();
-      } on HttpException catch (_) {} on SocketException catch (_) {} on StateError catch (_) {}
+      } on HttpException catch (_) {} on SocketException catch (_) {} on StateError catch (_) {} on OSError catch (_) {}
     });
 
 Uri randomlyAddRequestParams(Uri uri) {
diff --git a/runtime/tests/vm/dart/rematerialize_unboxed_double_field_test.dart b/runtime/tests/vm/dart/rematerialize_unboxed_double_field_test.dart
new file mode 100644
index 0000000..8442c38
--- /dev/null
+++ b/runtime/tests/vm/dart/rematerialize_unboxed_double_field_test.dart
@@ -0,0 +1,42 @@
+// 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.
+//
+// VMOptions=--deterministic --optimization-counter-threshold=10 --unbox-numeric-fields
+
+import 'package:expect/expect.dart';
+
+const magicDouble = 42.0;
+
+class C {
+  double d = magicDouble;
+}
+
+class NoopSink {
+  void leak(C c) {}
+}
+
+class RealSink {
+  static C o;
+  void leak(C c) {
+    o = c;
+  }
+}
+
+void foo(sink) {
+  sink.leak(C());
+}
+
+void main(List<String> args) {
+  var c = C();
+  for (var i = 0; i < 100; i++) c.d = 2.0;
+
+  for (var i = 0; i < 100; i++) {
+    foo(NoopSink());
+  }
+
+  foo(RealSink());
+  RealSink.o.d += 1234.0;
+  final TWO = args.length > 1024 ? "~" : 2;
+  Expect.equals(double.parse("4${TWO}.0"), magicDouble);
+}
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index ea7ef8c..a7b520f 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1232,7 +1232,6 @@
       zone, enum_cls.LookupStaticField(Symbols::_DeletedEnumSentinel()));
   ASSERT(!sentinel.IsNull());
   sentinel.SetStaticValue(enum_value, true);
-  sentinel.RecordStore(enum_value);
 
   ASSERT(enum_cls.is_declared_in_bytecode() || enum_cls.kernel_offset() > 0);
   Error& error = Error::Handle(zone);
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 195333e..23acce5 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -232,13 +232,6 @@
 void SharedClassTable::Grow(intptr_t new_capacity) {
   ASSERT(new_capacity >= capacity_);
 
-#ifndef PRODUCT
-  // Wait for any marking tasks to complete. Allocation stats in the
-  // marker rely on the class table size not changing.
-  Thread* thread = Thread::Current();
-  thread->heap()->WaitForMarkerTasks(thread);
-#endif
-
   intptr_t* new_table = static_cast<intptr_t*>(
       malloc(new_capacity * sizeof(intptr_t)));  // NOLINT
   memmove(new_table, table_, top_ * sizeof(intptr_t));
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 36be191..8647cb8 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -2016,38 +2016,39 @@
 }
 
 void FlowGraphCompiler::EmitPolymorphicInstanceCall(
+    const PolymorphicInstanceCallInstr* call,
     const CallTargets& targets,
-    const InstanceCallInstr& original_call,
     ArgumentsInfo args_info,
     intptr_t deopt_id,
     TokenPosition token_pos,
     LocationSummary* locs,
     bool complete,
     intptr_t total_ic_calls) {
+  ASSERT(call != nullptr);
   if (FLAG_polymorphic_with_deopt) {
     compiler::Label* deopt =
         AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail);
     compiler::Label ok;
-    EmitTestAndCall(targets, original_call.function_name(), args_info,
+    EmitTestAndCall(targets, call->function_name(), args_info,
                     deopt,  // No cid match.
                     &ok,    // Found cid.
                     deopt_id, token_pos, locs, complete, total_ic_calls,
-                    original_call.entry_kind());
+                    call->entry_kind());
     assembler()->Bind(&ok);
   } else {
     if (complete) {
       compiler::Label ok;
-      EmitTestAndCall(targets, original_call.function_name(), args_info,
+      EmitTestAndCall(targets, call->function_name(), args_info,
                       NULL,  // No cid match.
                       &ok,   // Found cid.
                       deopt_id, token_pos, locs, true, total_ic_calls,
-                      original_call.entry_kind());
+                      call->entry_kind());
       assembler()->Bind(&ok);
     } else {
-      const ICData& unary_checks = ICData::ZoneHandle(
-          zone(), original_call.ic_data()->AsUnaryClassChecks());
+      const ICData& unary_checks =
+          ICData::ZoneHandle(zone(), call->ic_data()->AsUnaryClassChecks());
       EmitInstanceCallAOT(unary_checks, deopt_id, token_pos, locs,
-                          original_call.entry_kind());
+                          call->entry_kind());
     }
   }
 }
@@ -2240,6 +2241,20 @@
           (type.IsTypeParameter() || (type.IsType() && type.IsInstantiated())));
 }
 
+FlowGraphCompiler::TypeTestStubKind
+FlowGraphCompiler::GetTypeTestStubKindForTypeParameter(
+    const TypeParameter& type_param) {
+  // TODO(regis): Revisit the bound check taking NNBD into consideration.
+  // If it's guaranteed, by type-parameter bound, that the type parameter will
+  // never have a value of a function type, then we can safely do a 4-type
+  // test instead of a 6-type test.
+  const AbstractType& bound = AbstractType::Handle(zone(), type_param.bound());
+  return !bound.NNBD_IsTopType() && !bound.IsFunctionType() &&
+                 !bound.IsDartFunctionType() && bound.IsType()
+             ? kTestTypeFourArgs
+             : kTestTypeSixArgs;
+}
+
 void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
     const AbstractType& dst_type,
     const String& dst_name,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 38d30c0..6f7b426 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -638,15 +638,14 @@
                            LocationSummary* locs,
                            Code::EntryKind entry_kind);
 
-  void EmitPolymorphicInstanceCall(
-      const CallTargets& targets,
-      const InstanceCallInstr& original_instruction,
-      ArgumentsInfo args_info,
-      intptr_t deopt_id,
-      TokenPosition token_pos,
-      LocationSummary* locs,
-      bool complete,
-      intptr_t total_call_count);
+  void EmitPolymorphicInstanceCall(const PolymorphicInstanceCallInstr* call,
+                                   const CallTargets& targets,
+                                   ArgumentsInfo args_info,
+                                   intptr_t deopt_id,
+                                   TokenPosition token_pos,
+                                   LocationSummary* locs,
+                                   bool complete,
+                                   intptr_t total_call_count);
 
   // Pass a value for try-index where block is not available (e.g. slow path).
   void EmitMegamorphicInstanceCall(const String& function_name,
@@ -985,6 +984,10 @@
     kTestTypeSixArgs,
   };
 
+  // Returns type test stub kind for a type test against type parameter type.
+  TypeTestStubKind GetTypeTestStubKindForTypeParameter(
+      const TypeParameter& type_param);
+
   RawSubtypeTestCache* GenerateCallSubtypeTestStub(
       TypeTestStubKind test_kind,
       Register instance_reg,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 521bc11..bc3c01e 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -468,7 +468,6 @@
   // Skip check if destination is a dynamic type.
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
-    const AbstractType& bound = AbstractType::Handle(type_param.bound());
 
     __ ldm(IA, SP,
            (1 << kFunctionTypeArgumentsReg) |
@@ -504,16 +503,7 @@
     // Smi can be handled by type test cache.
     __ Bind(&not_smi);
 
-    // TODO(regis): Revisit the bound check taking NNBD into consideration.
-    // TODO(alexmarkov): Fix issue #40066.
-    // If it's guaranteed, by type-parameter bound, that the type parameter will
-    // never have a value of a function type, then we can safely do a 4-type
-    // test instead of a 6-type test.
-    auto test_kind = !bound.NNBD_IsTopType() && !bound.IsFunctionType() &&
-                             !bound.IsDartFunctionType() && bound.IsType()
-                         ? kTestTypeSixArgs
-                         : kTestTypeFourArgs;
-
+    const auto test_kind = GetTypeTestStubKindForTypeParameter(type_param);
     const SubtypeTestCache& type_test_cache = SubtypeTestCache::ZoneHandle(
         zone(), GenerateCallSubtypeTestStub(
                     test_kind, kInstanceReg, kInstantiatorTypeArgumentsReg,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index b4ee10f..d88102c 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -451,7 +451,6 @@
   // Skip check if destination is a dynamic type.
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
-    const AbstractType& bound = AbstractType::Handle(type_param.bound());
 
     // Get instantiator type args (high, R1) and function type args (low, R2).
     __ ldp(R2, R1,
@@ -483,16 +482,7 @@
     // Smi can be handled by type test cache.
     __ Bind(&not_smi);
 
-    // TODO(regis): Revisit the bound check taking NNBD into consideration.
-    // TODO(alexmarkov): Fix issue #40066.
-    // If it's guaranteed, by type-parameter bound, that the type parameter will
-    // never have a value of a function type, then we can safely do a 4-type
-    // test instead of a 6-type test.
-    auto test_kind = !bound.NNBD_IsTopType() && !bound.IsFunctionType() &&
-                             !bound.IsDartFunctionType() && bound.IsType()
-                         ? kTestTypeSixArgs
-                         : kTestTypeFourArgs;
-
+    const auto test_kind = GetTypeTestStubKindForTypeParameter(type_param);
     const SubtypeTestCache& type_test_cache = SubtypeTestCache::ZoneHandle(
         zone(), GenerateCallSubtypeTestStub(
                     test_kind, kInstanceReg, kInstantiatorTypeArgumentsReg,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 594ac84..ffe5bd0 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -446,7 +446,6 @@
       compiler::Immediate(reinterpret_cast<intptr_t>(Object::null()));
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
-    const AbstractType& bound = AbstractType::Handle(type_param.bound());
 
     __ movl(EDX, compiler::Address(
                      ESP, 1 * kWordSize));  // Get instantiator type args.
@@ -482,15 +481,7 @@
     // Smi can be handled by type test cache.
     __ Bind(&not_smi);
 
-    // TODO(regis): Revisit the bound check taking NNBD into consideration.
-    // TODO(alexmarkov): Fix issue #40066.
-    // If it's guaranteed, by type-parameter bound, that the type parameter will
-    // never have a value of a function type.
-    auto test_kind = !bound.NNBD_IsTopType() && !bound.IsFunctionType() &&
-                             !bound.IsDartFunctionType() && bound.IsType()
-                         ? kTestTypeSixArgs
-                         : kTestTypeFourArgs;
-
+    const auto test_kind = GetTypeTestStubKindForTypeParameter(type_param);
     const SubtypeTestCache& type_test_cache = SubtypeTestCache::ZoneHandle(
         zone(), GenerateCallSubtypeTestStub(
                     test_kind, kInstanceReg, kInstantiatorTypeArgumentsReg,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 9485ea4..26be96d 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -476,7 +476,6 @@
   // Skip check if destination is a dynamic type.
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
-    const AbstractType& bound = AbstractType::Handle(type_param.bound());
 
     // RDX: instantiator type arguments.
     // RCX: function type arguments.
@@ -509,16 +508,7 @@
     // Smi can be handled by type test cache.
     __ Bind(&not_smi);
 
-    // TODO(regis): Revisit the bound check taking NNBD into consideration.
-    // TODO(alexmarkov): Fix issue #40066.
-    // If it's guaranteed, by type-parameter bound, that the type parameter will
-    // never have a value of a function type, then we can safely do a 4-type
-    // test instead of a 6-type test.
-    auto test_kind = !bound.NNBD_IsTopType() && !bound.IsFunctionType() &&
-                             !bound.IsDartFunctionType() && bound.IsType()
-                         ? kTestTypeSixArgs
-                         : kTestTypeFourArgs;
-
+    const auto test_kind = GetTypeTestStubKindForTypeParameter(type_param);
     const SubtypeTestCache& type_test_cache = SubtypeTestCache::ZoneHandle(
         zone(), GenerateCallSubtypeTestStub(
                     test_kind, kInstanceReg, kInstantiatorTypeArgumentsReg,
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index d78a065..7cdad60 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -45,10 +45,7 @@
             two_args_smi_icd,
             true,
             "Generate special IC stubs for two args Smi operations");
-DEFINE_FLAG(bool,
-            unbox_numeric_fields,
-            true,
-            "Support unboxed double and float32x4 fields.");
+DECLARE_FLAG(bool, unbox_numeric_fields);
 
 class SubclassFinder {
  public:
@@ -556,33 +553,18 @@
 }
 
 const ICData* Instruction::GetICData(
-    const ZoneGrowableArray<const ICData*>& ic_data_array) const {
+    const ZoneGrowableArray<const ICData*>& ic_data_array,
+    intptr_t deopt_id,
+    bool is_static_call) {
   // The deopt_id can be outside the range of the IC data array for
   // computations added in the optimizing compiler.
-  ASSERT(deopt_id_ != DeoptId::kNone);
-  if (deopt_id_ < ic_data_array.length()) {
-    const ICData* result = ic_data_array[deopt_id_];
-#if defined(DEBUG)
-    if (result != NULL) {
-      switch (tag()) {
-        case kInstanceCall:
-          if (result->is_static_call()) {
-            FATAL("ICData tag mismatch");
-          }
-          break;
-        case kStaticCall:
-          if (!result->is_static_call()) {
-            FATAL("ICData tag mismatch");
-          }
-          break;
-        default:
-          UNREACHABLE();
-      }
-    }
-#endif
-    return result;
+  ASSERT(deopt_id != DeoptId::kNone);
+  if (deopt_id >= ic_data_array.length()) {
+    return nullptr;
   }
-  return NULL;
+  const ICData* result = ic_data_array[deopt_id];
+  ASSERT(result == nullptr || is_static_call == result->is_static_call());
+  return result;
 }
 
 intptr_t Instruction::Hashcode() const {
@@ -1326,8 +1308,8 @@
 // Default implementation of visiting basic blocks.  Can be overridden.
 void FlowGraphVisitor::VisitBlocks() {
   ASSERT(current_iterator_ == NULL);
-  for (intptr_t i = 0; i < block_order_.length(); ++i) {
-    BlockEntryInstr* entry = block_order_[i];
+  for (intptr_t i = 0; i < block_order_->length(); ++i) {
+    BlockEntryInstr* entry = (*block_order_)[i];
     entry->Accept(this);
     ForwardInstructionIterator it(entry);
     current_iterator_ = &it;
@@ -4343,7 +4325,7 @@
   return Library::IsPrivateCoreLibName(function_name(), name);
 }
 
-RawFunction* InstanceCallInstr::ResolveForReceiverClass(
+RawFunction* InstanceCallBaseInstr::ResolveForReceiverClass(
     const Class& cls,
     bool allow_add /* = true */) {
   const Array& args_desc_array = Array::Handle(GetArgumentsDescriptor());
@@ -4463,9 +4445,9 @@
 
 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ArgumentsInfo args_info(type_args_len(), ArgumentCount(), argument_names());
-  compiler->EmitPolymorphicInstanceCall(targets_, *instance_call(), args_info,
-                                        deopt_id(), token_pos(), locs(),
-                                        complete(), total_call_count());
+  compiler->EmitPolymorphicInstanceCall(this, targets(), args_info, deopt_id(),
+                                        token_pos(), locs(), complete(),
+                                        total_call_count());
 }
 
 RawType* PolymorphicInstanceCallInstr::ComputeRuntimeType(
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 9d4e713..8bf7f24 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -496,14 +496,15 @@
   M(SimdOp, kNoGC)
 
 #define FOR_EACH_ABSTRACT_INSTRUCTION(M)                                       \
+  M(Allocation, _)                                                             \
+  M(BinaryIntegerOp, _)                                                        \
   M(BlockEntry, _)                                                             \
   M(BoxInteger, _)                                                             \
-  M(UnboxInteger, _)                                                           \
   M(Comparison, _)                                                             \
-  M(UnaryIntegerOp, _)                                                         \
-  M(BinaryIntegerOp, _)                                                        \
+  M(InstanceCallBase, _)                                                       \
   M(ShiftIntegerOp, _)                                                         \
-  M(Allocation, _)
+  M(UnaryIntegerOp, _)                                                         \
+  M(UnboxInteger, _)
 
 #define FORWARD_DECLARATION(type, attrs) class type##Instr;
 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
@@ -791,8 +792,10 @@
     return GetDeoptId();
   }
 
-  const ICData* GetICData(
-      const ZoneGrowableArray<const ICData*>& ic_data_array) const;
+  static const ICData* GetICData(
+      const ZoneGrowableArray<const ICData*>& ic_data_array,
+      intptr_t deopt_id,
+      bool is_static_call);
 
   virtual TokenPosition token_pos() const { return TokenPosition::kNoSource; }
 
@@ -3706,34 +3709,32 @@
   DISALLOW_COPY_AND_ASSIGN(ClosureCallInstr);
 };
 
-class InstanceCallInstr : public TemplateDartCall<0> {
+// Common base class for various kinds of instance call instructions
+// (InstanceCallInstr, PolymorphicInstanceCallInstr).
+class InstanceCallBaseInstr : public TemplateDartCall<0> {
  public:
-  InstanceCallInstr(
-      TokenPosition token_pos,
-      const String& function_name,
-      Token::Kind token_kind,
-      InputsArray* arguments,
-      intptr_t type_args_len,
-      const Array& argument_names,
-      intptr_t checked_argument_count,
-      const ZoneGrowableArray<const ICData*>& ic_data_array,
-      intptr_t deopt_id,
-      const Function& interface_target = Function::null_function())
+  InstanceCallBaseInstr(TokenPosition token_pos,
+                        const String& function_name,
+                        Token::Kind token_kind,
+                        InputsArray* arguments,
+                        intptr_t type_args_len,
+                        const Array& argument_names,
+                        const ICData* ic_data,
+                        intptr_t deopt_id,
+                        const Function& interface_target)
       : TemplateDartCall(deopt_id,
                          type_args_len,
                          argument_names,
                          arguments,
                          token_pos),
-        ic_data_(NULL),
+        ic_data_(ic_data),
         function_name_(function_name),
         token_kind_(token_kind),
-        checked_argument_count_(checked_argument_count),
         interface_target_(interface_target),
-        result_type_(NULL),
+        result_type_(nullptr),
         has_unique_selector_(false) {
-    ic_data_ = GetICData(ic_data_array);
     ASSERT(function_name.IsNotTemporaryScopedHandle());
-    ASSERT(interface_target_.IsNotTemporaryScopedHandle());
+    ASSERT(interface_target.IsNotTemporaryScopedHandle());
     ASSERT(!arguments->is_empty());
     ASSERT(Token::IsBinaryOperator(token_kind) ||
            Token::IsEqualityOperator(token_kind) ||
@@ -3745,72 +3746,25 @@
            token_kind == Token::kSET || token_kind == Token::kILLEGAL);
   }
 
-  InstanceCallInstr(
-      TokenPosition token_pos,
-      const String& function_name,
-      Token::Kind token_kind,
-      InputsArray* arguments,
-      intptr_t type_args_len,
-      const Array& argument_names,
-      intptr_t checked_argument_count,
-      intptr_t deopt_id,
-      const Function& interface_target = Function::null_function())
-      : TemplateDartCall(deopt_id,
-                         type_args_len,
-                         argument_names,
-                         arguments,
-                         token_pos),
-        ic_data_(NULL),
-        function_name_(function_name),
-        token_kind_(token_kind),
-        checked_argument_count_(checked_argument_count),
-        interface_target_(interface_target),
-        result_type_(NULL),
-        has_unique_selector_(false) {
-    ASSERT(function_name.IsNotTemporaryScopedHandle());
-    ASSERT(interface_target_.IsNotTemporaryScopedHandle());
-    ASSERT(!arguments->is_empty());
-    ASSERT(Token::IsBinaryOperator(token_kind) ||
-           Token::IsEqualityOperator(token_kind) ||
-           Token::IsRelationalOperator(token_kind) ||
-           Token::IsUnaryOperator(token_kind) ||
-           Token::IsIndexOperator(token_kind) ||
-           Token::IsTypeTestOperator(token_kind) ||
-           Token::IsTypeCastOperator(token_kind) || token_kind == Token::kGET ||
-           token_kind == Token::kSET || token_kind == Token::kILLEGAL);
-  }
-
-  DECLARE_INSTRUCTION(InstanceCall)
-
   const ICData* ic_data() const { return ic_data_; }
-  bool HasICData() const { return (ic_data() != NULL) && !ic_data()->IsNull(); }
+  bool HasICData() const {
+    return (ic_data() != nullptr) && !ic_data()->IsNull();
+  }
 
   // ICData can be replaced by optimizer.
   void set_ic_data(const ICData* value) { ic_data_ = value; }
 
   const String& function_name() const { return function_name_; }
   Token::Kind token_kind() const { return token_kind_; }
-  intptr_t checked_argument_count() const { return checked_argument_count_; }
   const Function& interface_target() const { return interface_target_; }
 
-  void set_receivers_static_type(const AbstractType* receiver_type) {
-    ASSERT(receiver_type != nullptr);
-    receivers_static_type_ = receiver_type;
-  }
-
   bool has_unique_selector() const { return has_unique_selector_; }
   void set_has_unique_selector(bool b) { has_unique_selector_ = b; }
 
-  virtual intptr_t CallCount() const {
-    return ic_data() == NULL ? 0 : ic_data()->AggregateCount();
-  }
-
   virtual CompileType ComputeType() const;
 
   virtual bool ComputeCanDeoptimize() const { return !FLAG_precompiled_mode; }
 
-  virtual Definition* Canonicalize(FlowGraph* flow_graph);
-
   virtual bool CanBecomeDeoptimizationTarget() const {
     // Instance calls that are specialized by the optimizer need a
     // deoptimization descriptor before the call.
@@ -3826,69 +3780,144 @@
   CompileType* result_type() const { return result_type_; }
 
   intptr_t result_cid() const {
-    if (result_type_ == NULL) {
+    if (result_type_ == nullptr) {
       return kDynamicCid;
     }
     return result_type_->ToCid();
   }
 
-  PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
-
-  bool MatchesCoreName(const String& name);
-
   RawFunction* ResolveForReceiverClass(const Class& cls, bool allow_add = true);
 
   Code::EntryKind entry_kind() const { return entry_kind_; }
-
   void set_entry_kind(Code::EntryKind value) { entry_kind_ = value; }
 
-  const CallTargets& Targets();
-  void SetTargets(const CallTargets* targets) { targets_ = targets; }
+  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
+  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
+  DEFINE_INSTRUCTION_TYPE_CHECK(InstanceCallBase);
+
+ protected:
+  friend class CallSpecializer;
+  void set_ic_data(ICData* value) { ic_data_ = value; }
+  void set_result_type(CompileType* result_type) { result_type_ = result_type; }
+
+ private:
+  const ICData* ic_data_;
+  const String& function_name_;
+  const Token::Kind token_kind_;  // Binary op, unary op, kGET or kILLEGAL.
+  const Function& interface_target_;
+  CompileType* result_type_;  // Inferred result type.
+  bool has_unique_selector_;
+  Code::EntryKind entry_kind_ = Code::EntryKind::kNormal;
+
+  DISALLOW_COPY_AND_ASSIGN(InstanceCallBaseInstr);
+};
+
+class InstanceCallInstr : public InstanceCallBaseInstr {
+ public:
+  InstanceCallInstr(
+      TokenPosition token_pos,
+      const String& function_name,
+      Token::Kind token_kind,
+      InputsArray* arguments,
+      intptr_t type_args_len,
+      const Array& argument_names,
+      intptr_t checked_argument_count,
+      const ZoneGrowableArray<const ICData*>& ic_data_array,
+      intptr_t deopt_id,
+      const Function& interface_target = Function::null_function())
+      : InstanceCallBaseInstr(
+            token_pos,
+            function_name,
+            token_kind,
+            arguments,
+            type_args_len,
+            argument_names,
+            GetICData(ic_data_array, deopt_id, /*is_static_call=*/false),
+            deopt_id,
+            interface_target),
+        checked_argument_count_(checked_argument_count) {}
+
+  InstanceCallInstr(
+      TokenPosition token_pos,
+      const String& function_name,
+      Token::Kind token_kind,
+      InputsArray* arguments,
+      intptr_t type_args_len,
+      const Array& argument_names,
+      intptr_t checked_argument_count,
+      intptr_t deopt_id,
+      const Function& interface_target = Function::null_function())
+      : InstanceCallBaseInstr(token_pos,
+                              function_name,
+                              token_kind,
+                              arguments,
+                              type_args_len,
+                              argument_names,
+                              /*ic_data=*/nullptr,
+                              deopt_id,
+                              interface_target),
+        checked_argument_count_(checked_argument_count) {}
+
+  DECLARE_INSTRUCTION(InstanceCall)
+
+  intptr_t checked_argument_count() const { return checked_argument_count_; }
+
+  virtual intptr_t CallCount() const {
+    return ic_data() == nullptr ? 0 : ic_data()->AggregateCount();
+  }
+
+  void set_receivers_static_type(const AbstractType* receiver_type) {
+    ASSERT(receiver_type != nullptr);
+    receivers_static_type_ = receiver_type;
+  }
+
+  virtual Definition* Canonicalize(FlowGraph* flow_graph);
+
+  PRINT_OPERANDS_TO_SUPPORT
+  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
+
+  bool MatchesCoreName(const String& name);
 
   const class BinaryFeedback& BinaryFeedback();
   void SetBinaryFeedback(const class BinaryFeedback* binary) {
     binary_ = binary;
   }
 
- protected:
-  friend class CallSpecializer;
-  void set_ic_data(ICData* value) { ic_data_ = value; }
+  const CallTargets& Targets();
+  void SetTargets(const CallTargets* targets) { targets_ = targets; }
 
  private:
-  const ICData* ic_data_;
   const CallTargets* targets_ = nullptr;
   const class BinaryFeedback* binary_ = nullptr;
-  const String& function_name_;
-  const Token::Kind token_kind_;  // Binary op, unary op, kGET or kILLEGAL.
   const intptr_t checked_argument_count_;
-  const Function& interface_target_;
-  CompileType* result_type_;  // Inferred result type.
-  bool has_unique_selector_;
-  Code::EntryKind entry_kind_ = Code::EntryKind::kNormal;
-
   const AbstractType* receivers_static_type_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(InstanceCallInstr);
 };
 
-class PolymorphicInstanceCallInstr : public TemplateDartCall<0> {
+class PolymorphicInstanceCallInstr : public InstanceCallBaseInstr {
  public:
   // Generate a replacement polymorphic call instruction.
   static PolymorphicInstanceCallInstr* FromCall(Zone* zone,
-                                                InstanceCallInstr* call,
+                                                InstanceCallBaseInstr* call,
                                                 const CallTargets& targets,
                                                 bool complete) {
-    return FromCall(zone, call, call, targets, complete);
-  }
-
-  static PolymorphicInstanceCallInstr* FromCall(
-      Zone* zone,
-      PolymorphicInstanceCallInstr* call,
-      const CallTargets& targets,
-      bool complete) {
-    return FromCall(zone, call, call->instance_call(), targets, complete);
+    ASSERT(!call->HasPushArguments());
+    InputsArray* args = new (zone) InputsArray(zone, call->ArgumentCount());
+    for (intptr_t i = 0, n = call->ArgumentCount(); i < n; ++i) {
+      args->Add(call->ArgumentValueAt(i)->CopyWithType(zone));
+    }
+    auto new_call = new (zone) PolymorphicInstanceCallInstr(
+        call->token_pos(), call->function_name(), call->token_kind(), args,
+        call->type_args_len(), call->argument_names(), call->ic_data(),
+        call->deopt_id(), call->interface_target(), targets, complete);
+    if (call->has_inlining_id()) {
+      new_call->set_inlining_id(call->inlining_id());
+    }
+    new_call->set_result_type(call->result_type());
+    new_call->set_entry_kind(call->entry_kind());
+    new_call->set_has_unique_selector(call->has_unique_selector());
+    return new_call;
   }
 
   bool complete() const { return complete_; }
@@ -3917,70 +3946,40 @@
 
   DECLARE_INSTRUCTION(PolymorphicInstanceCall)
 
-  virtual bool ComputeCanDeoptimize() const { return !FLAG_precompiled_mode; }
-
-  virtual bool HasUnknownSideEffects() const { return true; }
-
   virtual Definition* Canonicalize(FlowGraph* graph);
 
   static RawType* ComputeRuntimeType(const CallTargets& targets);
 
-  CompileType* result_type() const { return instance_call()->result_type(); }
-  intptr_t result_cid() const { return instance_call()->result_cid(); }
-  const String& function_name() const {
-    return instance_call()->function_name();
-  }
-  Token::Kind token_kind() const { return instance_call()->token_kind(); }
-  Code::EntryKind entry_kind() const { return instance_call()->entry_kind(); }
-  const ICData* ic_data() const { return instance_call()->ic_data(); }
-  bool has_unique_selector() const {
-    return instance_call()->has_unique_selector();
-  }
-  RawFunction* ResolveForReceiverClass(const Class& cls) {
-    return instance_call()->ResolveForReceiverClass(cls);
-  }
-
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
   ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
-  PolymorphicInstanceCallInstr(InstanceCallInstr* instance_call,
+  PolymorphicInstanceCallInstr(TokenPosition token_pos,
+                               const String& function_name,
+                               Token::Kind token_kind,
                                InputsArray* arguments,
+                               intptr_t type_args_len,
+                               const Array& argument_names,
+                               const ICData* ic_data,
+                               intptr_t deopt_id,
+                               const Function& interface_target,
                                const CallTargets& targets,
                                bool complete)
-      : TemplateDartCall<0>(instance_call->deopt_id(),
-                            instance_call->type_args_len(),
-                            instance_call->argument_names(),
-                            arguments,
-                            instance_call->token_pos()),
-        instance_call_(instance_call),
+      : InstanceCallBaseInstr(token_pos,
+                              function_name,
+                              token_kind,
+                              arguments,
+                              type_args_len,
+                              argument_names,
+                              ic_data,
+                              deopt_id,
+                              interface_target),
         targets_(targets),
         complete_(complete) {
-    ASSERT(instance_call_ != nullptr);
     ASSERT(targets.length() != 0);
     total_call_count_ = CallCount();
   }
 
-  static PolymorphicInstanceCallInstr* FromCall(
-      Zone* zone,
-      Instruction* call_for_arguments,
-      InstanceCallInstr* call_for_attributes,
-      const CallTargets& targets,
-      bool complete) {
-    ASSERT(!call_for_arguments->HasPushArguments());
-    InputsArray* args =
-        new (zone) InputsArray(zone, call_for_arguments->ArgumentCount());
-    for (intptr_t i = 0, n = call_for_arguments->ArgumentCount(); i < n; ++i) {
-      args->Add(call_for_arguments->ArgumentValueAt(i)->CopyWithType(zone));
-    }
-    return new (zone) PolymorphicInstanceCallInstr(call_for_attributes, args,
-                                                   targets, complete);
-  }
-
-  InstanceCallInstr* instance_call() const { return instance_call_; }
-
-  InstanceCallInstr* instance_call_;
   const CallTargets& targets_;
   const bool complete_;
   intptr_t total_call_count_;
@@ -4299,7 +4298,7 @@
         result_type_(NULL),
         is_known_list_constructor_(false),
         identity_(AliasIdentity::Unknown()) {
-    ic_data_ = GetICData(ic_data_array);
+    ic_data_ = GetICData(ic_data_array, deopt_id, /*is_static_call=*/true);
     ASSERT(function.IsZoneHandle());
     ASSERT(!function.IsNull());
   }
@@ -8835,7 +8834,7 @@
 class FlowGraphVisitor : public ValueObject {
  public:
   explicit FlowGraphVisitor(const GrowableArray<BlockEntryInstr*>& block_order)
-      : current_iterator_(NULL), block_order_(block_order) {}
+      : current_iterator_(NULL), block_order_(&block_order) {}
   virtual ~FlowGraphVisitor() {}
 
   ForwardInstructionIterator* current_iterator() const {
@@ -8856,10 +8855,14 @@
 #undef DECLARE_VISIT_INSTRUCTION
 
  protected:
+  void set_block_order(const GrowableArray<BlockEntryInstr*>& block_order) {
+    block_order_ = &block_order;
+  }
+
   ForwardInstructionIterator* current_iterator_;
 
  private:
-  const GrowableArray<BlockEntryInstr*>& block_order_;
+  const GrowableArray<BlockEntryInstr*>* block_order_;
   DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor);
 };
 
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index b0efd4e..055963c 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -381,15 +381,19 @@
   // R4: Arguments descriptor.
   // R0: Function.
   ASSERT(locs()->in(0).reg() == R0);
-  __ ldr(CODE_REG,
-         compiler::FieldAddress(R0, compiler::target::Function::code_offset()));
-  __ ldr(R2, compiler::FieldAddress(
-                 R0, compiler::target::Code::function_entry_point_offset(
-                         entry_kind())));
+  if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
+    __ ldr(CODE_REG, compiler::FieldAddress(
+                         R0, compiler::target::Function::code_offset()));
+  }
+  __ ldr(R2,
+         compiler::FieldAddress(
+             R0, compiler::target::Function::entry_point_offset(entry_kind())));
 
   // R2: instructions entry point.
-  // R9: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
-  __ LoadImmediate(R9, 0);
+  if (!FLAG_precompiled_mode) {
+    // R9: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
+    __ LoadImmediate(R9, 0);
+  }
   __ blx(R2);
   compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
                                  RawPcDescriptors::kOther, locs());
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 45a4987..7a56b46 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -319,14 +319,18 @@
   // R4: Arguments descriptor.
   // R0: Function.
   ASSERT(locs()->in(0).reg() == R0);
-  __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
+  if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
+    __ LoadFieldFromOffset(CODE_REG, R0,
+                           compiler::target::Function::code_offset());
+  }
   __ LoadFieldFromOffset(
-      R2, CODE_REG, compiler::target::Code::entry_point_offset(entry_kind()));
+      R2, R0, compiler::target::Function::entry_point_offset(entry_kind()));
 
   // R2: instructions.
-  // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
-  __ LoadImmediate(R5, 0);
-  //??
+  if (!FLAG_precompiled_mode) {
+    // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
+    __ LoadImmediate(R5, 0);
+  }
   __ blr(R2);
   compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
                                  RawPcDescriptors::kOther, locs());
diff --git a/runtime/vm/compiler/backend/il_deserializer.cc b/runtime/vm/compiler/backend/il_deserializer.cc
index 6251bf8..5f91cf9 100644
--- a/runtime/vm/compiler/backend/il_deserializer.cc
+++ b/runtime/vm/compiler/backend/il_deserializer.cc
@@ -8,6 +8,7 @@
 
 #include "vm/compiler/backend/il_serializer.h"
 #include "vm/compiler/backend/range_analysis.h"
+#include "vm/compiler/call_specializer.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/flags.h"
 #include "vm/json_writer.h"
@@ -126,7 +127,7 @@
 }
 
 void FlowGraphDeserializer::RoundTripSerialization(CompilerPassState* state) {
-  auto const flow_graph = state->flow_graph;
+  auto const flow_graph = state->flow_graph();
 
   // The deserialized flow graph must be in the same zone as the original flow
   // graph, to ensure it has the right lifetime. Thus, we leave an explicit
@@ -195,7 +196,9 @@
 
   if (FLAG_print_json_round_trip_results) PrintRoundTripResults(zone, results);
 
-  if (new_graph != nullptr) state->flow_graph = new_graph;
+  if (new_graph != nullptr) {
+    state->set_flow_graph(new_graph);
+  }
 }
 
 #define HANDLED_CASE(name)                                                     \
@@ -346,7 +349,13 @@
   }
 
   flow_graph_->set_max_block_id(max_block_id_);
-  flow_graph_->set_current_ssa_temp_index(max_ssa_index_ + 1);
+  // The highest numbered SSA temp might need two slots (e.g. for unboxed
+  // integers on 32-bit platforms), so we add 2 to the highest seen SSA temp
+  // index to get to the new current SSA temp index. In cases where the highest
+  // numbered SSA temp originally had only one slot assigned, this can result
+  // in different SSA temp numbering in later passes between the original and
+  // deserialized graphs.
+  flow_graph_->set_current_ssa_temp_index(max_ssa_index_ + 2);
   // Now that the deserializer has finished re-creating all the blocks in the
   // flow graph, the blocks must be rediscovered. In addition, if ComputeSSA
   // has already been run, dominators must be recomputed as well.
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index d039bf3..78b937e 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -532,8 +532,7 @@
 }
 
 void PolymorphicInstanceCallInstr::PrintOperandsTo(BufferFormatter* f) const {
-  f->Print(" %s<%" Pd ">", instance_call()->function_name().ToCString(),
-           instance_call()->type_args_len());
+  f->Print(" %s<%" Pd ">", function_name().ToCString(), type_args_len());
   for (intptr_t i = 0; i < ArgumentCount(); ++i) {
     f->Print(", ");
     ArgumentValueAt(i)->PrintTo(f);
@@ -542,7 +541,7 @@
   if (complete()) {
     f->Print(" COMPLETE");
   }
-  if (instance_call()->entry_kind() == Code::EntryKind::kUnchecked) {
+  if (entry_kind() == Code::EntryKind::kUnchecked) {
     f->Print(" using unchecked entrypoint");
   }
 }
diff --git a/runtime/vm/compiler/backend/il_serializer.cc b/runtime/vm/compiler/backend/il_serializer.cc
index e1032a2..2ec431ae 100644
--- a/runtime/vm/compiler/backend/il_serializer.cc
+++ b/runtime/vm/compiler/backend/il_serializer.cc
@@ -1211,12 +1211,13 @@
   }
 }
 
-void InstanceCallInstr::AddOperandsToSExpression(SExpList* sexp,
-                                                 FlowGraphSerializer* s) const {
+void InstanceCallBaseInstr::AddOperandsToSExpression(
+    SExpList* sexp,
+    FlowGraphSerializer* s) const {
   Instruction::AddOperandsToSExpression(sexp, s);
 }
 
-void InstanceCallInstr::AddExtraInfoToSExpression(
+void InstanceCallBaseInstr::AddExtraInfoToSExpression(
     SExpList* sexp,
     FlowGraphSerializer* s) const {
   TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s);
@@ -1243,9 +1244,6 @@
   if (token_kind() != Token::kILLEGAL) {
     s->AddExtraSymbol(sexp, "token_kind", Token::Str(token_kind()));
   }
-  if (checked_argument_count() > 0 || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "checked_arg_count", checked_argument_count());
-  }
 
   if (ShouldSerializeType(result_type())) {
     sexp->AddExtra("result_type", result_type()->ToSExpression(s));
@@ -1258,19 +1256,21 @@
   }
 }
 
-void PolymorphicInstanceCallInstr::AddOperandsToSExpression(
+void InstanceCallInstr::AddExtraInfoToSExpression(
     SExpList* sexp,
     FlowGraphSerializer* s) const {
-  Instruction::AddOperandsToSExpression(sexp, s);
+  InstanceCallBaseInstr::AddExtraInfoToSExpression(sexp, s);
+
+  if (checked_argument_count() > 0 || FLAG_verbose_flow_graph_serialization) {
+    s->AddExtraInteger(sexp, "checked_arg_count", checked_argument_count());
+  }
 }
 
 void PolymorphicInstanceCallInstr::AddExtraInfoToSExpression(
     SExpList* sexp,
     FlowGraphSerializer* s) const {
-  TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s);
-  // TODO(alexmarkov): figure out how to serialize information from
-  // inner InstanceCall
-  // sexp->AddExtra("instance_call", instance_call()->ToSExpression(s));
+  InstanceCallBaseInstr::AddExtraInfoToSExpression(sexp, s);
+
   if (targets().length() > 0 || FLAG_verbose_flow_graph_serialization) {
     auto elem_list = new (s->zone()) SExpList(s->zone());
     for (intptr_t i = 0; i < targets().length(); i++) {
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 43e04dd..dd48008 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -6752,14 +6752,21 @@
 
   // Function in RAX.
   ASSERT(locs()->in(0).reg() == RAX);
-  __ movq(CODE_REG, compiler::FieldAddress(RAX, Function::code_offset()));
-  __ movq(RCX, compiler::FieldAddress(
-                   RAX, Code::function_entry_point_offset(entry_kind())));
+  if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
+    __ movq(CODE_REG, compiler::FieldAddress(
+                          RAX, compiler::target::Function::code_offset()));
+  }
+  __ movq(
+      RCX,
+      compiler::FieldAddress(
+          RAX, compiler::target::Function::entry_point_offset(entry_kind())));
 
   // RAX: Function.
   // R10: Arguments descriptor array.
-  // RBX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
-  __ xorq(RBX, RBX);
+  if (!FLAG_precompiled_mode) {
+    // RBX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
+    __ xorq(RBX, RBX);
+  }
   __ call(RCX);
   compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
                                  RawPcDescriptors::kOther, locs());
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 0fd3634..6133a0a 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1261,7 +1261,7 @@
                      &Object::dynamic_type());
 }
 
-CompileType InstanceCallInstr::ComputeType() const {
+CompileType InstanceCallBaseInstr::ComputeType() const {
   // TODO(alexmarkov): calculate type of InstanceCallInstr eagerly
   // (in optimized mode) and avoid keeping separate result_type.
   CompileType* inferred_type = result_type();
@@ -1310,13 +1310,8 @@
     }
   }
 
-  if (Isolate::Current()->can_use_strong_mode_types()) {
-    CompileType* type = instance_call()->Type();
-    TraceStrongModeType(this, type);
-    return is_nullable ? *type : type->CopyNonNullable();
-  }
-
-  return CompileType::Dynamic();
+  CompileType type = InstanceCallBaseInstr::ComputeType();
+  return is_nullable ? type : type.CopyNonNullable();
 }
 
 CompileType StaticCallInstr::ComputeType() const {
diff --git a/runtime/vm/compiler/call_specializer.h b/runtime/vm/compiler/call_specializer.h
index 940243d..bc8544d 100644
--- a/runtime/vm/compiler/call_specializer.h
+++ b/runtime/vm/compiler/call_specializer.h
@@ -41,6 +41,11 @@
 
   FlowGraph* flow_graph() const { return flow_graph_; }
 
+  void set_flow_graph(FlowGraph* flow_graph) {
+    flow_graph_ = flow_graph;
+    set_block_order(flow_graph->reverse_postorder());
+  }
+
   // Use ICData to optimize, replace or eliminate instructions.
   void ApplyICData();
 
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 82f1c16..1142355 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -34,7 +34,7 @@
                                                                                \
    protected:                                                                  \
     virtual bool DoBody(CompilerPassState* state) const {                      \
-      FlowGraph* flow_graph = state->flow_graph;                               \
+      FlowGraph* flow_graph = state->flow_graph();                             \
       USE(flow_graph);                                                         \
       Body;                                                                    \
     }                                                                          \
@@ -67,6 +67,13 @@
 DECLARE_FLAG(bool, print_flow_graph);
 DECLARE_FLAG(bool, print_flow_graph_optimized);
 
+void CompilerPassState::set_flow_graph(FlowGraph* flow_graph) {
+  flow_graph_ = flow_graph;
+  if (call_specializer != nullptr) {
+    call_specializer->set_flow_graph(flow_graph);
+  }
+}
+
 static const char* kCompilerPassesUsage =
     "=== How to use --compiler-passes flag\n"
     "\n"
@@ -191,7 +198,7 @@
     }
     PrintGraph(state, kTraceAfter, round);
 #if defined(DEBUG)
-    FlowGraphChecker(state->flow_graph).Check(name());
+    FlowGraphChecker(state->flow_graph()).Check(name());
 #endif
   }
 }
@@ -200,7 +207,7 @@
                               Flag mask,
                               intptr_t round) const {
   const intptr_t current_flags = flags() | state->sticky_flags;
-  FlowGraph* flow_graph = state->flow_graph;
+  FlowGraph* flow_graph = state->flow_graph();
 
   if ((FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) &&
       flow_graph->should_print() && ((current_flags & mask) != 0)) {
@@ -271,7 +278,7 @@
   }
   INVOKE_PASS(AllocateRegisters);
   INVOKE_PASS(ReorderBlocks);
-  return pass_state->flow_graph;
+  return pass_state->flow_graph();
 }
 
 FlowGraph* CompilerPass::RunPipeline(PipelineMode mode,
@@ -355,7 +362,7 @@
   }
   INVOKE_PASS(AllocateRegisters);
   INVOKE_PASS(ReorderBlocks);
-  return pass_state->flow_graph;
+  return pass_state->flow_graph();
 }
 
 FlowGraph* CompilerPass::RunPipelineWithPasses(
@@ -364,7 +371,7 @@
   for (auto pass_id : passes) {
     passes_[pass_id]->Run(state);
   }
-  return state->flow_graph;
+  return state->flow_graph();
 }
 
 COMPILER_PASS(ComputeSSA, {
@@ -583,7 +590,7 @@
 
 COMPILER_PASS(RoundTripSerialization, {
   FlowGraphDeserializer::RoundTripSerialization(state);
-  ASSERT(state->flow_graph != nullptr);
+  ASSERT(state->flow_graph() != nullptr);
 })
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/compiler_pass.h b/runtime/vm/compiler/compiler_pass.h
index b5dd477..a9d1f87 100644
--- a/runtime/vm/compiler/compiler_pass.h
+++ b/runtime/vm/compiler/compiler_pass.h
@@ -67,18 +67,20 @@
                     SpeculativeInliningPolicy* speculative_policy,
                     Precompiler* precompiler = NULL)
       : thread(thread),
-        flow_graph(flow_graph),
         precompiler(precompiler),
         inlining_depth(0),
         sinking(NULL),
         call_specializer(NULL),
         speculative_policy(speculative_policy),
         reorder_blocks(false),
-        sticky_flags(0) {
-  }
+        sticky_flags(0),
+        flow_graph_(flow_graph) {}
+
+  FlowGraph* flow_graph() const { return flow_graph_; }
+
+  void set_flow_graph(FlowGraph* flow_graph);
 
   Thread* const thread;
-  FlowGraph* flow_graph;
   Precompiler* const precompiler;
   int inlining_depth;
   AllocationSinking* sinking;
@@ -98,6 +100,9 @@
   bool reorder_blocks;
 
   intptr_t sticky_flags;
+
+ private:
+  FlowGraph* flow_graph_;
 };
 
 class CompilerPass {
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index b1d1bd3..9dd83de 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -423,9 +423,8 @@
 class Function : public AllStatic {
  public:
   static word code_offset();
-  static word entry_point_offset();
+  static word entry_point_offset(CodeEntryKind kind = CodeEntryKind::kNormal);
   static word usage_counter_offset();
-  static word unchecked_entry_point_offset();
 };
 
 class ICData : public AllStatic {
@@ -807,7 +806,6 @@
 
   static word object_pool_offset();
   static word entry_point_offset(CodeEntryKind kind = CodeEntryKind::kNormal);
-  static word function_entry_point_offset(CodeEntryKind kind);
   static word saved_instructions_offset();
   static word owner_offset();
 };
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 94bdeb6..2fb12cf 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -111,9 +111,8 @@
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 46;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 60;
 static constexpr dart::compiler::target::word Function_code_offset = 44;
-static constexpr dart::compiler::target::word Function_entry_point_offset = 4;
-static constexpr dart::compiler::target::word
-    Function_unchecked_entry_point_offset = 8;
+static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
+    4, 8};
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
     76;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -361,8 +360,6 @@
 static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
-    Code_function_entry_point_offset[] = {4, 8};
-static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
         628, 632, 636, 640, 644, -1, 648, 652,
         656, 660, -1,  -1,  -1,  -1, -1,  -1};
@@ -485,9 +482,8 @@
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 82;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 104;
 static constexpr dart::compiler::target::word Function_code_offset = 88;
-static constexpr dart::compiler::target::word Function_entry_point_offset = 8;
-static constexpr dart::compiler::target::word
-    Function_unchecked_entry_point_offset = 16;
+static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
+    8, 16};
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
     132;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -737,8 +733,6 @@
 static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
-    Code_function_entry_point_offset[] = {8, 16};
-static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
         1248, 1256, 1264, 1272, -1,   -1,   1280, 1288,
         1296, 1304, 1312, -1,   1320, 1328, -1,   -1};
@@ -859,9 +853,8 @@
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 46;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 60;
 static constexpr dart::compiler::target::word Function_code_offset = 44;
-static constexpr dart::compiler::target::word Function_entry_point_offset = 4;
-static constexpr dart::compiler::target::word
-    Function_unchecked_entry_point_offset = 8;
+static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
+    4, 8};
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
     76;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -1108,8 +1101,6 @@
 static constexpr dart::compiler::target::word ClassTable_element_size = 1;
 static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
     4, 12, 8, 16};
-static constexpr dart::compiler::target::word
-    Code_function_entry_point_offset[] = {4, 8};
 static constexpr dart::compiler::target::word Array_header_size = 12;
 static constexpr dart::compiler::target::word Context_header_size = 12;
 static constexpr dart::compiler::target::word Double_InstanceSize = 16;
@@ -1229,9 +1220,8 @@
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 82;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 104;
 static constexpr dart::compiler::target::word Function_code_offset = 88;
-static constexpr dart::compiler::target::word Function_entry_point_offset = 8;
-static constexpr dart::compiler::target::word
-    Function_unchecked_entry_point_offset = 16;
+static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
+    8, 16};
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
     132;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -1481,8 +1471,6 @@
 static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
-    Code_function_entry_point_offset[] = {8, 16};
-static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
         1248, 1256, 1264, 1272, 1280, 1288, 1296, 1304, 1312, 1320, 1328,
         1336, 1344, 1352, 1360, -1,   -1,   -1,   -1,   1368, 1376, 1384,
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index 5c88c8e..b2ba63a 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -90,8 +90,8 @@
   PRECOMP_NO_CHECK(FIELD(Field, is_nullable_offset))                           \
   PRECOMP_NO_CHECK(FIELD(Field, kind_bits_offset))                             \
   FIELD(Function, code_offset)                                                 \
-  FIELD(Function, entry_point_offset)                                          \
-  FIELD(Function, unchecked_entry_point_offset)                                \
+  RANGE(Function, entry_point_offset, CodeEntryKind, CodeEntryKind::kNormal,   \
+        CodeEntryKind::kUnchecked, [](CodeEntryKind value) { return true; })   \
   PRECOMP_NO_CHECK(FIELD(Function, usage_counter_offset))                      \
   FIELD(GrowableObjectArray, data_offset)                                      \
   FIELD(GrowableObjectArray, length_offset)                                    \
@@ -244,9 +244,6 @@
   RANGE(Code, entry_point_offset, CodeEntryKind, CodeEntryKind::kNormal,       \
         CodeEntryKind::kMonomorphicUnchecked,                                  \
         [](CodeEntryKind value) { return true; })                              \
-  RANGE(Code, function_entry_point_offset, CodeEntryKind,                      \
-        CodeEntryKind::kNormal, CodeEntryKind::kUnchecked,                     \
-        [](CodeEntryKind value) { return true; })                              \
   ONLY_IN_ARM_ARM64_X64(RANGE(                                                 \
       Thread, write_barrier_wrappers_thread_offset, Register, 0,               \
       kNumberOfCpuRegisters - 1,                                               \
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 0af2249..c0f58fc 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -2057,8 +2057,10 @@
   __ mov(R3, Operand(target::Function::entry_point_offset() - kHeapObjectTag));
   __ b(&done);
   __ BindUncheckedEntryPoint();
-  __ mov(R3, Operand(target::Function::unchecked_entry_point_offset() -
-                     kHeapObjectTag));
+  __ mov(
+      R3,
+      Operand(target::Function::entry_point_offset(CodeEntryKind::kUnchecked) -
+              kHeapObjectTag));
   __ Bind(&done);
 }
 
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index a1162b8..9d9e357 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -2159,7 +2159,8 @@
   __ b(&done);
   __ BindUncheckedEntryPoint();
   __ LoadImmediate(
-      R8, target::Function::unchecked_entry_point_offset() - kHeapObjectTag);
+      R8, target::Function::entry_point_offset(CodeEntryKind::kUnchecked) -
+              kHeapObjectTag);
   __ Bind(&done);
 }
 
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 4b42c72..3e5ae59 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -1921,8 +1921,7 @@
   __ Bind(&call_target_function);
   __ Comment("Call target");
   // EAX: Target function.
-  __ jmp(
-      FieldAddress(EAX, target::Code::function_entry_point_offset(entry_kind)));
+  __ jmp(FieldAddress(EAX, target::Function::entry_point_offset(entry_kind)));
 
 #if !defined(PRODUCT)
   if (optimized == kUnoptimized) {
@@ -2088,8 +2087,7 @@
 
   // Get function and call it, if possible.
   __ movl(EAX, Address(EBX, target_offset));
-  __ jmp(
-      FieldAddress(EAX, target::Code::function_entry_point_offset(entry_kind)));
+  __ jmp(FieldAddress(EAX, target::Function::entry_point_offset(entry_kind)));
 
 #if !defined(PRODUCT)
   __ Bind(&stepping);
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 1a105a8..bf6415f 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -2087,7 +2087,8 @@
           Immediate(target::Function::entry_point_offset() - kHeapObjectTag));
   __ jmp(&done);
   __ BindUncheckedEntryPoint();
-  __ movq(R8, Immediate(target::Function::unchecked_entry_point_offset() -
+  __ movq(R8, Immediate(target::Function::entry_point_offset(
+                            CodeEntryKind::kUnchecked) -
                         kHeapObjectTag));
   __ Bind(&done);
 }
@@ -2329,7 +2330,8 @@
     __ Comment("Call target (via unchecked entry point)");
     __ movq(RAX, Address(R13, target_offset));
     __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
-    __ jmp(FieldAddress(RAX, target::Function::unchecked_entry_point_offset()));
+    __ jmp(FieldAddress(
+        RAX, target::Function::entry_point_offset(CodeEntryKind::kUnchecked)));
   }
 
 #if !defined(PRODUCT)
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index f3ac03a..add8913 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -90,11 +90,6 @@
                      MarkingStack* deferred_marking_stack)
       : ObjectPointerVisitor(isolate),
         thread_(Thread::Current()),
-#ifndef PRODUCT
-        num_classes_(isolate->shared_class_table()->Capacity()),
-        class_stats_count_(new intptr_t[num_classes_]),
-        class_stats_size_(new intptr_t[num_classes_]),
-#endif  // !PRODUCT
         page_space_(page_space),
         work_list_(marking_stack),
         deferred_work_list_(deferred_marking_stack),
@@ -102,33 +97,12 @@
         marked_bytes_(0),
         marked_micros_(0) {
     ASSERT(thread_->isolate() == isolate);
-#ifndef PRODUCT
-    for (intptr_t i = 0; i < num_classes_; i++) {
-      class_stats_count_[i] = 0;
-      class_stats_size_[i] = 0;
-    }
-#endif  // !PRODUCT
-  }
-
-  ~MarkingVisitorBase() {
-#ifndef PRODUCT
-    delete[] class_stats_count_;
-    delete[] class_stats_size_;
-#endif  // !PRODUCT
   }
 
   uintptr_t marked_bytes() const { return marked_bytes_; }
   int64_t marked_micros() const { return marked_micros_; }
   void AddMicros(int64_t micros) { marked_micros_ += micros; }
 
-#ifndef PRODUCT
-  intptr_t live_count(intptr_t class_id) {
-    return class_stats_count_[class_id];
-  }
-
-  intptr_t live_size(intptr_t class_id) { return class_stats_size_[class_id]; }
-#endif  // !PRODUCT
-
   bool ProcessPendingWeakProperties() {
     bool marked = false;
     RawWeakProperty* cur_weak = delayed_weak_properties_;
@@ -178,7 +152,6 @@
           size = ProcessWeakProperty(raw_weak);
         }
         marked_bytes_ += size;
-        NOT_IN_PRODUCT(UpdateLiveOld(class_id, size));
 
         raw_obj = work_list_.Pop();
       } while (raw_obj != NULL);
@@ -252,7 +225,6 @@
       // double-counting.
       if (TryAcquireMarkBit(raw_obj)) {
         marked_bytes_ += size;
-        NOT_IN_PRODUCT(UpdateLiveOld(class_id, size));
       }
     }
   }
@@ -344,20 +316,7 @@
     PushMarked(raw_obj);
   }
 
-#ifndef PRODUCT
-  void UpdateLiveOld(intptr_t class_id, intptr_t size) {
-    ASSERT(class_id < num_classes_);
-    class_stats_count_[class_id] += 1;
-    class_stats_size_[class_id] += size;
-  }
-#endif  // !PRODUCT
-
   Thread* thread_;
-#ifndef PRODUCT
-  intptr_t num_classes_;
-  intptr_t* class_stats_count_;
-  intptr_t* class_stats_size_;
-#endif  // !PRODUCT
   PageSpace* page_space_;
   MarkerWorkList work_list_;
   MarkerWorkList deferred_work_list_;
@@ -419,7 +378,113 @@
 #endif
 }
 
-void GCMarker::Epilogue() {
+void GCMarker::Epilogue() {}
+
+enum RootSlices {
+  kIsolate = 0,
+  kNewSpace = 1,
+  kNumRootSlices = 2,
+};
+
+void GCMarker::ResetSlices() {
+  root_slices_started_ = 0;
+  root_slices_finished_ = 0;
+  weak_slices_started_ = 0;
+}
+
+void GCMarker::IterateRoots(ObjectPointerVisitor* visitor) {
+  for (;;) {
+    intptr_t slice = root_slices_started_.fetch_add(1);
+    if (slice >= kNumRootSlices) {
+      return;  // No more slices.
+    }
+
+    switch (slice) {
+      case kIsolate: {
+        TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ProcessIsolate");
+        isolate_->VisitObjectPointers(visitor,
+                                      ValidationPolicy::kDontValidateFrames);
+        break;
+      }
+      case kNewSpace: {
+        TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ProcessNewSpace");
+        heap_->new_space()->VisitObjectPointers(visitor);
+        break;
+      }
+      default:
+        UNREACHABLE();
+    }
+
+    MonitorLocker ml(&root_slices_monitor_);
+    root_slices_finished_++;
+    if (root_slices_finished_ == kNumRootSlices) {
+      ml.Notify();
+    }
+  }
+}
+
+enum WeakSlices {
+  kWeakHandles = 0,
+  kWeakTables,
+  kObjectIdRing,
+  kRememberedSet,
+  kNumWeakSlices,
+};
+
+void GCMarker::IterateWeakRoots(Thread* thread) {
+  for (;;) {
+    intptr_t slice = weak_slices_started_.fetch_add(1);
+    if (slice >= kNumWeakSlices) {
+      return;  // No more slices.
+    }
+
+    switch (slice) {
+      case kWeakHandles:
+        ProcessWeakHandles(thread);
+        break;
+      case kWeakTables:
+        ProcessWeakTables(thread);
+        break;
+      case kObjectIdRing:
+        ProcessObjectIdTable(thread);
+        break;
+      case kRememberedSet:
+        ProcessRememberedSet(thread);
+        break;
+      default:
+        UNREACHABLE();
+    }
+  }
+}
+
+void GCMarker::ProcessWeakHandles(Thread* thread) {
+  TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessWeakHandles");
+  MarkingWeakVisitor visitor(thread);
+  ApiState* state = isolate_->api_state();
+  ASSERT(state != NULL);
+  isolate_->VisitWeakPersistentHandles(&visitor);
+}
+
+void GCMarker::ProcessWeakTables(Thread* thread) {
+  TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessWeakTables");
+  for (int sel = 0; sel < Heap::kNumWeakSelectors; sel++) {
+    WeakTable* table =
+        heap_->GetWeakTable(Heap::kOld, static_cast<Heap::WeakSelector>(sel));
+    intptr_t size = table->size();
+    for (intptr_t i = 0; i < size; i++) {
+      if (table->IsValidEntryAtExclusive(i)) {
+        RawObject* raw_obj = table->ObjectAtExclusive(i);
+        ASSERT(raw_obj->IsHeapObject());
+        if (!raw_obj->IsMarked()) {
+          table->InvalidateAtExclusive(i);
+        }
+      }
+    }
+  }
+}
+
+void GCMarker::ProcessRememberedSet(Thread* thread) {
+  TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessRememberedSet");
   // Filter collected objects from the remembered set.
   StoreBuffer* store_buffer = isolate_->store_buffer();
   StoreBufferBlock* reading = store_buffer->Blocks();
@@ -448,72 +513,6 @@
   store_buffer->PushBlock(writing, StoreBuffer::kIgnoreThreshold);
 }
 
-enum RootSlices {
-  kIsolate = 0,
-  kNewSpace = 1,
-  kNumRootSlices = 2,
-};
-
-void GCMarker::ResetRootSlices() {
-  root_slices_not_started_ = kNumRootSlices;
-  root_slices_not_finished_ = kNumRootSlices;
-}
-
-void GCMarker::IterateRoots(ObjectPointerVisitor* visitor) {
-  for (;;) {
-    intptr_t task = root_slices_not_started_.fetch_sub(1) - 1;
-    if (task < 0) {
-      return;  // No more tasks.
-    }
-
-    switch (task) {
-      case kIsolate: {
-        TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ProcessRoots");
-        isolate_->VisitObjectPointers(visitor,
-                                      ValidationPolicy::kDontValidateFrames);
-        break;
-      }
-      case kNewSpace: {
-        TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ProcessNewSpace");
-        heap_->new_space()->VisitObjectPointers(visitor);
-        break;
-      }
-      default:
-        FATAL1("%" Pd, task);
-        UNREACHABLE();
-    }
-
-    MonitorLocker ml(&root_slices_monitor_);
-    root_slices_not_finished_--;
-    if (root_slices_not_finished_ == 0) {
-      ml.Notify();
-    }
-  }
-}
-
-void GCMarker::IterateWeakRoots(HandleVisitor* visitor) {
-  ApiState* state = isolate_->api_state();
-  ASSERT(state != NULL);
-  isolate_->VisitWeakPersistentHandles(visitor);
-}
-
-void GCMarker::ProcessWeakTables(PageSpace* page_space) {
-  for (int sel = 0; sel < Heap::kNumWeakSelectors; sel++) {
-    WeakTable* table =
-        heap_->GetWeakTable(Heap::kOld, static_cast<Heap::WeakSelector>(sel));
-    intptr_t size = table->size();
-    for (intptr_t i = 0; i < size; i++) {
-      if (table->IsValidEntryAtExclusive(i)) {
-        RawObject* raw_obj = table->ObjectAtExclusive(i);
-        ASSERT(raw_obj->IsHeapObject());
-        if (!raw_obj->IsMarked()) {
-          table->InvalidateAtExclusive(i);
-        }
-      }
-    }
-  }
-}
-
 class ObjectIdRingClearPointerVisitor : public ObjectPointerVisitor {
  public:
   explicit ObjectIdRingClearPointerVisitor(Isolate* isolate)
@@ -531,11 +530,12 @@
   }
 };
 
-void GCMarker::ProcessObjectIdTable() {
+void GCMarker::ProcessObjectIdTable(Thread* thread) {
 #ifndef PRODUCT
   if (!FLAG_support_service) {
     return;
   }
+  TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessObjectIdTable");
   ObjectIdRingClearPointerVisitor visitor(isolate_);
   ObjectIdRing* ring = isolate_->object_id_ring();
   ASSERT(ring != NULL);
@@ -563,7 +563,8 @@
         Thread::EnterIsolateAsHelper(isolate_, Thread::kMarkerTask, true);
     ASSERT(result);
     {
-      TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ParallelMark");
+      Thread* thread = Thread::Current();
+      TIMELINE_FUNCTION_GC_DURATION(thread, "ParallelMark");
       int64_t start = OS::GetCurrentMonotonicMicros();
 
       // Phase 1: Iterate over roots and drain marking stack in tasks.
@@ -623,12 +624,15 @@
         barrier_->Sync();
       } while (more_to_mark);
 
+      // Phase 2: deferred marking.
       visitor_->FinalizeDeferredMarking();
-
-      // Phase 2: Weak processing and follow-up marking on main thread.
       barrier_->Sync();
 
-      // Phase 3: Finalize results from all markers (detach code, etc.).
+      // Phase 3: Weak processing.
+      marker_->IterateWeakRoots(thread);
+      barrier_->Sync();
+
+      // Phase 4: Gather statistics from all markers.
       int64_t stop = OS::GetCurrentMonotonicMicros();
       visitor_->AddMicros(stop - start);
       if (FLAG_log_marker_tasks) {
@@ -786,7 +790,7 @@
         page_space->concurrent_marker_tasks() + num_tasks);
   }
 
-  ResetRootSlices();
+  ResetSlices();
   for (intptr_t i = 0; i < num_tasks; i++) {
     ASSERT(visitors_[i] == NULL);
     visitors_[i] = new SyncMarkingVisitor(isolate_, page_space, &marking_stack_,
@@ -800,7 +804,7 @@
 
   // Wait for roots to be marked before exiting safepoint.
   MonitorLocker ml(&root_slices_monitor_);
-  while (root_slices_not_finished_ > 0) {
+  while (root_slices_finished_ != kNumRootSlices) {
     ml.Wait();
   }
 }
@@ -820,16 +824,12 @@
       // Mark everything on main thread.
       UnsyncMarkingVisitor mark(isolate_, page_space, &marking_stack_,
                                 &deferred_marking_stack_);
-      ResetRootSlices();
+      ResetSlices();
       IterateRoots(&mark);
       mark.ProcessDeferredMarking();
       mark.DrainMarkingStack();
       mark.FinalizeDeferredMarking();
-      {
-        TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessWeakHandles");
-        MarkingWeakVisitor mark_weak(thread);
-        IterateWeakRoots(&mark_weak);
-      }
+      IterateWeakRoots(thread);
       // All marking done; detach code, etc.
       int64_t stop = OS::GetCurrentMonotonicMicros();
       mark.AddMicros(stop - start);
@@ -837,7 +837,7 @@
     } else {
       ThreadBarrier barrier(num_tasks + 1, heap_->barrier(),
                             heap_->barrier_done());
-      ResetRootSlices();
+      ResetSlices();
       // Used to coordinate draining among tasks; all start out as 'busy'.
       RelaxedAtomic<uintptr_t> num_busy(num_tasks);
       // Phase 1: Iterate over roots and drain marking stack in tasks.
@@ -876,19 +876,16 @@
         barrier.Sync();
       } while (more_to_mark);
 
-      // Phase 2: Weak processing on main thread.
-      {
-        TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessWeakHandles");
-        MarkingWeakVisitor mark_weak(thread);
-        IterateWeakRoots(&mark_weak);
-      }
+      // Phase 2: Deferred marking.
       barrier.Sync();
 
-      // Phase 3: Finalize results from all markers (detach code, etc.).
+      // Phase 3: Weak processing.
+      IterateWeakRoots(thread);
+      barrier.Sync();
+
+      // Phase 4: Gather statistics from all markers.
       barrier.Exit();
     }
-    ProcessWeakTables(page_space);
-    ProcessObjectIdTable();
   }
   Epilogue();
 }
diff --git a/runtime/vm/heap/marker.h b/runtime/vm/heap/marker.h
index 2fd9282..35ebea9 100644
--- a/runtime/vm/heap/marker.h
+++ b/runtime/vm/heap/marker.h
@@ -20,6 +20,7 @@
 class RawWeakProperty;
 template <bool sync>
 class MarkingVisitorBase;
+class Thread;
 
 // The class GCMarker is used to mark reachable old generation objects as part
 // of the mark-sweep collection. The marking bit used is defined in RawObject.
@@ -47,13 +48,13 @@
  private:
   void Prologue();
   void Epilogue();
-  void ResetRootSlices();
+  void ResetSlices();
   void IterateRoots(ObjectPointerVisitor* visitor);
-  void IterateWeakRoots(HandleVisitor* visitor);
-  template <class MarkingVisitorType>
-  void IterateWeakReferences(MarkingVisitorType* visitor);
-  void ProcessWeakTables(PageSpace* page_space);
-  void ProcessObjectIdTable();
+  void IterateWeakRoots(Thread* thread);
+  void ProcessWeakHandles(Thread* thread);
+  void ProcessWeakTables(Thread* thread);
+  void ProcessRememberedSet(Thread* thread);
+  void ProcessObjectIdTable(Thread* thread);
 
   // Called by anyone: finalize and accumulate stats from 'visitor'.
   template <class MarkingVisitorType>
@@ -66,8 +67,9 @@
   MarkingVisitorBase<true>** visitors_;
 
   Monitor root_slices_monitor_;
-  RelaxedAtomic<intptr_t> root_slices_not_started_;
-  intptr_t root_slices_not_finished_;
+  RelaxedAtomic<intptr_t> root_slices_started_;
+  intptr_t root_slices_finished_;
+  RelaxedAtomic<intptr_t> weak_slices_started_;
 
   Mutex stats_mutex_;
   uintptr_t marked_bytes_;
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 15700c1..6c5a066 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -221,6 +221,12 @@
     : freelist_(),
       heap_(heap),
       pages_lock_(),
+      pages_(NULL),
+      pages_tail_(NULL),
+      exec_pages_(NULL),
+      exec_pages_tail_(NULL),
+      large_pages_(NULL),
+      image_pages_(NULL),
       bump_top_(0),
       bump_end_(0),
       max_capacity_in_words_(max_capacity_in_words),
@@ -267,95 +273,49 @@
   return page_size >> kWordSizeLog2;
 }
 
-void PageSpace::AddPageLocked(HeapPage* page) {
-  if (pages_ == nullptr) {
-    pages_ = page;
-  } else {
-    pages_tail_->set_next(page);
-  }
-  pages_tail_ = page;
-}
-
-void PageSpace::AddLargePageLocked(HeapPage* page) {
-  if (large_pages_ == nullptr) {
-    large_pages_ = page;
-  } else {
-    large_pages_tail_->set_next(page);
-  }
-  large_pages_tail_ = page;
-}
-
-void PageSpace::AddExecPageLocked(HeapPage* page) {
-  if (exec_pages_ == nullptr) {
-    exec_pages_ = page;
-  } else {
-    if (FLAG_write_protect_code) {
-      exec_pages_tail_->WriteProtect(false);
-    }
-    exec_pages_tail_->set_next(page);
-    if (FLAG_write_protect_code) {
-      exec_pages_tail_->WriteProtect(true);
-    }
-  }
-  exec_pages_tail_ = page;
-}
-
-void PageSpace::RemovePageLocked(HeapPage* page, HeapPage* previous_page) {
-  if (previous_page != NULL) {
-    previous_page->set_next(page->next());
-  } else {
-    pages_ = page->next();
-  }
-  if (page == pages_tail_) {
-    pages_tail_ = previous_page;
-  }
-}
-
-void PageSpace::RemoveLargePageLocked(HeapPage* page, HeapPage* previous_page) {
-  if (previous_page != NULL) {
-    previous_page->set_next(page->next());
-  } else {
-    large_pages_ = page->next();
-  }
-  if (page == large_pages_tail_) {
-    large_pages_tail_ = previous_page;
-  }
-}
-
-void PageSpace::RemoveExecPageLocked(HeapPage* page, HeapPage* previous_page) {
-  if (previous_page != NULL) {
-    previous_page->set_next(page->next());
-  } else {
-    exec_pages_ = page->next();
-  }
-  if (page == exec_pages_tail_) {
-    exec_pages_tail_ = previous_page;
-  }
-}
-
 HeapPage* PageSpace::AllocatePage(HeapPage::PageType type, bool link) {
   {
     MutexLocker ml(&pages_lock_);
     if (!CanIncreaseCapacityInWordsLocked(kPageSizeInWords)) {
-      return nullptr;
+      return NULL;
     }
     IncreaseCapacityInWordsLocked(kPageSizeInWords);
   }
   const bool is_exec = (type == HeapPage::kExecutable);
   const char* name = Heap::RegionName(is_exec ? Heap::kCode : Heap::kOld);
   HeapPage* page = HeapPage::Allocate(kPageSizeInWords, type, name);
-  if (page == nullptr) {
+  if (page == NULL) {
     RELEASE_ASSERT(!FLAG_abort_on_oom);
     IncreaseCapacityInWords(-kPageSizeInWords);
-    return nullptr;
+    return NULL;
   }
 
   MutexLocker ml(&pages_lock_);
   if (link) {
-    if (is_exec) {
-      AddExecPageLocked(page);
+    if (!is_exec) {
+      if (pages_ == NULL) {
+        pages_ = page;
+      } else {
+        pages_tail_->set_next(page);
+      }
+      pages_tail_ = page;
     } else {
-      AddPageLocked(page);
+      // Should not allocate executable pages when running from a precompiled
+      // snapshot.
+      ASSERT(Dart::vm_snapshot_kind() != Snapshot::kFullAOT);
+
+      if (exec_pages_ == NULL) {
+        exec_pages_ = page;
+      } else {
+        if (FLAG_write_protect_code) {
+          exec_pages_tail_->WriteProtect(false);
+        }
+        exec_pages_tail_->set_next(page);
+        if (FLAG_write_protect_code) {
+          exec_pages_tail_->WriteProtect(true);
+        }
+      }
+      exec_pages_tail_ = page;
     }
   }
 
@@ -372,28 +332,26 @@
   {
     MutexLocker ml(&pages_lock_);
     if (!CanIncreaseCapacityInWordsLocked(page_size_in_words)) {
-      return nullptr;
+      return NULL;
     }
     IncreaseCapacityInWordsLocked(page_size_in_words);
   }
   const bool is_exec = (type == HeapPage::kExecutable);
   const char* name = Heap::RegionName(is_exec ? Heap::kCode : Heap::kOld);
   HeapPage* page = HeapPage::Allocate(page_size_in_words, type, name);
+  {
+    MutexLocker ml(&pages_lock_);
+    if (page == nullptr) {
+      IncreaseCapacityInWordsLocked(-page_size_in_words);
+      return nullptr;
+    }
+    page->set_next(large_pages_);
+    large_pages_ = page;
 
-  MutexLocker ml(&pages_lock_);
-  if (page == nullptr) {
-    IncreaseCapacityInWordsLocked(-page_size_in_words);
-    return nullptr;
+    // Only one object in this page (at least until Array::MakeFixedLength
+    // is called).
+    page->set_object_end(page->object_start() + size);
   }
-  if (is_exec) {
-    AddExecPageLocked(page);
-  } else {
-    AddLargePageLocked(page);
-  }
-
-  // Only one object in this page (at least until Array::MakeFixedLength
-  // is called).
-  page->set_object_end(page->object_start() + size);
   return page;
 }
 
@@ -418,10 +376,26 @@
   {
     MutexLocker ml(&pages_lock_);
     IncreaseCapacityInWordsLocked(-(page->memory_->size() >> kWordSizeLog2));
-    if (is_exec) {
-      RemoveExecPageLocked(page, previous_page);
+    if (!is_exec) {
+      // Remove the page from the list of data pages.
+      if (previous_page != NULL) {
+        previous_page->set_next(page->next());
+      } else {
+        pages_ = page->next();
+      }
+      if (page == pages_tail_) {
+        pages_tail_ = previous_page;
+      }
     } else {
-      RemovePageLocked(page, previous_page);
+      // Remove the page from the list of executable pages.
+      if (previous_page != NULL) {
+        previous_page->set_next(page->next());
+      } else {
+        exec_pages_ = page->next();
+      }
+      if (page == exec_pages_tail_) {
+        exec_pages_tail_ = previous_page;
+      }
     }
   }
   // TODO(iposva): Consider adding to a pool of empty pages.
@@ -429,10 +403,16 @@
 }
 
 void PageSpace::FreeLargePage(HeapPage* page, HeapPage* previous_page) {
-  ASSERT(page->type() != HeapPage::kExecutable);
-  MutexLocker ml(&pages_lock_);
-  IncreaseCapacityInWordsLocked(-(page->memory_->size() >> kWordSizeLog2));
-  RemoveLargePageLocked(page, previous_page);
+  // Thread should be at a safepoint when this code is called and hence
+  // it is not necessary to lock large_pages_.
+  ASSERT(Thread::Current()->IsAtSafepoint());
+  IncreaseCapacityInWords(-(page->memory_->size() >> kWordSizeLog2));
+  // Remove the page from the list.
+  if (previous_page != NULL) {
+    previous_page->set_next(page->next());
+  } else {
+    large_pages_ = page->next();
+  }
   page->Deallocate();
 }
 
@@ -1152,18 +1132,36 @@
       OS::PrintErr(" done.\n");
     }
 
-    // Executable pages are always swept immediately to simplify
-    // code protection.
-
-    TIMELINE_FUNCTION_GC_DURATION(thread, "SweepExecutable");
+    TIMELINE_FUNCTION_GC_DURATION(thread, "SweepLargeAndExecutablePages");
     GCSweeper sweeper;
+
+    // During stop-the-world phases we should use bulk lock when adding
+    // elements to the free list.
+    MutexLocker mld(freelist_[HeapPage::kData].mutex());
+    MutexLocker mle(freelist_[HeapPage::kExecutable].mutex());
+
+    // Large and executable pages are always swept immediately.
     HeapPage* prev_page = NULL;
-    HeapPage* page = exec_pages_;
-    FreeList* freelist = &freelist_[HeapPage::kExecutable];
-    MutexLocker ml(freelist->mutex());
+    HeapPage* page = large_pages_;
     while (page != NULL) {
       HeapPage* next_page = page->next();
-      bool page_in_use = sweeper.SweepPage(page, freelist, true /*is_locked*/);
+      const intptr_t words_to_end = sweeper.SweepLargePage(page);
+      if (words_to_end == 0) {
+        FreeLargePage(page, prev_page);
+      } else {
+        TruncateLargePage(page, words_to_end << kWordSizeLog2);
+        prev_page = page;
+      }
+      // Advance to the next page.
+      page = next_page;
+    }
+
+    prev_page = NULL;
+    page = exec_pages_;
+    FreeList* freelist = &freelist_[HeapPage::kExecutable];
+    while (page != NULL) {
+      HeapPage* next_page = page->next();
+      bool page_in_use = sweeper.SweepPage(page, freelist, true);
       if (page_in_use) {
         prev_page = page;
       } else {
@@ -1177,14 +1175,12 @@
   }
 
   if (compact) {
-    SweepLarge();
     Compact(thread);
     set_phase(kDone);
   } else if (FLAG_concurrent_sweep) {
     ConcurrentSweep(isolate);
   } else {
-    SweepLarge();
-    Sweep();
+    BlockingSweep();
     set_phase(kDone);
   }
 
@@ -1217,38 +1213,19 @@
   }
 }
 
-void PageSpace::SweepLarge() {
-  TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "SweepLarge");
-
-  GCSweeper sweeper;
-  HeapPage* prev_page = nullptr;
-  HeapPage* page = large_pages_;
-  while (page != nullptr) {
-    HeapPage* next_page = page->next();
-    const intptr_t words_to_end = sweeper.SweepLargePage(page);
-    if (words_to_end == 0) {
-      FreeLargePage(page, prev_page);
-    } else {
-      TruncateLargePage(page, words_to_end << kWordSizeLog2);
-      prev_page = page;
-    }
-    // Advance to the next page.
-    page = next_page;
-  }
-}
-
-void PageSpace::Sweep() {
+void PageSpace::BlockingSweep() {
   TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "Sweep");
 
+  MutexLocker mld(freelist_[HeapPage::kData].mutex());
+  MutexLocker mle(freelist_[HeapPage::kExecutable].mutex());
+
+  // Sweep all regular sized pages now.
   GCSweeper sweeper;
-  HeapPage* prev_page = nullptr;
+  HeapPage* prev_page = NULL;
   HeapPage* page = pages_;
-  FreeList* freelist = &freelist_[HeapPage::kData];
-  MutexLocker ml(freelist_->mutex());
-  while (page != nullptr) {
+  while (page != NULL) {
     HeapPage* next_page = page->next();
-    ASSERT(page->type() == HeapPage::kData);
-    bool page_in_use = sweeper.SweepPage(page, freelist, true /*is_locked*/);
+    bool page_in_use = sweeper.SweepPage(page, &freelist_[page->type()], true);
     if (page_in_use) {
       prev_page = page;
     } else {
@@ -1267,8 +1244,8 @@
 
 void PageSpace::ConcurrentSweep(Isolate* isolate) {
   // Start the concurrent sweeper task now.
-  GCSweeper::SweepConcurrent(isolate, pages_, pages_tail_, large_pages_,
-                             large_pages_tail_, &freelist_[HeapPage::kData]);
+  GCSweeper::SweepConcurrent(isolate, pages_, pages_tail_,
+                             &freelist_[HeapPage::kData]);
 }
 
 void PageSpace::Compact(Thread* thread) {
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 417e14d..83ca216 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -479,19 +479,10 @@
 
   // Makes bump block walkable; do not call concurrently with mutator.
   void MakeIterable() const;
-
-  void AddPageLocked(HeapPage* page);
-  void AddLargePageLocked(HeapPage* page);
-  void AddExecPageLocked(HeapPage* page);
-  void RemovePageLocked(HeapPage* page, HeapPage* previous_page);
-  void RemoveLargePageLocked(HeapPage* page, HeapPage* previous_page);
-  void RemoveExecPageLocked(HeapPage* page, HeapPage* previous_page);
-
   HeapPage* AllocatePage(HeapPage::PageType type, bool link = true);
-  HeapPage* AllocateLargePage(intptr_t size, HeapPage::PageType type);
-
-  void TruncateLargePage(HeapPage* page, intptr_t new_object_size_in_bytes);
   void FreePage(HeapPage* page, HeapPage* previous_page);
+  HeapPage* AllocateLargePage(intptr_t size, HeapPage::PageType type);
+  void TruncateLargePage(HeapPage* page, intptr_t new_object_size_in_bytes);
   void FreeLargePage(HeapPage* page, HeapPage* previous_page);
   void FreePages(HeapPage* pages);
 
@@ -499,8 +490,7 @@
                                  bool finalize,
                                  int64_t pre_wait_for_sweepers,
                                  int64_t pre_safe_point);
-  void SweepLarge();
-  void Sweep();
+  void BlockingSweep();
   void ConcurrentSweep(Isolate* isolate);
   void Compact(Thread* thread);
 
@@ -523,13 +513,12 @@
 
   // Use ExclusivePageIterator for safe access to these.
   mutable Mutex pages_lock_;
-  HeapPage* pages_ = nullptr;
-  HeapPage* pages_tail_ = nullptr;
-  HeapPage* exec_pages_ = nullptr;
-  HeapPage* exec_pages_tail_ = nullptr;
-  HeapPage* large_pages_ = nullptr;
-  HeapPage* large_pages_tail_ = nullptr;
-  HeapPage* image_pages_ = nullptr;
+  HeapPage* pages_;
+  HeapPage* pages_tail_;
+  HeapPage* exec_pages_;
+  HeapPage* exec_pages_tail_;
+  HeapPage* large_pages_;
+  HeapPage* image_pages_;
 
   // A block of memory in a data page, managed by bump allocation. The remainder
   // is kept formatted as a FreeListElement, but is not in any freelist.
diff --git a/runtime/vm/heap/sweeper.cc b/runtime/vm/heap/sweeper.cc
index 2786390..fa294d9 100644
--- a/runtime/vm/heap/sweeper.cc
+++ b/runtime/vm/heap/sweeper.cc
@@ -110,15 +110,11 @@
                         PageSpace* old_space,
                         HeapPage* first,
                         HeapPage* last,
-                        HeapPage* large_first,
-                        HeapPage* large_last,
                         FreeList* freelist)
       : task_isolate_(isolate),
         old_space_(old_space),
         first_(first),
         last_(last),
-        large_first_(large_first),
-        large_last_(large_last),
         freelist_(freelist) {
     ASSERT(task_isolate_ != NULL);
     ASSERT(first_ != NULL);
@@ -136,35 +132,14 @@
     ASSERT(result);
     {
       Thread* thread = Thread::Current();
-      ASSERT(thread->BypassSafepoints());  // Or we should be checking in.
       TIMELINE_FUNCTION_GC_DURATION(thread, "ConcurrentSweep");
       GCSweeper sweeper;
 
-      HeapPage* page = large_first_;
+      HeapPage* page = first_;
       HeapPage* prev_page = NULL;
-      while (page != NULL) {
-        HeapPage* next_page;
-        if (page == large_last_) {
-          // Don't access page->next(), which would be a race with mutator
-          // allocating new pages.
-          next_page = NULL;
-        } else {
-          next_page = page->next();
-        }
-        ASSERT(page->type() == HeapPage::kData);
-        const intptr_t words_to_end = sweeper.SweepLargePage(page);
-        if (words_to_end == 0) {
-          old_space_->FreeLargePage(page, prev_page);
-        } else {
-          old_space_->TruncateLargePage(page, words_to_end << kWordSizeLog2);
-          prev_page = page;
-        }
-        page = next_page;
-      }
 
-      page = first_;
-      prev_page = NULL;
       while (page != NULL) {
+        ASSERT(thread->BypassSafepoints());  // Or we should be checking in.
         HeapPage* next_page;
         if (page == last_) {
           // Don't access page->next(), which would be a race with mutator
@@ -206,20 +181,15 @@
   PageSpace* old_space_;
   HeapPage* first_;
   HeapPage* last_;
-  HeapPage* large_first_;
-  HeapPage* large_last_;
   FreeList* freelist_;
 };
 
 void GCSweeper::SweepConcurrent(Isolate* isolate,
                                 HeapPage* first,
                                 HeapPage* last,
-                                HeapPage* large_first,
-                                HeapPage* large_last,
                                 FreeList* freelist) {
   bool result = Dart::thread_pool()->Run<ConcurrentSweeperTask>(
-      isolate, isolate->heap()->old_space(), first, last, large_first,
-      large_last, freelist);
+      isolate, isolate->heap()->old_space(), first, last, freelist);
   ASSERT(result);
 }
 
diff --git a/runtime/vm/heap/sweeper.h b/runtime/vm/heap/sweeper.h
index 068a30d..609b962 100644
--- a/runtime/vm/heap/sweeper.h
+++ b/runtime/vm/heap/sweeper.h
@@ -38,8 +38,6 @@
   static void SweepConcurrent(Isolate* isolate,
                               HeapPage* first,
                               HeapPage* last,
-                              HeapPage* large_first,
-                              HeapPage* large_last,
                               FreeList* freelist);
 };
 
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index d739365..2061521 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,7 +20,7 @@
 
 // Both version numbers are inclusive.
 static const uint32_t kMinSupportedKernelFormatVersion = 29;
-static const uint32_t kMaxSupportedKernelFormatVersion = 36;
+static const uint32_t kMaxSupportedKernelFormatVersion = 37;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 8564b07..419a241 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -93,6 +93,11 @@
 DECLARE_FLAG(bool, precompiled_mode);
 DECLARE_FLAG(int, max_polymorphic_checks);
 
+DEFINE_FLAG(bool,
+            unbox_numeric_fields,
+            true,
+            "Support unboxed double and float32x4 fields.");
+
 static const char* const kGetterPrefix = "get:";
 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
 static const char* const kSetterPrefix = "set:";
@@ -8637,6 +8642,27 @@
   }
 }
 
+void Instance::SetField(const Field& field, const Object& value) const {
+  field.RecordStore(value);
+  const Object* stored_value = field.CloneForUnboxed(value);
+  StorePointer(FieldAddr(field), stored_value->raw());
+}
+
+const Object* Field::CloneForUnboxed(const Object& value) const {
+  if (FLAG_unbox_numeric_fields && is_unboxing_candidate() && !is_nullable()) {
+    switch (guarded_cid()) {
+      case kDoubleCid:
+      case kFloat32x4Cid:
+      case kFloat64x2Cid:
+        return &Object::Handle(Object::Clone(value, Heap::kNew));
+      default:
+        // Not a supported unboxed field type.
+        return &value;
+    }
+  }
+  return &value;
+}
+
 void Field::SetOriginal(const Field& value) const {
   ASSERT(value.IsOriginal());
   ASSERT(!value.IsNull());
@@ -8828,7 +8854,7 @@
   result.set_end_token_pos(end_token_pos);
   result.set_has_nontrivial_initializer(false);
   result.set_has_initializer(false);
-  result.set_is_unboxing_candidate(!is_final && !is_late);
+  result.set_is_unboxing_candidate(!is_final && !is_late && !is_static);
   result.set_initializer_changed_after_initialization(false);
   NOT_IN_PRECOMPILED(result.set_is_declared_in_bytecode(false));
   NOT_IN_PRECOMPILED(result.set_binary_declaration_offset(0));
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index c36d28c..e0bcdb9 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -3857,6 +3857,10 @@
   void set_type_test_cache(const SubtypeTestCache& cache) const;
 #endif
 
+  // Unboxed fields require exclusive ownership of the box.
+  // Ensure this by cloning the box if necessary.
+  const Object* CloneForUnboxed(const Object& value) const;
+
  private:
   static void InitializeNew(const Field& result,
                             const String& name,
@@ -5353,18 +5357,6 @@
     }
   }
 
-  static intptr_t function_entry_point_offset(EntryKind kind) {
-    switch (kind) {
-      case EntryKind::kNormal:
-        return Function::entry_point_offset();
-      case EntryKind::kUnchecked:
-        return Function::unchecked_entry_point_offset();
-      default:
-        ASSERT(false && "Invalid entry kind.");
-        UNREACHABLE();
-    }
-  }
-
   RawObjectPool* object_pool() const { return raw_ptr()->object_pool_; }
   static intptr_t object_pool_offset() {
     return OFFSET_OF(RawCode, object_pool_);
@@ -6522,10 +6514,7 @@
 
   RawObject* GetField(const Field& field) const { return *FieldAddr(field); }
 
-  void SetField(const Field& field, const Object& value) const {
-    field.RecordStore(value);
-    StorePointer(FieldAddr(field), value.raw());
-  }
+  void SetField(const Field& field, const Object& value) const;
 
   RawAbstractType* GetType(Heap::Space space) const;
 
diff --git a/samples/ffi/sample_ffi_functions.dart b/samples/ffi/sample_ffi_functions.dart
index 72db3eb..ed641e9 100644
--- a/samples/ffi/sample_ffi_functions.dart
+++ b/samples/ffi/sample_ffi_functions.dart
@@ -20,6 +20,8 @@
 typedef NativeFloatUnaryOp = Float Function(Float);
 typedef NativeDecenaryOp = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr,
     IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
+typedef NativeDecenaryOp2 = Int16 Function(
+    Int8, Int16, Int8, Int16, Int8, Int16, Int8, Int16, Int8, Int16);
 typedef NativeDoubleDecenaryOp = Double Function(Double, Double, Double, Double,
     Double, Double, Double, Double, Double, Double);
 typedef NativeVigesimalOp = Double Function(
@@ -150,6 +152,15 @@
   }
 
   {
+    // Function with many arguments: arguments get passed in registers and stack.
+    DecenaryOp sumManyInts = ffiTestFunctions
+        .lookupFunction<NativeDecenaryOp2, DecenaryOp>("SumManySmallInts");
+    var result = sumManyInts(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+    print(result);
+    print(result.runtimeType);
+  }
+
+  {
     // Function with many double arguments.
     DoubleDecenaryOp sumManyDoubles = ffiTestFunctions.lookupFunction<
         NativeDoubleDecenaryOp, DoubleDecenaryOp>("SumManyDoubles");
diff --git a/sdk/lib/_internal/js_dev_runtime/libraries.dart b/sdk/lib/_internal/js_dev_runtime/libraries.dart
index 283133c..88b2efa 100644
--- a/sdk/lib/_internal/js_dev_runtime/libraries.dart
+++ b/sdk/lib/_internal/js_dev_runtime/libraries.dart
@@ -91,7 +91,7 @@
       maturity: Maturity.STABLE,
       platforms: DART2JS_PLATFORM,
       dart2jsPatchPath: "_internal/js_runtime/lib/js_patch.dart"),
-  "js_util": const LibraryInfo("js_util/dart2js/js_util_dart2js.dart",
+  "js_util": const LibraryInfo("js_util/js_util.dart",
       categories: "Client",
       maturity: Maturity.STABLE,
       platforms: DART2JS_PLATFORM),
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
index af9ae7d..0d8628d 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
@@ -553,6 +553,12 @@
   }
 
   @patch
+  factory List.of(Iterable<E> elements, {bool growable = true}) {
+    // TODO(32937): Specialize to benefit from known element type.
+    return List.from(elements, growable: growable);
+  }
+
+  @patch
   factory List.unmodifiable(Iterable elements) {
     var list = List<E>.from(elements);
     JSArray.markUnmodifiableList(list);
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 2f9c880..5a80b9b 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -441,6 +441,12 @@
   }
 
   @patch
+  factory List.of(Iterable<E> elements, {bool growable: true}) {
+    // TODO(32937): Specialize to benefit from known element type.
+    return List.from(elements, growable: growable);
+  }
+
+  @patch
   factory List.unmodifiable(Iterable elements) {
     List result = new List<E>.from(elements, growable: false);
     return makeFixedListUnmodifiable(result);
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index d86d322..2975bdc 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -101,7 +101,7 @@
       dart2jsPatchPath: "js/_js_client.dart",
       documented: false,
       platforms: DART2JS_PLATFORM),
-  "js_util": const LibraryInfo("js_util/dart2js/js_util_dart2js.dart",
+  "js_util": const LibraryInfo("js_util/js_util.dart",
       categories: "Client",
       maturity: Maturity.STABLE,
       platforms: DART2JS_PLATFORM),
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/sdk/lib/_internal/vm/bin/vmservice_io.dart
similarity index 99%
rename from runtime/bin/vmservice/vmservice_io.dart
rename to sdk/lib/_internal/vm/bin/vmservice_io.dart
index 46fb27e..29fa6db 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/sdk/lib/_internal/vm/bin/vmservice_io.dart
@@ -14,7 +14,7 @@
 import 'dart:typed_data';
 import 'dart:_vmservice';
 
-part 'server.dart';
+part 'vmservice_server.dart';
 
 // The TCP ip/port that the HTTP server listens on.
 @pragma("vm:entry-point")
diff --git a/runtime/bin/vmservice/server.dart b/sdk/lib/_internal/vm/bin/vmservice_server.dart
similarity index 98%
rename from runtime/bin/vmservice/server.dart
rename to sdk/lib/_internal/vm/bin/vmservice_server.dart
index e3388a8a..46ac1e2 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/sdk/lib/_internal/vm/bin/vmservice_server.dart
@@ -379,7 +379,7 @@
       'uri': serverAddress.toString(),
     };
     final file = File.fromUri(Uri.parse(_serviceInfoFilename));
-    file.writeAsString(json.encode(serviceInfo));
+    return file.writeAsString(json.encode(serviceInfo));
   }
 
   Future startup() async {
@@ -440,7 +440,7 @@
       new File(path)..createSync(recursive: true);
     }
     if (_serviceInfoFilename != null && _serviceInfoFilename.isNotEmpty) {
-      _dumpServiceInfoToFile();
+      await _dumpServiceInfoToFile();
     }
     // Server is up and running.
     _notifyServerState(serverAddress.toString());
diff --git a/sdk/lib/_internal/vm/lib/array_patch.dart b/sdk/lib/_internal/vm/lib/array_patch.dart
index 26e6865..fff0490 100644
--- a/sdk/lib/_internal/vm/lib/array_patch.dart
+++ b/sdk/lib/_internal/vm/lib/array_patch.dart
@@ -60,6 +60,12 @@
   }
 
   @patch
+  factory List.of(Iterable<E> elements, {bool growable: true}) {
+    // TODO(32937): Specialize to benefit from known element type.
+    return List.from(elements, growable: growable);
+  }
+
+  @patch
   factory List.unmodifiable(Iterable elements) {
     final result = new List<E>.from(elements, growable: false);
     return makeFixedListUnmodifiable(result);
diff --git a/sdk/lib/_internal/vm/lib/mirrors_impl.dart b/sdk/lib/_internal/vm/lib/mirrors_impl.dart
index 8101907..0bad369 100644
--- a/sdk/lib/_internal/vm/lib/mirrors_impl.dart
+++ b/sdk/lib/_internal/vm/lib/mirrors_impl.dart
@@ -14,9 +14,13 @@
   String toString() => _msg;
 }
 
-String _n(Symbol symbol) => internal.Symbol.getName(symbol);
+String _n(Symbol symbol) => internal.Symbol.getName(symbol as internal.Symbol);
 
 Symbol _s(String name) {
+  return new internal.Symbol.unvalidated(name);
+}
+
+Symbol _sOpt(String name) {
   if (name == null) return null;
   return new internal.Symbol.unvalidated(name);
 }
@@ -67,6 +71,14 @@
 
 List<dynamic> _metadata(reflectee) native 'DeclarationMirror_metadata';
 
+List<InstanceMirror> _wrapMetadata(List reflectees) {
+  var mirrors = new List<InstanceMirror>();
+  for (var reflectee in reflectees) {
+    mirrors.add(reflect(reflectee));
+  }
+  return new UnmodifiableListView<InstanceMirror>(mirrors);
+}
+
 bool _subtypeTest(Type a, Type b) native 'TypeMirror_subtypeTest';
 
 class _MirrorSystem extends MirrorSystem {
@@ -90,10 +102,9 @@
 
   IsolateMirror _isolate;
   IsolateMirror get isolate {
-    if (_isolate == null) {
-      _isolate = _computeIsolate();
-    }
-    return _isolate;
+    var i = _isolate;
+    if (i != null) return i;
+    return _isolate = _computeIsolate();
   }
 
   static IsolateMirror _computeIsolate() native "MirrorSystem_isolate";
@@ -267,12 +278,12 @@
 
   ClassMirror _type;
   ClassMirror get type {
-    if (_type == null) {
-      // Note it not safe to use reflectee.runtimeType because runtimeType may
-      // be overridden.
-      _type = reflectType(_computeType(reflectee));
-    }
-    return _type;
+    var t = _type;
+    if (t != null) return t;
+
+    // Note it not safe to use reflectee.runtimeType because runtimeType may
+    // be overridden.
+    return _type = reflectType(_computeType(reflectee)) as ClassMirror;
   }
 
   // LocalInstanceMirrors always reflect local instances
@@ -339,14 +350,13 @@
 
   MethodMirror _function;
   MethodMirror get function {
-    if (_function == null) {
-      _function = _computeFunction(reflectee);
-    }
-    return _function;
+    var f = _function;
+    if (f != null) return f;
+    return _function = _computeFunction(reflectee);
   }
 
-  InstanceMirror apply(List<Object> positionalArguments,
-      [Map<Symbol, Object> namedArguments]) {
+  InstanceMirror apply(List positionalArguments,
+      [Map<Symbol, dynamic> namedArguments]) {
     return this.invoke(#call, positionalArguments, namedArguments);
   }
 
@@ -385,7 +395,7 @@
       this._isTransformedMixinApplication,
       this._isGenericDeclaration,
       this.isEnum)
-      : this._simpleName = _s(simpleName),
+      : this._simpleName = _sOpt(simpleName),
         this._reflectedType = reflectedType,
         this._instantiator = reflectedType,
         super._(reflectee);
@@ -401,26 +411,26 @@
 
   Symbol get simpleName {
     // All but anonymous mixin applications have their name set at construction.
-    if (_simpleName == null) {
-      _simpleName = this._mixinApplicationName;
-    }
-    return _simpleName;
+    var n = _simpleName;
+    if (n != null) return n;
+
+    return _simpleName = this._mixinApplicationName;
   }
 
   Symbol _qualifiedName;
   Symbol get qualifiedName {
-    if (_qualifiedName == null) {
-      _qualifiedName = _computeQualifiedName(owner, simpleName);
-    }
-    return _qualifiedName;
+    var n = _qualifiedName;
+    if (n != null) return n;
+
+    return _qualifiedName = _computeQualifiedName(owner, simpleName);
   }
 
   DeclarationMirror get owner {
-    if (_owner == null) {
-      var uri = _ClassMirror._libraryUri(_reflectee);
-      _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
-    }
-    return _owner;
+    var o = _owner;
+    if (o != null) return o;
+
+    var uri = _ClassMirror._libraryUri(_reflectee);
+    return _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
   }
 
   bool get isPrivate => _n(simpleName).startsWith('_');
@@ -441,8 +451,9 @@
         // Object has no superclass.
         return null;
       }
-      _trueSuperclassField = reflectType(supertype);
-      _trueSuperclassField._instantiator = _instantiator;
+      var supertypeMirror = reflectType(supertype) as _ClassMirror;
+      supertypeMirror._instantiator = _instantiator;
+      _trueSuperclassField = supertypeMirror;
     }
     return _trueSuperclassField;
   }
@@ -453,108 +464,112 @@
 
   var _superinterfaces;
   List<ClassMirror> get superinterfaces {
-    if (_superinterfaces == null) {
-      var interfaceTypes = isOriginalDeclaration
-          ? _nativeInterfaces(_reflectedType)
-          : _nativeInterfacesInstantiated(_reflectedType);
-      if (_isTransformedMixinApplication) {
-        interfaceTypes = interfaceTypes.sublist(0, interfaceTypes.length - 1);
-      }
-      var interfaceMirrors = new List<ClassMirror>();
-      for (var interfaceType in interfaceTypes) {
-        interfaceMirrors.add(reflectType(interfaceType));
-      }
-      _superinterfaces =
-          new UnmodifiableListView<ClassMirror>(interfaceMirrors);
+    var i = _superinterfaces;
+    if (i != null) return i;
+
+    var interfaceTypes = isOriginalDeclaration
+        ? _nativeInterfaces(_reflectedType)
+        : _nativeInterfacesInstantiated(_reflectedType);
+    if (_isTransformedMixinApplication) {
+      interfaceTypes = interfaceTypes.sublist(0, interfaceTypes.length - 1);
     }
-    return _superinterfaces;
+    var interfaceMirrors = new List<ClassMirror>();
+    for (var interfaceType in interfaceTypes) {
+      interfaceMirrors.add(reflectType(interfaceType) as ClassMirror);
+    }
+    return _superinterfaces =
+        new UnmodifiableListView<ClassMirror>(interfaceMirrors);
   }
 
-  get _mixinApplicationName {
+  Symbol get _mixinApplicationName {
     var mixins = new List<ClassMirror>();
     var klass = this;
     while (_nativeMixin(klass._reflectedType) != null) {
       mixins.add(klass.mixin);
-      klass = klass.superclass;
+      klass = klass.superclass as _ClassMirror;
     }
     return _s(_n(klass.qualifiedName) +
         ' with ' +
-        mixins.reversed.map((m) => _n(m.qualifiedName)).join(', '));
+        mixins.reversed.map((ClassMirror m) => _n(m.qualifiedName)).join(', '));
   }
 
-  var _mixin;
+  ClassMirror _mixin;
   ClassMirror get mixin {
-    if (_mixin == null) {
-      Type mixinType = _nativeMixinInstantiated(_reflectedType, _instantiator);
-      if (mixinType == null) {
-        // The reflectee is not a mixin application.
-        _mixin = this;
-      } else {
-        _mixin = reflectType(mixinType);
-      }
+    var m = _mixin;
+    if (m != null) return m;
+
+    Type mixinType = _nativeMixinInstantiated(_reflectedType, _instantiator);
+    if (mixinType == null) {
+      // The reflectee is not a mixin application.
+      return _mixin = this;
+    } else {
+      return _mixin = reflectType(mixinType) as ClassMirror;
     }
-    return _mixin;
   }
 
   var _cachedStaticMembers;
   Map<Symbol, MethodMirror> get staticMembers {
-    if (_cachedStaticMembers == null) {
-      var result = new Map<Symbol, MethodMirror>();
-      declarations.values.forEach((decl) {
-        if (decl is MethodMirror && decl.isStatic && !decl.isConstructor) {
-          result[decl.simpleName] = decl;
+    var m = _cachedStaticMembers;
+    if (m != null) m;
+
+    var result = new Map<Symbol, MethodMirror>();
+    var library = this.owner as LibraryMirror;
+    declarations.values.forEach((decl) {
+      if (decl is MethodMirror && decl.isStatic && !decl.isConstructor) {
+        result[decl.simpleName] = decl;
+      }
+      if (decl is VariableMirror && decl.isStatic) {
+        var getterName = decl.simpleName;
+        result[getterName] =
+            new _SyntheticAccessor(this, getterName, true, true, false, decl);
+        if (!decl.isFinal) {
+          var setterName = _asSetter(decl.simpleName, library);
+          result[setterName] = new _SyntheticAccessor(
+              this, setterName, false, true, false, decl);
         }
-        if (decl is VariableMirror && decl.isStatic) {
-          var getterName = decl.simpleName;
-          result[getterName] =
-              new _SyntheticAccessor(this, getterName, true, true, false, decl);
-          if (!decl.isFinal) {
-            var setterName = _asSetter(decl.simpleName, this.owner);
-            result[setterName] = new _SyntheticAccessor(
-                this, setterName, false, true, false, decl);
-          }
-        }
-      });
-      _cachedStaticMembers =
-          new UnmodifiableMapView<Symbol, MethodMirror>(result);
-    }
-    return _cachedStaticMembers;
+      }
+    });
+    return _cachedStaticMembers =
+        new UnmodifiableMapView<Symbol, MethodMirror>(result);
   }
 
   var _cachedInstanceMembers;
   Map<Symbol, MethodMirror> get instanceMembers {
-    if (_cachedInstanceMembers == null) {
-      var result = new Map<Symbol, MethodMirror>();
-      if (superclass != null) {
-        result.addAll(superclass.instanceMembers);
-      }
-      declarations.values.forEach((decl) {
-        if (decl is MethodMirror &&
-            !decl.isStatic &&
-            !decl.isConstructor &&
-            !decl.isAbstract) {
-          result[decl.simpleName] = decl;
-        }
-        if (decl is VariableMirror && !decl.isStatic) {
-          var getterName = decl.simpleName;
-          result[getterName] = new _SyntheticAccessor(
-              this, getterName, true, false, false, decl);
-          if (!decl.isFinal) {
-            var setterName = _asSetter(decl.simpleName, this.owner);
-            result[setterName] = new _SyntheticAccessor(
-                this, setterName, false, false, false, decl);
-          }
-        }
-      });
-      _cachedInstanceMembers =
-          new UnmodifiableMapView<Symbol, MethodMirror>(result);
+    var m = _cachedInstanceMembers;
+    if (m != null) return m;
+
+    var result = new Map<Symbol, MethodMirror>();
+    var library = this.owner as LibraryMirror;
+    var sup = superclass;
+    if (sup != null) {
+      result.addAll(sup.instanceMembers);
     }
-    return _cachedInstanceMembers;
+    declarations.values.forEach((decl) {
+      if (decl is MethodMirror &&
+          !decl.isStatic &&
+          !decl.isConstructor &&
+          !decl.isAbstract) {
+        result[decl.simpleName] = decl;
+      }
+      if (decl is VariableMirror && !decl.isStatic) {
+        var getterName = decl.simpleName;
+        result[getterName] =
+            new _SyntheticAccessor(this, getterName, true, false, false, decl);
+        if (!decl.isFinal) {
+          var setterName = _asSetter(decl.simpleName, library);
+          result[setterName] = new _SyntheticAccessor(
+              this, setterName, false, false, false, decl);
+        }
+      }
+    });
+    return _cachedInstanceMembers =
+        new UnmodifiableMapView<Symbol, MethodMirror>(result);
   }
 
   Map<Symbol, DeclarationMirror> _declarations;
   Map<Symbol, DeclarationMirror> get declarations {
-    if (_declarations != null) return _declarations;
+    var d = _declarations;
+    if (d != null) return d;
 
     var decls = new Map<Symbol, DeclarationMirror>();
 
@@ -586,37 +601,37 @@
 
   List<TypeVariableMirror> _typeVariables;
   List<TypeVariableMirror> get typeVariables {
-    if (_typeVariables == null) {
-      if (!_isTransformedMixinApplication && _isAnonymousMixinApplication) {
-        return _typeVariables = const <TypeVariableMirror>[];
-      }
-      _typeVariables = new List<TypeVariableMirror>();
+    var v = _typeVariables;
+    if (v != null) return v;
 
-      List params = _ClassMirror_type_variables(_reflectee);
-      ClassMirror owner = originalDeclaration;
-      var mirror;
-      for (var i = 0; i < params.length; i += 2) {
-        mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
-        _typeVariables.add(mirror);
-      }
-      _typeVariables =
-          new UnmodifiableListView<TypeVariableMirror>(_typeVariables);
+    if (!_isTransformedMixinApplication && _isAnonymousMixinApplication) {
+      return _typeVariables = const <TypeVariableMirror>[];
     }
-    return _typeVariables;
+    var result = new List<TypeVariableMirror>();
+
+    List params = _ClassMirror_type_variables(_reflectee);
+    ClassMirror owner = originalDeclaration;
+    var mirror;
+    for (var i = 0; i < params.length; i += 2) {
+      mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
+      result.add(mirror);
+    }
+    return _typeVariables =
+        new UnmodifiableListView<TypeVariableMirror>(result);
   }
 
   List<TypeMirror> _typeArguments;
   List<TypeMirror> get typeArguments {
-    if (_typeArguments == null) {
-      if (_isGenericDeclaration ||
-          (!_isTransformedMixinApplication && _isAnonymousMixinApplication)) {
-        _typeArguments = const <TypeMirror>[];
-      } else {
-        _typeArguments = new UnmodifiableListView<TypeMirror>(
-            _computeTypeArguments(_reflectedType).cast<TypeMirror>());
-      }
+    var a = _typeArguments;
+    if (a != null) return a;
+
+    if (_isGenericDeclaration ||
+        (!_isTransformedMixinApplication && _isAnonymousMixinApplication)) {
+      return _typeArguments = const <TypeMirror>[];
+    } else {
+      return _typeArguments = new UnmodifiableListView<TypeMirror>(
+          _computeTypeArguments(_reflectedType).cast<TypeMirror>());
     }
-    return _typeArguments;
   }
 
   bool get isOriginalDeclaration => !_isGeneric || _isGenericDeclaration;
@@ -655,10 +670,7 @@
   }
 
   List<InstanceMirror> get metadata {
-    // Get the metadata objects, convert them into InstanceMirrors using
-    // reflect() and then make them into a Dart list.
-    return new UnmodifiableListView<InstanceMirror>(
-        _metadata(_reflectee).map(reflect));
+    return _wrapMetadata(_metadata(_reflectee));
   }
 
   bool operator ==(other) {
@@ -686,12 +698,12 @@
 
   bool isSubclassOf(ClassMirror other) {
     if (other is! ClassMirror) throw new ArgumentError(other);
-    ClassMirror otherDeclaration = other.originalDeclaration;
+    ClassMirror otherDeclaration = other.originalDeclaration as ClassMirror;
     ClassMirror c = this;
     while (c != null) {
-      c = c.originalDeclaration;
+      c = c.originalDeclaration as ClassMirror;
       if (c == otherDeclaration) return true;
-      c = c.superclass;
+      c = c.superclass as ClassMirror;
     }
     return false;
   }
@@ -748,45 +760,41 @@
   // FunctionTypeMirrors have a simpleName generated from their signature.
   Symbol _simpleName;
   Symbol get simpleName {
-    if (_simpleName == null) {
-      _simpleName = _s(_makeSignatureString(returnType, parameters));
-    }
-    return _simpleName;
+    var n = _simpleName;
+    if (n != null) return n;
+    return _simpleName = _s(_makeSignatureString(returnType, parameters));
   }
 
   MethodMirror _callMethod;
   MethodMirror get callMethod {
-    if (_callMethod == null) {
-      _callMethod = _FunctionTypeMirror_call_method(_functionReflectee);
-    }
-    return _callMethod;
+    var m = _callMethod;
+    if (m != null) return m;
+    return _callMethod = _FunctionTypeMirror_call_method(_functionReflectee);
   }
 
   TypeMirror _returnType;
   TypeMirror get returnType {
-    if (_returnType == null) {
-      _returnType =
-          reflectType(_FunctionTypeMirror_return_type(_functionReflectee));
-    }
-    return _returnType;
+    var t = _returnType;
+    if (t != null) return t;
+    return _returnType =
+        reflectType(_FunctionTypeMirror_return_type(_functionReflectee));
   }
 
   List<ParameterMirror> _parameters;
   List<ParameterMirror> get parameters {
-    if (_parameters == null) {
-      _parameters = _FunctionTypeMirror_parameters(_functionReflectee)
-          .cast<ParameterMirror>();
-      _parameters = new UnmodifiableListView<ParameterMirror>(_parameters);
-    }
-    return _parameters;
+    var p = _parameters;
+    if (p != null) return p;
+    return _parameters = new UnmodifiableListView<ParameterMirror>(
+        _FunctionTypeMirror_parameters(_functionReflectee)
+            .cast<ParameterMirror>());
   }
 
   bool get isOriginalDeclaration => true;
   ClassMirror get originalDeclaration => this;
-  get typeVariables => const <TypeVariableMirror>[];
-  get typeArguments => const <TypeMirror>[];
-  get metadata => const <InstanceMirror>[];
-  get location => null;
+  List<TypeVariableMirror> get typeVariables => const <TypeVariableMirror>[];
+  List<TypeMirror> get typeArguments => const <TypeMirror>[];
+  List<InstanceMirror> get metadata => const <InstanceMirror>[];
+  SourceLocation get location => null;
 
   String toString() => "FunctionTypeMirror on '${_n(simpleName)}'";
 
@@ -810,10 +818,9 @@
 
   Symbol _qualifiedName;
   Symbol get qualifiedName {
-    if (_qualifiedName == null) {
-      _qualifiedName = _computeQualifiedName(owner, simpleName);
-    }
-    return _qualifiedName;
+    var n = _qualifiedName;
+    if (n != null) return n;
+    return _qualifiedName = _computeQualifiedName(owner, simpleName);
   }
 
   bool get isPrivate => _n(simpleName).startsWith('_');
@@ -823,10 +830,7 @@
   }
 
   List<InstanceMirror> get metadata {
-    // Get the metadata objects, convert them into InstanceMirrors using
-    // reflect() and then make them into a Dart list.
-    return new UnmodifiableListView<InstanceMirror>(
-        _metadata(_reflectee).map(reflect));
+    return _wrapMetadata(_metadata(_reflectee));
   }
 
   bool operator ==(other) {
@@ -844,11 +848,10 @@
 
   DeclarationMirror _owner;
   DeclarationMirror get owner {
-    if (_owner == null) {
-      _owner = (_TypeVariableMirror_owner(_reflectee) as TypeMirror)
-          .originalDeclaration;
-    }
-    return _owner;
+    var o = _owner;
+    if (o != null) return o;
+    return _owner = (_TypeVariableMirror_owner(_reflectee) as TypeMirror)
+        .originalDeclaration;
   }
 
   bool get isStatic => false;
@@ -856,10 +859,10 @@
 
   TypeMirror _upperBound;
   TypeMirror get upperBound {
-    if (_upperBound == null) {
-      _upperBound = reflectType(_TypeVariableMirror_upper_bound(_reflectee));
-    }
-    return _upperBound;
+    var b = _upperBound;
+    if (b != null) return b;
+    return _upperBound =
+        reflectType(_TypeVariableMirror_upper_bound(_reflectee));
   }
 
   bool get hasReflectedType => false;
@@ -877,7 +880,7 @@
 
   String toString() => "TypeVariableMirror on '${_n(simpleName)}'";
 
-  operator ==(other) {
+  bool operator ==(other) {
     return other is TypeVariableMirror &&
         simpleName == other.simpleName &&
         owner == other.owner;
@@ -920,20 +923,19 @@
 
   DeclarationMirror _owner;
   DeclarationMirror get owner {
-    if (_owner == null) {
-      var uri = _ClassMirror._libraryUri(_reflectee);
-      _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
-    }
-    return _owner;
+    var o = _owner;
+    if (o != null) return o;
+    var uri = _ClassMirror._libraryUri(_reflectee);
+    return _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
   }
 
   _FunctionTypeMirror _referent;
   FunctionTypeMirror get referent {
-    if (_referent == null) {
-      _referent = _nativeReferent(_reflectedType);
-      _referent._instantiator = _reflectedType;
-    }
-    return _referent;
+    var r = _referent;
+    if (r != null) return r;
+    var result = _nativeReferent(_reflectedType) as _FunctionTypeMirror;
+    result._instantiator = _reflectedType;
+    return _referent = result;
   }
 
   bool get hasReflectedType => !_isGenericDeclaration;
@@ -957,31 +959,33 @@
 
   List<TypeVariableMirror> _typeVariables;
   List<TypeVariableMirror> get typeVariables {
-    if (_typeVariables == null) {
-      _typeVariables = new List<TypeVariableMirror>();
-      List params = _ClassMirror._ClassMirror_type_variables(_reflectee);
-      TypedefMirror owner = originalDeclaration;
-      var mirror;
-      for (var i = 0; i < params.length; i += 2) {
-        mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
-        _typeVariables.add(mirror);
-      }
+    var v = _typeVariables;
+    if (v != null) return v;
+
+    var result = new List<TypeVariableMirror>();
+    List params = _ClassMirror._ClassMirror_type_variables(_reflectee);
+    TypedefMirror owner = originalDeclaration;
+    var mirror;
+    for (var i = 0; i < params.length; i += 2) {
+      mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
+      result.add(mirror);
     }
-    return _typeVariables;
+    return _typeVariables =
+        new UnmodifiableListView<TypeVariableMirror>(result);
   }
 
   List<TypeMirror> _typeArguments;
   List<TypeMirror> get typeArguments {
-    if (_typeArguments == null) {
-      if (_isGenericDeclaration) {
-        _typeArguments = const <TypeMirror>[];
-      } else {
-        _typeArguments = new UnmodifiableListView<TypeMirror>(
-            _ClassMirror._computeTypeArguments(_reflectedType)
-                .cast<TypeMirror>());
-      }
+    var a = _typeArguments;
+    if (a != null) return a;
+
+    if (_isGenericDeclaration) {
+      return _typeArguments = const <TypeMirror>[];
+    } else {
+      return _typeArguments = new UnmodifiableListView<TypeMirror>(
+          _ClassMirror._computeTypeArguments(_reflectedType)
+              .cast<TypeMirror>());
     }
-    return _typeArguments;
   }
 
   String toString() => "TypedefMirror on '${_n(simpleName)}'";
@@ -1033,7 +1037,8 @@
 
   Map<Symbol, DeclarationMirror> _declarations;
   Map<Symbol, DeclarationMirror> get declarations {
-    if (_declarations != null) return _declarations;
+    var d = _declarations;
+    if (d != null) return d;
 
     var decls = new Map<Symbol, DeclarationMirror>();
     var members = _computeMembers(_reflectee);
@@ -1050,10 +1055,7 @@
   }
 
   List<InstanceMirror> get metadata {
-    // Get the metadata objects, convert them into InstanceMirrors using
-    // reflect() and then make them into a Dart list.
-    return new UnmodifiableListView<InstanceMirror>(
-        _metadata(_reflectee).map(reflect));
+    return _wrapMetadata(_metadata(_reflectee));
   }
 
   bool operator ==(other) {
@@ -1067,12 +1069,11 @@
 
   var _cachedLibraryDependencies;
   get libraryDependencies {
-    if (_cachedLibraryDependencies == null) {
-      _cachedLibraryDependencies =
-          new UnmodifiableListView<LibraryDependencyMirror>(
-              _libraryDependencies(_reflectee).cast<LibraryDependencyMirror>());
-    }
-    return _cachedLibraryDependencies;
+    var d = _cachedLibraryDependencies;
+    if (d != null) return d;
+    return _cachedLibraryDependencies =
+        new UnmodifiableListView<LibraryDependencyMirror>(
+            _libraryDependencies(_reflectee).cast<LibraryDependencyMirror>());
   }
 
   List<dynamic> _libraryDependencies(reflectee)
@@ -1107,11 +1108,10 @@
       this.isImport,
       this.isDeferred,
       List<dynamic> unwrappedMetadata)
-      : prefix = _s(prefixString),
+      : prefix = _sOpt(prefixString),
         combinators = new UnmodifiableListView<CombinatorMirror>(
             mutableCombinators.cast<CombinatorMirror>()),
-        metadata = new UnmodifiableListView<InstanceMirror>(
-            unwrappedMetadata.map(reflect));
+        metadata = _wrapMetadata(unwrappedMetadata);
 
   bool get isExport => !isImport;
 
@@ -1200,10 +1200,9 @@
   DeclarationMirror get owner {
     // For nested closures it is possible, that the mirror for the owner has not
     // been created yet.
-    if (_owner == null) {
-      _owner = _MethodMirror_owner(_reflectee, _instantiator);
-    }
-    return _owner;
+    var o = _owner;
+    if (o != null) return o;
+    return _owner = _MethodMirror_owner(_reflectee, _instantiator);
   }
 
   bool get isPrivate =>
@@ -1213,48 +1212,47 @@
 
   TypeMirror _returnType;
   TypeMirror get returnType {
-    if (_returnType == null) {
-      if (isConstructor) {
-        _returnType = owner;
-      } else {
-        _returnType =
-            reflectType(_MethodMirror_return_type(_reflectee, _instantiator));
-      }
+    var t = _returnType;
+    if (t != null) return t;
+    if (isConstructor) {
+      return _returnType = owner as _ClassMirror;
+    } else {
+      return _returnType =
+          reflectType(_MethodMirror_return_type(_reflectee, _instantiator));
     }
-    return _returnType;
   }
 
   List<ParameterMirror> _parameters;
   List<ParameterMirror> get parameters {
-    if (_parameters == null) {
-      _parameters = new UnmodifiableListView<ParameterMirror>(
-          _MethodMirror_parameters(_reflectee).cast<ParameterMirror>());
-    }
-    return _parameters;
+    var p = _parameters;
+    if (p != null) return p;
+    return _parameters = new UnmodifiableListView<ParameterMirror>(
+        _MethodMirror_parameters(_reflectee).cast<ParameterMirror>());
   }
 
   bool get isRegularMethod => !isGetter && !isSetter && !isConstructor;
 
   Symbol _constructorName;
   Symbol get constructorName {
-    if (_constructorName == null) {
-      if (!isConstructor) {
-        _constructorName = _s('');
+    var n = _constructorName;
+    if (n != null) return n;
+
+    if (!isConstructor) {
+      return _constructorName = _s('');
+    } else {
+      var parts = MirrorSystem.getName(simpleName).split('.');
+      if (parts.length > 2) {
+        throw new _InternalMirrorError(
+            'Internal error in MethodMirror.constructorName: '
+            'malformed name <$simpleName>');
+      } else if (parts.length == 2) {
+        LibraryMirror definingLibrary = owner.owner as _LibraryMirror;
+        return _constructorName =
+            MirrorSystem.getSymbol(parts[1], definingLibrary);
       } else {
-        var parts = MirrorSystem.getName(simpleName).split('.');
-        if (parts.length > 2) {
-          throw new _InternalMirrorError(
-              'Internal error in MethodMirror.constructorName: '
-              'malformed name <$simpleName>');
-        } else if (parts.length == 2) {
-          LibraryMirror definingLibrary = owner.owner;
-          _constructorName = MirrorSystem.getSymbol(parts[1], definingLibrary);
-        } else {
-          _constructorName = _s('');
-        }
+        return _constructorName = _s('');
       }
     }
-    return _constructorName;
   }
 
   String get source => _MethodMirror_source(_reflectee);
@@ -1310,10 +1308,9 @@
 
   TypeMirror _type;
   TypeMirror get type {
-    if (_type == null) {
-      _type = reflectType(_VariableMirror_type(_reflectee, _instantiator));
-    }
-    return _type;
+    var t = _type;
+    if (t != null) return t;
+    return _type = reflectType(_VariableMirror_type(_reflectee, _instantiator));
   }
 
   String toString() =>
@@ -1369,18 +1366,17 @@
   }
 
   List<InstanceMirror> get metadata {
-    if (_unmirroredMetadata == null) return const <InstanceMirror>[];
-    return new UnmodifiableListView<InstanceMirror>(
-        _unmirroredMetadata.map(reflect));
+    var m = _unmirroredMetadata;
+    if (m == null) return const <InstanceMirror>[];
+    return _wrapMetadata(m);
   }
 
   TypeMirror _type;
   TypeMirror get type {
-    if (_type == null) {
-      _type = reflectType(
-          _ParameterMirror_type(_reflectee, _position, _instantiator));
-    }
-    return _type;
+    var t = _type;
+    if (t != null) return t;
+    return _type = reflectType(
+        _ParameterMirror_type(_reflectee, _position, _instantiator));
   }
 
   String toString() => "ParameterMirror on '${_n(simpleName)}'";
@@ -1450,7 +1446,7 @@
         : new _InstanceMirror._(reflectee);
   }
 
-  static ClassMirror _makeLocalClassMirror(Type key)
+  static _ClassMirror _makeLocalClassMirror(Type key)
       native "Mirrors_makeLocalClassMirror";
   static TypeMirror _makeLocalTypeMirror(Type key)
       native "Mirrors_makeLocalTypeMirror";
diff --git a/sdk/lib/_internal/vm/lib/mirrors_patch.dart b/sdk/lib/_internal/vm/lib/mirrors_patch.dart
index 1adbcbb..299ff50 100644
--- a/sdk/lib/_internal/vm/lib/mirrors_patch.dart
+++ b/sdk/lib/_internal/vm/lib/mirrors_patch.dart
@@ -75,7 +75,7 @@
 
   @patch
   static String getName(Symbol symbol) {
-    return internal.Symbol.computeUnmangledName(symbol);
+    return internal.Symbol.computeUnmangledName(symbol as internal.Symbol);
   }
 
   @patch
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index 9500c56..647f277 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -139,8 +139,7 @@
    * This constructor creates a growable list when [growable] is true;
    * otherwise, it returns a fixed-length list.
    */
-  factory List.of(Iterable<E> elements, {bool growable = true}) =>
-      List<E>.from(elements, growable: growable);
+  external factory List.of(Iterable<E> elements, {bool growable = true});
 
   /**
    * Generates a list of values.
@@ -729,5 +728,5 @@
   * Even if [other] is also a list, the equality comparison
   * does not compare the elements of the two lists.
   */
- bool operator ==(Object other);
+  bool operator ==(Object other);
 }
diff --git a/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart b/sdk/lib/js_util/js_util.dart
similarity index 96%
rename from sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart
rename to sdk/lib/js_util/js_util.dart
index a01a537..7718644 100644
--- a/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart
+++ b/sdk/lib/js_util/js_util.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
+// @dart = 2.6
 
 /// Utility methods to efficiently manipulate typed JSInterop objects in cases
 /// where the name to call is not known at runtime. You should only use these
@@ -30,13 +30,13 @@
 /// JavaScript type, and all other objects are proxied.
 jsify(object) {
   if ((object is! Map) && (object is! Iterable)) {
-    throw new ArgumentError("object must be a Map or Iterable");
+    throw ArgumentError("object must be a Map or Iterable");
   }
   return _convertDataTree(object);
 }
 
 _convertDataTree(data) {
-  var _convertedObjects = new HashMap.identity();
+  var _convertedObjects = HashMap.identity();
 
   _convert(o) {
     if (_convertedObjects.containsKey(o)) {
@@ -65,13 +65,16 @@
 newObject() => JS('=Object', '{}');
 
 bool hasProperty(o, name) => JS('bool', '# in #', name, o);
+
 getProperty(o, name) => JS('Object|Null', '#[#]', o, name);
+
 setProperty(o, name, value) => JS('', '#[#]=#', o, name, value);
 
 callMethod(o, String method, List args) =>
     JS('Object|Null', '#[#].apply(#, #)', o, method, o, args);
 
 bool instanceof(o, Function type) => JS('bool', '# instanceof #', o, type);
+
 callConstructor(Function constr, List arguments) {
   if (arguments == null) {
     return JS('Object', 'new #()', constr);
diff --git a/sdk/lib/js_util/js_util_sources.gni b/sdk/lib/js_util/js_util_sources.gni
index 3b7c1b1..ad6a4f0 100644
--- a/sdk/lib/js_util/js_util_sources.gni
+++ b/sdk/lib/js_util/js_util_sources.gni
@@ -2,4 +2,4 @@
 # 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.
 
-js_util_sdk_sources = [ "dart2js/js_util_dart2js.dart" ]
+js_util_sdk_sources = [ "js_util.dart", "dart2js/js_util_dart2js.dart" ]
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index f31091f..1241331 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -154,7 +154,7 @@
         "uri": "vmservice/vmservice.dart"
       },
       "vmservice_io": {
-        "uri": "../../runtime/bin/vmservice/vmservice_io.dart"
+        "uri": "_internal/vm/bin/vmservice_io.dart"
       }
     }
   },
@@ -211,7 +211,7 @@
         "patches": "js/_js_client.dart"
       },
       "js_util": {
-        "uri": "js_util/dart2js/js_util_dart2js.dart"
+        "uri": "js_util/js_util.dart"
       },
       "math": {
         "uri": "math/math.dart",
@@ -321,7 +321,7 @@
         "patches": "js/_js_server.dart"
       },
       "js_util": {
-        "uri": "js_util/dart2js/js_util_dart2js.dart"
+        "uri": "js_util/js_util.dart"
       },
       "math": {
         "uri": "math/math.dart",
@@ -468,7 +468,7 @@
         "patches": "_internal/js_dev_runtime/patch/js_patch.dart"
       },
       "js_util": {
-        "uri": "_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart"
+        "uri": "js_util/js_util.dart"
       },
       "svg": {
         "uri": "svg/dart2js/svg_dart2js.dart"
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index d4a3d8b..191c2c3 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -153,7 +153,7 @@
       uri: "vmservice/vmservice.dart"
 
     vmservice_io:
-      uri: "../../runtime/bin/vmservice/vmservice_io.dart"
+      uri: "_internal/vm/bin/vmservice_io.dart"
 
 dart2js:
   libraries:
@@ -208,7 +208,7 @@
       patches: "js/_js_client.dart"
 
     js_util:
-      uri: "js_util/dart2js/js_util_dart2js.dart"
+      uri: "js_util/js_util.dart"
 
     math:
       uri: "math/math.dart"
@@ -316,7 +316,7 @@
       patches: "js/_js_server.dart"
 
     js_util:
-      uri: "js_util/dart2js/js_util_dart2js.dart"
+      uri: "js_util/js_util.dart"
 
     math:
       uri: "math/math.dart"
@@ -461,7 +461,7 @@
         patches: "_internal/js_dev_runtime/patch/js_patch.dart"
 
       js_util:
-        uri: "_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart"
+        uri: "js_util/js_util.dart"
 
       svg:
         uri: "svg/dart2js/svg_dart2js.dart"
diff --git a/sdk/lib/vmservice_libraries.json b/sdk/lib/vmservice_libraries.json
index c25ffe5..af43f48 100644
--- a/sdk/lib/vmservice_libraries.json
+++ b/sdk/lib/vmservice_libraries.json
@@ -2,11 +2,11 @@
   "vm": {
     "libraries": {
       "vmservice_io": {
-        "uri": "../../runtime/bin/vmservice/vmservice_io.dart"
+        "uri": "_internal/vm/bin/vmservice_io.dart"
       },
       "_vmservice": {
         "uri": "vmservice/vmservice.dart"
       }
     }
   }
-}
\ No newline at end of file
+}
diff --git a/sdk/lib/vmservice_libraries.yaml b/sdk/lib/vmservice_libraries.yaml
index 737e361..169d6af 100644
--- a/sdk/lib/vmservice_libraries.yaml
+++ b/sdk/lib/vmservice_libraries.yaml
@@ -17,4 +17,4 @@
       uri: "vmservice/vmservice.dart"
 
     vmservice_io:
-      uri: "../../runtime/bin/vmservice/vmservice_io.dart"
+      uri: "_internal/vm/bin/vmservice_io.dart"
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
deleted file mode 100644
index 1cccbaa..0000000
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart = 2.5
-
-/// Utility methods to efficiently manipulate typed JSInterop objects in cases
-/// where the name to call is not known at runtime. You should only use these
-/// methods when the same effect cannot be achieved with @JS annotations.
-/// These methods would be extension methods on JSObject if Dart supported
-/// extension methods.
-library dart.js_util;
-
-import 'dart:_foreign_helper' show JS;
-import 'dart:collection' show HashMap;
-import 'dart:async' show Completer;
-import 'dart:_js_helper' show convertDartClosureToJS;
-
-/// WARNING: performance of this method is much worse than other uitil
-/// methods in this library. Only use this method as a last resort.
-///
-/// Recursively converts a JSON-like collection of Dart objects to a
-/// collection of JavaScript objects and returns a [JsObject] proxy to it.
-///
-/// [object] must be a [Map] or [Iterable], the contents of which are also
-/// converted. Maps and Iterables are copied to a new JavaScript object.
-/// Primitives and other transferrable values are directly converted to their
-/// JavaScript type, and all other objects are proxied.
-jsify(object) {
-  if ((object is! Map) && (object is! Iterable)) {
-    throw ArgumentError("object must be a Map or Iterable");
-  }
-  return _convertDataTree(object);
-}
-
-_convertDataTree(data) {
-  var _convertedObjects = HashMap.identity();
-
-  _convert(o) {
-    if (_convertedObjects.containsKey(o)) {
-      return _convertedObjects[o];
-    }
-    if (o is Map) {
-      final convertedMap = JS('=Object', '{}');
-      _convertedObjects[o] = convertedMap;
-      for (var key in o.keys) {
-        JS('=Object', '#[#]=#', convertedMap, key, _convert(o[key]));
-      }
-      return convertedMap;
-    } else if (o is Iterable) {
-      var convertedList = [];
-      _convertedObjects[o] = convertedList;
-      convertedList.addAll(o.map(_convert));
-      return convertedList;
-    } else {
-      return o;
-    }
-  }
-
-  return _convert(data);
-}
-
-newObject() => JS('=Object', '{}');
-
-hasProperty(o, name) => JS<bool>('!', '# in #', name, o);
-getProperty(o, name) => JS('Object', '#[#]', o, name);
-setProperty(o, name, value) => JS('', '#[#]=#', o, name, value);
-
-callMethod(o, String method, List args) =>
-    JS('Object', '#[#].apply(#, #)', o, method, o, args);
-
-instanceof(o, Function type) => JS<bool>('!', '# instanceof #', o, type);
-callConstructor(Function constr, List arguments) {
-  if (arguments == null) {
-    return JS('Object', 'new #()', constr);
-  }
-
-  if (JS<bool>('!', '# instanceof Array', arguments)) {
-    int argumentCount = JS('!', '#.length', arguments);
-    switch (argumentCount) {
-      case 0:
-        return JS('Object', 'new #()', constr);
-
-      case 1:
-        var arg0 = JS('', '#[0]', arguments);
-        return JS('Object', 'new #(#)', constr, arg0);
-
-      case 2:
-        var arg0 = JS('', '#[0]', arguments);
-        var arg1 = JS('', '#[1]', arguments);
-        return JS('Object', 'new #(#, #)', constr, arg0, arg1);
-
-      case 3:
-        var arg0 = JS('', '#[0]', arguments);
-        var arg1 = JS('', '#[1]', arguments);
-        var arg2 = JS('', '#[2]', arguments);
-        return JS('Object', 'new #(#, #, #)', constr, arg0, arg1, arg2);
-
-      case 4:
-        var arg0 = JS('', '#[0]', arguments);
-        var arg1 = JS('', '#[1]', arguments);
-        var arg2 = JS('', '#[2]', arguments);
-        var arg3 = JS('', '#[3]', arguments);
-        return JS(
-            'Object', 'new #(#, #, #, #)', constr, arg0, arg1, arg2, arg3);
-    }
-  }
-
-  // The following code solves the problem of invoking a JavaScript
-  // constructor with an unknown number arguments.
-  // First bind the constructor to the argument list using bind.apply().
-  // The first argument to bind() is the binding of 't', so add 'null' to
-  // the arguments list passed to apply().
-  // After that, use the JavaScript 'new' operator which overrides any binding
-  // of 'this' with the new instance.
-  var args = <dynamic>[null]..addAll(arguments);
-  var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args);
-  // Without this line, calling factoryFunction as a constructor throws
-  JS<String>('!', 'String(#)', factoryFunction);
-  // This could return an UnknownJavaScriptObject, or a native
-  // object for which there is an interceptor
-  return JS('Object', 'new #()', factoryFunction);
-
-  // TODO(sra): Investigate:
-  //
-  //     var jsObj = JS('', 'Object.create(#.prototype)', constr);
-  //     JS('', '#.apply(#, #)', constr, jsObj,
-  //         []..addAll(arguments.map(_convertToJS)));
-  //     return _wrapToDart(jsObj);
-}
-
-/// Converts a JavaScript Promise to a Dart [Future].
-///
-/// ```dart
-/// @JS()
-/// external Promise<num> get threePromise; // Resolves to 3
-///
-/// final Future<num> threeFuture = promiseToFuture(threePromise);
-///
-/// final three = await threeFuture; // == 3
-/// ```
-Future<T> promiseToFuture<T>(jsPromise) {
-  final completer = Completer<T>();
-
-  final success = convertDartClosureToJS((r) => completer.complete(r), 1);
-  final error = convertDartClosureToJS((e) => completer.completeError(e), 1);
-
-  JS('', '#.then(#, #)', jsPromise, success, error);
-  return completer.future;
-}
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart
index 1f1c981..9121353 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart
@@ -555,6 +555,12 @@
   }
 
   @patch
+  factory List.of(Iterable<E> elements, {bool growable = true}) {
+    // TODO(32937): Specialize to benefit from known element type.
+    return List.from(elements, growable: growable);
+  }
+
+  @patch
   factory List.unmodifiable(Iterable elements) {
     var list = List<E>.from(elements);
     JSArray.markUnmodifiableList(list);
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart
index 9aca3ee..b018b3f 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 // Patch library for dart:mirrors.
 
 import 'dart:_js_helper' show patch;
@@ -46,7 +44,7 @@
 }
 
 @patch
-TypeMirror reflectType(Type type, [List<Type> typeArguments]) {
+TypeMirror reflectType(Type type, [List<Type> typeArguments = const <Type>[]]) {
   if (typeArguments != null) {
     type = _instantiateClass(type, typeArguments);
   }
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index edde391..9161304 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -1494,7 +1494,7 @@
       }
     }
     for (var name in supertypeRequiredNamed.keys) {
-      var subtypeParamType = subtypeRequiredNamed[name] ?? subtypeNamed[name];
+      var subtypeParamType = subtypeRequiredNamed[name] ?? subtypeNamed[name]!;
       if (!_isSubtypeMatch(supertypeRequiredNamed[name]!, subtypeParamType)) {
         return false;
       }
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_mirrors.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_mirrors.dart
index 42db17d..4d66e7d 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_mirrors.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_mirrors.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 library dart._js_mirrors;
 
 import 'dart:mirrors';
@@ -37,7 +35,7 @@
   }
 }
 
-TypeMirror reflectType(Type key) {
+TypeMirror reflectType(Type key, [List<Type> typeArguments = const <Type>[]]) {
   var unwrapped = dart.unwrapType(key);
   var property =
       JS('', 'Object.getOwnPropertyDescriptor(#, #)', unwrapped, _typeMirror);
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/mirror_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/mirror_helper.dart
index 96d2da9..1b78136 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/mirror_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/mirror_helper.dart
@@ -1,7 +1,6 @@
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-// @dart = 2.5
 
 /**
  * Helps dealing with reflection in the case that the source code has been
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
index ce924cd..cc6e81e 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
@@ -441,6 +441,12 @@
   }
 
   @patch
+  factory List.of(Iterable<E> elements, {bool growable: true}) {
+    // TODO(32937): Specialize to benefit from known element type.
+    return List.from(elements, growable: growable);
+  }
+
+  @patch
   factory List.unmodifiable(Iterable elements) {
     List result = new List<E>.from(elements, growable: false);
     return makeFixedListUnmodifiable(result);
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
index 005b14f..40490a3 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 // Patch library for dart:mirrors.
 
 import 'dart:_js_helper' show patch;
@@ -22,5 +20,5 @@
 ClassMirror reflectClass(Type key) => throw new UnsupportedError(_message);
 
 @patch
-TypeMirror reflectType(Type key, [List<Type> typeArguments]) =>
+TypeMirror reflectType(Type key, [List<Type> typeArguments = const <Type>[]]) =>
     throw new UnsupportedError(_message);
diff --git a/sdk_nnbd/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk_nnbd/lib/_internal/sdk_library_metadata/lib/libraries.dart
index b8e584b..2b3e33c 100644
--- a/sdk_nnbd/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk_nnbd/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -101,7 +101,7 @@
       dart2jsPatchPath: "js/_js_client.dart",
       documented: false,
       platforms: DART2JS_PLATFORM),
-  "js_util": const LibraryInfo("js_util/dart2js/js_util_dart2js.dart",
+  "js_util": const LibraryInfo("js_util/js_util.dart",
       categories: "Client",
       maturity: Maturity.STABLE,
       platforms: DART2JS_PLATFORM),
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/sdk_nnbd/lib/_internal/vm/bin/vmservice_io.dart
similarity index 73%
copy from runtime/bin/vmservice/vmservice_io.dart
copy to sdk_nnbd/lib/_internal/vm/bin/vmservice_io.dart
index 46fb27e..6ab703d 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/vmservice_io.dart
@@ -2,58 +2,55 @@
 // 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
-
 library vmservice_io;
 
 import 'dart:async';
-import 'dart:collection';
 import 'dart:convert';
 import 'dart:io';
-import 'dart:isolate';
-import 'dart:typed_data';
 import 'dart:_vmservice';
 
-part 'server.dart';
+part 'vmservice_server.dart';
 
 // The TCP ip/port that the HTTP server listens on.
 @pragma("vm:entry-point")
-int _port;
+int _port = 0;
 @pragma("vm:entry-point")
-String _ip;
+String _ip = '';
 // Should the HTTP server auto start?
 @pragma("vm:entry-point")
-bool _autoStart;
+bool _autoStart = false;
 // Should the HTTP server require an auth code?
 @pragma("vm:entry-point")
-bool _authCodesDisabled;
+bool _authCodesDisabled = false;
 // Should the HTTP server run in devmode?
 @pragma("vm:entry-point")
-bool _originCheckDisabled;
+bool _originCheckDisabled = false;
 // Location of file to output VM service connection info.
 @pragma("vm:entry-point")
-String _serviceInfoFilename;
+String? _serviceInfoFilename;
 @pragma("vm:entry-point")
 bool _isWindows = false;
 @pragma("vm:entry-point")
 bool _isFuchsia = false;
 @pragma("vm:entry-point")
-var _signalWatch;
+var _signalWatch = null;
 var _signalSubscription;
 
 // HTTP server.
-Server server;
-Future<Server> serverFuture;
+Server? server;
+Future<Server>? serverFuture;
 
-_lazyServerBoot() {
+Server _lazyServerBoot() {
   if (server != null) {
-    return;
+    return server!;
   }
   // Lazily create service.
-  var service = new VMService();
+  var service = VMService();
   // Lazily create server.
-  server = new Server(service, _ip, _port, _originCheckDisabled,
+  final _server = Server(service, _ip, _port, _originCheckDisabled,
       _authCodesDisabled, _serviceInfoFilename);
+  server = _server;
+  return _server;
 }
 
 Future cleanupCallback() async {
@@ -64,13 +61,13 @@
   }
   if (server != null) {
     try {
-      await server.cleanup(true);
+      await server!.cleanup(true);
     } catch (e, st) {
       print("Error in vm-service shutdown: $e\n$st\n");
     }
   }
   if (_registerSignalHandlerTimer != null) {
-    _registerSignalHandlerTimer.cancel();
+    _registerSignalHandlerTimer!.cancel();
     _registerSignalHandlerTimer = null;
   }
   // Call out to embedder's shutdown callback.
@@ -81,37 +78,37 @@
   Directory temp = await Directory.systemTemp.createTemp(base);
   // Underneath the temporary directory, create a directory with the
   // same name as the DevFS name [base].
-  var fsUri = temp.uri.resolveUri(new Uri.directory(base));
-  await new Directory.fromUri(fsUri).create();
+  var fsUri = temp.uri.resolveUri(Uri.directory(base));
+  await Directory.fromUri(fsUri).create();
   return fsUri;
 }
 
 Future deleteDirCallback(Uri path) async {
-  Directory dir = new Directory.fromUri(path);
+  Directory dir = Directory.fromUri(path);
   await dir.delete(recursive: true);
 }
 
 class PendingWrite {
   PendingWrite(this.uri, this.bytes);
-  final Completer completer = new Completer();
+  final Completer completer = Completer();
   final Uri uri;
   final List<int> bytes;
 
   Future write() async {
-    var file = new File.fromUri(uri);
+    var file = File.fromUri(uri);
     var parent_directory = file.parent;
     await parent_directory.create(recursive: true);
     if (await file.exists()) {
       await file.delete();
     }
-    var result = await file.writeAsBytes(bytes);
+    await file.writeAsBytes(bytes);
     completer.complete(null);
     WriteLimiter._writeCompleted();
   }
 }
 
 class WriteLimiter {
-  static final List<PendingWrite> pendingWrites = new List<PendingWrite>();
+  static final List<PendingWrite> pendingWrites = <PendingWrite>[];
 
   // non-rooted Android devices have a very low limit for the number of
   // open files. Artificially cap ourselves to 16.
@@ -120,7 +117,7 @@
 
   static Future scheduleWrite(Uri path, List<int> bytes) async {
     // Create a new pending write.
-    PendingWrite pw = new PendingWrite(path, bytes);
+    PendingWrite pw = PendingWrite(path, bytes);
     pendingWrites.add(pw);
     _maybeWriteFiles();
     return pw.completer.future;
@@ -149,8 +146,8 @@
   return WriteLimiter.scheduleWrite(path, bytes);
 }
 
-Future writeStreamFileCallback(Uri path, Stream<List<int>> bytes) async {
-  var file = new File.fromUri(path);
+Future<void> writeStreamFileCallback(Uri path, Stream<List<int>> bytes) async {
+  var file = File.fromUri(path);
   var parent_directory = file.parent;
   await parent_directory.create(recursive: true);
   if (await file.exists()) {
@@ -162,19 +159,19 @@
 }
 
 Future<List<int>> readFileCallback(Uri path) async {
-  var file = new File.fromUri(path);
+  var file = File.fromUri(path);
   return await file.readAsBytes();
 }
 
 Future<List<Map<String, dynamic>>> listFilesCallback(Uri dirPath) async {
-  var dir = new Directory.fromUri(dirPath);
+  var dir = Directory.fromUri(dirPath);
   var dirPathStr = dirPath.path;
   var stream = dir.list(recursive: true);
   var result = <Map<String, dynamic>>[];
   await for (var fileEntity in stream) {
-    var filePath = new Uri.file(fileEntity.path).path;
+    var filePath = Uri.file(fileEntity.path).path;
     var stat = await fileEntity.stat();
-    if (stat.type == FileSystemEntityType.FILE &&
+    if (stat.type == FileSystemEntityType.file &&
         filePath.startsWith(dirPathStr)) {
       var map = <String, dynamic>{};
       map['name'] = '/' + filePath.substring(dirPathStr.length);
@@ -186,28 +183,22 @@
   return result;
 }
 
-Future<Uri> serverInformationCallback() async {
-  _lazyServerBoot();
-  return server.serverAddress;
-}
+Future<Uri> serverInformationCallback() async =>
+    await _lazyServerBoot().serverAddress!;
 
 Future<Uri> webServerControlCallback(bool enable) async {
-  _lazyServerBoot();
-  if (server.running == enable) {
-    // No change.
-    return server.serverAddress;
+  final _server = _lazyServerBoot();
+  if (_server.running != enable) {
+    if (enable) {
+      await _server.startup();
+    } else {
+      await _server.shutdown(true);
+    }
   }
-
-  if (enable) {
-    await server.startup();
-    return server.serverAddress;
-  } else {
-    await server.shutdown(true);
-    return server.serverAddress;
-  }
+  return _server.serverAddress!;
 }
 
-Null _clearFuture(_) {
+void _clearFuture(_) {
   serverFuture = null;
 }
 
@@ -216,16 +207,16 @@
     // Still waiting.
     return;
   }
-  _lazyServerBoot();
+  final _server = _lazyServerBoot();
   // Toggle HTTP server.
-  if (server.running) {
-    serverFuture = server.shutdown(true).then(_clearFuture);
+  if (_server.running) {
+    _server.shutdown(true).then(_clearFuture);
   } else {
-    serverFuture = server.startup().then(_clearFuture);
+    _server.startup().then(_clearFuture);
   }
 }
 
-Timer _registerSignalHandlerTimer;
+Timer? _registerSignalHandlerTimer;
 
 _registerSignalHandler() {
   _registerSignalHandlerTimer = null;
@@ -237,7 +228,7 @@
     // Cannot register for signals on Windows or Fuchsia.
     return;
   }
-  _signalSubscription = _signalWatch(ProcessSignal.SIGQUIT).listen(_onSignal);
+  _signalSubscription = _signalWatch(ProcessSignal.sigquit).listen(_onSignal);
 }
 
 @pragma("vm:entry-point", !const bool.fromEnvironment("dart.vm.product"))
@@ -254,17 +245,17 @@
   VMServiceEmbedderHooks.webServerControl = webServerControlCallback;
   // Always instantiate the vmservice object so that the exit message
   // can be delivered and waiting loaders can be cancelled.
-  new VMService();
+  VMService();
   if (_autoStart) {
-    _lazyServerBoot();
-    server.startup();
+    final _server = _lazyServerBoot();
+    _server.startup();
     // It's just here to push an event on the event loop so that we invoke the
     // scheduled microtasks.
     Timer.run(() {});
   }
   // Register signal handler after a small delay to avoid stalling main
   // isolate startup.
-  _registerSignalHandlerTimer = new Timer(shortDelay, _registerSignalHandler);
+  _registerSignalHandlerTimer = Timer(shortDelay, _registerSignalHandler);
 }
 
 _shutdown() native "VMServiceIO_Shutdown";
diff --git a/runtime/bin/vmservice/server.dart b/sdk_nnbd/lib/_internal/vm/bin/vmservice_server.dart
similarity index 82%
copy from runtime/bin/vmservice/server.dart
copy to sdk_nnbd/lib/_internal/vm/bin/vmservice_server.dart
index e3388a8a..d94fc54 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/vmservice_server.dart
@@ -2,11 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.6
-
 part of vmservice_io;
 
-final bool silentObservatory = new bool.fromEnvironment('SILENT_OBSERVATORY');
+final bool silentObservatory = bool.fromEnvironment('SILENT_OBSERVATORY');
 
 void serverPrint(String s) {
   if (silentObservatory) {
@@ -17,10 +15,10 @@
 }
 
 class WebSocketClient extends Client {
-  static const int PARSE_ERROR_CODE = 4000;
-  static const int BINARY_MESSAGE_ERROR_CODE = 4001;
-  static const int NOT_MAP_ERROR_CODE = 4002;
-  static const int ID_ERROR_CODE = 4003;
+  static const int parseErrorCode = 4000;
+  static const int binaryMessageErrorCode = 4001;
+  static const int notMapErrorCode = 4002;
+  static const int idErrorCode = 4003;
   final WebSocket socket;
 
   WebSocketClient(this.socket, VMService service) : super(service) {
@@ -40,15 +38,15 @@
       try {
         map = json.decode(message);
       } catch (e) {
-        socket.close(PARSE_ERROR_CODE, 'Message parse error: $e');
+        socket.close(parseErrorCode, 'Message parse error: $e');
         return;
       }
       if (map is! Map) {
-        socket.close(NOT_MAP_ERROR_CODE, 'Message must be a JSON map.');
+        socket.close(notMapErrorCode, 'Message must be a JSON map.');
         return;
       }
       try {
-        final rpc = new Message.fromJsonRpc(this, map);
+        final rpc = Message.fromJsonRpc(this, map);
         switch (rpc.type) {
           case MessageType.Request:
             onRequest(rpc);
@@ -61,18 +59,14 @@
             break;
         }
       } catch (e) {
-        socket.close(ID_ERROR_CODE, e.message);
+        socket.close(idErrorCode, e.message);
       }
     } else {
-      socket.close(BINARY_MESSAGE_ERROR_CODE, 'Message must be a string.');
+      socket.close(binaryMessageErrorCode, 'Message must be a string.');
     }
   }
 
   void post(Response result) {
-    if (result == null) {
-      // Do nothing.
-      return;
-    }
     try {
       switch (result.kind) {
         case ResponsePayloadKind.String:
@@ -89,17 +83,16 @@
     }
   }
 
-  dynamic toJson() {
-    Map map = super.toJson();
-    map['type'] = 'WebSocketClient';
-    map['socket'] = '$socket';
-    return map;
-  }
+  Map toJson() => {
+        ...super.toJson(),
+        'type': 'WebSocketClient',
+        'socket': '$socket',
+      };
 }
 
 class HttpRequestClient extends Client {
   static ContentType jsonContentType =
-      new ContentType("application", "json", charset: "utf-8");
+      ContentType("application", "json", charset: "utf-8");
   final HttpRequest request;
 
   HttpRequestClient(this.request, VMService service)
@@ -111,10 +104,6 @@
   }
 
   void post(Response result) {
-    if (result == null) {
-      close();
-      return;
-    }
     HttpResponse response = request.response;
     // We closed the connection for bad origins earlier.
     response.headers.add('Access-Control-Allow-Origin', '*');
@@ -150,19 +139,20 @@
   final int _port;
   final bool _originCheckDisabled;
   final bool _authCodesDisabled;
-  final String _serviceInfoFilename;
-  HttpServer _server;
+  final String? _serviceInfoFilename;
+  HttpServer? _server;
   bool get running => _server != null;
 
   /// Returns the server address including the auth token.
-  Uri get serverAddress {
+  Uri? get serverAddress {
     if (!running) {
       return null;
     }
-    var ip = _server.address.address;
-    var port = _server.port;
+    final server = _server!;
+    var ip = server.address.address;
+    var port = server.port;
     var path = !_authCodesDisabled ? "$serviceAuthToken/" : "/";
-    return new Uri(scheme: 'http', host: ip, port: port, path: path);
+    return Uri(scheme: 'http', host: ip, port: port, path: path);
   }
 
   // On Fuchsia, authentication codes are disabled by default. To enable, the authentication token
@@ -187,9 +177,10 @@
       return true;
     }
 
-    if ((uri.port == _server.port) &&
-        ((uri.host == _server.address.address) ||
-            (uri.host == _server.address.host))) {
+    final server = _server!;
+    if ((uri.port == server.port) &&
+        ((uri.host == server.address.address) ||
+            (uri.host == server.address.host))) {
       return true;
     }
 
@@ -202,7 +193,7 @@
       return true;
     }
     // First check the web-socket specific origin.
-    List<String> origins = request.headers["Sec-WebSocket-Origin"];
+    List<String>? origins = request.headers["Sec-WebSocket-Origin"];
     if (origins == null) {
       // Fall back to the general Origin field.
       origins = request.headers["Origin"];
@@ -268,15 +259,15 @@
 
       List fsNameList;
       List fsPathList;
-      List fsPathBase64List;
-      List fsUriBase64List;
-      Object fsName;
-      Object fsPath;
-      Object fsUri;
+      List? fsPathBase64List;
+      List? fsUriBase64List;
+      Object? fsName;
+      Object? fsPath;
+      Uri? fsUri;
 
       try {
         // Extract the fs name and fs path from the request headers.
-        fsNameList = request.headers['dev_fs_name'];
+        fsNameList = request.headers['dev_fs_name']!;
         fsName = fsNameList[0];
 
         // Prefer Uri encoding first.
@@ -288,7 +279,7 @@
 
         // Fallback to path encoding.
         if (fsUri == null) {
-          fsPathList = request.headers['dev_fs_path'];
+          fsPathList = request.headers['dev_fs_path']!;
           fsPathBase64List = request.headers['dev_fs_path_b64'];
           // If the 'dev_fs_path_b64' header field was sent, use that instead.
           if ((fsPathBase64List != null) && (fsPathBase64List.length > 0)) {
@@ -302,7 +293,7 @@
       String result;
       try {
         result = await _service.devfs.handlePutStream(fsName, fsPath, fsUri,
-            request.cast<List<int>>().transform(GZIP.decoder));
+            request.cast<List<int>>().transform(gzip.decoder));
       } catch (e) {
         request.response.statusCode = HttpStatus.internalServerError;
         request.response.write(e);
@@ -338,7 +329,7 @@
       // The URI contains the valid auth token but is missing a trailing '/'.
       // Redirect to the same URI with the trailing '/' to correctly serve
       // index.html.
-      request.response.redirect(result as Uri);
+      request.response.redirect(result);
       request.response.close();
       return;
     }
@@ -348,18 +339,18 @@
       WebSocketTransformer.upgrade(request,
               compression: CompressionOptions.compressionOff)
           .then((WebSocket webSocket) {
-        new WebSocketClient(webSocket, _service);
+        WebSocketClient(webSocket, _service);
       });
       return;
     }
 
     if (assets == null) {
-      request.response.headers.contentType = ContentType.TEXT;
+      request.response.headers.contentType = ContentType.text;
       request.response.write("This VM was built without the Observatory UI.");
       request.response.close();
       return;
     }
-    Asset asset = assets[path];
+    Asset? asset = assets[path];
     if (asset != null) {
       // Serving up a static asset (e.g. .css, .html, .png).
       request.response.headers.contentType = ContentType.parse(asset.mimeType);
@@ -368,8 +359,8 @@
       return;
     }
     // HTTP based service request.
-    final client = new HttpRequestClient(request, _service);
-    final message = new Message.fromUri(
+    final client = HttpRequestClient(request, _service);
+    final message = Message.fromUri(
         client, Uri(path: path, queryParameters: request.uri.queryParameters));
     client.onRequest(message); // exception free, no need to try catch
   }
@@ -379,7 +370,7 @@
       'uri': serverAddress.toString(),
     };
     final file = File.fromUri(Uri.parse(_serviceInfoFilename));
-    file.writeAsString(json.encode(serviceInfo));
+    return file.writeAsString(json.encode(serviceInfo));
   }
 
   Future startup() async {
@@ -398,7 +389,7 @@
         // Prefer IPv4 addresses.
         for (var i = 0; i < addresses.length; i++) {
           address = addresses[i];
-          if (address.type == InternetAddressType.IP_V4) break;
+          if (address.type == InternetAddressType.IPv4) break;
         }
         _server = await HttpServer.bind(address, _port);
         return true;
@@ -422,7 +413,7 @@
         onServerAddressChange(null);
         return this;
       }
-      await new Future<Null>.delayed(const Duration(seconds: 1));
+      await Future<void>.delayed(const Duration(seconds: 1));
     }
     if (_service.isExiting) {
       serverPrint('Observatory HTTP server exiting before listening as '
@@ -430,17 +421,18 @@
       await shutdown(true);
       return this;
     }
-    _server.listen(_requestHandler, cancelOnError: true);
+    final server = _server!;
+    server.listen(_requestHandler, cancelOnError: true);
     serverPrint('Observatory listening on $serverAddress');
     if (Platform.isFuchsia) {
       // Create a file with the port number.
       String tmp = Directory.systemTemp.path;
-      String path = "$tmp/dart.services/${_server.port}";
+      String path = "$tmp/dart.services/${server.port}";
       serverPrint("Creating $path");
-      new File(path)..createSync(recursive: true);
+      File(path)..createSync(recursive: true);
     }
     if (_serviceInfoFilename != null && _serviceInfoFilename.isNotEmpty) {
-      _dumpServiceInfoToFile();
+      await _dumpServiceInfoToFile();
     }
     // Server is up and running.
     _notifyServerState(serverAddress.toString());
@@ -448,28 +440,29 @@
     return this;
   }
 
-  Future cleanup(bool force) {
+  Future<void> cleanup(bool force) {
     if (_server == null) {
-      return new Future.value(null);
+      return Future.value();
     }
+    final server = _server!;
     if (Platform.isFuchsia) {
       // Remove the file with the port number.
       String tmp = Directory.systemTemp.path;
-      String path = "$tmp/dart.services/${_server.port}";
+      String path = "$tmp/dart.services/${server.port}";
       serverPrint("Deleting $path");
-      new File(path)..deleteSync();
+      File(path)..deleteSync();
     }
-    return _server.close(force: force);
+    return server.close(force: force);
   }
 
   Future shutdown(bool forced) {
     if (_server == null) {
       // Not started.
-      return new Future.value(this);
+      return Future.value(this);
     }
 
     // Shutdown HTTP server and subscription.
-    Uri oldServerAddress = serverAddress;
+    Uri oldServerAddress = serverAddress!;
     return cleanup(forced).then((_) {
       serverPrint('Observatory no longer listening on $oldServerAddress');
       _server = null;
diff --git a/sdk_nnbd/lib/_internal/vm/lib/array_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/array_patch.dart
index f19d3a8..6ad5297 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/array_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/array_patch.dart
@@ -63,6 +63,12 @@
   }
 
   @patch
+  factory List.of(Iterable<E> elements, {bool growable: true}) {
+    // TODO(32937): Specialize to benefit from known element type.
+    return List.from(elements, growable: growable);
+  }
+
+  @patch
   factory List.unmodifiable(Iterable elements) {
     final result = new List<E>.from(elements, growable: false);
     return makeFixedListUnmodifiable(result);
diff --git a/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
index b0231b2..9cf6af2 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
@@ -12,14 +12,18 @@
   String toString() => _msg;
 }
 
-String _n(Symbol symbol) => internal.Symbol.getName(symbol);
+String _n(Symbol symbol) => internal.Symbol.getName(symbol as internal.Symbol);
 
 Symbol _s(String name) {
+  return new internal.Symbol.unvalidated(name);
+}
+
+Symbol? _sOpt(String? name) {
   if (name == null) return null;
   return new internal.Symbol.unvalidated(name);
 }
 
-Symbol _computeQualifiedName(DeclarationMirror owner, Symbol simpleName) {
+Symbol _computeQualifiedName(DeclarationMirror? owner, Symbol simpleName) {
   if (owner == null) return simpleName;
   return _s('${_n(owner.qualifiedName)}.${_n(simpleName)}');
 }
@@ -61,10 +65,18 @@
   return buf.toString();
 }
 
-SourceLocation _location(reflectee) native "DeclarationMirror_location";
+SourceLocation? _location(reflectee) native "DeclarationMirror_location";
 
 List<dynamic> _metadata(reflectee) native 'DeclarationMirror_metadata';
 
+List<InstanceMirror> _wrapMetadata(List reflectees) {
+  var mirrors = new List<InstanceMirror>();
+  for (var reflectee in reflectees) {
+    mirrors.add(reflect(reflectee));
+  }
+  return new UnmodifiableListView<InstanceMirror>(mirrors);
+}
+
 bool _subtypeTest(Type a, Type b) native 'TypeMirror_subtypeTest';
 
 class _MirrorSystem extends MirrorSystem {
@@ -86,12 +98,11 @@
 
   static List<dynamic> _computeLibraries() native "MirrorSystem_libraries";
 
-  IsolateMirror _isolate;
+  IsolateMirror? _isolate;
   IsolateMirror get isolate {
-    if (_isolate == null) {
-      _isolate = _computeIsolate();
-    }
-    return _isolate;
+    var i = _isolate;
+    if (i != null) return i;
+    return _isolate = _computeIsolate();
   }
 
   static IsolateMirror _computeIsolate() native "MirrorSystem_isolate";
@@ -172,9 +183,9 @@
         <ParameterMirror>[new _SyntheticSetterParameter(this, this._target)]);
   }
 
-  SourceLocation get location => null;
+  SourceLocation? get location => null;
   List<InstanceMirror> get metadata => const <InstanceMirror>[];
-  String get source => null;
+  String? get source => null;
 }
 
 class _SyntheticSetterParameter implements ParameterMirror {
@@ -196,8 +207,8 @@
   bool get isPrivate => false;
   bool get isExtensionMember => false;
   bool get hasDefaultValue => false;
-  InstanceMirror get defaultValue => null;
-  SourceLocation get location => null;
+  InstanceMirror? get defaultValue => null;
+  SourceLocation? get location => null;
   List<InstanceMirror> get metadata => const <InstanceMirror>[];
 }
 
@@ -211,9 +222,9 @@
   _ObjectMirror._(this._reflectee);
 
   InstanceMirror invoke(Symbol memberName, List positionalArguments,
-      [Map<Symbol, dynamic> namedArguments]) {
+      [Map<Symbol, dynamic> namedArguments = const <Symbol, dynamic>{}]) {
     int numPositionalArguments = positionalArguments.length;
-    int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
+    int numNamedArguments = namedArguments.length;
     int numArguments = numPositionalArguments + numNamedArguments;
     List arguments = new List(numArguments);
     arguments.setRange(0, numPositionalArguments, positionalArguments);
@@ -263,14 +274,14 @@
 class _InstanceMirror extends _ObjectMirror implements InstanceMirror {
   _InstanceMirror._(reflectee) : super._(reflectee);
 
-  ClassMirror _type;
+  ClassMirror? _type;
   ClassMirror get type {
-    if (_type == null) {
-      // Note it not safe to use reflectee.runtimeType because runtimeType may
-      // be overridden.
-      _type = reflectType(_computeType(reflectee));
-    }
-    return _type;
+    var t = _type;
+    if (t != null) return t;
+
+    // Note it not safe to use reflectee.runtimeType because runtimeType may
+    // be overridden.
+    return _type = reflectType(_computeType(reflectee)) as ClassMirror;
   }
 
   // LocalInstanceMirrors always reflect local instances
@@ -301,9 +312,9 @@
 
   // Override to include the receiver in the arguments.
   InstanceMirror invoke(Symbol memberName, List positionalArguments,
-      [Map<Symbol, dynamic> namedArguments]) {
+      [Map<Symbol, dynamic> namedArguments = const <Symbol, dynamic>{}]) {
     int numPositionalArguments = positionalArguments.length + 1; // Receiver.
-    int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
+    int numNamedArguments = namedArguments.length;
     int numArguments = numPositionalArguments + numNamedArguments;
     List arguments = new List(numArguments);
     arguments[0] = _reflectee; // Receiver.
@@ -335,16 +346,15 @@
 class _ClosureMirror extends _InstanceMirror implements ClosureMirror {
   _ClosureMirror._(reflectee) : super._(reflectee);
 
-  MethodMirror _function;
+  MethodMirror? _function;
   MethodMirror get function {
-    if (_function == null) {
-      _function = _computeFunction(reflectee);
-    }
-    return _function;
+    var f = _function;
+    if (f != null) return f;
+    return _function = _computeFunction(reflectee);
   }
 
-  InstanceMirror apply(List<Object> positionalArguments,
-      [Map<Symbol, Object> namedArguments]) {
+  InstanceMirror apply(List positionalArguments,
+      [Map<Symbol, dynamic> namedArguments = const <Symbol, dynamic>{}]) {
     return this.invoke(#call, positionalArguments, namedArguments);
   }
 
@@ -359,8 +369,8 @@
 
 class _ClassMirror extends _ObjectMirror implements ClassMirror, _TypeMirror {
   final Type _reflectedType;
-  Symbol _simpleName;
-  DeclarationMirror _owner;
+  Symbol? _simpleName;
+  DeclarationMirror? _owner;
   final bool isAbstract;
   final bool _isGeneric;
 
@@ -376,14 +386,14 @@
   _ClassMirror._(
       reflectee,
       reflectedType,
-      String simpleName,
+      String? simpleName,
       this._owner,
       this.isAbstract,
       this._isGeneric,
       this._isTransformedMixinApplication,
       this._isGenericDeclaration,
       this.isEnum)
-      : this._simpleName = _s(simpleName),
+      : this._simpleName = _sOpt(simpleName),
         this._reflectedType = reflectedType,
         this._instantiator = reflectedType,
         super._(reflectee);
@@ -399,38 +409,38 @@
 
   Symbol get simpleName {
     // All but anonymous mixin applications have their name set at construction.
-    if (_simpleName == null) {
-      _simpleName = this._mixinApplicationName;
-    }
-    return _simpleName;
+    var n = _simpleName;
+    if (n != null) return n;
+
+    return _simpleName = this._mixinApplicationName;
   }
 
-  Symbol _qualifiedName;
+  Symbol? _qualifiedName;
   Symbol get qualifiedName {
-    if (_qualifiedName == null) {
-      _qualifiedName = _computeQualifiedName(owner, simpleName);
-    }
-    return _qualifiedName;
+    var n = _qualifiedName;
+    if (n != null) return n;
+
+    return _qualifiedName = _computeQualifiedName(owner, simpleName);
   }
 
   DeclarationMirror get owner {
-    if (_owner == null) {
-      var uri = _ClassMirror._libraryUri(_reflectee);
-      _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
-    }
-    return _owner;
+    var o = _owner;
+    if (o != null) return o;
+
+    var uri = _ClassMirror._libraryUri(_reflectee);
+    return _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
   }
 
   bool get isPrivate => _n(simpleName).startsWith('_');
 
   bool get isTopLevel => true;
 
-  SourceLocation get location {
+  SourceLocation? get location {
     return _location(_reflectee);
   }
 
-  _ClassMirror _trueSuperclassField;
-  _ClassMirror get _trueSuperclass {
+  _ClassMirror? _trueSuperclassField;
+  _ClassMirror? get _trueSuperclass {
     if (_trueSuperclassField == null) {
       Type supertype = isOriginalDeclaration
           ? _supertype(_reflectedType)
@@ -439,120 +449,125 @@
         // Object has no superclass.
         return null;
       }
-      _trueSuperclassField = reflectType(supertype);
-      _trueSuperclassField._instantiator = _instantiator;
+      var supertypeMirror = reflectType(supertype) as _ClassMirror;
+      supertypeMirror._instantiator = _instantiator;
+      _trueSuperclassField = supertypeMirror;
     }
     return _trueSuperclassField;
   }
 
-  ClassMirror get superclass {
+  ClassMirror? get superclass {
     return _trueSuperclass;
   }
 
   var _superinterfaces;
   List<ClassMirror> get superinterfaces {
-    if (_superinterfaces == null) {
-      var interfaceTypes = isOriginalDeclaration
-          ? _nativeInterfaces(_reflectedType)
-          : _nativeInterfacesInstantiated(_reflectedType);
-      if (_isTransformedMixinApplication) {
-        interfaceTypes = interfaceTypes.sublist(0, interfaceTypes.length - 1);
-      }
-      var interfaceMirrors = new List<ClassMirror>();
-      for (var interfaceType in interfaceTypes) {
-        interfaceMirrors.add(reflectType(interfaceType));
-      }
-      _superinterfaces =
-          new UnmodifiableListView<ClassMirror>(interfaceMirrors);
+    var i = _superinterfaces;
+    if (i != null) return i;
+
+    var interfaceTypes = isOriginalDeclaration
+        ? _nativeInterfaces(_reflectedType)
+        : _nativeInterfacesInstantiated(_reflectedType);
+    if (_isTransformedMixinApplication) {
+      interfaceTypes = interfaceTypes.sublist(0, interfaceTypes.length - 1);
     }
-    return _superinterfaces;
+    var interfaceMirrors = new List<ClassMirror>();
+    for (var interfaceType in interfaceTypes) {
+      interfaceMirrors.add(reflectType(interfaceType) as ClassMirror);
+    }
+    return _superinterfaces =
+        new UnmodifiableListView<ClassMirror>(interfaceMirrors);
   }
 
-  get _mixinApplicationName {
+  Symbol get _mixinApplicationName {
     var mixins = new List<ClassMirror>();
     var klass = this;
     while (_nativeMixin(klass._reflectedType) != null) {
       mixins.add(klass.mixin);
-      klass = klass.superclass;
+      klass = klass.superclass as _ClassMirror;
     }
     return _s(_n(klass.qualifiedName) +
         ' with ' +
-        mixins.reversed.map((m) => _n(m.qualifiedName)).join(', '));
+        mixins.reversed.map((ClassMirror m) => _n(m.qualifiedName)).join(', '));
   }
 
-  var _mixin;
+  ClassMirror? _mixin;
   ClassMirror get mixin {
-    if (_mixin == null) {
-      Type mixinType = _nativeMixinInstantiated(_reflectedType, _instantiator);
-      if (mixinType == null) {
-        // The reflectee is not a mixin application.
-        _mixin = this;
-      } else {
-        _mixin = reflectType(mixinType);
-      }
+    var m = _mixin;
+    if (m != null) return m;
+
+    Type mixinType = _nativeMixinInstantiated(_reflectedType, _instantiator);
+    if (mixinType == null) {
+      // The reflectee is not a mixin application.
+      return _mixin = this;
+    } else {
+      return _mixin = reflectType(mixinType) as ClassMirror;
     }
-    return _mixin;
   }
 
   var _cachedStaticMembers;
   Map<Symbol, MethodMirror> get staticMembers {
-    if (_cachedStaticMembers == null) {
-      var result = new Map<Symbol, MethodMirror>();
-      declarations.values.forEach((decl) {
-        if (decl is MethodMirror && decl.isStatic && !decl.isConstructor) {
-          result[decl.simpleName] = decl;
+    var m = _cachedStaticMembers;
+    if (m != null) m;
+
+    var result = new Map<Symbol, MethodMirror>();
+    var library = this.owner as LibraryMirror;
+    declarations.values.forEach((decl) {
+      if (decl is MethodMirror && decl.isStatic && !decl.isConstructor) {
+        result[decl.simpleName] = decl;
+      }
+      if (decl is VariableMirror && decl.isStatic) {
+        var getterName = decl.simpleName;
+        result[getterName] =
+            new _SyntheticAccessor(this, getterName, true, true, false, decl);
+        if (!decl.isFinal) {
+          var setterName = _asSetter(decl.simpleName, library);
+          result[setterName] = new _SyntheticAccessor(
+              this, setterName, false, true, false, decl);
         }
-        if (decl is VariableMirror && decl.isStatic) {
-          var getterName = decl.simpleName;
-          result[getterName] =
-              new _SyntheticAccessor(this, getterName, true, true, false, decl);
-          if (!decl.isFinal) {
-            var setterName = _asSetter(decl.simpleName, this.owner);
-            result[setterName] = new _SyntheticAccessor(
-                this, setterName, false, true, false, decl);
-          }
-        }
-      });
-      _cachedStaticMembers =
-          new UnmodifiableMapView<Symbol, MethodMirror>(result);
-    }
-    return _cachedStaticMembers;
+      }
+    });
+    return _cachedStaticMembers =
+        new UnmodifiableMapView<Symbol, MethodMirror>(result);
   }
 
   var _cachedInstanceMembers;
   Map<Symbol, MethodMirror> get instanceMembers {
-    if (_cachedInstanceMembers == null) {
-      var result = new Map<Symbol, MethodMirror>();
-      if (superclass != null) {
-        result.addAll(superclass.instanceMembers);
-      }
-      declarations.values.forEach((decl) {
-        if (decl is MethodMirror &&
-            !decl.isStatic &&
-            !decl.isConstructor &&
-            !decl.isAbstract) {
-          result[decl.simpleName] = decl;
-        }
-        if (decl is VariableMirror && !decl.isStatic) {
-          var getterName = decl.simpleName;
-          result[getterName] = new _SyntheticAccessor(
-              this, getterName, true, false, false, decl);
-          if (!decl.isFinal) {
-            var setterName = _asSetter(decl.simpleName, this.owner);
-            result[setterName] = new _SyntheticAccessor(
-                this, setterName, false, false, false, decl);
-          }
-        }
-      });
-      _cachedInstanceMembers =
-          new UnmodifiableMapView<Symbol, MethodMirror>(result);
+    var m = _cachedInstanceMembers;
+    if (m != null) return m;
+
+    var result = new Map<Symbol, MethodMirror>();
+    var library = this.owner as LibraryMirror;
+    var sup = superclass;
+    if (sup != null) {
+      result.addAll(sup.instanceMembers);
     }
-    return _cachedInstanceMembers;
+    declarations.values.forEach((decl) {
+      if (decl is MethodMirror &&
+          !decl.isStatic &&
+          !decl.isConstructor &&
+          !decl.isAbstract) {
+        result[decl.simpleName] = decl;
+      }
+      if (decl is VariableMirror && !decl.isStatic) {
+        var getterName = decl.simpleName;
+        result[getterName] =
+            new _SyntheticAccessor(this, getterName, true, false, false, decl);
+        if (!decl.isFinal) {
+          var setterName = _asSetter(decl.simpleName, library);
+          result[setterName] = new _SyntheticAccessor(
+              this, setterName, false, false, false, decl);
+        }
+      }
+    });
+    return _cachedInstanceMembers =
+        new UnmodifiableMapView<Symbol, MethodMirror>(result);
   }
 
-  Map<Symbol, DeclarationMirror> _declarations;
+  Map<Symbol, DeclarationMirror>? _declarations;
   Map<Symbol, DeclarationMirror> get declarations {
-    if (_declarations != null) return _declarations;
+    var d = _declarations;
+    if (d != null) return d;
 
     var decls = new Map<Symbol, DeclarationMirror>();
 
@@ -582,39 +597,39 @@
     return true;
   }
 
-  List<TypeVariableMirror> _typeVariables;
+  List<TypeVariableMirror>? _typeVariables;
   List<TypeVariableMirror> get typeVariables {
-    if (_typeVariables == null) {
-      if (!_isTransformedMixinApplication && _isAnonymousMixinApplication) {
-        return _typeVariables = const <TypeVariableMirror>[];
-      }
-      _typeVariables = new List<TypeVariableMirror>();
+    var v = _typeVariables;
+    if (v != null) return v;
 
-      List params = _ClassMirror_type_variables(_reflectee);
-      ClassMirror owner = originalDeclaration;
-      var mirror;
-      for (var i = 0; i < params.length; i += 2) {
-        mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
-        _typeVariables.add(mirror);
-      }
-      _typeVariables =
-          new UnmodifiableListView<TypeVariableMirror>(_typeVariables);
+    if (!_isTransformedMixinApplication && _isAnonymousMixinApplication) {
+      return _typeVariables = const <TypeVariableMirror>[];
     }
-    return _typeVariables;
+    var result = new List<TypeVariableMirror>();
+
+    List params = _ClassMirror_type_variables(_reflectee);
+    ClassMirror owner = originalDeclaration;
+    var mirror;
+    for (var i = 0; i < params.length; i += 2) {
+      mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
+      result.add(mirror);
+    }
+    return _typeVariables =
+        new UnmodifiableListView<TypeVariableMirror>(result);
   }
 
-  List<TypeMirror> _typeArguments;
+  List<TypeMirror>? _typeArguments;
   List<TypeMirror> get typeArguments {
-    if (_typeArguments == null) {
-      if (_isGenericDeclaration ||
-          (!_isTransformedMixinApplication && _isAnonymousMixinApplication)) {
-        _typeArguments = const <TypeMirror>[];
-      } else {
-        _typeArguments = new UnmodifiableListView<TypeMirror>(
-            _computeTypeArguments(_reflectedType).cast<TypeMirror>());
-      }
+    var a = _typeArguments;
+    if (a != null) return a;
+
+    if (_isGenericDeclaration ||
+        (!_isTransformedMixinApplication && _isAnonymousMixinApplication)) {
+      return _typeArguments = const <TypeMirror>[];
+    } else {
+      return _typeArguments = new UnmodifiableListView<TypeMirror>(
+          _computeTypeArguments(_reflectedType).cast<TypeMirror>());
     }
-    return _typeArguments;
   }
 
   bool get isOriginalDeclaration => !_isGeneric || _isGenericDeclaration;
@@ -630,11 +645,11 @@
   String toString() => "ClassMirror on '${MirrorSystem.getName(simpleName)}'";
 
   InstanceMirror newInstance(Symbol constructorName, List positionalArguments,
-      [Map<Symbol, dynamic> namedArguments]) {
+      [Map<Symbol, dynamic> namedArguments = const <Symbol, dynamic>{}]) {
     // Native code will add the 1 or 2 implicit arguments depending on whether
     // we end up invoking a factory or constructor respectively.
     int numPositionalArguments = positionalArguments.length;
-    int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
+    int numNamedArguments = namedArguments.length;
     int numArguments = numPositionalArguments + numNamedArguments;
     List arguments = new List(numArguments);
     arguments.setRange(0, numPositionalArguments, positionalArguments);
@@ -653,10 +668,7 @@
   }
 
   List<InstanceMirror> get metadata {
-    // Get the metadata objects, convert them into InstanceMirrors using
-    // reflect() and then make them into a Dart list.
-    return new UnmodifiableListView<InstanceMirror>(
-        _metadata(_reflectee).map(reflect));
+    return _wrapMetadata(_metadata(_reflectee));
   }
 
   bool operator ==(other) {
@@ -684,12 +696,12 @@
 
   bool isSubclassOf(ClassMirror other) {
     if (other is! ClassMirror) throw new ArgumentError(other);
-    ClassMirror otherDeclaration = other.originalDeclaration;
+    ClassMirror otherDeclaration = other.originalDeclaration as ClassMirror;
     ClassMirror c = this;
     while (c != null) {
-      c = c.originalDeclaration;
+      c = c.originalDeclaration as ClassMirror;
       if (c == otherDeclaration) return true;
-      c = c.superclass;
+      c = c.superclass as ClassMirror;
     }
     return false;
   }
@@ -744,47 +756,43 @@
   bool get _isAnonymousMixinApplication => false;
 
   // FunctionTypeMirrors have a simpleName generated from their signature.
-  Symbol _simpleName;
+  Symbol? _simpleName;
   Symbol get simpleName {
-    if (_simpleName == null) {
-      _simpleName = _s(_makeSignatureString(returnType, parameters));
-    }
-    return _simpleName;
+    var n = _simpleName;
+    if (n != null) return n;
+    return _simpleName = _s(_makeSignatureString(returnType, parameters));
   }
 
-  MethodMirror _callMethod;
+  MethodMirror? _callMethod;
   MethodMirror get callMethod {
-    if (_callMethod == null) {
-      _callMethod = _FunctionTypeMirror_call_method(_functionReflectee);
-    }
-    return _callMethod;
+    var m = _callMethod;
+    if (m != null) return m;
+    return _callMethod = _FunctionTypeMirror_call_method(_functionReflectee);
   }
 
-  TypeMirror _returnType;
+  TypeMirror? _returnType;
   TypeMirror get returnType {
-    if (_returnType == null) {
-      _returnType =
-          reflectType(_FunctionTypeMirror_return_type(_functionReflectee));
-    }
-    return _returnType;
+    var t = _returnType;
+    if (t != null) return t;
+    return _returnType =
+        reflectType(_FunctionTypeMirror_return_type(_functionReflectee));
   }
 
-  List<ParameterMirror> _parameters;
+  List<ParameterMirror>? _parameters;
   List<ParameterMirror> get parameters {
-    if (_parameters == null) {
-      _parameters = _FunctionTypeMirror_parameters(_functionReflectee)
-          .cast<ParameterMirror>();
-      _parameters = new UnmodifiableListView<ParameterMirror>(_parameters);
-    }
-    return _parameters;
+    var p = _parameters;
+    if (p != null) return p;
+    return _parameters = new UnmodifiableListView<ParameterMirror>(
+        _FunctionTypeMirror_parameters(_functionReflectee)
+            .cast<ParameterMirror>());
   }
 
   bool get isOriginalDeclaration => true;
   ClassMirror get originalDeclaration => this;
-  get typeVariables => const <TypeVariableMirror>[];
-  get typeArguments => const <TypeMirror>[];
-  get metadata => const <InstanceMirror>[];
-  get location => null;
+  List<TypeVariableMirror> get typeVariables => const <TypeVariableMirror>[];
+  List<TypeMirror> get typeArguments => const <TypeMirror>[];
+  List<InstanceMirror> get metadata => const <InstanceMirror>[];
+  SourceLocation? get location => null;
 
   String toString() => "FunctionTypeMirror on '${_n(simpleName)}'";
 
@@ -806,25 +814,21 @@
 
   Symbol get simpleName => _simpleName;
 
-  Symbol _qualifiedName;
+  Symbol? _qualifiedName;
   Symbol get qualifiedName {
-    if (_qualifiedName == null) {
-      _qualifiedName = _computeQualifiedName(owner, simpleName);
-    }
-    return _qualifiedName;
+    var n = _qualifiedName;
+    if (n != null) return n;
+    return _qualifiedName = _computeQualifiedName(owner, simpleName);
   }
 
   bool get isPrivate => _n(simpleName).startsWith('_');
 
-  SourceLocation get location {
+  SourceLocation? get location {
     return _location(_reflectee);
   }
 
   List<InstanceMirror> get metadata {
-    // Get the metadata objects, convert them into InstanceMirrors using
-    // reflect() and then make them into a Dart list.
-    return new UnmodifiableListView<InstanceMirror>(
-        _metadata(_reflectee).map(reflect));
+    return _wrapMetadata(_metadata(_reflectee));
   }
 
   bool operator ==(other) {
@@ -840,24 +844,23 @@
   _TypeVariableMirror._(reflectee, String simpleName, this._owner)
       : super._(reflectee, _s(simpleName));
 
-  DeclarationMirror _owner;
+  DeclarationMirror? _owner;
   DeclarationMirror get owner {
-    if (_owner == null) {
-      _owner = (_TypeVariableMirror_owner(_reflectee) as TypeMirror)
-          .originalDeclaration;
-    }
-    return _owner;
+    var o = _owner;
+    if (o != null) return o;
+    return _owner = (_TypeVariableMirror_owner(_reflectee) as TypeMirror)
+        .originalDeclaration;
   }
 
   bool get isStatic => false;
   bool get isTopLevel => false;
 
-  TypeMirror _upperBound;
+  TypeMirror? _upperBound;
   TypeMirror get upperBound {
-    if (_upperBound == null) {
-      _upperBound = reflectType(_TypeVariableMirror_upper_bound(_reflectee));
-    }
-    return _upperBound;
+    var b = _upperBound;
+    if (b != null) return b;
+    return _upperBound =
+        reflectType(_TypeVariableMirror_upper_bound(_reflectee));
   }
 
   bool get hasReflectedType => false;
@@ -875,7 +878,7 @@
 
   String toString() => "TypeVariableMirror on '${_n(simpleName)}'";
 
-  operator ==(other) {
+  bool operator ==(other) {
     return other is TypeVariableMirror &&
         simpleName == other.simpleName &&
         owner == other.owner;
@@ -916,22 +919,21 @@
 
   bool get isTopLevel => true;
 
-  DeclarationMirror _owner;
+  DeclarationMirror? _owner;
   DeclarationMirror get owner {
-    if (_owner == null) {
-      var uri = _ClassMirror._libraryUri(_reflectee);
-      _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
-    }
-    return _owner;
+    var o = _owner;
+    if (o != null) return o;
+    var uri = _ClassMirror._libraryUri(_reflectee);
+    return _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
   }
 
-  _FunctionTypeMirror _referent;
+  _FunctionTypeMirror? _referent;
   FunctionTypeMirror get referent {
-    if (_referent == null) {
-      _referent = _nativeReferent(_reflectedType);
-      _referent._instantiator = _reflectedType;
-    }
-    return _referent;
+    var r = _referent;
+    if (r != null) return r;
+    var result = _nativeReferent(_reflectedType) as _FunctionTypeMirror;
+    result._instantiator = _reflectedType;
+    return _referent = result;
   }
 
   bool get hasReflectedType => !_isGenericDeclaration;
@@ -953,33 +955,35 @@
     }
   }
 
-  List<TypeVariableMirror> _typeVariables;
+  List<TypeVariableMirror>? _typeVariables;
   List<TypeVariableMirror> get typeVariables {
-    if (_typeVariables == null) {
-      _typeVariables = new List<TypeVariableMirror>();
-      List params = _ClassMirror._ClassMirror_type_variables(_reflectee);
-      TypedefMirror owner = originalDeclaration;
-      var mirror;
-      for (var i = 0; i < params.length; i += 2) {
-        mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
-        _typeVariables.add(mirror);
-      }
+    var v = _typeVariables;
+    if (v != null) return v;
+
+    var result = new List<TypeVariableMirror>();
+    List params = _ClassMirror._ClassMirror_type_variables(_reflectee);
+    TypedefMirror owner = originalDeclaration;
+    var mirror;
+    for (var i = 0; i < params.length; i += 2) {
+      mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
+      result.add(mirror);
     }
-    return _typeVariables;
+    return _typeVariables =
+        new UnmodifiableListView<TypeVariableMirror>(result);
   }
 
-  List<TypeMirror> _typeArguments;
+  List<TypeMirror>? _typeArguments;
   List<TypeMirror> get typeArguments {
-    if (_typeArguments == null) {
-      if (_isGenericDeclaration) {
-        _typeArguments = const <TypeMirror>[];
-      } else {
-        _typeArguments = new UnmodifiableListView<TypeMirror>(
-            _ClassMirror._computeTypeArguments(_reflectedType)
-                .cast<TypeMirror>());
-      }
+    var a = _typeArguments;
+    if (a != null) return a;
+
+    if (_isGenericDeclaration) {
+      return _typeArguments = const <TypeMirror>[];
+    } else {
+      return _typeArguments = new UnmodifiableListView<TypeMirror>(
+          _ClassMirror._computeTypeArguments(_reflectedType)
+              .cast<TypeMirror>());
     }
-    return _typeArguments;
   }
 
   String toString() => "TypedefMirror on '${_n(simpleName)}'";
@@ -1022,16 +1026,17 @@
   // The simple name and the qualified name are the same for a library.
   Symbol get qualifiedName => simpleName;
 
-  DeclarationMirror get owner => null;
+  DeclarationMirror? get owner => null;
 
   bool get isPrivate => false;
   bool get isTopLevel => false;
 
-  Type get _instantiator => null;
+  Type? get _instantiator => null;
 
-  Map<Symbol, DeclarationMirror> _declarations;
+  Map<Symbol, DeclarationMirror>? _declarations;
   Map<Symbol, DeclarationMirror> get declarations {
-    if (_declarations != null) return _declarations;
+    var d = _declarations;
+    if (d != null) return d;
 
     var decls = new Map<Symbol, DeclarationMirror>();
     var members = _computeMembers(_reflectee);
@@ -1043,15 +1048,12 @@
         new UnmodifiableMapView<Symbol, DeclarationMirror>(decls);
   }
 
-  SourceLocation get location {
+  SourceLocation? get location {
     return _location(_reflectee);
   }
 
   List<InstanceMirror> get metadata {
-    // Get the metadata objects, convert them into InstanceMirrors using
-    // reflect() and then make them into a Dart list.
-    return new UnmodifiableListView<InstanceMirror>(
-        _metadata(_reflectee).map(reflect));
+    return _wrapMetadata(_metadata(_reflectee));
   }
 
   bool operator ==(other) {
@@ -1065,12 +1067,11 @@
 
   var _cachedLibraryDependencies;
   get libraryDependencies {
-    if (_cachedLibraryDependencies == null) {
-      _cachedLibraryDependencies =
-          new UnmodifiableListView<LibraryDependencyMirror>(
-              _libraryDependencies(_reflectee).cast<LibraryDependencyMirror>());
-    }
-    return _cachedLibraryDependencies;
+    var d = _cachedLibraryDependencies;
+    if (d != null) return d;
+    return _cachedLibraryDependencies =
+        new UnmodifiableListView<LibraryDependencyMirror>(
+            _libraryDependencies(_reflectee).cast<LibraryDependencyMirror>());
   }
 
   List<dynamic> _libraryDependencies(reflectee)
@@ -1092,7 +1093,7 @@
   final LibraryMirror sourceLibrary;
   var _targetMirrorOrPrefix;
   final List<CombinatorMirror> combinators;
-  final Symbol prefix;
+  final Symbol? prefix;
   final bool isImport;
   final bool isDeferred;
   final List<InstanceMirror> metadata;
@@ -1105,15 +1106,14 @@
       this.isImport,
       this.isDeferred,
       List<dynamic> unwrappedMetadata)
-      : prefix = _s(prefixString),
+      : prefix = _sOpt(prefixString),
         combinators = new UnmodifiableListView<CombinatorMirror>(
             mutableCombinators.cast<CombinatorMirror>()),
-        metadata = new UnmodifiableListView<InstanceMirror>(
-            unwrappedMetadata.map(reflect));
+        metadata = _wrapMetadata(unwrappedMetadata);
 
   bool get isExport => !isImport;
 
-  LibraryMirror get targetLibrary {
+  LibraryMirror? get targetLibrary {
     if (_targetMirrorOrPrefix is _LibraryMirror) {
       return _targetMirrorOrPrefix;
     }
@@ -1137,7 +1137,7 @@
   static LibraryMirror _tryUpgradePrefix(libraryPrefix)
       native "LibraryMirror_fromPrefix";
 
-  SourceLocation get location => null;
+  SourceLocation? get location => null;
 }
 
 class _CombinatorMirror extends Mirror implements CombinatorMirror {
@@ -1194,14 +1194,13 @@
   ];
   bool get isOperator => _operators.contains(_n(simpleName));
 
-  DeclarationMirror _owner;
+  DeclarationMirror? _owner;
   DeclarationMirror get owner {
     // For nested closures it is possible, that the mirror for the owner has not
     // been created yet.
-    if (_owner == null) {
-      _owner = _MethodMirror_owner(_reflectee, _instantiator);
-    }
-    return _owner;
+    var o = _owner;
+    if (o != null) return o;
+    return _owner = _MethodMirror_owner(_reflectee, _instantiator);
   }
 
   bool get isPrivate =>
@@ -1209,53 +1208,52 @@
 
   bool get isTopLevel => owner is LibraryMirror;
 
-  TypeMirror _returnType;
+  TypeMirror? _returnType;
   TypeMirror get returnType {
-    if (_returnType == null) {
-      if (isConstructor) {
-        _returnType = owner;
-      } else {
-        _returnType =
-            reflectType(_MethodMirror_return_type(_reflectee, _instantiator));
-      }
+    var t = _returnType;
+    if (t != null) return t;
+    if (isConstructor) {
+      return _returnType = owner as _ClassMirror;
+    } else {
+      return _returnType =
+          reflectType(_MethodMirror_return_type(_reflectee, _instantiator));
     }
-    return _returnType;
   }
 
-  List<ParameterMirror> _parameters;
+  List<ParameterMirror>? _parameters;
   List<ParameterMirror> get parameters {
-    if (_parameters == null) {
-      _parameters = new UnmodifiableListView<ParameterMirror>(
-          _MethodMirror_parameters(_reflectee).cast<ParameterMirror>());
-    }
-    return _parameters;
+    var p = _parameters;
+    if (p != null) return p;
+    return _parameters = new UnmodifiableListView<ParameterMirror>(
+        _MethodMirror_parameters(_reflectee).cast<ParameterMirror>());
   }
 
   bool get isRegularMethod => !isGetter && !isSetter && !isConstructor;
 
-  Symbol _constructorName;
+  Symbol? _constructorName;
   Symbol get constructorName {
-    if (_constructorName == null) {
-      if (!isConstructor) {
-        _constructorName = _s('');
+    var n = _constructorName;
+    if (n != null) return n;
+
+    if (!isConstructor) {
+      return _constructorName = _s('');
+    } else {
+      var parts = MirrorSystem.getName(simpleName).split('.');
+      if (parts.length > 2) {
+        throw new _InternalMirrorError(
+            'Internal error in MethodMirror.constructorName: '
+            'malformed name <$simpleName>');
+      } else if (parts.length == 2) {
+        LibraryMirror definingLibrary = owner.owner as _LibraryMirror;
+        return _constructorName =
+            MirrorSystem.getSymbol(parts[1], definingLibrary);
       } else {
-        var parts = MirrorSystem.getName(simpleName).split('.');
-        if (parts.length > 2) {
-          throw new _InternalMirrorError(
-              'Internal error in MethodMirror.constructorName: '
-              'malformed name <$simpleName>');
-        } else if (parts.length == 2) {
-          LibraryMirror definingLibrary = owner.owner;
-          _constructorName = MirrorSystem.getSymbol(parts[1], definingLibrary);
-        } else {
-          _constructorName = _s('');
-        }
+        return _constructorName = _s('');
       }
     }
-    return _constructorName;
   }
 
-  String get source => _MethodMirror_source(_reflectee);
+  String? get source => _MethodMirror_source(_reflectee);
 
   void _patchConstructorName(ownerName) {
     var cn = _n(constructorName);
@@ -1277,7 +1275,7 @@
   List<dynamic> _MethodMirror_parameters(reflectee)
       native "MethodMirror_parameters";
 
-  static String _MethodMirror_source(reflectee) native "MethodMirror_source";
+  static String? _MethodMirror_source(reflectee) native "MethodMirror_source";
 }
 
 class _VariableMirror extends _DeclarationMirror implements VariableMirror {
@@ -1293,7 +1291,7 @@
 
   bool get isTopLevel => owner is LibraryMirror;
 
-  Type get _instantiator {
+  Type? get _instantiator {
     final o = owner; // Note: need local variable for promotion to happen.
     if (o is _ClassMirror) {
       return o._instantiator;
@@ -1306,12 +1304,11 @@
     }
   }
 
-  TypeMirror _type;
+  TypeMirror? _type;
   TypeMirror get type {
-    if (_type == null) {
-      _type = reflectType(_VariableMirror_type(_reflectee, _instantiator));
-    }
-    return _type;
+    var t = _type;
+    if (t != null) return t;
+    return _type = reflectType(_VariableMirror_type(_reflectee, _instantiator));
   }
 
   String toString() =>
@@ -1349,8 +1346,8 @@
             );
 
   Object _defaultValueReflectee;
-  InstanceMirror _defaultValue;
-  InstanceMirror get defaultValue {
+  InstanceMirror? _defaultValue;
+  InstanceMirror? get defaultValue {
     if (!isOptional) {
       return null;
     }
@@ -1362,23 +1359,22 @@
 
   bool get hasDefaultValue => _defaultValueReflectee != null;
 
-  SourceLocation get location {
+  SourceLocation? get location {
     throw new UnsupportedError("ParameterMirror.location unimplemented");
   }
 
   List<InstanceMirror> get metadata {
-    if (_unmirroredMetadata == null) return const <InstanceMirror>[];
-    return new UnmodifiableListView<InstanceMirror>(
-        _unmirroredMetadata.map(reflect));
+    var m = _unmirroredMetadata;
+    if (m == null) return const <InstanceMirror>[];
+    return _wrapMetadata(m);
   }
 
-  TypeMirror _type;
+  TypeMirror? _type;
   TypeMirror get type {
-    if (_type == null) {
-      _type = reflectType(
-          _ParameterMirror_type(_reflectee, _position, _instantiator));
-    }
-    return _type;
+    var t = _type;
+    if (t != null) return t;
+    return _type = reflectType(
+        _ParameterMirror_type(_reflectee, _position, _instantiator));
   }
 
   String toString() => "ParameterMirror on '${_n(simpleName)}'";
@@ -1396,9 +1392,9 @@
   bool get isPrivate => false;
   bool get isTopLevel => true;
 
-  DeclarationMirror get owner => null;
+  DeclarationMirror? get owner => null;
 
-  SourceLocation get location => null;
+  SourceLocation? get location => null;
   List<InstanceMirror> get metadata => const <InstanceMirror>[];
 
   bool get hasReflectedType => simpleName == #dynamic;
@@ -1448,7 +1444,7 @@
         : new _InstanceMirror._(reflectee);
   }
 
-  static ClassMirror _makeLocalClassMirror(Type key)
+  static _ClassMirror _makeLocalClassMirror(Type key)
       native "Mirrors_makeLocalClassMirror";
   static TypeMirror _makeLocalTypeMirror(Type key)
       native "Mirrors_makeLocalTypeMirror";
@@ -1470,8 +1466,9 @@
     return classMirror;
   }
 
-  static TypeMirror reflectType(Type key, [List<Type> typeArguments]) {
-    if (typeArguments != null) {
+  static TypeMirror reflectType(Type key,
+      [List<Type> typeArguments = const <Type>[]]) {
+    if (typeArguments.length != 0) {
       key = _instantiateType(key, typeArguments);
     }
     var typeMirror = _instantiationCache[key];
diff --git a/sdk_nnbd/lib/_internal/vm/lib/mirrors_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/mirrors_patch.dart
index 623fd65..ca51d0c 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/mirrors_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/mirrors_patch.dart
@@ -50,7 +50,7 @@
 }
 
 @patch
-TypeMirror reflectType(Type key, [List<Type> typeArguments]) {
+TypeMirror reflectType(Type key, [List<Type> typeArguments = const <Type>[]]) {
   return _Mirrors.reflectType(key, typeArguments);
 }
 
@@ -73,17 +73,17 @@
 
   @patch
   static String getName(Symbol symbol) {
-    return internal.Symbol.computeUnmangledName(symbol);
+    return internal.Symbol.computeUnmangledName(symbol as internal.Symbol);
   }
 
   @patch
-  static Symbol getSymbol(String name, [LibraryMirror library]) {
-    if ((library != null && library is! _LocalLibraryMirror) ||
+  static Symbol getSymbol(String name, [LibraryMirror? library]) {
+    if ((library != null && library is! _LibraryMirror) ||
         ((name.length > 0) && (name[0] == '_') && (library == null))) {
       throw new ArgumentError(library);
     }
     if (library != null) {
-      name = _mangleName(name, (library as _LocalLibraryMirror)._reflectee);
+      name = _mangleName(name, (library as _LibraryMirror)._reflectee);
     }
     return new internal.Symbol.unvalidated(name);
   }
diff --git a/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart
index 1372932..78c474a 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart
@@ -37,7 +37,7 @@
 @patch
 class WasmMemory {
   @patch
-  factory WasmMemory(int initialPages, [int maxPages]) {
+  factory WasmMemory(int initialPages, [int? maxPages]) {
     return _NativeWasmMemory(initialPages, maxPages);
   }
 }
@@ -108,7 +108,7 @@
   int _pages;
   Uint8List _buffer;
 
-  _NativeWasmMemory(int initialPages, int maxPages) : _pages = initialPages {
+  _NativeWasmMemory(int initialPages, int? maxPages) : _pages = initialPages {
     _buffer = _init(initialPages, maxPages);
   }
 
@@ -131,7 +131,7 @@
     return oldPages;
   }
 
-  Uint8List _init(int initialPages, int maxPages) native 'Wasm_initMemory';
+  Uint8List _init(int initialPages, int? maxPages) native 'Wasm_initMemory';
   Uint8List _grow(int deltaPages) native 'Wasm_growMemory';
   Uint8List _initFromInstance(_NativeWasmInstance inst)
       native 'Wasm_initMemoryFromInstance';
diff --git a/sdk_nnbd/lib/async/stream.dart b/sdk_nnbd/lib/async/stream.dart
index afcd3c5..2a24b97 100644
--- a/sdk_nnbd/lib/async/stream.dart
+++ b/sdk_nnbd/lib/async/stream.dart
@@ -497,7 +497,9 @@
       StreamSubscription<T> subscription = this.listen(null,
           onError: controller._addError, // Avoid Zone error replacement.
           onDone: controller.close);
-      final add = controller.add;
+      FutureOr<Null> add(E value) {
+        controller.add(value);
+      }
       final addError = controller._addError;
       subscription.onData((T event) {
         FutureOr<E> newValue;
@@ -1275,7 +1277,7 @@
         _completeWithErrorCallback(future, e, s);
       }
     }, cancelOnError: true);
-    subscription.onError((T value) {
+    subscription.onData((T value) {
       if (foundResult) {
         // This is the second element we get.
         try {
diff --git a/sdk_nnbd/lib/async/stream_impl.dart b/sdk_nnbd/lib/async/stream_impl.dart
index 7ed7a7c..257551b 100644
--- a/sdk_nnbd/lib/async/stream_impl.dart
+++ b/sdk_nnbd/lib/async/stream_impl.dart
@@ -329,12 +329,7 @@
    * of pending events later (if necessary).
    */
   void _addPending(_DelayedEvent event) {
-    // TODO(lrn): Restore to:
-    // _StreamImplEvents<T> pending = (_pending ??= _StreamImplEvents<T>());
-    // when that type-checks.
-    var streamEvents = _StreamImplEvents<T>();
-    _pending ??= streamEvents;
-    _StreamImplEvents<T> pending = streamEvents;
+    var pending = (_pending ??= _StreamImplEvents<T>()) as _StreamImplEvents<T>;
     pending.add(event);
     if (!_hasPending) {
       _state |= _STATE_HAS_PENDING;
diff --git a/sdk_nnbd/lib/cli/cli.dart b/sdk_nnbd/lib/cli/cli.dart
index 4748181..9c19c3a 100644
--- a/sdk_nnbd/lib/cli/cli.dart
+++ b/sdk_nnbd/lib/cli/cli.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 /// {@category VM}
 library dart.cli;
 
diff --git a/sdk_nnbd/lib/cli/wait_for.dart b/sdk_nnbd/lib/cli/wait_for.dart
index d4dd71e..3c9525b 100644
--- a/sdk_nnbd/lib/cli/wait_for.dart
+++ b/sdk_nnbd/lib/cli/wait_for.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.cli;
 
 /**
@@ -55,10 +53,10 @@
 // native implementation. In the standalone VM this is set to _waitForEvent()
 // above. If it is null, calling waitFor() will throw an UnsupportedError.
 @pragma("vm:entry-point")
-void Function(int) _waitForEventClosure;
+void Function(int)? _waitForEventClosure;
 
 class _WaitForUtils {
-  static void waitForEvent({Duration timeout}) {
+  static void waitForEvent({Duration? timeout}) {
     if (_waitForEventClosure == null) {
       throw new UnsupportedError("waitFor is not supported by this embedder");
     }
@@ -113,11 +111,11 @@
  * subsequent calls block waiting for a condition that is only satisfied when
  * an earlier call returns.
  */
-T waitFor<T>(Future<T> future, {Duration timeout}) {
-  T result;
+T waitFor<T>(Future<T> future, {Duration? timeout}) {
+  late T result;
   bool futureCompleted = false;
-  Object error;
-  StackTrace stacktrace;
+  Object? error;
+  StackTrace? stacktrace;
   future.then((r) {
     futureCompleted = true;
     result = r;
@@ -126,13 +124,13 @@
     stacktrace = st;
   });
 
-  Stopwatch s;
+  late Stopwatch s;
   if (timeout != null) {
     s = new Stopwatch()..start();
   }
   Timer.run(() {}); // Enusre there is at least one message.
   while (!futureCompleted && (error == null)) {
-    Duration remaining;
+    Duration? remaining;
     if (timeout != null) {
       if (s.elapsed >= timeout) {
         throw new TimeoutException("waitFor() timed out", timeout);
diff --git a/sdk_nnbd/lib/core/list.dart b/sdk_nnbd/lib/core/list.dart
index f72158f..a6be658 100644
--- a/sdk_nnbd/lib/core/list.dart
+++ b/sdk_nnbd/lib/core/list.dart
@@ -157,8 +157,7 @@
    * This constructor creates a growable list when [growable] is true;
    * otherwise, it returns a fixed-length list.
    */
-  factory List.of(Iterable<E> elements, {bool growable = true}) =>
-      List<E>.from(elements, growable: growable);
+  external factory List.of(Iterable<E> elements, {bool growable = true});
 
   /**
    * Generates a list of values.
diff --git a/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart b/sdk_nnbd/lib/js_util/js_util.dart
similarity index 96%
copy from sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart
copy to sdk_nnbd/lib/js_util/js_util.dart
index a01a537..7718644 100644
--- a/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart
+++ b/sdk_nnbd/lib/js_util/js_util.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
+// @dart = 2.6
 
 /// Utility methods to efficiently manipulate typed JSInterop objects in cases
 /// where the name to call is not known at runtime. You should only use these
@@ -30,13 +30,13 @@
 /// JavaScript type, and all other objects are proxied.
 jsify(object) {
   if ((object is! Map) && (object is! Iterable)) {
-    throw new ArgumentError("object must be a Map or Iterable");
+    throw ArgumentError("object must be a Map or Iterable");
   }
   return _convertDataTree(object);
 }
 
 _convertDataTree(data) {
-  var _convertedObjects = new HashMap.identity();
+  var _convertedObjects = HashMap.identity();
 
   _convert(o) {
     if (_convertedObjects.containsKey(o)) {
@@ -65,13 +65,16 @@
 newObject() => JS('=Object', '{}');
 
 bool hasProperty(o, name) => JS('bool', '# in #', name, o);
+
 getProperty(o, name) => JS('Object|Null', '#[#]', o, name);
+
 setProperty(o, name, value) => JS('', '#[#]=#', o, name, value);
 
 callMethod(o, String method, List args) =>
     JS('Object|Null', '#[#].apply(#, #)', o, method, o, args);
 
 bool instanceof(o, Function type) => JS('bool', '# instanceof #', o, type);
+
 callConstructor(Function constr, List arguments) {
   if (arguments == null) {
     return JS('Object', 'new #()', constr);
diff --git a/sdk_nnbd/lib/js_util/js_util_sources.gni b/sdk_nnbd/lib/js_util/js_util_sources.gni
index 3b7c1b1..d3ac6d2 100644
--- a/sdk_nnbd/lib/js_util/js_util_sources.gni
+++ b/sdk_nnbd/lib/js_util/js_util_sources.gni
@@ -2,4 +2,4 @@
 # 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.
 
-js_util_sdk_sources = [ "dart2js/js_util_dart2js.dart" ]
+js_util_sdk_sources = [ "js_util.dart" ]
diff --git a/sdk_nnbd/lib/libraries.json b/sdk_nnbd/lib/libraries.json
index 3391292..7ef76a8 100644
--- a/sdk_nnbd/lib/libraries.json
+++ b/sdk_nnbd/lib/libraries.json
@@ -130,20 +130,20 @@
         "patches": "../../sdk/lib/_internal/vm/lib/math_patch.dart"
       },
       "mirrors": {
-        "uri": "../../sdk/lib/mirrors/mirrors.dart",
+        "uri": "mirrors/mirrors.dart",
         "patches": [
-          "../../sdk/lib/_internal/vm/lib/mirrors_patch.dart",
-          "../../sdk/lib/_internal/vm/lib/mirrors_impl.dart",
-          "../../sdk/lib/_internal/vm/lib/mirror_reference.dart"
+          "_internal/vm/lib/mirrors_patch.dart",
+          "_internal/vm/lib/mirrors_impl.dart",
+          "_internal/vm/lib/mirror_reference.dart"
         ]
       },
       "nativewrappers": {
         "uri": "../../sdk/lib/html/dartium/nativewrappers.dart"
       },
       "cli": {
-        "uri": "../../sdk/lib/cli/cli.dart",
+        "uri": "cli/cli.dart",
         "patches": [
-          "../../sdk/lib/_internal/vm/bin/cli_patch.dart"
+          "_internal/vm/bin/cli_patch.dart"
         ]
       },
       "typed_data": {
@@ -151,10 +151,10 @@
         "patches": "../../sdk/lib/_internal/vm/lib/typed_data_patch.dart"
       },
       "_vmservice": {
-        "uri": "../../sdk/lib/vmservice/vmservice.dart"
+        "uri": "vmservice/vmservice.dart"
       },
       "vmservice_io": {
-        "uri": "../../runtime/bin/vmservice/vmservice_io.dart"
+        "uri": "_internal/vm/bin/vmservice_io.dart"
       }
     }
   },
@@ -211,7 +211,7 @@
         "patches": "../../sdk/lib/js/_js_client.dart"
       },
       "js_util": {
-        "uri": "../../sdk/lib/js_util/dart2js/js_util_dart2js.dart"
+        "uri": "../../sdk/lib/js_util/js_util.dart"
       },
       "math": {
         "uri": "../../sdk/lib/math/math.dart",
@@ -321,7 +321,7 @@
         "patches": "../../sdk/lib/js/_js_server.dart"
       },
       "js_util": {
-        "uri": "../../sdk/lib/js_util/dart2js/js_util_dart2js.dart"
+        "uri": "../../sdk/lib/js_util/js_util.dart"
       },
       "math": {
         "uri": "../../sdk/lib/math/math.dart",
@@ -468,7 +468,7 @@
         "patches": "_internal/js_dev_runtime/patch/js_patch.dart"
       },
       "js_util": {
-        "uri": "_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart"
+        "uri": "js_util/js_util.dart"
       },
       "svg": {
         "uri": "svg/dart2js/svg_dart2js.dart"
diff --git a/sdk_nnbd/lib/libraries.yaml b/sdk_nnbd/lib/libraries.yaml
index 1aa29b8..d5079fa 100644
--- a/sdk_nnbd/lib/libraries.yaml
+++ b/sdk_nnbd/lib/libraries.yaml
@@ -95,9 +95,9 @@
         - "../../sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart"
 
     wasm:
-      uri: "../../sdk/lib/wasm/wasm.dart"
+      uri: "wasm/wasm.dart"
       patches:
-        - "../../sdk/lib/_internal/vm/lib/wasm_patch.dart"
+        - "_internal/vm/lib/wasm_patch.dart"
 
     _http:
       uri: "../../sdk/lib/_http/http.dart"
@@ -131,29 +131,29 @@
       patches: "../../sdk/lib/_internal/vm/lib/math_patch.dart"
 
     mirrors:
-      uri: "../../sdk/lib/mirrors/mirrors.dart"
+      uri: "mirrors/mirrors.dart"
       patches:
-        - "../../sdk/lib/_internal/vm/lib/mirrors_patch.dart"
-        - "../../sdk/lib/_internal/vm/lib/mirrors_impl.dart"
-        - "../../sdk/lib/_internal/vm/lib/mirror_reference.dart"
+        - "_internal/vm/lib/mirrors_patch.dart"
+        - "_internal/vm/lib/mirrors_impl.dart"
+        - "_internal/vm/lib/mirror_reference.dart"
 
     nativewrappers:
       uri: "../../sdk/lib/html/dartium/nativewrappers.dart"
 
     cli:
-      uri: "../../sdk/lib/cli/cli.dart"
+      uri: "cli/cli.dart"
       patches:
-        - "../../sdk/lib/_internal/vm/bin/cli_patch.dart"
+        - "_internal/vm/bin/cli_patch.dart"
 
     typed_data:
       uri: "../../sdk/lib/typed_data/typed_data.dart"
       patches: "../../sdk/lib/_internal/vm/lib/typed_data_patch.dart"
 
     _vmservice:
-      uri: "../../sdk/lib/vmservice/vmservice.dart"
+      uri: "vmservice/vmservice.dart"
 
     vmservice_io:
-      uri: "../../runtime/bin/vmservice/vmservice_io.dart"
+      uri: "_internal/vm/bin/vmservice_io.dart"
 
 dart2js:
   libraries:
@@ -208,7 +208,7 @@
       patches: "../../sdk/lib/js/_js_client.dart"
 
     js_util:
-      uri: "../../sdk/lib/js_util/dart2js/js_util_dart2js.dart"
+      uri: "../../sdk/lib/js_util/js_util.dart"
 
     math:
       uri: "../../sdk/lib/math/math.dart"
@@ -316,7 +316,7 @@
       patches: "../../sdk/lib/js/_js_server.dart"
 
     js_util:
-      uri: "../../sdk/lib/js_util/dart2js/js_util_dart2js.dart"
+      uri: "../../sdk/lib/js_util/js_util.dart"
 
     math:
       uri: "../../sdk/lib/math/math.dart"
@@ -461,7 +461,7 @@
         patches: "_internal/js_dev_runtime/patch/js_patch.dart"
 
       js_util:
-        uri: "_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart"
+        uri: "js_util/js_util.dart"
 
       svg:
         uri: "svg/dart2js/svg_dart2js.dart"
diff --git a/sdk_nnbd/lib/mirrors/mirrors.dart b/sdk_nnbd/lib/mirrors/mirrors.dart
index ec27699..d8ed89f 100644
--- a/sdk_nnbd/lib/mirrors/mirrors.dart
+++ b/sdk_nnbd/lib/mirrors/mirrors.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 // For the purposes of the mirrors library, we adopt a naming
 // convention with respect to getters and setters.  Specifically, for
 // some variable or field...
@@ -132,7 +130,7 @@
    * Using this method may result in larger output.  If possible, use
    * the const constructor of [Symbol] or symbol literals.
    */
-  external static Symbol getSymbol(String name, [LibraryMirror library]);
+  external static Symbol getSymbol(String name, [LibraryMirror? library]);
 }
 
 /**
@@ -184,7 +182,8 @@
  * function can only be used to obtain type mirrors on types of the current
  * isolate.
  */
-external TypeMirror reflectType(Type key, [List<Type> typeArguments]);
+external TypeMirror reflectType(Type key,
+    [List<Type> typeArguments = const <Type>[]]);
 
 /**
  * A [Mirror] reflects some Dart language entity.
@@ -293,7 +292,7 @@
    * * For a parameter, local variable or local function the owner is the
    *   immediately enclosing function.
    */
-  DeclarationMirror get owner;
+  DeclarationMirror? get owner;
 
   /**
    * Whether this declaration is library private.
@@ -345,7 +344,7 @@
    *
    * This operation is optional and may throw an [UnsupportedError].
    */
-  SourceLocation get location;
+  SourceLocation? get location;
 
   /**
    * A list of the metadata associated with this declaration.
@@ -406,7 +405,7 @@
    * TODO(turnidge): Handle optional & named arguments.
    */
   InstanceMirror invoke(Symbol memberName, List positionalArguments,
-      [Map<Symbol, dynamic> namedArguments]);
+      [Map<Symbol, dynamic> namedArguments = const <Symbol, dynamic>{}]);
 
   /**
    * Invokes a getter and returns a mirror on the result.
@@ -598,7 +597,7 @@
    * method throws *e*.
    */
   InstanceMirror apply(List positionalArguments,
-      [Map<Symbol, dynamic> namedArguments]);
+      [Map<Symbol, dynamic> namedArguments = const <Symbol, dynamic>{}]);
 }
 
 /**
@@ -656,17 +655,17 @@
 
   /// Returns the library mirror of the library that is imported or exported,
   /// or null if the library is not loaded.
-  LibraryMirror get targetLibrary;
+  LibraryMirror? get targetLibrary;
 
   /// Returns the prefix if this is a prefixed import and `null` otherwise.
-  Symbol get prefix;
+  Symbol? get prefix;
 
   /// Returns the list of show/hide combinators on the import/export
   /// declaration.
   List<CombinatorMirror> get combinators;
 
   /// Returns the source location for this import/export declaration.
-  SourceLocation get location;
+  SourceLocation? get location;
 
   List<InstanceMirror> get metadata;
 
@@ -781,7 +780,7 @@
    *
    * If this type is [:Object:], the superclass will be null.
    */
-  ClassMirror get superclass;
+  ClassMirror? get superclass;
 
   /**
    * A list of mirrors on the superinterfaces of the reflectee.
@@ -879,7 +878,7 @@
    *   catch), this method throws *e*.
    */
   InstanceMirror newInstance(Symbol constructorName, List positionalArguments,
-      [Map<Symbol, dynamic> namedArguments]);
+      [Map<Symbol, dynamic> namedArguments = const <Symbol, dynamic>{}]);
 
   /**
    * Whether this mirror is equal to [other].
@@ -983,7 +982,7 @@
   /**
    * The source code for the reflectee, if available. Otherwise null.
    */
-  String get source;
+  String? get source;
 
   /**
    * A list of mirrors on the parameters for the reflectee.
@@ -1171,7 +1170,7 @@
    *
    * Returns `null` for a required parameter.
    */
-  InstanceMirror get defaultValue;
+  InstanceMirror? get defaultValue;
 }
 
 /**
diff --git a/sdk_nnbd/lib/vmservice/asset.dart b/sdk_nnbd/lib/vmservice/asset.dart
index a6b3927..484dc33 100644
--- a/sdk_nnbd/lib/vmservice/asset.dart
+++ b/sdk_nnbd/lib/vmservice/asset.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._vmservice;
 
 class Asset {
@@ -39,15 +37,15 @@
     }
   }
 
-  static Map<String, Asset> request() {
-    Uint8List tarBytes = _requestAssets();
+  static Map<String, Asset>? request() {
+    Uint8List? tarBytes = _requestAssets();
     if (tarBytes == null) {
       return null;
     }
     List assetList = _decodeAssets(tarBytes);
-    Map<String, Asset> assets = new HashMap<String, Asset>();
+    Map<String, Asset> assets = HashMap<String, Asset>();
     for (int i = 0; i < assetList.length; i += 2) {
-      var a = new Asset(assetList[i], assetList[i + 1]);
+      var a = Asset(assetList[i], assetList[i + 1]);
       assets[a.name] = a;
     }
     return assets;
@@ -58,7 +56,7 @@
 
 List _decodeAssets(Uint8List data) native "VMService_DecodeAssets";
 
-Map<String, Asset> _assets;
+Map<String, Asset>? _assets;
 Map<String, Asset> get assets {
   if (_assets == null) {
     try {
@@ -67,5 +65,5 @@
       print('Could not load Observatory assets: $e');
     }
   }
-  return _assets;
+  return _assets!;
 }
diff --git a/sdk_nnbd/lib/vmservice/client.dart b/sdk_nnbd/lib/vmservice/client.dart
index 70d978c..cbe365e 100644
--- a/sdk_nnbd/lib/vmservice/client.dart
+++ b/sdk_nnbd/lib/vmservice/client.dart
@@ -2,11 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._vmservice;
 
-typedef void ClientServiceHandle(Message response);
+typedef void ClientServiceHandle(Message? response);
 
 // A service client.
 abstract class Client {
@@ -14,18 +12,18 @@
   final bool sendEvents;
 
   /// A set streamIds which describes the streams the client is connected to
-  final Set<String> streams = new Set<String>();
+  final Set<String> streams = <String>{};
 
   /// Services registered and their aliases
   /// key: service
   /// value: alias
-  final Map<String, String> services = new Map<String, String>();
+  final Map<String, String> services = <String, String>{};
 
   /// Callbacks registered for service invocations set to the client
   /// key: RPC id used for the request
   /// value: callback that should be invoked
   final Map<String, ClientServiceHandle> serviceHandles =
-      new Map<String, ClientServiceHandle>();
+      <String, ClientServiceHandle>{};
 
   Client(this.service, {bool sendEvents: true}) : this.sendEvents = sendEvents {
     service._addClient(this);
@@ -58,10 +56,8 @@
     service.routeRequest(service, message);
   }
 
-  // Sends a result to the client.  Implemented in subclasses.
+  // Sends a result to the client. Implemented in subclasses.
   void post(Response result);
 
-  dynamic toJson() {
-    return {};
-  }
+  dynamic toJson() => {};
 }
diff --git a/sdk_nnbd/lib/vmservice/constants.dart b/sdk_nnbd/lib/vmservice/constants.dart
index 5edd3ef..914576b 100644
--- a/sdk_nnbd/lib/vmservice/constants.dart
+++ b/sdk_nnbd/lib/vmservice/constants.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._vmservice;
 
 // These must be kept in sync with runtime/vm/service.cc.
diff --git a/sdk_nnbd/lib/vmservice/devfs.dart b/sdk_nnbd/lib/vmservice/devfs.dart
index d5ca40f..3eeb14c 100644
--- a/sdk_nnbd/lib/vmservice/devfs.dart
+++ b/sdk_nnbd/lib/vmservice/devfs.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._vmservice;
 
 String _encodeDevFSDisabledError(Message message) {
@@ -27,7 +25,7 @@
   final String name;
   final Uri uri;
 
-  Uri resolvePath(String path) {
+  Uri? resolvePath(String path) {
     if (path.startsWith('/')) {
       path = path.substring(1);
     }
@@ -36,19 +34,21 @@
     }
     Uri pathUri;
     try {
-      pathUri = new Uri.file(path);
-    } on FormatException catch (e) {
+      pathUri = Uri.file(path);
+      // ignore: unused_catch_clause
+    } on FormatException catch (_) {
       return null;
     }
 
     return resolve(pathUri);
   }
 
-  Uri resolve(Uri pathUri) {
+  Uri? resolve(Uri pathUri) {
     try {
       // Make sure that this pathUri can be converted to a file path.
       pathUri.toFilePath();
-    } on UnsupportedError catch (e) {
+      // ignore: unused_catch_clause
+    } on UnsupportedError catch (_) {
       return null;
     }
 
@@ -60,21 +60,19 @@
     return resolvedUri;
   }
 
-  Map toMap() {
-    return {
-      'type': 'FileSystem',
-      'name': name,
-      'uri': uri.toString(),
-    };
-  }
+  Map<String, String> toMap() => {
+        'type': 'FileSystem',
+        'name': name,
+        'uri': uri.toString(),
+      };
 }
 
 class DevFS {
   DevFS();
 
-  Map<String, _FileSystem> _fsMap = {};
+  final Map<String, _FileSystem> _fsMap = {};
 
-  final Set _rpcNames = new Set.from([
+  final Set _rpcNames = <String>{
     '_listDevFS',
     '_createDevFS',
     '_deleteDevFS',
@@ -82,7 +80,7 @@
     '_writeDevFSFile',
     '_writeDevFSFiles',
     '_listDevFSFiles',
-  ]);
+  };
 
   void cleanup() {
     var deleteDir = VMServiceEmbedderHooks.deleteDir;
@@ -102,7 +100,7 @@
   }
 
   Future<String> handleMessage(Message message) async {
-    switch (message.method) {
+    switch (message.method!) {
       case '_listDevFS':
         return _listDevFS(message);
       case '_createDevFS':
@@ -124,9 +122,9 @@
   }
 
   Future<String> handlePutStream(
-      Object fsName, Object path, Uri fsUri, Stream<List<int>> bytes) async {
+      Object? fsName, Object? path, Uri? fsUri, Stream<List<int>> bytes) async {
     // A dummy Message for error message construction.
-    Message message = new Message.forMethod('_writeDevFSFile');
+    Message message = Message.forMethod('_writeDevFSFile');
     var writeStreamFile = VMServiceEmbedderHooks.writeStreamFile;
     if (writeStreamFile == null) {
       return _encodeDevFSDisabledError(message);
@@ -141,7 +139,7 @@
     if (fs == null) {
       return _encodeFileSystemDoesNotExistError(message, fsName);
     }
-    Uri uri = fsUri;
+    Uri? uri = fsUri;
     if (uri == null) {
       if (path == null) {
         return encodeMissingParamError(message, 'path');
@@ -187,7 +185,7 @@
       return _encodeFileSystemAlreadyExistsError(message, fsName);
     }
     var tempDir = await createTempDir(fsName);
-    fs = new _FileSystem(fsName, tempDir);
+    fs = _FileSystem(fsName, tempDir);
     _fsMap[fsName] = fs;
     return encodeResult(message, fs.toMap());
   }
@@ -228,7 +226,7 @@
     if (fs == null) {
       return _encodeFileSystemDoesNotExistError(message, fsName);
     }
-    Uri uri;
+    Uri? uri;
     if (message.params['uri'] != null) {
       try {
         var uriParam = message.params['uri'];
@@ -282,7 +280,7 @@
     if (fs == null) {
       return _encodeFileSystemDoesNotExistError(message, fsName);
     }
-    Uri uri;
+    Uri? uri;
     if (message.params['uri'] != null) {
       try {
         var uriParam = message.params['uri'];
diff --git a/sdk_nnbd/lib/vmservice/message.dart b/sdk_nnbd/lib/vmservice/message.dart
index efe0f06..51d8d22 100644
--- a/sdk_nnbd/lib/vmservice/message.dart
+++ b/sdk_nnbd/lib/vmservice/message.dart
@@ -2,19 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._vmservice;
 
 enum MessageType { Request, Notification, Response }
 
 class Message {
-  final Completer<Response> _completer = new Completer<Response>.sync();
+  final Completer<Response> _completer = Completer<Response>.sync();
   bool get completed => _completer.isCompleted;
 
   /// Future of response.
   Future<Response> get response => _completer.future;
-  Client client;
+  Client? client;
 
   // Is a notification message (no serial)
   final MessageType type;
@@ -22,35 +20,35 @@
   // Client-side identifier for this message.
   final serial;
 
-  final String method;
+  final String? method;
 
-  final Map params = new Map();
-  final Map result = new Map();
-  final Map error = new Map();
+  final Map<String, dynamic> params = {};
+  final Map result = {};
+  final Map error = {};
 
-  factory Message.fromJsonRpc(Client client, Map map) {
+  factory Message.fromJsonRpc(Client? client, Map map) {
     if (map.containsKey('id')) {
       final id = map['id'];
       if (id != null && id is! num && id is! String) {
-        throw new Exception('"id" must be a number, string, or null.');
+        throw Exception('"id" must be a number, string, or null.');
       }
       if (map.containsKey('method')) {
-        return new Message._fromJsonRpcRequest(client, map);
+        return Message._fromJsonRpcRequest(client, map);
       }
       if (map.containsKey('result')) {
-        return new Message._fromJsonRpcResult(client, map);
+        return Message._fromJsonRpcResult(client, map);
       }
       if (map.containsKey('error')) {
-        return new Message._fromJsonRpcError(client, map);
+        return Message._fromJsonRpcError(client, map);
       }
     } else if (map.containsKey('method')) {
-      return new Message._fromJsonRpcNotification(client, map);
+      return Message._fromJsonRpcNotification(client, map);
     }
-    throw new Exception('Invalid message format');
+    throw Exception('Invalid message format');
   }
 
   // http://www.jsonrpc.org/specification#request_object
-  Message._fromJsonRpcRequest(Client client, Map map)
+  Message._fromJsonRpcRequest(Client? client, Map map)
       : client = client,
         type = MessageType.Request,
         serial = map['id'],
@@ -61,7 +59,7 @@
   }
 
   // http://www.jsonrpc.org/specification#notification
-  Message._fromJsonRpcNotification(Client client, Map map)
+  Message._fromJsonRpcNotification(Client? client, Map map)
       : client = client,
         type = MessageType.Notification,
         method = map['method'],
@@ -72,7 +70,7 @@
   }
 
   // http://www.jsonrpc.org/specification#response_object
-  Message._fromJsonRpcResult(Client client, Map map)
+  Message._fromJsonRpcResult(Client? client, Map map)
       : client = client,
         type = MessageType.Response,
         serial = map['id'],
@@ -81,7 +79,7 @@
   }
 
   // http://www.jsonrpc.org/specification#response_object
-  Message._fromJsonRpcError(Client client, Map map)
+  Message._fromJsonRpcError(Client? client, Map map)
       : client = client,
         type = MessageType.Response,
         serial = map['id'],
@@ -120,15 +118,13 @@
     params['isolateId'] = isolate.serviceId;
   }
 
-  Uri toUri() {
-    return new Uri(path: method, queryParameters: params);
-  }
+  Uri toUri() => Uri(path: method!, queryParameters: params);
 
   dynamic toJson() {
     throw 'unsupported';
   }
 
-  dynamic forwardToJson([Map overloads]) {
+  dynamic forwardToJson([Map? overloads]) {
     Map<dynamic, dynamic> json = {'jsonrpc': '2.0', 'id': serial};
     switch (type) {
       case MessageType.Request:
@@ -157,25 +153,21 @@
   // This has a side effect that boolean literal values like true become 'true'
   // and thus indistinguishable from the string literal 'true'.
   List<String> _makeAllString(List list) {
-    if (list == null) {
-      return null;
-    }
-    var new_list = new List<String>(list.length);
-    for (var i = 0; i < list.length; i++) {
-      new_list[i] = list[i].toString();
-    }
-    return new_list;
+    var newList = <String>[
+      for (final e in list) e.toString(),
+    ];
+    return newList;
   }
 
   Future<Response> sendToIsolate(SendPort sendPort) {
-    final receivePort = new RawReceivePort();
+    final receivePort = RawReceivePort();
     receivePort.handler = (value) {
       receivePort.close();
       _setResponseFromPort(value);
     };
     var keys = _makeAllString(params.keys.toList(growable: false));
     var values = _makeAllString(params.values.toList(growable: false));
-    var request = new List(6)
+    var request = List(6)
       ..[0] = 0 // Make room for OOB message type.
       ..[1] = receivePort.sendPort
       ..[2] = serial
@@ -184,7 +176,7 @@
       ..[5] = values;
     if (!sendIsolateServiceMessage(sendPort, request)) {
       receivePort.close();
-      _completer.complete(new Response.internalError(
+      _completer.complete(Response.internalError(
           'could not send message [${serial}] to isolate'));
     }
     return _completer.future;
@@ -212,19 +204,19 @@
   }
 
   Future<Response> sendToVM() {
-    final receivePort = new RawReceivePort();
+    final receivePort = RawReceivePort();
     receivePort.handler = (value) {
       receivePort.close();
       _setResponseFromPort(value);
     };
     var keys = params.keys.toList(growable: false);
     var values = params.values.toList(growable: false);
-    if (!_methodNeedsObjectParameters(method)) {
+    if (!_methodNeedsObjectParameters(method!)) {
       keys = _makeAllString(keys);
       values = _makeAllString(values);
     }
 
-    final request = new List(6)
+    final request = List(6)
       ..[0] = 0 // Make room for OOB message type.
       ..[1] = receivePort.sendPort
       ..[2] = serial
@@ -232,7 +224,7 @@
       ..[4] = keys
       ..[5] = values;
 
-    if (_methodNeedsObjectParameters(method)) {
+    if (_methodNeedsObjectParameters(method!)) {
       // We use a different method invocation path here.
       sendObjectRootServiceMessage(request);
     } else {
@@ -252,7 +244,7 @@
   }
 
   void setResponse(String response) {
-    _completer.complete(new Response(ResponsePayloadKind.String, response));
+    _completer.complete(Response(ResponsePayloadKind.String, response));
   }
 
   void setErrorResponse(int code, String details) {
diff --git a/sdk_nnbd/lib/vmservice/message_router.dart b/sdk_nnbd/lib/vmservice/message_router.dart
index 6c6c746..3af7319 100644
--- a/sdk_nnbd/lib/vmservice/message_router.dart
+++ b/sdk_nnbd/lib/vmservice/message_router.dart
@@ -2,12 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._vmservice;
 
 abstract class MessageRouter {
-  Future<Response> routeRequest(VMService service, Message message);
+  Future<Response?> routeRequest(VMService service, Message message);
   void routeResponse(Message message);
 }
 
@@ -35,6 +33,8 @@
         case ResponsePayloadKind.Binary:
         case ResponsePayloadKind.Utf8String:
           return payload is Uint8List;
+        default:
+          return false;
       }
     }());
   }
@@ -45,7 +45,7 @@
       : this(ResponsePayloadKind.String, json.encode(value));
 
   factory Response.internalError(String message) {
-    return new Response.json({
+    return Response.json({
       'type': 'ServiceError',
       'id': '',
       'kind': 'InternalError',
@@ -59,13 +59,12 @@
   ///     Utf8String: a single element list containing Uint8List
   factory Response.from(Object value) {
     if (value is String) {
-      return new Response(ResponsePayloadKind.String, value);
+      return Response(ResponsePayloadKind.String, value);
     } else if (value is Uint8List) {
-      return new Response(ResponsePayloadKind.Binary, value);
+      return Response(ResponsePayloadKind.Binary, value);
     } else if (value is List) {
       assert(value.length == 1);
-      return new Response(
-          ResponsePayloadKind.Utf8String, value[0] as Uint8List);
+      return Response(ResponsePayloadKind.Utf8String, value[0] as Uint8List);
     } else if (value is Response) {
       return value;
     } else {
diff --git a/sdk_nnbd/lib/vmservice/named_lookup.dart b/sdk_nnbd/lib/vmservice/named_lookup.dart
index a53c57a..176d1a7 100644
--- a/sdk_nnbd/lib/vmservice/named_lookup.dart
+++ b/sdk_nnbd/lib/vmservice/named_lookup.dart
@@ -2,18 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._vmservice;
 
 /// Set like containes which automatically generated String ids for its items
-class NamedLookup<E> extends Object with IterableMixin<E> {
+class NamedLookup<E extends Object> extends Object with IterableMixin<E> {
   final IdGenerator _generator;
-  final Map<String, E> _elements = new Map<String, E>();
-  final Map<E, String> _ids = new Map<E, String>();
+  final Map<String, E> _elements = <String, E>{};
+  final Map<E, String> _ids = <E, String>{};
 
   NamedLookup({String prologue = ''})
-      : _generator = new IdGenerator(prologue: prologue);
+      : _generator = IdGenerator(prologue: prologue);
 
   void add(E e) {
     final id = _generator.newId();
@@ -22,13 +20,13 @@
   }
 
   void remove(E e) {
-    final id = _ids.remove(e);
+    final id = _ids.remove(e)!;
     _elements.remove(id);
     _generator.release(id);
   }
 
-  E operator [](String id) => _elements[id];
-  String keyOf(E e) => _ids[e];
+  E operator [](String id) => _elements[id]!;
+  String keyOf(E e) => _ids[e]!;
 
   Iterator<E> get iterator => _ids.keys.iterator;
 }
@@ -38,10 +36,10 @@
   /// Fixed initial part of the id
   final String prologue;
   // Ids in use
-  final Set<String> _used = new Set<String>();
+  final Set<String> _used = <String>{};
 
   /// Ids that has been released (use these before generate new ones)
-  final Set<String> _free = new Set<String>();
+  final Set<String> _free = <String>{};
 
   /// Next id to generate if no one can be recycled (first use _free);
   int _next = 0;
diff --git a/sdk_nnbd/lib/vmservice/running_isolate.dart b/sdk_nnbd/lib/vmservice/running_isolate.dart
index cfe9be9..8a6dd36 100644
--- a/sdk_nnbd/lib/vmservice/running_isolate.dart
+++ b/sdk_nnbd/lib/vmservice/running_isolate.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._vmservice;
 
 class RunningIsolate implements MessageRouter {
diff --git a/sdk_nnbd/lib/vmservice/running_isolates.dart b/sdk_nnbd/lib/vmservice/running_isolates.dart
index e925e03..5f99a26 100644
--- a/sdk_nnbd/lib/vmservice/running_isolates.dart
+++ b/sdk_nnbd/lib/vmservice/running_isolates.dart
@@ -2,13 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart._vmservice;
 
 class RunningIsolates implements MessageRouter {
-  final Map<int, RunningIsolate> isolates = new Map<int, RunningIsolate>();
-  int _rootPortId;
+  final Map<int, RunningIsolate> isolates = <int, RunningIsolate>{};
+  int? _rootPortId;
 
   RunningIsolates();
 
@@ -16,7 +14,7 @@
     if (_rootPortId == null) {
       _rootPortId = portId;
     }
-    var ri = new RunningIsolate(portId, sp, name);
+    var ri = RunningIsolate(portId, sp, name);
     isolates[portId] = ri;
   }
 
@@ -29,7 +27,7 @@
 
   @override
   Future<Response> routeRequest(VMService service, Message message) {
-    String isolateParam = message.params['isolateId'];
+    String isolateParam = message.params['isolateId']!;
     int isolateId;
     if (!isolateParam.startsWith('isolates/')) {
       message.setErrorResponse(
@@ -38,7 +36,7 @@
     }
     isolateParam = isolateParam.substring('isolates/'.length);
     if (isolateParam == 'root') {
-      isolateId = _rootPortId;
+      isolateId = _rootPortId!;
     } else {
       try {
         isolateId = int.parse(isolateParam);
@@ -62,7 +60,7 @@
     }
 
     if (message.method == 'evaluateInFrame' || message.method == 'evaluate') {
-      return new _Evaluator(message, isolate, service).run();
+      return _Evaluator(message, isolate, service).run();
     } else {
       return isolate.routeRequest(service, message);
     }
@@ -81,7 +79,7 @@
     Map<String, dynamic> responseJson = buildScopeResponse.decodeJson();
 
     if (responseJson.containsKey('error')) {
-      return new Response.from(encodeCompilationError(
+      return Response.from(encodeCompilationError(
           _message, responseJson['error']['data']['details']));
     }
 
@@ -89,9 +87,9 @@
     try {
       kernelBase64 = await _compileExpression(responseJson['result']);
     } catch (e) {
-      return new Response.from(encodeCompilationError(_message, e.toString()));
+      return Response.from(encodeCompilationError(_message, e.toString()));
     }
-    return _evaluateCompiledExpression(kernelBase64);
+    return await _evaluateCompiledExpression(kernelBase64);
   }
 
   Message _message;
@@ -110,7 +108,7 @@
       buildScopeParams['params']['scope'] = _message.params['scope'];
     }
     var buildScope =
-        new Message._fromJsonRpcRequest(_message.client, buildScopeParams);
+        Message._fromJsonRpcRequest(_message.client!, buildScopeParams);
 
     // Decode the JSON and and insert it into the map. The map key
     // is the request Uri.
@@ -119,37 +117,37 @@
 
   Future<String> _compileExpression(
       Map<String, dynamic> buildScopeResponseResult) {
-    Client externalClient =
+    Client? externalClient =
         _service._findFirstClientThatHandlesService('compileExpression');
 
-    Map compileParams = {
-      'isolateId': _message.params['isolateId'],
-      'expression': _message.params['expression'],
-      'definitions': buildScopeResponseResult['param_names'],
-      'typeDefinitions': buildScopeResponseResult['type_params_names'],
-      'libraryUri': buildScopeResponseResult['libraryUri'],
-      'isStatic': buildScopeResponseResult['isStatic'],
+    final compileParams = <String, String>{
+      'isolateId': _message.params['isolateId']!,
+      'expression': _message.params['expression']!,
+      'definitions': buildScopeResponseResult['param_names']!,
+      'typeDefinitions': buildScopeResponseResult['type_params_names']!,
+      'libraryUri': buildScopeResponseResult['libraryUri']!,
+      'isStatic': buildScopeResponseResult['isStatic']!,
     };
     dynamic klass = buildScopeResponseResult['klass'];
     if (klass != null) {
       compileParams['klass'] = klass;
     }
     if (externalClient != null) {
-      var compileExpression = new Message.forMethod('compileExpression');
+      var compileExpression = Message.forMethod('compileExpression');
       compileExpression.client = externalClient;
       compileExpression.params.addAll(compileParams);
 
       final id = _service._serviceRequests.newId();
       final oldId = _message.serial;
-      final completer = new Completer<String>();
-      externalClient.serviceHandles[id] = (Message m) {
+      final completer = Completer<String>();
+      externalClient.serviceHandles[id] = (Message? m) {
         if (m != null) {
           completer.complete(json.encode(m.forwardToJson({'id': oldId})));
         } else {
           completer.complete(encodeRpcError(_message, kServiceDisappeared));
         }
       };
-      externalClient.post(new Response.json(compileExpression
+      externalClient.post(Response.json(compileExpression
           .forwardToJson({'id': id, 'method': 'compileExpression'})));
       return completer.future
           .then((String s) => jsonDecode(s))
@@ -167,8 +165,8 @@
         'id': _message.serial,
         'params': compileParams,
       };
-      var compileExpression = new Message._fromJsonRpcRequest(
-          _message.client, compileExpressionParams);
+      var compileExpression = Message._fromJsonRpcRequest(
+          _message.client!, compileExpressionParams);
 
       return _isolate
           .routeRequest(_service, compileExpression)
@@ -197,7 +195,7 @@
         runParams['params']['scope'] = _message.params['scope'];
       }
       var runExpression =
-          new Message._fromJsonRpcRequest(_message.client, runParams);
+          Message._fromJsonRpcRequest(_message.client!, runParams);
       return _isolate.routeRequest(_service, runExpression); // _message
     } else {
       // empty kernel indicates dart1 mode
diff --git a/sdk_nnbd/lib/vmservice/vmservice.dart b/sdk_nnbd/lib/vmservice/vmservice.dart
index aa7878f..fa5ac5c 100644
--- a/sdk_nnbd/lib/vmservice/vmservice.dart
+++ b/sdk_nnbd/lib/vmservice/vmservice.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 library dart._vmservice;
 
 import 'dart:async';
@@ -23,8 +21,8 @@
 part 'message_router.dart';
 part 'named_lookup.dart';
 
-final RawReceivePort isolateControlPort = new RawReceivePort();
-final RawReceivePort scriptLoadPort = new RawReceivePort();
+final RawReceivePort isolateControlPort = RawReceivePort();
+final RawReceivePort scriptLoadPort = RawReceivePort();
 
 abstract class IsolateEmbedderData {
   void cleanup();
@@ -32,8 +30,8 @@
 
 String _makeAuthToken() {
   final kTokenByteSize = 8;
-  Uint8List bytes = new Uint8List(kTokenByteSize);
-  Random random = new Random.secure();
+  Uint8List bytes = Uint8List(kTokenByteSize);
+  Random random = Random.secure();
   for (int i = 0; i < kTokenByteSize; i++) {
     bytes[i] = random.nextInt(256);
   }
@@ -47,7 +45,7 @@
 // anything implementing IsolateEmbedderData. When an isolate goes away,
 // the cleanup method will be invoked after being removed from the map.
 final Map<int, IsolateEmbedderData> isolateEmbedderData =
-    new Map<int, IsolateEmbedderData>();
+    <int, IsolateEmbedderData>{};
 
 // These must be kept in sync with the declarations in vm/json_stream.h.
 const kParseError = -32700;
@@ -94,7 +92,7 @@
       'due to the current configuration',
 };
 
-String encodeRpcError(Message message, int code, {String details}) {
+String encodeRpcError(Message message, int code, {String? details}) {
   var response = {
     'jsonrpc': '2.0',
     'id': message.serial,
@@ -180,31 +178,31 @@
 
 /// Hooks that are setup by the embedder.
 class VMServiceEmbedderHooks {
-  static ServerStartCallback serverStart;
-  static ServerStopCallback serverStop;
-  static CleanupCallback cleanup;
-  static CreateTempDirCallback createTempDir;
-  static DeleteDirCallback deleteDir;
-  static WriteFileCallback writeFile;
-  static WriteStreamFileCallback writeStreamFile;
-  static ReadFileCallback readFile;
-  static ListFilesCallback listFiles;
-  static ServerInformationCallback serverInformation;
-  static WebServerControlCallback webServerControl;
+  static ServerStartCallback? serverStart;
+  static ServerStopCallback? serverStop;
+  static CleanupCallback? cleanup;
+  static CreateTempDirCallback? createTempDir;
+  static DeleteDirCallback? deleteDir;
+  static WriteFileCallback? writeFile;
+  static WriteStreamFileCallback? writeStreamFile;
+  static ReadFileCallback? readFile;
+  static ListFilesCallback? listFiles;
+  static ServerInformationCallback? serverInformation;
+  static WebServerControlCallback? webServerControl;
 }
 
 class VMService extends MessageRouter {
-  static VMService _instance;
+  static VMService? _instance;
 
   static const serviceNamespace = 's';
 
   /// Collection of currently connected clients.
   final NamedLookup<Client> clients =
-      new NamedLookup<Client>(prologue: serviceNamespace);
-  final IdGenerator _serviceRequests = new IdGenerator(prologue: 'sr');
+      NamedLookup<Client>(prologue: serviceNamespace);
+  final IdGenerator _serviceRequests = IdGenerator(prologue: 'sr');
 
   /// Collection of currently running isolates.
-  RunningIsolates runningIsolates = new RunningIsolates();
+  RunningIsolates runningIsolates = RunningIsolates();
 
   /// Flag to indicate VM service is exiting.
   bool isExiting = false;
@@ -212,7 +210,7 @@
   /// A port used to receive events from the VM.
   final RawReceivePort eventPort;
 
-  final devfs = new DevFS();
+  final devfs = DevFS();
 
   void _addClient(Client client) {
     assert(client.streams.isEmpty);
@@ -231,7 +229,7 @@
     for (var service in client.services.keys) {
       _eventMessageHandler(
           'Service',
-          new Response.json({
+          Response.json({
             'jsonrpc': '2.0',
             'method': 'streamNotify',
             'params': {
@@ -239,7 +237,7 @@
               'event': {
                 "type": "Event",
                 "kind": "ServiceUnregistered",
-                'timestamp': new DateTime.now().millisecondsSinceEpoch,
+                'timestamp': DateTime.now().millisecondsSinceEpoch,
                 'service': service,
                 'method': namespace + '.' + service,
               }
@@ -267,15 +265,12 @@
         break;
       case Constants.ISOLATE_SHUTDOWN_MESSAGE_ID:
         runningIsolates.isolateShutdown(portId, sp);
-        IsolateEmbedderData ied = isolateEmbedderData.remove(portId);
-        if (ied != null) {
-          ied.cleanup();
-        }
+        isolateEmbedderData.remove(portId)?.cleanup();
         break;
     }
   }
 
-  Future<Null> _serverMessageHandler(int code, SendPort sp, bool enable) async {
+  Future<void> _serverMessageHandler(int code, SendPort sp, bool enable) async {
     switch (code) {
       case Constants.WEB_SERVER_CONTROL_MESSAGE_ID:
         if (VMServiceEmbedderHooks.webServerControl == null) {
@@ -296,28 +291,28 @@
     }
   }
 
-  Future<Null> _handleNativeRpcCall(message, SendPort replyPort) async {
+  Future<void> _handleNativeRpcCall(message, SendPort replyPort) async {
     // Keep in sync with "runtime/vm/service_isolate.cc:InvokeServiceRpc".
     Response response;
 
     try {
-      final Message rpc = new Message.fromJsonRpc(
+      final Message rpc = Message.fromJsonRpc(
           null, json.decode(utf8.decode(message as List<int>)));
       if (rpc.type != MessageType.Request) {
-        response = new Response.internalError(
+        response = Response.internalError(
             'The client sent a non-request json-rpc message.');
       } else {
-        response = await routeRequest(this, rpc);
+        response = (await routeRequest(this, rpc))!;
       }
     } catch (exception) {
-      response = new Response.internalError(
+      response = Response.internalError(
           'The rpc call resulted in exception: $exception.');
     }
-    List<int> bytes;
+    late List<int> bytes;
     switch (response.kind) {
       case ResponsePayloadKind.String:
         bytes = utf8.encode(response.payload);
-        bytes = bytes is Uint8List ? bytes : new Uint8List.fromList(bytes);
+        bytes = bytes is Uint8List ? bytes : Uint8List.fromList(bytes);
         break;
       case ResponsePayloadKind.Binary:
       case ResponsePayloadKind.Utf8String:
@@ -358,7 +353,7 @@
     if (message is List) {
       if (message.length == 2) {
         // This is an event.
-        _eventMessageHandler(message[0], new Response.from(message[1]));
+        _eventMessageHandler(message[0], Response.from(message[1]));
         return;
       }
       if (message.length == 1) {
@@ -395,11 +390,13 @@
   }
 
   factory VMService() {
-    if (VMService._instance == null) {
-      VMService._instance = new VMService._internal();
+    VMService? instance = VMService._instance;
+    if (instance == null) {
+      instance = VMService._internal();
+      VMService._instance = instance;
       _onStart();
     }
-    return _instance;
+    return instance;
   }
 
   bool _isAnyClientSubscribed(String streamId) {
@@ -411,7 +408,7 @@
     return false;
   }
 
-  Client _findFirstClientThatHandlesService(String service) {
+  Client? _findFirstClientThatHandlesService(String service) {
     if (clients != null) {
       for (Client c in clients) {
         if (c.services.containsKey(service)) {
@@ -426,8 +423,8 @@
   static const serviceStreams = const [kServiceStream];
 
   Future<String> _streamListen(Message message) async {
-    var client = message.client;
-    var streamId = message.params['streamId'];
+    var client = message.client!;
+    var streamId = message.params['streamId']!;
 
     if (client.streams.contains(streamId)) {
       return encodeRpcError(message, kStreamAlreadySubscribed);
@@ -457,8 +454,8 @@
   }
 
   Future<String> _streamCancel(Message message) async {
-    var client = message.client;
-    var streamId = message.params['streamId'];
+    var client = message.client!;
+    var streamId = message.params['streamId']!;
 
     if (!client.streams.contains(streamId)) {
       return encodeRpcError(message, kStreamNotSubscribed);
@@ -479,7 +476,7 @@
   static String _getMethod(String method) => method.split('.').last;
 
   Future<String> _registerService(Message message) async {
-    final client = message.client;
+    final client = message.client!;
     final service = message.params['service'];
     final alias = message.params['alias'];
 
@@ -496,7 +493,7 @@
     }
     client.services[service] = alias;
 
-    bool removed;
+    bool removed = false;
     try {
       // Do not send streaming events to the client which registers the service
       removed = client.streams.remove(kServiceStream);
@@ -509,10 +506,10 @@
   }
 
   _sendServiceRegisteredEvent(Client client, String service,
-      {Client target}) async {
+      {Client? target}) async {
     final namespace = clients.keyOf(client);
     final alias = client.services[service];
-    final event = new Response.json({
+    final event = Response.json({
       'jsonrpc': '2.0',
       'method': 'streamNotify',
       'params': {
@@ -520,7 +517,7 @@
         'event': {
           "type": "Event",
           "kind": "ServiceRegistered",
-          'timestamp': new DateTime.now().millisecondsSinceEpoch,
+          'timestamp': DateTime.now().millisecondsSinceEpoch,
           'service': service,
           'method': namespace + '.' + service,
           'alias': alias
@@ -535,23 +532,23 @@
   }
 
   Future<String> _handleService(Message message) async {
-    final namespace = _getNamespace(message.method);
-    final method = _getMethod(message.method);
+    final namespace = _getNamespace(message.method!);
+    final method = _getMethod(message.method!);
     final client = clients[namespace];
     if (client != null) {
       if (client.services.containsKey(method)) {
         final id = _serviceRequests.newId();
         final oldId = message.serial;
-        final completer = new Completer<String>();
-        client.serviceHandles[id] = (Message m) {
+        final completer = Completer<String>();
+        client.serviceHandles[id] = (Message? m) {
           if (m != null) {
             completer.complete(json.encode(m.forwardToJson({'id': oldId})));
           } else {
             completer.complete(encodeRpcError(message, kServiceDisappeared));
           }
         };
-        client.post(new Response.json(
-            message.forwardToJson({'id': id, 'method': method})));
+        client.post(
+            Response.json(message.forwardToJson({'id': id, 'method': method})));
         return completer.future;
       }
     }
@@ -575,7 +572,7 @@
       return encodeInvalidParamError(message, 'uri');
     }
     var args = message.params['args'];
-    var argsOfString = new List<String>();
+    var argsOfString = <String>[];
     if (args != null) {
       if (args is! List) {
         return encodeInvalidParamError(message, 'args');
@@ -598,14 +595,14 @@
     return encodeSuccess(message);
   }
 
-  Future<Response> routeRequest(VMService _, Message message) async {
+  Future<Response?> routeRequest(VMService _, Message message) async {
     final response = await _routeRequestImpl(message);
     if (response == null) {
       // We should only have a null response for Notifications.
       assert(message.type == MessageType.Notification);
       return null;
     }
-    return new Response.from(response);
+    return Response.from(response);
   }
 
   Future _routeRequestImpl(Message message) async {
@@ -628,7 +625,7 @@
       if (devfs.shouldHandleMessage(message)) {
         return await devfs.handleMessage(message);
       }
-      if (_hasNamespace(message.method)) {
+      if (_hasNamespace(message.method!)) {
         return await _handleService(message);
       }
       if (message.params['isolateId'] != null) {
@@ -642,9 +639,9 @@
   }
 
   void routeResponse(message) {
-    final client = message.client;
+    final client = message.client!;
     if (client.serviceHandles.containsKey(message.serial)) {
-      client.serviceHandles.remove(message.serial)(message);
+      client.serviceHandles.remove(message.serial)!(message);
       _serviceRequests.release(message.serial);
     }
   }
@@ -658,8 +655,9 @@
 }
 
 @pragma("vm:entry-point", !const bool.fromEnvironment("dart.vm.product"))
+// ignore: unused_element
 void _registerIsolate(int port_id, SendPort sp, String name) {
-  var service = new VMService();
+  var service = VMService();
   service.runningIsolates.isolateStartup(port_id, sp, name);
 }
 
@@ -670,7 +668,7 @@
 void _onExit() native "VMService_OnExit";
 
 /// Notify the VM that the server's address has changed.
-void onServerAddressChange(String address)
+void onServerAddressChange(String? address)
     native "VMService_OnServerAddressChange";
 
 /// Subscribe to a service stream.
diff --git a/sdk_nnbd/lib/vmservice_libraries.json b/sdk_nnbd/lib/vmservice_libraries.json
index c25ffe5..d0b1297 100644
--- a/sdk_nnbd/lib/vmservice_libraries.json
+++ b/sdk_nnbd/lib/vmservice_libraries.json
@@ -1,11 +1,13 @@
 {
+  "comment:0": "NOTE: THIS FILE IS GENERATED. DO NOT EDIT.",
+  "comment:1": "Instead modify 'sdk_nnbd/lib/vmservice_libraries.yaml' and follow the instructions therein.",
   "vm": {
     "libraries": {
-      "vmservice_io": {
-        "uri": "../../runtime/bin/vmservice/vmservice_io.dart"
-      },
       "_vmservice": {
         "uri": "vmservice/vmservice.dart"
+      },
+      "vmservice_io": {
+        "uri": "_internal/vm/bin/vmservice_io.dart"
       }
     }
   }
diff --git a/sdk_nnbd/lib/vmservice_libraries.yaml b/sdk_nnbd/lib/vmservice_libraries.yaml
index 737e361..169d6af 100644
--- a/sdk_nnbd/lib/vmservice_libraries.yaml
+++ b/sdk_nnbd/lib/vmservice_libraries.yaml
@@ -17,4 +17,4 @@
       uri: "vmservice/vmservice.dart"
 
     vmservice_io:
-      uri: "../../runtime/bin/vmservice/vmservice_io.dart"
+      uri: "_internal/vm/bin/vmservice_io.dart"
diff --git a/sdk_nnbd/lib/wasm/wasm.dart b/sdk_nnbd/lib/wasm/wasm.dart
index f1c05c7..768445e 100644
--- a/sdk_nnbd/lib/wasm/wasm.dart
+++ b/sdk_nnbd/lib/wasm/wasm.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 /// {@category VM}
 /// {@nodoc}
 library dart.wasm;
@@ -57,7 +55,7 @@
 abstract class WasmMemory {
   // Create a new memory with the given number of initial pages, and optional
   // maximum number of pages.
-  external factory WasmMemory(int initialPages, [int maxPages]);
+  external factory WasmMemory(int initialPages, [int? maxPages]);
 
   // The WASM spec defines the page size as 64KiB.
   static const int kPageSizeInBytes = 64 * 1024;
diff --git a/tests/compiler/dart2js/analyses/analysis_helper.dart b/tests/compiler/dart2js/analyses/analysis_helper.dart
index 4cef73d..b422f84 100644
--- a/tests/compiler/dart2js/analyses/analysis_helper.dart
+++ b/tests/compiler/dart2js/analyses/analysis_helper.dart
@@ -20,7 +20,7 @@
 import 'package:expect/expect.dart';
 import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
 import 'package:front_end/src/api_unstable/dart2js.dart'
-    show isRedirectingFactory, relativizeUri;
+    show isRedirectingFactory, isRedirectingFactoryField, relativizeUri;
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/class_hierarchy.dart' as ir;
 import 'package:kernel/core_types.dart' as ir;
@@ -102,10 +102,6 @@
       // Don't visit redirecting factories.
       return;
     }
-    if (node.name.name.contains('#')) {
-      // Skip synthetic .dill members.
-      return;
-    }
     staticTypeContext = new ir.StaticTypeContext(node, typeEnvironment);
     variableScopeModel =
         new ScopeModel.from(node, _constantEvaluator).variableScopeModel;
@@ -116,7 +112,7 @@
 
   @override
   Null visitField(ir.Field node) {
-    if (node.name.name.contains('#')) {
+    if (isRedirectingFactoryField(node)) {
       // Skip synthetic .dill members.
       return;
     }
@@ -130,10 +126,6 @@
 
   @override
   Null visitConstructor(ir.Constructor node) {
-    if (node.name.name.contains('#')) {
-      // Skip synthetic .dill members.
-      return;
-    }
     staticTypeContext = new ir.StaticTypeContext(node, typeEnvironment);
     variableScopeModel =
         new ScopeModel.from(node, _constantEvaluator).variableScopeModel;
diff --git a/tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart b/tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart
index dbb63a7..2f3cf75 100644
--- a/tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart
+++ b/tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import 'runtime_utils.dart';
+import 'runtime_utils.dart' show voidType;
 import 'runtime_utils_nnbd.dart';
 
 class A {}
diff --git a/tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart b/tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart
index f0e56fa..a21a178 100644
--- a/tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart
+++ b/tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-import 'runtime_utils.dart';
+import 'runtime_utils.dart' show voidType;
 import 'runtime_utils_nnbd.dart';
 
 class A {}
diff --git a/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart b/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart
index 4d3aa65..8743e56 100644
--- a/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart
+++ b/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart
@@ -2,21 +2,109 @@
 // 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:_foreign_helper' show JS;
 import 'dart:_runtime' as dart;
 
+import 'package:expect/expect.dart';
+
 /// The runtime representation of the never type.
 final neverType = dart.wrapType(dart.never_);
 
+/// Unwrap the user code type representation to expose the runtime
+/// representation of [t].
+///
+/// Legacy types (produced by the legacy helper below) are returned unchanged
+/// because they are created unwrapped since wrapping will strip the legacy from
+/// them by design.
+Object unwrap(Type t) => t is dart.LegacyType ? t : dart.unwrapType(t);
+
 /// Returns tWrapped? as a wrapped type.
 Type nullable(Type tWrapped) {
-  var t = dart.unwrapType(tWrapped);
+  var t = unwrap(tWrapped);
   var tNullable = dart.nullable(t);
   return dart.wrapType(tNullable);
 }
 
-/// Returns tWrapped* as a wrapped type.
+/// Returns tWrapped* as an *unwrapped* type when it produces a legacy type, and
+/// a *wrapped* type when the legacy has been normalized away.
+///
+/// For example DDC does not create a legacy dynamic type, only dynamic.
+///
+/// This is the only helper to return an unwrapped version of a type because
+/// wrapping a legacy type will strip off the legacy by design.
 Type legacy(Type tWrapped) {
-  var t = dart.unwrapType(tWrapped);
+  var t = unwrap(tWrapped);
   var tLegacy = dart.legacy(t);
-  return dart.wrapType(tLegacy);
+  // During normalization some types never get created as legacy versions.
+  // Ex: dynamic.
+  return tLegacy is dart.LegacyType ? tLegacy : dart.wrapType(tLegacy);
+}
+
+// Returns sWrapped<tWrapped> as a wrapped type.
+Type generic1(Type sWrapped, Type tWrapped) {
+  var s = unwrap(sWrapped);
+  var t = unwrap(tWrapped);
+  var sGeneric = dart.getGenericClass(s);
+  return dart.wrapType(JS('', '#(#)', sGeneric, t));
+}
+
+// Returns sWrapped<tWrapped, rWrapped> as a wrapped type.
+Type generic2(Type sWrapped, Type tWrapped, Type rWrapped) {
+  var s = unwrap(sWrapped);
+  var t = unwrap(tWrapped);
+  var r = unwrap(rWrapped);
+  var sGeneric = dart.getGenericClass(s);
+  return dart.wrapType(JS('', '#(#, #)', sGeneric, t, r));
+}
+
+// Returns a function type of argWrapped -> returnWrapped as a wrapped type.
+Type function1(Type returnWrapped, Type argWrapped) {
+  var returnType = unwrap(returnWrapped);
+  var argType = unwrap(argWrapped);
+  var fun = dart.fnType(returnType, [argType]);
+  return dart.wrapType(fun);
+}
+
+// Returns a function type with a bounded type argument that takes no argument
+// and returns void as a wrapped type.
+Type genericFunction(Type boundWrapped) => dart.wrapType(
+    dart.gFnType((T) => [dart.VoidType, []], (T) => [unwrap(boundWrapped)]));
+
+// Returns a function type with a bounded generic return type of
+// <T extends boundWrapped> argWrapped -> T as a wrapped type.
+Type functionGenericReturn(Type boundWrapped, Type argWrapped) =>
+    dart.wrapType(dart.gFnType(
+        (T) => [
+              T,
+              [unwrap(argWrapped)]
+            ],
+        (T) => [unwrap(boundWrapped)]));
+
+// Returns a function with a bounded generic argument type of
+// <T extends boundWrapped> T -> returnWrapped as a wrapped type.
+Type functionGenericArg(Type boundWrapped, Type returnWrapped) =>
+    dart.wrapType(dart.gFnType(
+        (T) => [
+              unwrap(returnWrapped),
+              [T]
+            ],
+        (T) => [unwrap(boundWrapped)]));
+
+void checkSubtype(Type sWrapped, Type tWrapped) {
+  var s = unwrap(sWrapped);
+  var t = unwrap(tWrapped);
+  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
+}
+
+void checkProperSubtype(Type sWrapped, Type tWrapped) {
+  var s = unwrap(sWrapped);
+  var t = unwrap(tWrapped);
+  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
+  checkSubtypeFailure(tWrapped, sWrapped);
+}
+
+void checkSubtypeFailure(Type sWrapped, Type tWrapped) {
+  var s = unwrap(sWrapped);
+  var t = unwrap(tWrapped);
+  Expect.isFalse(dart.isSubtypeOf(s, t), '$s should not be subtype of $t.');
 }
diff --git a/tests/ffi/function_callbacks_test.dart b/tests/ffi/function_callbacks_test.dart
index 33241f2..9b59fb4 100644
--- a/tests/ffi/function_callbacks_test.dart
+++ b/tests/ffi/function_callbacks_test.dart
@@ -45,24 +45,40 @@
 }
 
 typedef SimpleAdditionType = Int32 Function(Int32, Int32);
-int simpleAddition(int x, int y) => x + y;
+int simpleAddition(int x, int y) {
+  print("simpleAddition($x, $y)");
+  return x + y;
+}
 
 typedef IntComputationType = Int64 Function(Int8, Int16, Int32, Int64);
-int intComputation(int a, int b, int c, int d) => d - c + b - a;
+int intComputation(int a, int b, int c, int d) {
+  print("intComputation($a, $b, $c, $d)");
+  return d - c + b - a;
+}
 
 typedef UintComputationType = Uint64 Function(Uint8, Uint16, Uint32, Uint64);
-int uintComputation(int a, int b, int c, int d) => d - c + b - a;
+int uintComputation(int a, int b, int c, int d) {
+  print("uintComputation($a, $b, $c, $d)");
+  return d - c + b - a;
+}
 
 typedef SimpleMultiplyType = Double Function(Double);
-double simpleMultiply(double x) => x * 1.337;
+double simpleMultiply(double x) {
+  print("simpleMultiply($x)");
+  return x * 1.337;
+}
 
 typedef SimpleMultiplyFloatType = Float Function(Float);
-double simpleMultiplyFloat(double x) => x * 1.337;
+double simpleMultiplyFloat(double x) {
+  print("simpleMultiplyFloat($x)");
+  return x * 1.337;
+}
 
 typedef ManyIntsType = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr, IntPtr,
     IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
 int manyInts(
     int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
+  print("manyInts($a, $b, $c, $d, $e, $f, $g, $h, $i, $j");
   return a + b + c + d + e + f + g + h + i + j;
 }
 
@@ -70,6 +86,7 @@
     Double, Double, Double, Double, Double, Double);
 double manyDoubles(double a, double b, double c, double d, double e, double f,
     double g, double h, double i, double j) {
+  print("manyDoubles($a, $b, $c, $d, $e, $f, $g, $h, $i, $j");
   return a + b + c + d + e + f + g + h + i + j;
 }
 
@@ -115,6 +132,8 @@
     double _18,
     int _19,
     double _20) {
+  print("manyArgs( $_1, $_2, $_3, $_4, $_5, $_6, $_7, $_8, $_9, $_10," +
+      "$_11, $_12, $_13, $_14, $_15, $_16, $_17, $_18, $_19, $_20)");
   return _1 +
       _2 +
       _3 +
diff --git a/tests/ffi/function_test.dart b/tests/ffi/function_test.dart
index 5ed233d..644605a 100644
--- a/tests/ffi/function_test.dart
+++ b/tests/ffi/function_test.dart
@@ -33,6 +33,7 @@
     testNativeFunctionManyArguments2();
     testNativeFunctionManyArguments3();
     testNativeFunctionManyArguments4();
+    testNativeFunctionManyArguments5();
     testNativeFunctionPointer();
     testNullInt();
     testNullDouble();
@@ -229,6 +230,8 @@
 
 typedef NativeDecenaryOp = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr,
     IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
+typedef NativeDecenaryOp2 = Int16 Function(
+    Int8, Int16, Int8, Int16, Int8, Int16, Int8, Int16, Int8, Int16);
 typedef DecenaryOp = int Function(
     int, int, int, int, int, int, int, int, int, int);
 
@@ -239,6 +242,13 @@
   Expect.equals(55, sumManyInts(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
 }
 
+DecenaryOp sumManySmallInts = ffiTestFunctions
+    .lookupFunction<NativeDecenaryOp2, DecenaryOp>("SumManySmallInts");
+
+void testNativeFunctionManyArguments5() {
+  Expect.equals(55, sumManySmallInts(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+}
+
 typedef NativeUndenaryOp = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr,
     IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
 typedef UndenaryOp = int Function(
diff --git a/tests/language/nnbd/syntax/class_member_declarations_error_test.dart b/tests/language/nnbd/syntax/class_member_declarations_error_test.dart
new file mode 100644
index 0000000..59f708f
--- /dev/null
+++ b/tests/language/nnbd/syntax/class_member_declarations_error_test.dart
@@ -0,0 +1,166 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+class A {
+  static late x1;
+  //     ^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  static late x5 = 0;
+  //     ^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  static final late x9;
+  //           ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'final'.
+  static final late A x10;
+  //           ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'final'.
+  static final late x11 = 0;
+  //           ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'final'.
+  static final late A x12 = null;
+  //           ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'final'.
+  //                        ^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+
+  covariant late x15;
+  //        ^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  covariant late x16 = '';
+  //        ^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  late covariant var x17;
+  //   ^^^^^^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'covariant' should be before the modifier 'late'.
+  late covariant var x18 = '';
+  //   ^^^^^^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'covariant' should be before the modifier 'late'.
+  late covariant x19;
+  //   ^^^^^^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'covariant' should be before the modifier 'late'.
+  late covariant x20 = '';
+  //   ^^^^^^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'covariant' should be before the modifier 'late'.
+
+  covariant var late x21;
+  //            ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'var'.
+  covariant var late x22 = '';
+  //            ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'var'.
+
+  covariant double late x23;
+  //               ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD
+  // [cfe] Expected ';' after this.
+  //               ^^^^
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  //                    ^^^
+  // [analyzer] SYNTACTIC_ERROR.MISSING_CONST_FINAL_VAR_OR_TYPE
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+  covariant String late x24 = '';
+  //               ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
+  // [cfe] 'late' is already declared in this scope.
+  //               ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD
+  // [cfe] Expected ';' after this.
+  //               ^^^^
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  //                    ^^^
+  // [analyzer] SYNTACTIC_ERROR.MISSING_CONST_FINAL_VAR_OR_TYPE
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+
+  late x25;
+  //   ^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+  late x29 = 0;
+  //   ^^^^
+  // [analyzer] unspecified
+  // [cfe] unspecified
+
+  final late x33;
+  //    ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'final'.
+  int late x34;
+  //  ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
+  // [cfe] 'late' is already declared in this scope.
+  //  ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD
+  // [cfe] Expected ';' after this.
+  //  ^^^^
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  //       ^^^
+  // [analyzer] SYNTACTIC_ERROR.MISSING_CONST_FINAL_VAR_OR_TYPE
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+  var late x35;
+  //  ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'var'.
+  final late A x36;
+  //    ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'final'.
+  final late x37 = 0;
+  //    ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'final'.
+  int late x38 = 0;
+  //  ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
+  // [cfe] 'late' is already declared in this scope.
+  //  ^^^^
+  // [analyzer] COMPILE_TIME_ERROR.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD
+  // [cfe] Expected ';' after this.
+  //  ^^^^
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  //       ^^^
+  // [analyzer] SYNTACTIC_ERROR.MISSING_CONST_FINAL_VAR_OR_TYPE
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+  var late x39 = 0;
+  //  ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'var'.
+  final late A? x40 = null;
+  //    ^^^^
+  // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
+  // [cfe] The modifier 'late' should be before the modifier 'final'.
+
+}
+
+abstract class B {
+  m1(int some, regular, covariant parameters, {
+      required p1,
+      required p2 = null,
+      //       ^^
+      // [analyzer] COMPILE_TIME_ERROR.DEFAULT_VALUE_ON_REQUIRED_PARAMETER
+      // [cfe] unspecified
+      required covariant p3,
+      required covariant int p4,
+  });
+}
+
+main() {
+}
diff --git a/tests/language/nnbd/syntax/class_member_declarations_test.dart b/tests/language/nnbd/syntax/class_member_declarations_test.dart
index bea6423..3aa7d26 100644
--- a/tests/language/nnbd/syntax/class_member_declarations_test.dart
+++ b/tests/language/nnbd/syntax/class_member_declarations_test.dart
@@ -5,57 +5,26 @@
 // SharedOptions=--enable-experiment=non-nullable
 
 class A {
-  static late x1; //# 01: syntax error
   static late final x2;
   static late int x3;
   static late final A x4;
-  static late x5 = 0; //# 02: syntax error
   static late final x6 = 0;
   static late int x7 = 0;
   static late final A? x8 = null;
 
-  static final late x9; //# 03: syntax error
-  static final late A x10; //# 04: syntax error
-  static final late x11 = 0; //# 05: syntax error
-  static final late A x12 = null; //# 06: syntax error
-
   covariant late var x13;
   covariant late var x14 = '';
-  covariant late x15; //# 07: syntax error
-  covariant late x16 = ''; //# 08: syntax error
-
-  late covariant var x17; //# 09: syntax error
-  late covariant var x18 = '';  //# 10: syntax error
-  late covariant x19; //# 11: syntax error
-  late covariant x20 = ''; //# 12: syntax error
-
-  covariant var late x21; //# 13: syntax error
-  covariant var late x22 = '';  //# 14: syntax error
 
   covariant late double x23;
   covariant late String x24 = '';
 
-  covariant double late x23; //# 15: syntax error
-  covariant String late x24 = ''; //# 16: syntax error
-
-  late x25; //# 17: syntax error
   late final x26;
   late int x27;
   late final A x28;
-  late x29 = 0; //# 18: syntax error
   late final x30 = 0;
   late int x31 = 0;
   late final A? x32 = null;
 
-  final late x33; //# 19: syntax error
-  int late x34; //# 20: syntax error
-  var late x35; //# 21: syntax error
-  final late A x36; //# 22: syntax error
-  final late x37 = 0; //# 23: syntax error
-  int late x38 = 0; //# 24: syntax error
-  var late x39 = 0; //# 25: syntax error
-  final late A? x40 = null; //# 26: syntax error
-
   List foo() {
     final x41 = true;
     late final x42;
@@ -65,16 +34,20 @@
 }
 
 abstract class B {
-  m1(int some, regular, covariant parameters, {
-      required p1,
-      // required p2 = null, // Likely intended to be an error.
-      required covariant p3,
-      required covariant int p4,
+  m1(
+    int some,
+    regular,
+    covariant parameters, {
+    required p1,
+    required covariant p3,
+    required covariant int p4,
   });
 }
 
 main() {
   A? a;
   String? s = '';
-  a?..foo().length..x27 = s!.toString().length;
+  a
+    ?..foo().length
+    ..x27 = s!.toString().length;
 }
diff --git a/tests/language_2/async_star/async_star2_regression_test.dart b/tests/language_2/async_star/async_star2_regression_test.dart
new file mode 100644
index 0000000..7c8acfc
--- /dev/null
+++ b/tests/language_2/async_star/async_star2_regression_test.dart
@@ -0,0 +1,30 @@
+// 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 async_start_test;
+
+import "dart:async";
+
+import "package:expect/expect.dart";
+
+void main() async {
+  var results = [];
+
+  f() async* {
+    yield 0;
+    yield 1;
+    yield 2;
+  }
+
+  //Broken, the value 1 was lost.
+  await for (var i in f()) {
+    results.add(i);
+    if (i == 0) {
+      // This should pause the stream subscription.
+      await Future.delayed(Duration(milliseconds: 500));
+    }
+  }
+
+  Expect.listEquals([0, 1, 2], results);
+}
diff --git a/tests/language_2/async_star/async_star2_test.dart b/tests/language_2/async_star/async_star2_test.dart
deleted file mode 100644
index 72d772e..0000000
--- a/tests/language_2/async_star/async_star2_test.dart
+++ /dev/null
@@ -1,1024 +0,0 @@
-// Copyright (c) 2015, 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 async_start_test;
-
-import "dart:async";
-
-import "package:async_helper/async_minitest.dart";
-
-main() {
-  group("basic", () {
-    test("empty", () {
-      f() async* {}
-      return f().toList().then((v) {
-        expect(v, equals([]));
-      });
-    });
-
-    test("single", () {
-      f() async* {
-        yield 42;
-      }
-
-      return f().toList().then((v) {
-        expect(v, equals([42]));
-      });
-    });
-
-    test("call delays", () {
-      var list = [];
-      f() async* {
-        list.add(1);
-        yield 2;
-      }
-
-      var res = f().forEach(list.add);
-      list.add(0);
-      return res.whenComplete(() {
-        expect(list, equals([0, 1, 2]));
-      });
-    });
-
-    test("throws", () {
-      f() async* {
-        yield 1;
-        throw 2;
-      }
-
-      var completer = new Completer();
-      var list = [];
-      f().listen(list.add,
-          onError: (v) => list.add("$v"), onDone: completer.complete);
-      return completer.future.whenComplete(() {
-        expect(list, equals([1, "2"]));
-      });
-    });
-
-    test("multiple", () {
-      f() async* {
-        for (int i = 0; i < 10; i++) {
-          yield i;
-        }
-      }
-
-      return expectList(f(), new List.generate(10, id));
-    });
-
-    test("allows await", () {
-      f() async* {
-        var x = await new Future.value(42);
-        yield x;
-        x = await new Future.value(42);
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("allows await in loop", () {
-      f() async* {
-        for (int i = 0; i < 10; i++) {
-          yield await i;
-        }
-      }
-
-      return expectList(f(), new List.generate(10, id));
-    });
-
-    test("allows yield*", () {
-      f() async* {
-        yield* new Stream.fromIterable([1, 2, 3]);
-      }
-
-      return expectList(f(), [1, 2, 3]);
-    });
-
-    test("allows yield* of async*", () {
-      f(n) async* {
-        yield n;
-        if (n == 0) return;
-        yield* f(n - 1);
-        yield n;
-      }
-
-      return expectList(f(3), [3, 2, 1, 0, 1, 2, 3]);
-    });
-
-    test("Cannot yield* non-stream", () {
-      f(Object s) async* {
-        yield* s;
-      }
-
-      return f(42).transform(getErrors).single.then((v) {
-        // Not implementing Stream.
-        expect(v is Error, isTrue);
-      });
-    });
-
-    test("Cannot yield* non-stream 2", () {
-      f(Object s) async* {
-        yield* s;
-      }
-
-      return f(new NotAStream()).transform(getErrors).single.then((v) {
-        // Not implementing Stream.
-        expect(v is Error, isTrue);
-      });
-    });
-  });
-
-  group("yield statement context", () {
-    test("plain", () {
-      f() async* {
-        yield 0;
-      }
-
-      return expectList(f(), [0]);
-    });
-
-    test("if-then-else", () {
-      f(b) async* {
-        if (b)
-          yield 0;
-        else
-          yield 1;
-      }
-
-      return expectList(f(true), [0]).whenComplete(() {
-        expectList(f(false), [1]);
-      });
-    });
-
-    test("block", () {
-      f() async* {
-        yield 0;
-        {
-          yield 1;
-        }
-        yield 2;
-      }
-
-      return expectList(f(), [0, 1, 2]);
-    });
-
-    test("labeled", () {
-      f() async* {
-        label1:
-        yield 0;
-      }
-
-      return expectList(f(), [0]);
-    });
-
-    // VM issue 2238
-    test("labeled 2", () { //         //# 01: ok
-      f() async* { //                 //# 01: continued
-        label1: label2: yield 0; //   //# 01: continued
-      } //                            //# 01: continued
-      return expectList(f(), [0]); // //# 01: continued
-    }); //                            //# 01: continued
-
-    test("for-loop", () {
-      f() async* {
-        for (int i = 0; i < 3; i++) yield i;
-      }
-
-      return expectList(f(), [0, 1, 2]);
-    });
-
-    test("for-in-loop", () {
-      f() async* {
-        for (var i in [0, 1, 2]) yield i;
-      }
-
-      return expectList(f(), [0, 1, 2]);
-    });
-
-    test("await for-in-loop", () {
-      f() async* {
-        await for (var i in new Stream.fromIterable([0, 1, 2])) yield i;
-      }
-
-      return expectList(f(), [0, 1, 2]);
-    });
-
-    test("while-loop", () {
-      f() async* {
-        int i = 0;
-        while (i < 3) yield i++;
-      }
-
-      return expectList(f(), [0, 1, 2]);
-    });
-
-    test("do-while-loop", () {
-      f() async* {
-        int i = 0;
-        do yield i++; while (i < 3);
-      }
-
-      return expectList(f(), [0, 1, 2]);
-    });
-
-    test("try-catch-finally", () {
-      f() async* {
-        try {
-          yield 0;
-        } catch (e) {
-          yield 1;
-        } finally {
-          yield 2;
-        }
-      }
-
-      return expectList(f(), [0, 2]);
-    });
-
-    test("try-catch-finally 2", () {
-      f() async* {
-        try {
-          yield throw 0;
-        } catch (e) {
-          yield 1;
-        } finally {
-          yield 2;
-        }
-      }
-
-      return expectList(f(), [1, 2]);
-    });
-
-    test("switch-case", () {
-      f(v) async* {
-        switch (v) {
-          case 0:
-            yield 0;
-            continue label1;
-          label1:
-          case 1:
-            yield 1;
-            break;
-          default:
-            yield 2;
-        }
-      }
-      return expectList(f(0), [0, 1]).whenComplete(() {
-        return expectList(f(1), [1]);
-      }).whenComplete(() {
-        return expectList(f(2), [2]);
-      });
-    });
-
-    test("dead-code return", () {
-      f() async* {
-        return;
-        yield 1;
-      }
-
-      return expectList(f(), []);
-    });
-
-    test("dead-code throw", () {
-      f() async* {
-        try {
-          throw 0;
-          yield 1;
-        } catch (_) {}
-      }
-
-      return expectList(f(), []);
-    });
-
-    test("dead-code break", () {
-      f() async* {
-        while (true) {
-          break;
-          yield 1;
-        }
-      }
-
-      return expectList(f(), []);
-    });
-
-    test("dead-code break 2", () {
-      f() async* {
-        label:
-        {
-          break label;
-          yield 1;
-        }
-      }
-
-      return expectList(f(), []);
-    });
-
-    test("dead-code continue", () {
-      f() async* {
-        do {
-          continue;
-          yield 1;
-        } while (false);
-      }
-
-      return expectList(f(), []);
-    });
-  });
-
-  group("yield expressions", () {
-    test("local variable", () {
-      f() async* {
-        var x = 42;
-        yield x;
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("constant variable", () {
-      f() async* {
-        const x = 42;
-        yield x;
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("function call", () {
-      g() => 42;
-      f() async* {
-        yield g();
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("unary operator", () {
-      f() async* {
-        var x = -42;
-        yield -x;
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("binary operator", () {
-      f() async* {
-        var x = 21;
-        yield x + x;
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("ternary operator", () {
-      f() async* {
-        var x = 21;
-        yield x == 21 ? x + x : x;
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("suffix post-increment", () {
-      f() async* {
-        var x = 42;
-        yield x++;
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("suffix pre-increment", () {
-      f() async* {
-        var x = 41;
-        yield ++x;
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("assignment", () {
-      f() async* {
-        var x = 37;
-        yield x = 42;
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("assignment op", () {
-      f() async* {
-        var x = 41;
-        yield x += 1;
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("await", () {
-      f() async* {
-        yield await new Future.value(42);
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("index operator", () {
-      f() async* {
-        var x = [42];
-        yield x[0];
-      }
-
-      return expectList(f(), [42]);
-    });
-
-    test("function expression block", () {
-      var o = new Object();
-      f() async* {
-        yield () {
-          return o;
-        };
-      }
-
-      return f().first.then((v) {
-        expect(v(), same(o));
-      });
-    });
-
-    test("function expression arrow", () {
-      var o = new Object();
-      f() async* {
-        yield () => o;
-      }
-
-      return f().first.then((v) {
-        expect(v(), same(o));
-      });
-    });
-
-    test("function expression block async", () {
-      var o = new Object();
-      f() async* {
-        yield () async {
-          return o;
-        };
-      }
-
-      return f().first.then((v) => v()).then((v) {
-        expect(v, same(o));
-      });
-    });
-
-    test("function expression arrow async", () {
-      var o = new Object();
-      f() async* {
-        yield () async => o;
-      }
-
-      return f().first.then((v) => v()).then((v) {
-        expect(v, same(o));
-      });
-    });
-
-    test("function expression block async*", () {
-      var o = new Object();
-      f() async* {
-        yield () async* {
-          yield o;
-        };
-      }
-
-      return f().first.then((v) => v().first).then((v) {
-        expect(v, same(o));
-      });
-    });
-  });
-
-  group("loops", () {
-    test("simple yield", () {
-      f() async* {
-        for (int i = 0; i < 3; i++) {
-          yield i;
-        }
-      }
-
-      return expectList(f(), [0, 1, 2]);
-    });
-
-    test("yield in double loop", () {
-      f() async* {
-        for (int i = 0; i < 3; i++) {
-          for (int j = 0; j < 2; j++) {
-            yield i * 2 + j;
-          }
-        }
-      }
-
-      return expectList(f(), [0, 1, 2, 3, 4, 5]);
-    });
-
-    test("yield in try body", () {
-      var list = [];
-      f() async* {
-        for (int i = 0; i < 3; i++) {
-          try {
-            yield i;
-          } finally {
-            list.add("$i");
-          }
-        }
-      }
-
-      return expectList(f(), [0, 1, 2]).whenComplete(() {
-        expect(list, equals(["0", "1", "2"]));
-      });
-    });
-
-    test("yield in catch", () {
-      var list = [];
-      f() async* {
-        for (int i = 0; i < 3; i++) {
-          try {
-            throw i;
-          } catch (e) {
-            yield e;
-          } finally {
-            list.add("$i");
-          }
-        }
-      }
-
-      return expectList(f(), [0, 1, 2]).whenComplete(() {
-        expect(list, equals(["0", "1", "2"]));
-      });
-    });
-
-    test("yield in finally", () {
-      var list = [];
-      f() async* {
-        for (int i = 0; i < 3; i++) {
-          try {
-            throw i;
-          } finally {
-            yield i;
-            list.add("$i");
-            continue;
-          }
-        }
-      }
-
-      return expectList(f(), [0, 1, 2]).whenComplete(() {
-        expect(list, equals(["0", "1", "2"]));
-      });
-    });
-
-    test("keep yielding after cancel", () {
-      f() async* {
-        for (int i = 0; i < 10; i++) {
-          try {
-            yield i;
-          } finally {
-            continue;
-          }
-        }
-      }
-
-      return expectList(f().take(3), [0, 1, 2]);
-    });
-  });
-
-  group("canceling", () {
-    // Stream.take(n) automatically cancels after seeing the n'th value.
-
-    test("cancels at yield", () {
-      Completer exits = new Completer();
-      var list = [];
-      f() async* {
-        try {
-          list.add(0);
-          list.add(1);
-          yield null;
-          list.add(2);
-        } finally {
-          exits.complete(3);
-        }
-      }
-
-      // No events must be fired synchronously in response to a listen.
-      var subscription = f().listen((v) {
-        fail("Received event $v");
-      }, onDone: () {
-        fail("Received done");
-      });
-      // No events must be delivered after a cancel.
-      subscription.cancel();
-      return exits.future.then((v) {
-        expect(v, equals(3));
-        expect(list, equals([0, 1]));
-      });
-    });
-
-    test("does cancel eventually", () {
-      var exits = new Completer();
-      var list = [];
-      f() async* {
-        int i = 0;
-        try {
-          while (true) yield i++;
-        } finally {
-          list.add("a");
-          exits.complete(i);
-        }
-      }
-
-      return expectList(f().take(5), [0, 1, 2, 3, 4])
-          .then((_) => exits.future)
-          .then((v) {
-        expect(v, greaterThan(4));
-        expect(list, ["a"]);
-      });
-    });
-
-    group("at index", () {
-      f() async* {
-        try {
-          yield await new Future.microtask(() => 1);
-        } finally {
-          try {
-            yield await new Future.microtask(() => 2);
-          } finally {
-            yield await new Future.microtask(() => 3);
-          }
-        }
-      }
-
-      test("- all, sanity check", () {
-        return expectList(f(), [1, 2, 3]);
-      });
-      test("after end", () {
-        return expectList(f().take(4), [1, 2, 3]);
-      });
-      test("at end", () {
-        return expectList(f().take(3), [1, 2, 3]);
-      });
-      test("before end", () {
-        return expectList(f().take(2), [1, 2]);
-      });
-      test("early", () {
-        return expectList(f().take(1), [1]);
-      });
-      test("at start", () {
-        return expectList(f().take(0), []);
-      });
-    });
-
-    test("regression-fugl/fisk", () {
-      var res = [];
-      fisk() async* {
-        res.add("+fisk");
-        try {
-          for (int i = 0; i < 2; i++) {
-            yield await new Future.microtask(() => i);
-          }
-        } finally {
-          res.add("-fisk");
-        }
-      }
-
-      fugl(int count) async {
-        res.add("fisk $count");
-        try {
-          await for(int i in fisk().take(count)) res.add(i);
-        } finally {
-          res.add("done");
-        }
-      }
-
-      return fugl(3).whenComplete(() => fugl(2))
-                    .whenComplete(() => fugl(1))
-                    .whenComplete(() {
-        expect(res, ["fisk 3", "+fisk", 0, 1, "-fisk", "done",
-                     "fisk 2", "+fisk", 0, 1, "-fisk", "done",
-                     "fisk 1", "+fisk", 0, "-fisk", "done", ]);
-      });
-    });
-  });
-
-  group("pausing", () {
-    test("pauses execution at yield for at least a microtask", () {
-      var list = [];
-      f() async* {
-        list.add(1);
-        yield 2;
-        list.add(3);
-        yield 4;
-        list.add(5);
-      }
-
-      var done = new Completer();
-      var sub = f().listen((v) {
-        if (v == 2) {
-          expect(list, equals([1]));
-        } else if (v == 4) {
-          expect(list, equals([1, 3]));
-        } else {
-          fail("Unexpected value $v");
-        }
-      }, onDone: () {
-        expect(list, equals([1, 3, 5]));
-        done.complete();
-      });
-      return done.future;
-    });
-
-    test("pause stops execution at yield", () {
-      var list = [];
-      f() async* {
-        list.add(1);
-        yield 2;
-        list.add(3);
-        yield 4;
-        list.add(5);
-      }
-
-      var done = new Completer();
-      var sub;
-      sub = f().listen((v) {
-        if (v == 2) {
-          expect(list, equals([1]));
-          sub.pause();
-          new Timer(MS * 300, () {
-            expect(list.length, lessThan(3));
-            sub.resume();
-          });
-        } else if (v == 4) {
-          expect(list, equals([1, 3]));
-        } else {
-          fail("Unexpected value $v");
-        }
-      }, onDone: () {
-        expect(list, equals([1, 3, 5]));
-        done.complete();
-      });
-      return done.future;
-    });
-
-    test("pause stops execution at yield 2", () {
-      var list = [];
-      f() async* {
-        int i = 0;
-        while (true) {
-          yield i;
-          list.add(i);
-          i++;
-        }
-      }
-
-      int expected = 0;
-      var done = new Completer();
-      var sub;
-      sub = f().listen((v) {
-        expect(v, equals(expected++));
-        if (v % 5 == 0) {
-          sub.pause(new Future.delayed(MS * 300));
-        } else if (v == 17) {
-          sub.cancel();
-          done.complete();
-        }
-      }, onDone: () {
-        fail("Unexpected done!");
-      });
-      return done.future.whenComplete(() {
-        expect(list.length == 18 || list.length == 19, isTrue);
-      });
-    });
-
-    test("canceling while paused at yield", () { //                 //# 02: ok
-      var list = []; //                                             //# 02: continued
-      var sync = new Sync(); //                                     //# 02: continued
-      f() async* { //                                               //# 02: continued
-        list.add("*1"); //                                          //# 02: continued
-        yield 1; //                                                 //# 02: continued
-        await sync.wait(); //                                       //# 02: continued
-        sync.release(); //                                          //# 02: continued
-        list.add("*2"); //                                          //# 02: continued
-        yield 2; //                                                 //# 02: continued
-        list.add("*3"); //                                          //# 02: continued
-      }; //                                                         //# 02: continued
-      var stream = f(); //                                          //# 02: continued
-    // TODO(jmesserly): added workaround for:
-    // https://github.com/dart-lang/dev_compiler/issues/269
-      var sub = stream.listen((x) => list.add(x)); //                         //# 02: continued
-      return sync.wait().whenComplete(() { //                       //# 02: continued
-        expect(list, equals(["*1", 1])); //                         //# 02: continued
-        sub.pause(); //                                             //# 02: continued
-        return sync.wait(); //                                      //# 02: continued
-      }).whenComplete(() { //                                       //# 02: continued
-        expect(list, equals(["*1", 1, "*2"])); //                   //# 02: continued
-        sub.cancel(); //                                            //# 02: continued
-        return new Future.delayed(MS * 200, () { //                 //# 02: continued
-          // Should not have yielded 2 or added *3 while paused. // //# 02: continued
-          expect(list, equals(["*1", 1, "*2"])); //                 //# 02: continued
-        }); //                                                      //# 02: continued
-      }); //                                                        //# 02: continued
-    }); //                                                          //# 02: continued
-  });
-
-  group("await for", () {
-    mkStream(int n) async* {
-      for (int i = 0; i < n; i++) yield i;
-    }
-
-    test("simple stream", () {
-      f(s) async {
-        var r = 0;
-        await for (var v in s) r += v;
-        return r;
-      }
-
-      return f(mkStream(5)).then((v) {
-        expect(v, equals(10));
-      });
-    });
-
-    test("simple stream, await", () {
-      f(s) async {
-        var r = 0;
-        await for (var v in s) r += await new Future.microtask(() => v);
-        return r;
-      }
-
-      return f(mkStream(5)).then((v) {
-        expect(v, equals(10));
-      });
-    });
-
-    test("simple stream - take", () { //          //# 03: ok
-      f(s) async { //                             //# 03: continued
-        var r = 0; //                             //# 03: continued
-        await for(var v in s.take(5)) r += v; //  //# 03: continued
-        return r; //                              //# 03: continued
-      } //                                        //# 03: continued
-      return f(mkStream(10)).then((v) { //        //# 03: continued
-        expect(v, equals(10)); //                 //# 03: continued
-      }); //                                      //# 03: continued
-    }); //                                        //# 03: continued
-
-    test("simple stream reyield", () {
-      f(s) async* {
-        var r = 0;
-        await for (var v in s) yield r += v;
-      }
-
-      return expectList(f(mkStream(5)), [0, 1, 3, 6, 10]);
-    });
-
-    test("simple stream, await, reyield", () {
-      f(s) async* {
-        var r = 0;
-        await for (var v in s) yield r += await new Future.microtask(() => v);
-      }
-
-      return expectList(f(mkStream(5)), [0, 1, 3, 6, 10]);
-    });
-
-    test("simple stream - take, reyield", () { //               //# 04: ok
-      f(s) async* { //                                          //# 04: continued
-        var r = 0; //                                           //# 04: continued
-        await for(var v in s.take(5)) yield r += v; //          //# 04: continued
-      } //                                                      //# 04: continued
-      return expectList(f(mkStream(10)), [0, 1, 3, 6, 10]); //  //# 04: continued
-    }); //                                                      //# 04: continued
-
-    test("nested", () {
-      f() async {
-        var r = 0;
-        await for (var i in mkStream(5)) {
-          await for (var j in mkStream(3)) {
-            r += i * j;
-          }
-        }
-        return r;
-      }
-
-      return f().then((v) {
-        expect(v, equals((1 + 2 + 3 + 4) * (1 + 2)));
-      });
-    });
-
-    test("nested, await", () {
-      f() async {
-        var r = 0;
-        await for (var i in mkStream(5)) {
-          await for (var j in mkStream(3)) {
-            r += await new Future.microtask(() => i * j);
-          }
-        }
-        return r;
-      }
-
-      return f().then((v) {
-        expect(v, equals((1 + 2 + 3 + 4) * (1 + 2)));
-      });
-    });
-
-    test("nested, await * 2", () {
-      f() async {
-        var r = 0;
-        await for (var i in mkStream(5)) {
-          var ai = await new Future.microtask(() => i);
-          await for (var j in mkStream(3)) {
-            r += await new Future.microtask(() => ai * j);
-          }
-        }
-        return r;
-      }
-
-      return f().then((v) {
-        expect(v, equals((1 + 2 + 3 + 4) * (1 + 2)));
-      });
-    });
-
-    test("await pauses loop", () { //                                  //# 05: ok
-      var sc; //                                                       //# 05: continued
-      var i = 0; //                                                    //# 05: continued
-      void send() { //                                                 //# 05: continued
-        if (i == 5) { //                                               //# 05: continued
-          sc.close(); //                                               //# 05: continued
-        } else { //                                                    //# 05: continued
-          sc.add(i++); //                                              //# 05: continued
-        } //                                                           //# 05: continued
-      } //                                                             //# 05: continued
-      sc = new StreamController(onListen: send, onResume: send); //    //# 05: continued
-      f(s) async { //                                                  //# 05: continued
-        var r = 0; //                                                  //# 05: continued
-        await for (var i in s) { //                                    //# 05: continued
-          r += await new Future.delayed(MS * 10, () => i); //          //# 05: continued
-        } //                                                           //# 05: continued
-        return r; //                                                   //# 05: continued
-      } //                                                             //# 05: continued
-      return f(sc.stream).then((v) { //                                //# 05: continued
-        expect(v, equals(10)); //                                      //# 05: continued
-      }); //                                                           //# 05: continued
-    }); //                                                             //# 05: continued
-  });
-}
-
-// Obscuring identity function.
-id(x) {
-  try {
-    if (x != null) throw x;
-  } catch (e) {
-    return e;
-  }
-  return null;
-}
-
-expectList(stream, list) {
-  return stream.toList().then((v) {
-    expect(v, equals(list));
-  });
-}
-
-const MS = const Duration(milliseconds: 1);
-
-StreamTransformer getErrors = new StreamTransformer.fromHandlers(handleData: (data, sink) {
-  fail("Unexpected value");
-}, handleError: (e, s, sink) {
-  sink.add(e);
-}, handleDone: (sink) {
-  sink.close();
-});
-
-class NotAStream {
-  listen(oData, {onError, onDone, cancelOnError}) {
-    fail("Not implementing Stream.");
-  }
-}
-
-/**
- * Allows two asynchronous executions to synchronize.
- *
- * Calling [wait] and waiting for the returned future to complete will
- * wait for the other executions to call [wait] again. At that point,
- * the waiting execution is allowed to continue (the returned future completes),
- * and the more resent call to [wait] is now the waiting execution.
- */
-class Sync {
-  Completer _completer = null;
-  // Release whoever is currently waiting and start waiting yourself.
-  Future wait([v]) {
-    if (_completer != null) _completer.complete(v);
-    _completer = new Completer();
-    return _completer.future;
-  }
-
-  // Release whoever is currently waiting.
-  void release([v]) {
-    if (_completer != null) {
-      _completer.complete(v);
-      _completer = null;
-    }
-  }
-}
diff --git a/tests/language_2/async_star/await_for_test.dart b/tests/language_2/async_star/await_for_test.dart
new file mode 100644
index 0000000..fb99084
--- /dev/null
+++ b/tests/language_2/async_star/await_for_test.dart
@@ -0,0 +1,148 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+main() {
+  test('simple stream', () {
+    f(s) async {
+      var r = 0;
+      await for (var v in s) r += v;
+      return r;
+    }
+
+    return f(mkStream(5)).then((v) {
+      expect(v, equals(10));
+    });
+  });
+
+  test('simple stream, await', () {
+    f(s) async {
+      var r = 0;
+      await for (var v in s) r += await Future.microtask(() => v);
+      return r;
+    }
+
+    return f(mkStream(5)).then((v) {
+      expect(v, equals(10));
+    });
+  });
+
+  test('simple stream - take', () {
+    f(s) async {
+      var r = 0;
+      await for (var v in s.take(5)) r += v;
+      return r;
+    }
+
+    return f(mkStream(10)).then((v) {
+      expect(v, equals(10));
+    });
+  });
+
+  test('simple stream reyield', () {
+    f(s) async* {
+      var r = 0;
+      await for (var v in s) yield r += v;
+    }
+
+    return expectList(f(mkStream(5)), [0, 1, 3, 6, 10]);
+  });
+
+  test('simple stream, await, reyield', () {
+    f(s) async* {
+      var r = 0;
+      await for (var v in s) yield r += await Future.microtask(() => v);
+    }
+
+    return expectList(f(mkStream(5)), [0, 1, 3, 6, 10]);
+  });
+
+  test('simple stream - take, reyield', () {
+    f(s) async* {
+      var r = 0;
+      await for (var v in s.take(5)) yield r += v;
+    }
+
+    return expectList(f(mkStream(10)), [0, 1, 3, 6, 10]);
+  });
+
+  test('nested', () {
+    f() async {
+      var r = 0;
+      await for (var i in mkStream(5)) {
+        await for (var j in mkStream(3)) {
+          r += i * j;
+        }
+      }
+      return r;
+    }
+
+    return f().then((v) {
+      expect(v, equals((1 + 2 + 3 + 4) * (1 + 2)));
+    });
+  });
+
+  test('nested, await', () {
+    f() async {
+      var r = 0;
+      await for (var i in mkStream(5)) {
+        await for (var j in mkStream(3)) {
+          r += await Future.microtask(() => i * j);
+        }
+      }
+      return r;
+    }
+
+    return f().then((v) {
+      expect(v, equals((1 + 2 + 3 + 4) * (1 + 2)));
+    });
+  });
+
+  test('nested, await * 2', () {
+    f() async {
+      var r = 0;
+      await for (var i in mkStream(5)) {
+        var ai = await Future.microtask(() => i);
+        await for (var j in mkStream(3)) {
+          r += await Future.microtask(() => ai * j);
+        }
+      }
+      return r;
+    }
+
+    return f().then((v) {
+      expect(v, equals((1 + 2 + 3 + 4) * (1 + 2)));
+    });
+  });
+
+  test('await pauses loop', () {
+    var sc;
+    var i = 0;
+    void send() {
+      if (i == 5) {
+        sc.close();
+      } else {
+        sc.add(i++);
+      }
+    }
+
+    sc = StreamController(onListen: send, onResume: send);
+    f(s) async {
+      var r = 0;
+      await for (var i in s) {
+        r += await Future.delayed(ms * 10, () => i);
+      }
+      return r;
+    }
+
+    return f(sc.stream).then((v) {
+      expect(v, equals(10));
+    });
+  });
+}
diff --git a/tests/language_2/async_star/basic_test.dart b/tests/language_2/async_star/basic_test.dart
new file mode 100644
index 0000000..73a956d
--- /dev/null
+++ b/tests/language_2/async_star/basic_test.dart
@@ -0,0 +1,153 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+class NotAStream {
+  listen(oData, {onError, onDone, cancelOnError}) {
+    fail('Not implementing Stream.');
+  }
+}
+
+StreamTransformer getErrors =
+    StreamTransformer.fromHandlers(handleData: (data, sink) {
+  fail('Unexpected value');
+}, handleError: (e, s, sink) {
+  sink.add(e);
+}, handleDone: (sink) {
+  sink.close();
+});
+
+// Obscuring identity function.
+id(x) {
+  try {
+    if (x != null) throw x;
+  } catch (e) {
+    return e;
+  }
+  return null;
+}
+
+main() {
+  test('empty', () {
+    f() async* {}
+    return f().toList().then((v) {
+      expect(v, equals([]));
+    });
+  });
+
+  test('single', () {
+    f() async* {
+      yield 42;
+    }
+
+    return f().toList().then((v) {
+      expect(v, equals([42]));
+    });
+  });
+
+  test('call delays', () {
+    var list = [];
+    f() async* {
+      list.add(1);
+      yield 2;
+    }
+
+    var res = f().forEach(list.add);
+    list.add(0);
+    return res.whenComplete(() {
+      expect(list, equals([0, 1, 2]));
+    });
+  });
+
+  test('throws', () {
+    f() async* {
+      yield 1;
+      throw 2;
+    }
+
+    var completer = Completer();
+    var list = [];
+    f().listen(list.add,
+        onError: (v) => list.add('$v'), onDone: completer.complete);
+    return completer.future.whenComplete(() {
+      expect(list, equals([1, '2']));
+    });
+  });
+
+  test('multiple', () {
+    f() async* {
+      for (int i = 0; i < 10; i++) {
+        yield i;
+      }
+    }
+
+    return expectList(f(), List.generate(10, id));
+  });
+
+  test('allows await', () {
+    f() async* {
+      var x = await Future.value(42);
+      yield x;
+      x = await Future.value(42);
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('allows await in loop', () {
+    f() async* {
+      for (int i = 0; i < 10; i++) {
+        yield await i;
+      }
+    }
+
+    return expectList(f(), List.generate(10, id));
+  });
+
+  test('allows yield*', () {
+    f() async* {
+      yield* Stream.fromIterable([1, 2, 3]);
+    }
+
+    return expectList(f(), [1, 2, 3]);
+  });
+
+  test('allows yield* of async*', () {
+    f(n) async* {
+      yield n;
+      if (n == 0) return;
+      yield* f(n - 1);
+      yield n;
+    }
+
+    return expectList(f(3), [3, 2, 1, 0, 1, 2, 3]);
+  });
+
+  test('Cannot yield* non-stream', () {
+    f(Object s) async* {
+      yield* s;
+    }
+
+    return f(42).transform(getErrors).single.then((v) {
+      // Not implementing Stream.
+      expect(v is Error, isTrue);
+    });
+  });
+
+  test('Cannot yield* non-stream 2', () {
+    f(Object s) async* {
+      yield* s;
+    }
+
+    return f(NotAStream()).transform(getErrors).single.then((v) {
+      // Not implementing Stream.
+      expect(v is Error, isTrue);
+    });
+  });
+}
diff --git a/tests/language_2/async_star/cancel_test.dart b/tests/language_2/async_star/cancel_test.dart
new file mode 100644
index 0000000..18c2787
--- /dev/null
+++ b/tests/language_2/async_star/cancel_test.dart
@@ -0,0 +1,142 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+main() {
+  // Stream.take(n) automatically cancels after seeing the n'th value.
+  test('cancels at yield', () {
+    Completer exits = Completer();
+    var list = [];
+    f() async* {
+      try {
+        list.add(0);
+        list.add(1);
+        yield null;
+        list.add(2);
+      } finally {
+        exits.complete(3);
+      }
+    }
+
+    // No events must be fired synchronously in response to a listen.
+    var subscription = f().listen((v) {
+      fail('Received event $v');
+    }, onDone: () {
+      fail('Received done');
+    });
+    // No events must be delivered after a cancel.
+    subscription.cancel();
+    return exits.future.then((v) {
+      expect(v, equals(3));
+      expect(list, equals([0, 1]));
+    });
+  });
+
+  test('does cancel eventually', () {
+    var exits = Completer();
+    var list = [];
+    f() async* {
+      int i = 0;
+      try {
+        while (true) yield i++;
+      } finally {
+        list.add('a');
+        exits.complete(i);
+      }
+    }
+
+    return expectList(f().take(5), [0, 1, 2, 3, 4])
+        .then((_) => exits.future)
+        .then((v) {
+      expect(v, greaterThan(4));
+      expect(list, ['a']);
+    });
+  });
+
+  group('at index', () {
+    f() async* {
+      try {
+        yield await Future.microtask(() => 1);
+      } finally {
+        try {
+          yield await Future.microtask(() => 2);
+        } finally {
+          yield await Future.microtask(() => 3);
+        }
+      }
+    }
+
+    test('- all, sanity check', () {
+      return expectList(f(), [1, 2, 3]);
+    });
+    test('after end', () {
+      return expectList(f().take(4), [1, 2, 3]);
+    });
+    test('at end', () {
+      return expectList(f().take(3), [1, 2, 3]);
+    });
+    test('before end', () {
+      return expectList(f().take(2), [1, 2]);
+    });
+    test('early', () {
+      return expectList(f().take(1), [1]);
+    });
+    test('at start', () {
+      return expectList(f().take(0), []);
+    });
+  });
+
+  test('regression-fugl/fisk', () {
+    var res = [];
+    fisk() async* {
+      res.add('+fisk');
+      try {
+        for (int i = 0; i < 2; i++) {
+          yield await Future.microtask(() => i);
+        }
+      } finally {
+        res.add('-fisk');
+      }
+    }
+
+    fugl(int count) async {
+      res.add('fisk $count');
+      try {
+        await for (int i in fisk().take(count)) res.add(i);
+      } finally {
+        res.add('done');
+      }
+    }
+
+    return fugl(3)
+        .whenComplete(() => fugl(2))
+        .whenComplete(() => fugl(1))
+        .whenComplete(() {
+      expect(res, [
+        'fisk 3',
+        '+fisk',
+        0,
+        1,
+        '-fisk',
+        'done',
+        'fisk 2',
+        '+fisk',
+        0,
+        1,
+        '-fisk',
+        'done',
+        'fisk 1',
+        '+fisk',
+        0,
+        '-fisk',
+        'done',
+      ]);
+    });
+  });
+}
diff --git a/tests/language_2/async_star/cancel_while_paused_at_yield_test.dart b/tests/language_2/async_star/cancel_while_paused_at_yield_test.dart
new file mode 100644
index 0000000..af7e846
--- /dev/null
+++ b/tests/language_2/async_star/cancel_while_paused_at_yield_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+main() {
+  test('canceling while paused at yield', () {
+    var list = [];
+    var sync = Sync();
+    f() async* {
+      list.add('*1');
+      yield 1;
+      await sync.wait();
+      sync.release();
+      list.add('*2');
+      yield 2;
+      list.add('*3');
+    }
+
+    var stream = f();
+    // TODO(jmesserly): added workaround for:
+    // https://github.com/dart-lang/dev_compiler/issues/269
+    var sub = stream.listen((x) => list.add(x));
+    return sync.wait().whenComplete(() {
+      expect(list, equals(['*1', 1]));
+      sub.pause();
+      return sync.wait();
+    }).whenComplete(() {
+      expect(list, equals(['*1', 1, '*2']));
+      sub.cancel();
+      return Future.delayed(ms * 200, () {
+        // Should not have yielded 2 or added *3 while paused.
+        expect(list, equals(['*1', 1, '*2']));
+      });
+    });
+  });
+}
diff --git a/tests/language_2/async_star/loops_test.dart b/tests/language_2/async_star/loops_test.dart
new file mode 100644
index 0000000..8d6df7c
--- /dev/null
+++ b/tests/language_2/async_star/loops_test.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+main() {
+  test('simple yield', () {
+    f() async* {
+      for (int i = 0; i < 3; i++) {
+        yield i;
+      }
+    }
+
+    return expectList(f(), [0, 1, 2]);
+  });
+
+  test('yield in double loop', () {
+    f() async* {
+      for (int i = 0; i < 3; i++) {
+        for (int j = 0; j < 2; j++) {
+          yield i * 2 + j;
+        }
+      }
+    }
+
+    return expectList(f(), [0, 1, 2, 3, 4, 5]);
+  });
+
+  test('yield in try body', () {
+    var list = [];
+    f() async* {
+      for (int i = 0; i < 3; i++) {
+        try {
+          yield i;
+        } finally {
+          list.add('$i');
+        }
+      }
+    }
+
+    return expectList(f(), [0, 1, 2]).whenComplete(() {
+      expect(list, equals(['0', '1', '2']));
+    });
+  });
+
+  test('yield in catch', () {
+    var list = [];
+    f() async* {
+      for (int i = 0; i < 3; i++) {
+        try {
+          throw i;
+        } catch (e) {
+          yield e;
+        } finally {
+          list.add('$i');
+        }
+      }
+    }
+
+    return expectList(f(), [0, 1, 2]).whenComplete(() {
+      expect(list, equals(['0', '1', '2']));
+    });
+  });
+
+  test('yield in finally', () {
+    var list = [];
+    f() async* {
+      for (int i = 0; i < 3; i++) {
+        try {
+          throw i;
+        } finally {
+          yield i;
+          list.add('$i');
+          continue;
+        }
+      }
+    }
+
+    return expectList(f(), [0, 1, 2]).whenComplete(() {
+      expect(list, equals(['0', '1', '2']));
+    });
+  });
+
+  test('keep yielding after cancel', () {
+    f() async* {
+      for (int i = 0; i < 10; i++) {
+        try {
+          yield i;
+        } finally {
+          continue;
+        }
+      }
+    }
+
+    return expectList(f().take(3), [0, 1, 2]);
+  });
+}
diff --git a/tests/language_2/async_star/pause_test2.dart b/tests/language_2/async_star/pause_test2.dart
new file mode 100644
index 0000000..a240d3d
--- /dev/null
+++ b/tests/language_2/async_star/pause_test2.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+main() {
+  test('pauses execution at yield for at least a microtask', () {
+    var list = [];
+    f() async* {
+      list.add(1);
+      yield 2;
+      list.add(3);
+      yield 4;
+      list.add(5);
+    }
+
+    var done = Completer();
+    var sub = f().listen((v) {
+      if (v == 2) {
+        expect(list, equals([1]));
+      } else if (v == 4) {
+        expect(list, equals([1, 3]));
+      } else {
+        fail('Unexpected value $v');
+      }
+    }, onDone: () {
+      expect(list, equals([1, 3, 5]));
+      done.complete();
+    });
+    return done.future;
+  });
+
+  test('pause stops execution at yield', () {
+    var list = [];
+    f() async* {
+      list.add(1);
+      yield 2;
+      list.add(3);
+      yield 4;
+      list.add(5);
+    }
+
+    var done = Completer();
+    var sub;
+    sub = f().listen((v) {
+      if (v == 2) {
+        expect(list, equals([1]));
+        sub.pause();
+        Timer(ms * 300, () {
+          expect(list.length, lessThan(3));
+          sub.resume();
+        });
+      } else if (v == 4) {
+        expect(list, equals([1, 3]));
+      } else {
+        fail('Unexpected value $v');
+      }
+    }, onDone: () {
+      expect(list, equals([1, 3, 5]));
+      done.complete();
+    });
+    return done.future;
+  });
+
+  test('pause stops execution at yield 2', () {
+    var list = [];
+    f() async* {
+      int i = 0;
+      while (true) {
+        yield i;
+        list.add(i);
+        i++;
+      }
+    }
+
+    int expected = 0;
+    var done = Completer();
+    var sub;
+    sub = f().listen((v) {
+      expect(v, equals(expected++));
+      if (v % 5 == 0) {
+        sub.pause(Future.delayed(ms * 300));
+      } else if (v == 17) {
+        sub.cancel();
+        done.complete();
+      }
+    }, onDone: () {
+      fail('Unexpected done!');
+    });
+    return done.future.whenComplete(() {
+      expect(list.length == 18 || list.length == 19, isTrue);
+    });
+  });
+}
diff --git a/tests/language_2/async_star/utils.dart b/tests/language_2/async_star/utils.dart
new file mode 100644
index 0000000..dfd97de
--- /dev/null
+++ b/tests/language_2/async_star/utils.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:async_helper/async_minitest.dart';
+
+const ms = const Duration(milliseconds: 1);
+
+/// Allows two asynchronous executions to synchronize.
+///
+/// Calling [wait] and waiting for the returned future to complete will wait for
+/// the other executions to call [wait] again. At that point, the waiting
+/// execution is allowed to continue (the returned future completes), and the
+/// more resent call to [wait] is now the waiting execution.
+class Sync {
+  Completer _completer = null;
+  // Release whoever is currently waiting and start waiting yourself.
+  Future wait([v]) {
+    if (_completer != null) _completer.complete(v);
+    _completer = Completer();
+    return _completer.future;
+  }
+
+  // Release whoever is currently waiting.
+  void release([v]) {
+    if (_completer != null) {
+      _completer.complete(v);
+      _completer = null;
+    }
+  }
+}
+
+expectList(stream, list) {
+  return stream.toList().then((v) {
+    expect(v, equals(list));
+  });
+}
+
+mkStream(int n) async* {
+  for (int i = 0; i < n; i++) yield i;
+}
diff --git a/tests/language_2/async_star/yield_expressions_test.dart b/tests/language_2/async_star/yield_expressions_test.dart
new file mode 100644
index 0000000..fe3578e
--- /dev/null
+++ b/tests/language_2/async_star/yield_expressions_test.dart
@@ -0,0 +1,177 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+main() {
+  test('local variable', () {
+    f() async* {
+      var x = 42;
+      yield x;
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('constant variable', () {
+    f() async* {
+      const x = 42;
+      yield x;
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('function call', () {
+    g() => 42;
+    f() async* {
+      yield g();
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('unary operator', () {
+    f() async* {
+      var x = -42;
+      yield -x;
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('binary operator', () {
+    f() async* {
+      var x = 21;
+      yield x + x;
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('ternary operator', () {
+    f() async* {
+      var x = 21;
+      yield x == 21 ? x + x : x;
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('suffix post-increment', () {
+    f() async* {
+      var x = 42;
+      yield x++;
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('suffix pre-increment', () {
+    f() async* {
+      var x = 41;
+      yield ++x;
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('assignment', () {
+    f() async* {
+      var x = 37;
+      yield x = 42;
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('assignment op', () {
+    f() async* {
+      var x = 41;
+      yield x += 1;
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('await', () {
+    f() async* {
+      yield await Future.value(42);
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('index operator', () {
+    f() async* {
+      var x = [42];
+      yield x[0];
+    }
+
+    return expectList(f(), [42]);
+  });
+
+  test('function expression block', () {
+    var o = Object();
+    f() async* {
+      yield () {
+        return o;
+      };
+    }
+
+    return f().first.then((v) {
+      expect(v(), same(o));
+    });
+  });
+
+  test('function expression arrow', () {
+    var o = Object();
+    f() async* {
+      yield () => o;
+    }
+
+    return f().first.then((v) {
+      expect(v(), same(o));
+    });
+  });
+
+  test('function expression block async', () {
+    var o = Object();
+    f() async* {
+      yield () async {
+        return o;
+      };
+    }
+
+    return f().first.then((v) => v()).then((v) {
+      expect(v, same(o));
+    });
+  });
+
+  test('function expression arrow async', () {
+    var o = Object();
+    f() async* {
+      yield () async => o;
+    }
+
+    return f().first.then((v) => v()).then((v) {
+      expect(v, same(o));
+    });
+  });
+
+  test('function expression block async*', () {
+    var o = Object();
+    f() async* {
+      yield () async* {
+        yield o;
+      };
+    }
+
+    return f().first.then((v) => v().first).then((v) {
+      expect(v, same(o));
+    });
+  });
+}
diff --git a/tests/language_2/async_star/yield_statement_context_test.dart b/tests/language_2/async_star/yield_statement_context_test.dart
new file mode 100644
index 0000000..7320f02
--- /dev/null
+++ b/tests/language_2/async_star/yield_statement_context_test.dart
@@ -0,0 +1,207 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:async_helper/async_minitest.dart';
+
+import 'utils.dart';
+
+void main() {
+  test('plain', () {
+    f() async* {
+      yield 0;
+    }
+
+    return expectList(f(), [0]);
+  });
+
+  test('if-then-else', () {
+    f(b) async* {
+      if (b)
+        yield 0;
+      else
+        yield 1;
+    }
+
+    return expectList(f(true), [0]).whenComplete(() {
+      expectList(f(false), [1]);
+    });
+  });
+
+  test('block', () {
+    f() async* {
+      yield 0;
+      {
+        yield 1;
+      }
+      yield 2;
+    }
+
+    return expectList(f(), [0, 1, 2]);
+  });
+
+  test('labeled', () {
+    f() async* {
+      label1:
+      yield 0;
+    }
+
+    return expectList(f(), [0]);
+  });
+
+  test('two labels on same line', () {
+    f() async* {
+      // DO NOT RUN dartfmt on this file. The labels should be on the same.
+      // line. Originally VM issue #2238.
+      label1: label2: yield 0;
+    }
+
+    return expectList(f(), [0]);
+  });
+
+  test('for-loop', () {
+    f() async* {
+      for (int i = 0; i < 3; i++) yield i;
+    }
+
+    return expectList(f(), [0, 1, 2]);
+  });
+
+  test('for-in-loop', () {
+    f() async* {
+      for (var i in [0, 1, 2]) yield i;
+    }
+
+    return expectList(f(), [0, 1, 2]);
+  });
+
+  test('await for-in-loop', () {
+    f() async* {
+      await for (var i in Stream.fromIterable([0, 1, 2])) yield i;
+    }
+
+    return expectList(f(), [0, 1, 2]);
+  });
+
+  test('while-loop', () {
+    f() async* {
+      int i = 0;
+      while (i < 3) yield i++;
+    }
+
+    return expectList(f(), [0, 1, 2]);
+  });
+
+  test('do-while-loop', () {
+    f() async* {
+      int i = 0;
+      do yield i++; while (i < 3);
+    }
+
+    return expectList(f(), [0, 1, 2]);
+  });
+
+  test('try-catch-finally', () {
+    f() async* {
+      try {
+        yield 0;
+      } catch (e) {
+        yield 1;
+      } finally {
+        yield 2;
+      }
+    }
+
+    return expectList(f(), [0, 2]);
+  });
+
+  test('try-catch-finally 2', () {
+    f() async* {
+      try {
+        yield throw 0;
+      } catch (e) {
+        yield 1;
+      } finally {
+        yield 2;
+      }
+    }
+
+    return expectList(f(), [1, 2]);
+  });
+
+  test('switch-case', () {
+    f(v) async* {
+      switch (v) {
+        case 0:
+          yield 0;
+          continue label1;
+        label1:
+        case 1:
+          yield 1;
+          break;
+        default:
+          yield 2;
+      }
+    }
+
+    return expectList(f(0), [0, 1]).whenComplete(() {
+      return expectList(f(1), [1]);
+    }).whenComplete(() {
+      return expectList(f(2), [2]);
+    });
+  });
+
+  test('dead-code return', () {
+    f() async* {
+      return;
+      yield 1;
+    }
+
+    return expectList(f(), []);
+  });
+
+  test('dead-code throw', () {
+    f() async* {
+      try {
+        throw 0;
+        yield 1;
+      } catch (_) {}
+    }
+
+    return expectList(f(), []);
+  });
+
+  test('dead-code break', () {
+    f() async* {
+      while (true) {
+        break;
+        yield 1;
+      }
+    }
+
+    return expectList(f(), []);
+  });
+
+  test('dead-code break 2', () {
+    f() async* {
+      label:
+      {
+        break label;
+        yield 1;
+      }
+    }
+
+    return expectList(f(), []);
+  });
+
+  test('dead-code continue', () {
+    f() async* {
+      do {
+        continue;
+        yield 1;
+      } while (false);
+    }
+
+    return expectList(f(), []);
+  });
+}
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 3910863..dce25e7 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -113,10 +113,6 @@
 [ $mode == debug && $runtime == vm && ($compiler == app_jitk || $compiler == dartk || $compiler == dartkb) ]
 optimize/deopt_inlined_function_lazy_test: Skip
 
-[ $mode == debug && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
-async_star/async_star2_test/01: Crash
-async_star/async_star2_test/05: Crash
-
 [ $mode == debug && ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
 enum/duplicate_test/02: Crash # Issue 34606
 enum/duplicate_test/none: Crash # Issue 34606
@@ -142,10 +138,4 @@
 symbol/conflict_test: Slow
 
 [ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
-async_star/async_star2_test/01: Skip # Timeout
-async_star/async_star2_test/02: Skip # Timeout
-async_star/async_star2_test/03: Skip # Timeout
-async_star/async_star2_test/04: Skip # Timeout
-async_star/async_star2_test/05: Skip # Timeout
-async_star/async_star2_test/none: Skip # Timeout
 type_constants_test/none: Skip # Deferred libraries and hot reload.
diff --git a/tests/language_2/regress/regress40066_test.dart b/tests/language_2/regress/regress40066_test.dart
new file mode 100644
index 0000000..caa08a4
--- /dev/null
+++ b/tests/language_2/regress/regress40066_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A<T> {
+  foo(T x) {
+    print('T = $T');
+    print('x.runtimeType = ${x.runtimeType}');
+    print('x is T = ${x is T}');
+  }
+}
+
+typedef IntFunc = void Function(int);
+typedef StringFunc = void Function(String);
+
+void main() {
+  void inner<S>(S y) {}
+
+  IntFunc innerOfInt = inner;
+  A a = new A<IntFunc>();
+  a.foo(innerOfInt);
+
+  StringFunc innerOfString = inner;
+  Expect.throwsTypeError(() {
+    a.foo(innerOfString);
+  });
+}
diff --git a/tests/lib/wasm/basic_test.dart b/tests/lib/wasm/basic_test.dart
new file mode 100644
index 0000000..b6dfaa9
--- /dev/null
+++ b/tests/lib/wasm/basic_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that we can load a wasm module, find a function, and call it.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // int64_t square(int64_t n) { return n * n; }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
+    0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01, 0x70,
+    0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f,
+    0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x6d, 0x65,
+    0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x73, 0x71, 0x75, 0x61, 0x72,
+    0x65, 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x00,
+    0x7e, 0x0b,
+  ]);
+
+  var inst = WasmModule(data).instantiate(WasmImports());
+  var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
+  int n = fn.call([1234]);
+
+  Expect.equals(1234 * 1234, n);
+}
diff --git a/tests/lib/wasm/corrupted_error_test.dart b/tests/lib/wasm/corrupted_error_test.dart
new file mode 100644
index 0000000..fcc4085
--- /dev/null
+++ b/tests/lib/wasm/corrupted_error_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test error thrown when the wasm module is corrupted.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  var data = Uint8List.fromList([
+    0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x7e, 0x01, 0x7e,
+    0x07, 0x13, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00,
+    0x06, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x00, 0x00, 0x00, 0x20, 0x00,
+    0x7e, 0x0b,
+  ]);
+
+  Expect.throwsArgumentError(() => WasmModule(data));
+}
diff --git a/tests/lib/wasm/fn_call_error_test.dart b/tests/lib/wasm/fn_call_error_test.dart
new file mode 100644
index 0000000..932afa3
--- /dev/null
+++ b/tests/lib/wasm/fn_call_error_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test error thrown when a function is called with the wrong args.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // int64_t square(int64_t n) { return n * n; }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
+    0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01, 0x70,
+    0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f,
+    0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x6d, 0x65,
+    0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x73, 0x71, 0x75, 0x61, 0x72,
+    0x65, 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x00,
+    0x7e, 0x0b,
+  ]);
+
+  var inst = WasmModule(data).instantiate(WasmImports());
+  var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
+
+  Expect.throwsArgumentError(() => fn.call([]));
+  Expect.throwsArgumentError(() => fn.call([1, 2, 3]));
+  Expect.throwsArgumentError(() => fn.call([1.23]));
+}
diff --git a/tests/lib/wasm/fn_import_error_test.dart b/tests/lib/wasm/fn_import_error_test.dart
new file mode 100644
index 0000000..40466fb
--- /dev/null
+++ b/tests/lib/wasm/fn_import_error_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test errors thrown by function imports.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // This module expects a function import like:
+  // int64_t someFn(int32_t a, int64_t b, float c, double d);
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x02, 0x60,
+    0x04, 0x7f, 0x7e, 0x7d, 0x7c, 0x01, 0x7e, 0x60, 0x00, 0x00, 0x02, 0x0e,
+    0x01, 0x03, 0x65, 0x6e, 0x76, 0x06, 0x73, 0x6f, 0x6d, 0x65, 0x46, 0x6e,
+    0x00, 0x00, 0x03, 0x02, 0x01, 0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01,
+    0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41,
+    0x80, 0x88, 0x04, 0x0b, 0x07, 0x11, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f,
+    0x72, 0x79, 0x02, 0x00, 0x04, 0x62, 0x6c, 0x61, 0x68, 0x00, 0x01, 0x0a,
+    0x1d, 0x01, 0x1b, 0x00, 0x41, 0x01, 0x42, 0x02, 0x43, 0x00, 0x00, 0x40,
+    0x40, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x10, 0x80,
+    0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b,
+  ]);
+
+  var mod = WasmModule(data);
+  var imp = WasmImports()
+    ..addFunction<Int64 Function(Int32, Int64, Float, Double)>(
+        "env", "someFn", (num a, num b, num c, num d) => 123);
+  mod.instantiate(imp);
+
+  imp = WasmImports();
+  Expect.throwsArgumentError(() => mod.instantiate(imp));
+
+  imp = WasmImports()
+    ..addFunction<Int64 Function(Int32)>("env", "someFn", (num a) => 123);
+  Expect.throwsArgumentError(() => mod.instantiate(imp));
+
+  imp = WasmImports()
+    ..addFunction<Double Function(Int32, Int64, Float, Double)>(
+        "env", "someFn", (num a, num b, num c, num d) => 123);
+  Expect.throwsArgumentError(() => mod.instantiate(imp));
+
+  imp = WasmImports()
+    ..addFunction<Int64 Function(Int32, Int64, Float, Float)>(
+        "env", "someFn", (num a, num b, num c, num d) => 123);
+  Expect.throwsArgumentError(() => mod.instantiate(imp));
+
+  Expect.throwsArgumentError(() => WasmImports()
+    ..addFunction<dynamic Function(Int32, Int64, Float, Double)>(
+        "env", "someFn", (num a, num b, num c, num d) => 123));
+
+  Expect.throwsArgumentError(() => WasmImports()
+    ..addFunction<Int64 Function(Int32, Int64, dynamic, Double)>(
+        "env", "someFn", (num a, num b, num c, num d) => 123));
+
+  imp = WasmImports()..addGlobal<Int64>("env", "someFn", 123, false);
+  Expect.throwsArgumentError(() => mod.instantiate(imp));
+}
diff --git a/tests/lib/wasm/fn_import_exception_test.dart b/tests/lib/wasm/fn_import_exception_test.dart
new file mode 100644
index 0000000..73298d9
--- /dev/null
+++ b/tests/lib/wasm/fn_import_exception_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test throwing exceptions from an imported function.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // int64_t fn(int64_t x) { return throwIfNegative(x); }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
+    0x01, 0x7e, 0x01, 0x7e, 0x02, 0x17, 0x01, 0x03, 0x65, 0x6e, 0x76, 0x0f,
+    0x74, 0x68, 0x72, 0x6f, 0x77, 0x49, 0x66, 0x4e, 0x65, 0x67, 0x61, 0x74,
+    0x69, 0x76, 0x65, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01,
+    0x70, 0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01,
+    0x7f, 0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x0f, 0x02, 0x06, 0x6d,
+    0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x02, 0x66, 0x6e, 0x00, 0x01,
+    0x0a, 0x0c, 0x01, 0x0a, 0x00, 0x20, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80,
+    0x00, 0x0b,
+  ]);
+
+  dynamic override = null;
+  var inst = WasmModule(data).instantiate(WasmImports()
+    ..addMemory("env", "memory", WasmMemory(256, 1024))
+    ..addGlobal<Int32>("env", "__memory_base", 1024, false)
+    ..addFunction<Int64 Function(Int64)>("env", "throwIfNegative", (int x) {
+      if (x < 0) {
+        throw Exception(x);
+      }
+      if (override != null) {
+        return override;
+      }
+      return x;
+    }));
+  var fn = inst.lookupFunction<Int64 Function(Int64)>("fn");
+
+  Expect.equals(123, fn.call([123]));
+  Expect.throws(() => fn.call([-456]), (Exception e) => "$e".contains("-456"));
+
+  override = "Not an integer";
+  Expect.throwsArgumentError(() => fn.call([789]));
+  override = 0.123;
+  Expect.throwsArgumentError(() => fn.call([789]));
+}
diff --git a/tests/lib/wasm/fn_import_test.dart b/tests/lib/wasm/fn_import_test.dart
new file mode 100644
index 0000000..a9f9bdb
--- /dev/null
+++ b/tests/lib/wasm/fn_import_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that we can load a wasm module, find a function, and call it.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // void reportStuff() { report(123, 456); }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x02, 0x60,
+    0x02, 0x7e, 0x7e, 0x00, 0x60, 0x00, 0x00, 0x02, 0x0e, 0x01, 0x03, 0x65,
+    0x6e, 0x76, 0x06, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x03,
+    0x02, 0x01, 0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01, 0x01, 0x05, 0x03,
+    0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41, 0x80, 0x88, 0x04,
+    0x0b, 0x07, 0x18, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02,
+    0x00, 0x0b, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x75, 0x66,
+    0x66, 0x00, 0x01, 0x0a, 0x10, 0x01, 0x0e, 0x00, 0x42, 0xfb, 0x00, 0x42,
+    0xc8, 0x03, 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, 0x0b,
+  ]);
+
+  int report_x = -1;
+  int report_y = -1;
+
+  var inst = WasmModule(data).instantiate(WasmImports()
+    ..addFunction<Void Function(Int64, Int64)>("env", "report", (int x, int y) {
+      report_x = x;
+      report_y = y;
+    }));
+  var fn = inst.lookupFunction<Void Function()>("reportStuff");
+  fn.call([]);
+  Expect.equals(report_x, 123);
+  Expect.equals(report_y, 456);
+}
diff --git a/tests/lib/wasm/fn_mismatch_error_test.dart b/tests/lib/wasm/fn_mismatch_error_test.dart
new file mode 100644
index 0000000..413260e
--- /dev/null
+++ b/tests/lib/wasm/fn_mismatch_error_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test error thrown when the loaded function can't be found.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // int64_t square(int64_t n) { return n * n; }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
+    0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01, 0x70,
+    0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f,
+    0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x6d, 0x65,
+    0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x73, 0x71, 0x75, 0x61, 0x72,
+    0x65, 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x00,
+    0x7e, 0x0b,
+  ]);
+
+  var inst = WasmModule(data).instantiate(WasmImports());
+  Expect.isNotNull(inst.lookupFunction<Int64 Function(Int64)>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Int64 Function(Int64)>("blah"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Int64 Function()>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Int64 Function(Int64, Int64)>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Void Function(Int64)>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Void Function(dynamic)>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Int64 Function(Float)>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Float Function(Int64)>("square"));
+}
diff --git a/tests/lib/wasm/hello_world_test.dart b/tests/lib/wasm/hello_world_test.dart
new file mode 100644
index 0000000..c4441e3
--- /dev/null
+++ b/tests/lib/wasm/hello_world_test.dart
@@ -0,0 +1,205 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test for hello world built using emscripten with WASI.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // Hello world module generated by emscripten+WASI. Exports a function like
+  // `void _start()`, and prints using `int fd_write(int, int, int, int)`.
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x33, 0x09, 0x60,
+    0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f,
+    0x01, 0x7f, 0x60, 0x00, 0x00, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60,
+    0x01, 0x7f, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, 0x7e, 0x60,
+    0x00, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x00, 0x60, 0x03, 0x7f, 0x7f, 0x7f,
+    0x00, 0x02, 0x1a, 0x01, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e,
+    0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x08, 0x66, 0x64, 0x5f, 0x77, 0x72,
+    0x69, 0x74, 0x65, 0x00, 0x01, 0x03, 0x0f, 0x0e, 0x03, 0x04, 0x00, 0x03,
+    0x02, 0x07, 0x05, 0x04, 0x03, 0x06, 0x02, 0x02, 0x08, 0x00, 0x04, 0x05,
+    0x01, 0x70, 0x01, 0x04, 0x04, 0x05, 0x06, 0x01, 0x01, 0x80, 0x02, 0x80,
+    0x02, 0x06, 0x09, 0x01, 0x7f, 0x01, 0x41, 0xc0, 0x95, 0xc0, 0x02, 0x0b,
+    0x07, 0x2e, 0x04, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00,
+    0x11, 0x5f, 0x5f, 0x77, 0x61, 0x73, 0x6d, 0x5f, 0x63, 0x61, 0x6c, 0x6c,
+    0x5f, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x00, 0x05, 0x04, 0x6d, 0x61, 0x69,
+    0x6e, 0x00, 0x04, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x0b,
+    0x09, 0x09, 0x01, 0x00, 0x41, 0x01, 0x0b, 0x03, 0x08, 0x0e, 0x07, 0x0a,
+    0xae, 0x0c, 0x0e, 0xbf, 0x01, 0x01, 0x05, 0x7f, 0x41, 0x80, 0x08, 0x21,
+    0x04, 0x02, 0x40, 0x20, 0x01, 0x28, 0x02, 0x10, 0x22, 0x02, 0x04, 0x7f,
+    0x20, 0x02, 0x05, 0x20, 0x01, 0x10, 0x02, 0x0d, 0x01, 0x20, 0x01, 0x28,
+    0x02, 0x10, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x14, 0x22, 0x05, 0x6b, 0x20,
+    0x00, 0x49, 0x04, 0x40, 0x20, 0x01, 0x41, 0x80, 0x08, 0x20, 0x00, 0x20,
+    0x01, 0x28, 0x02, 0x24, 0x11, 0x00, 0x00, 0x0f, 0x0b, 0x02, 0x40, 0x20,
+    0x01, 0x2c, 0x00, 0x4b, 0x41, 0x00, 0x48, 0x0d, 0x00, 0x20, 0x00, 0x21,
+    0x03, 0x03, 0x40, 0x20, 0x03, 0x22, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x02,
+    0x41, 0x7f, 0x6a, 0x22, 0x03, 0x41, 0x80, 0x08, 0x6a, 0x2d, 0x00, 0x00,
+    0x41, 0x0a, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x01, 0x41, 0x80, 0x08, 0x20,
+    0x02, 0x20, 0x01, 0x28, 0x02, 0x24, 0x11, 0x00, 0x00, 0x22, 0x03, 0x20,
+    0x02, 0x49, 0x0d, 0x01, 0x20, 0x00, 0x20, 0x02, 0x6b, 0x21, 0x00, 0x20,
+    0x02, 0x41, 0x80, 0x08, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x28, 0x02, 0x14,
+    0x21, 0x05, 0x20, 0x02, 0x21, 0x06, 0x0b, 0x20, 0x05, 0x20, 0x04, 0x20,
+    0x00, 0x10, 0x03, 0x1a, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x14, 0x20,
+    0x00, 0x6a, 0x36, 0x02, 0x14, 0x20, 0x00, 0x20, 0x06, 0x6a, 0x21, 0x03,
+    0x0b, 0x20, 0x03, 0x0b, 0x59, 0x01, 0x01, 0x7f, 0x20, 0x00, 0x20, 0x00,
+    0x2d, 0x00, 0x4a, 0x22, 0x01, 0x41, 0x7f, 0x6a, 0x20, 0x01, 0x72, 0x3a,
+    0x00, 0x4a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x08, 0x71,
+    0x04, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0x20, 0x72, 0x36, 0x02, 0x00,
+    0x41, 0x7f, 0x0f, 0x0b, 0x20, 0x00, 0x42, 0x00, 0x37, 0x02, 0x04, 0x20,
+    0x00, 0x20, 0x00, 0x28, 0x02, 0x2c, 0x22, 0x01, 0x36, 0x02, 0x1c, 0x20,
+    0x00, 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, 0x00, 0x20, 0x01, 0x20, 0x00,
+    0x28, 0x02, 0x30, 0x6a, 0x36, 0x02, 0x10, 0x41, 0x00, 0x0b, 0x82, 0x04,
+    0x01, 0x03, 0x7f, 0x20, 0x02, 0x41, 0x80, 0xc0, 0x00, 0x4f, 0x04, 0x40,
+    0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x0d, 0x20, 0x00, 0x0f, 0x0b,
+    0x20, 0x00, 0x20, 0x02, 0x6a, 0x21, 0x03, 0x02, 0x40, 0x20, 0x00, 0x20,
+    0x01, 0x73, 0x41, 0x03, 0x71, 0x45, 0x04, 0x40, 0x02, 0x40, 0x20, 0x02,
+    0x41, 0x01, 0x48, 0x04, 0x40, 0x20, 0x00, 0x21, 0x02, 0x0c, 0x01, 0x0b,
+    0x20, 0x00, 0x41, 0x03, 0x71, 0x45, 0x04, 0x40, 0x20, 0x00, 0x21, 0x02,
+    0x0c, 0x01, 0x0b, 0x20, 0x00, 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, 0x20,
+    0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x01, 0x41, 0x01, 0x6a,
+    0x21, 0x01, 0x20, 0x02, 0x41, 0x01, 0x6a, 0x22, 0x02, 0x20, 0x03, 0x4f,
+    0x0d, 0x01, 0x20, 0x02, 0x41, 0x03, 0x71, 0x0d, 0x00, 0x0b, 0x0b, 0x02,
+    0x40, 0x20, 0x03, 0x41, 0x7c, 0x71, 0x22, 0x04, 0x41, 0xc0, 0x00, 0x49,
+    0x0d, 0x00, 0x20, 0x02, 0x20, 0x04, 0x41, 0x40, 0x6a, 0x22, 0x05, 0x4b,
+    0x0d, 0x00, 0x03, 0x40, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x00, 0x36,
+    0x02, 0x00, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x04, 0x36, 0x02, 0x04,
+    0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x08, 0x36, 0x02, 0x08, 0x20, 0x02,
+    0x20, 0x01, 0x28, 0x02, 0x0c, 0x36, 0x02, 0x0c, 0x20, 0x02, 0x20, 0x01,
+    0x28, 0x02, 0x10, 0x36, 0x02, 0x10, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02,
+    0x14, 0x36, 0x02, 0x14, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x18, 0x36,
+    0x02, 0x18, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x1c, 0x36, 0x02, 0x1c,
+    0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x20, 0x36, 0x02, 0x20, 0x20, 0x02,
+    0x20, 0x01, 0x28, 0x02, 0x24, 0x36, 0x02, 0x24, 0x20, 0x02, 0x20, 0x01,
+    0x28, 0x02, 0x28, 0x36, 0x02, 0x28, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02,
+    0x2c, 0x36, 0x02, 0x2c, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x30, 0x36,
+    0x02, 0x30, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x34, 0x36, 0x02, 0x34,
+    0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x38, 0x36, 0x02, 0x38, 0x20, 0x02,
+    0x20, 0x01, 0x28, 0x02, 0x3c, 0x36, 0x02, 0x3c, 0x20, 0x01, 0x41, 0x40,
+    0x6b, 0x21, 0x01, 0x20, 0x02, 0x41, 0x40, 0x6b, 0x22, 0x02, 0x20, 0x05,
+    0x4d, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x02, 0x20, 0x04, 0x4f, 0x0d, 0x01,
+    0x03, 0x40, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00,
+    0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x41, 0x04, 0x6a,
+    0x22, 0x02, 0x20, 0x04, 0x49, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20,
+    0x03, 0x41, 0x04, 0x49, 0x04, 0x40, 0x20, 0x00, 0x21, 0x02, 0x0c, 0x01,
+    0x0b, 0x20, 0x03, 0x41, 0x7c, 0x6a, 0x22, 0x04, 0x20, 0x00, 0x49, 0x04,
+    0x40, 0x20, 0x00, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x21, 0x02,
+    0x03, 0x40, 0x20, 0x02, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00,
+    0x20, 0x02, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, 0x20, 0x02,
+    0x20, 0x01, 0x2d, 0x00, 0x02, 0x3a, 0x00, 0x02, 0x20, 0x02, 0x20, 0x01,
+    0x2d, 0x00, 0x03, 0x3a, 0x00, 0x03, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21,
+    0x01, 0x20, 0x02, 0x41, 0x04, 0x6a, 0x22, 0x02, 0x20, 0x04, 0x4d, 0x0d,
+    0x00, 0x0b, 0x0b, 0x20, 0x02, 0x20, 0x03, 0x49, 0x04, 0x40, 0x03, 0x40,
+    0x20, 0x02, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x01,
+    0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x41, 0x01, 0x6a, 0x22, 0x02,
+    0x20, 0x03, 0x47, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x0b, 0x06, 0x00,
+    0x10, 0x0c, 0x41, 0x00, 0x0b, 0x03, 0x00, 0x01, 0x0b, 0x7e, 0x01, 0x03,
+    0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x01, 0x24, 0x00, 0x20, 0x01,
+    0x41, 0x0a, 0x3a, 0x00, 0x0f, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x10,
+    0x22, 0x02, 0x45, 0x04, 0x40, 0x20, 0x00, 0x10, 0x02, 0x0d, 0x01, 0x20,
+    0x00, 0x28, 0x02, 0x10, 0x21, 0x02, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x28,
+    0x02, 0x14, 0x22, 0x03, 0x20, 0x02, 0x4f, 0x0d, 0x00, 0x20, 0x00, 0x2c,
+    0x00, 0x4b, 0x41, 0x0a, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x03, 0x41,
+    0x01, 0x6a, 0x36, 0x02, 0x14, 0x20, 0x03, 0x41, 0x0a, 0x3a, 0x00, 0x00,
+    0x0c, 0x01, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x41, 0x0f, 0x6a, 0x41, 0x01,
+    0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x00, 0x00, 0x41, 0x01, 0x47, 0x0d,
+    0x00, 0x20, 0x01, 0x2d, 0x00, 0x0f, 0x1a, 0x0b, 0x20, 0x01, 0x41, 0x10,
+    0x6a, 0x24, 0x00, 0x0b, 0x04, 0x00, 0x42, 0x00, 0x0b, 0x04, 0x00, 0x41,
+    0x00, 0x0b, 0x31, 0x01, 0x01, 0x7f, 0x20, 0x00, 0x21, 0x02, 0x20, 0x02,
+    0x02, 0x7f, 0x20, 0x01, 0x28, 0x02, 0x4c, 0x41, 0x7f, 0x4c, 0x04, 0x40,
+    0x20, 0x02, 0x20, 0x01, 0x10, 0x01, 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x20,
+    0x01, 0x10, 0x01, 0x0b, 0x22, 0x01, 0x46, 0x04, 0x40, 0x20, 0x00, 0x0f,
+    0x0b, 0x20, 0x01, 0x0b, 0x62, 0x01, 0x03, 0x7f, 0x41, 0x80, 0x08, 0x21,
+    0x00, 0x03, 0x40, 0x20, 0x00, 0x22, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x00,
+    0x20, 0x01, 0x28, 0x02, 0x00, 0x22, 0x02, 0x41, 0x7f, 0x73, 0x20, 0x02,
+    0x41, 0xff, 0xfd, 0xfb, 0x77, 0x6a, 0x71, 0x41, 0x80, 0x81, 0x82, 0x84,
+    0x78, 0x71, 0x45, 0x0d, 0x00, 0x0b, 0x02, 0x40, 0x20, 0x02, 0x41, 0xff,
+    0x01, 0x71, 0x45, 0x04, 0x40, 0x20, 0x01, 0x21, 0x00, 0x0c, 0x01, 0x0b,
+    0x03, 0x40, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x21, 0x02, 0x20, 0x01, 0x41,
+    0x01, 0x6a, 0x22, 0x00, 0x21, 0x01, 0x20, 0x02, 0x0d, 0x00, 0x0b, 0x0b,
+    0x20, 0x00, 0x41, 0x80, 0x08, 0x6b, 0x0b, 0x0c, 0x00, 0x02, 0x7f, 0x41,
+    0x00, 0x41, 0x00, 0x10, 0x04, 0x0b, 0x1a, 0x0b, 0x66, 0x01, 0x02, 0x7f,
+    0x41, 0x90, 0x08, 0x28, 0x02, 0x00, 0x22, 0x00, 0x28, 0x02, 0x4c, 0x41,
+    0x00, 0x4e, 0x04, 0x7f, 0x41, 0x01, 0x05, 0x20, 0x01, 0x0b, 0x1a, 0x02,
+    0x40, 0x41, 0x7f, 0x41, 0x00, 0x10, 0x0a, 0x22, 0x01, 0x20, 0x01, 0x20,
+    0x00, 0x10, 0x09, 0x47, 0x1b, 0x41, 0x00, 0x48, 0x0d, 0x00, 0x02, 0x40,
+    0x20, 0x00, 0x2d, 0x00, 0x4b, 0x41, 0x0a, 0x46, 0x0d, 0x00, 0x20, 0x00,
+    0x28, 0x02, 0x14, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x10, 0x4f, 0x0d,
+    0x00, 0x20, 0x00, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x14, 0x20,
+    0x01, 0x41, 0x0a, 0x3a, 0x00, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x10,
+    0x06, 0x0b, 0x0b, 0x3d, 0x01, 0x01, 0x7f, 0x20, 0x02, 0x04, 0x40, 0x03,
+    0x40, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x41, 0x80, 0xc0, 0x00, 0x20,
+    0x02, 0x41, 0x80, 0xc0, 0x00, 0x49, 0x1b, 0x22, 0x03, 0x10, 0x03, 0x21,
+    0x00, 0x20, 0x01, 0x41, 0x80, 0x40, 0x6b, 0x21, 0x01, 0x20, 0x00, 0x41,
+    0x80, 0x40, 0x6b, 0x21, 0x00, 0x20, 0x02, 0x20, 0x03, 0x6b, 0x22, 0x02,
+    0x0d, 0x00, 0x0b, 0x0b, 0x0b, 0xb1, 0x02, 0x01, 0x06, 0x7f, 0x23, 0x00,
+    0x41, 0x20, 0x6b, 0x22, 0x03, 0x24, 0x00, 0x20, 0x03, 0x20, 0x00, 0x28,
+    0x02, 0x1c, 0x22, 0x04, 0x36, 0x02, 0x10, 0x20, 0x00, 0x28, 0x02, 0x14,
+    0x21, 0x05, 0x20, 0x03, 0x20, 0x02, 0x36, 0x02, 0x1c, 0x20, 0x03, 0x20,
+    0x01, 0x36, 0x02, 0x18, 0x20, 0x03, 0x20, 0x05, 0x20, 0x04, 0x6b, 0x22,
+    0x01, 0x36, 0x02, 0x14, 0x20, 0x01, 0x20, 0x02, 0x6a, 0x21, 0x06, 0x41,
+    0x02, 0x21, 0x05, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x21, 0x01, 0x03, 0x40,
+    0x02, 0x40, 0x02, 0x7f, 0x20, 0x06, 0x02, 0x7f, 0x20, 0x00, 0x28, 0x02,
+    0x3c, 0x20, 0x01, 0x20, 0x05, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x10, 0x00,
+    0x04, 0x40, 0x20, 0x03, 0x41, 0x7f, 0x36, 0x02, 0x0c, 0x41, 0x7f, 0x0c,
+    0x01, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x0c, 0x0b, 0x22, 0x04, 0x46, 0x04,
+    0x40, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x2c, 0x22, 0x01, 0x36, 0x02,
+    0x1c, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, 0x00, 0x20, 0x01,
+    0x20, 0x00, 0x28, 0x02, 0x30, 0x6a, 0x36, 0x02, 0x10, 0x20, 0x02, 0x0c,
+    0x01, 0x0b, 0x20, 0x04, 0x41, 0x7f, 0x4a, 0x0d, 0x01, 0x20, 0x00, 0x41,
+    0x00, 0x36, 0x02, 0x1c, 0x20, 0x00, 0x42, 0x00, 0x37, 0x03, 0x10, 0x20,
+    0x00, 0x20, 0x00, 0x28, 0x02, 0x00, 0x41, 0x20, 0x72, 0x36, 0x02, 0x00,
+    0x41, 0x00, 0x20, 0x05, 0x41, 0x02, 0x46, 0x0d, 0x00, 0x1a, 0x20, 0x02,
+    0x20, 0x01, 0x28, 0x02, 0x04, 0x6b, 0x0b, 0x21, 0x04, 0x20, 0x03, 0x41,
+    0x20, 0x6a, 0x24, 0x00, 0x20, 0x04, 0x0f, 0x0b, 0x20, 0x01, 0x41, 0x08,
+    0x6a, 0x20, 0x01, 0x20, 0x04, 0x20, 0x01, 0x28, 0x02, 0x04, 0x22, 0x07,
+    0x4b, 0x22, 0x08, 0x1b, 0x22, 0x01, 0x20, 0x04, 0x20, 0x07, 0x41, 0x00,
+    0x20, 0x08, 0x1b, 0x6b, 0x22, 0x07, 0x20, 0x01, 0x28, 0x02, 0x00, 0x6a,
+    0x36, 0x02, 0x00, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x04, 0x20, 0x07,
+    0x6b, 0x36, 0x02, 0x04, 0x20, 0x06, 0x20, 0x04, 0x6b, 0x21, 0x06, 0x20,
+    0x05, 0x20, 0x08, 0x6b, 0x21, 0x05, 0x0c, 0x00, 0x00, 0x0b, 0x00, 0x0b,
+    0x0b, 0x4d, 0x06, 0x00, 0x41, 0x80, 0x08, 0x0b, 0x12, 0x68, 0x65, 0x6c,
+    0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x00, 0x00,
+    0x00, 0x18, 0x04, 0x00, 0x41, 0x98, 0x08, 0x0b, 0x01, 0x05, 0x00, 0x41,
+    0xa4, 0x08, 0x0b, 0x01, 0x01, 0x00, 0x41, 0xbc, 0x08, 0x0b, 0x0e, 0x02,
+    0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb8, 0x04, 0x00, 0x00, 0x00,
+    0x04, 0x00, 0x41, 0xd4, 0x08, 0x0b, 0x01, 0x01, 0x00, 0x41, 0xe3, 0x08,
+    0x0b, 0x05, 0x0a, 0xff, 0xff, 0xff, 0xff,
+  ]);
+
+  WasmMemory mem = null;
+  String out = "";
+  var getI32 = (int p) {
+    // Read a little-endian I32.
+    int n = 0;
+    for (var i = p + 3; i >= p; --i) {
+      n *= 256;
+      n += mem[i];
+    }
+    return n;
+  };
+  var inst = WasmModule(data).instantiate(WasmImports()
+    ..addFunction<Int32 Function(Int32, Int32, Int32, Int32)>(
+        "wasi_unstable", "fd_write",
+        (int fd, int iovs, int iovs_len, int unused) {
+      // iovs points to an array of length iovs_len. Each element is two I32s,
+      // a char* and a length.
+      String o = "";
+      for (var i = 0; i < iovs_len; ++i) {
+        var str = getI32(iovs + 8 * i);
+        var len = getI32(iovs + 4 + 8 * i);
+        for (var j = 0; j < len; ++j) {
+          o += String.fromCharCode(mem[str + j]);
+        }
+      }
+      out += o;
+      return o.length;
+    }));
+  mem = inst.memory;
+
+  var fn = inst.lookupFunction<Void Function()>("_start");
+  fn.call([]);
+  Expect.equals("hello, world!\n", out);
+}
diff --git a/tests/lib/wasm/import_error_test.dart b/tests/lib/wasm/import_error_test.dart
new file mode 100644
index 0000000..a06a3a9
--- /dev/null
+++ b/tests/lib/wasm/import_error_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test errors thrown by WasmImports.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  var imp = WasmImports();
+  imp.addGlobal<Int64>("env", "x", 123, false);
+  imp.addGlobal<Double>("env", "y", 4.56, true);
+  Expect.throwsArgumentError(() => imp.addGlobal<int>("env", "a", 1, true));
+  Expect.throwsArgumentError(() => imp.addGlobal<double>("env", "b", 2, true));
+  Expect.throwsArgumentError(() => imp.addGlobal<dynamic>("env", "c", 3, true));
+}
diff --git a/tests/lib/wasm/memory_error_test.dart b/tests/lib/wasm/memory_error_test.dart
new file mode 100644
index 0000000..e866bf0
--- /dev/null
+++ b/tests/lib/wasm/memory_error_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test errors thrown by WasmMemory.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  Expect.throwsArgumentError(() => WasmMemory(1000000000));
+  var mem = WasmMemory(1000);
+  Expect.throwsArgumentError(() => mem.grow(1000000000));
+}
diff --git a/tests/lib/wasm/memory_test.dart b/tests/lib/wasm/memory_test.dart
new file mode 100644
index 0000000..52d12c3
--- /dev/null
+++ b/tests/lib/wasm/memory_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that we can create a WasmMemory, edit it, and grow it.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  var mem = WasmMemory(1000);
+  Expect.equals(1000, mem.lengthInPages);
+  Expect.equals(1000 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
+
+  mem[123] = 45;
+  Expect.equals(45, mem[123]);
+
+  mem.grow(100);
+  Expect.equals(1100, mem.lengthInPages);
+  Expect.equals(1100 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
+  Expect.equals(45, mem[123]);
+
+  Expect.throwsArgumentError(() => WasmMemory(1000000000));
+  Expect.throwsArgumentError(() => mem.grow(1000000000));
+}
diff --git a/tests/lib/wasm/numerics_test.dart b/tests/lib/wasm/numerics_test.dart
new file mode 100644
index 0000000..8651caa
--- /dev/null
+++ b/tests/lib/wasm/numerics_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test numeric types.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // int64_t addI64(int64_t x, int64_t y) { return x + y; }
+  // int32_t addI32(int32_t x, int32_t y) { return x + y; }
+  // double addF64(double x, double y) { return x + y; }
+  // float addF32(float x, float y) { return x + y; }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x19, 0x04, 0x60,
+    0x02, 0x7e, 0x7e, 0x01, 0x7e, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60,
+    0x02, 0x7c, 0x7c, 0x01, 0x7c, 0x60, 0x02, 0x7d, 0x7d, 0x01, 0x7d, 0x03,
+    0x05, 0x04, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01,
+    0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41,
+    0x80, 0x88, 0x04, 0x0b, 0x07, 0x2e, 0x05, 0x06, 0x6d, 0x65, 0x6d, 0x6f,
+    0x72, 0x79, 0x02, 0x00, 0x06, 0x61, 0x64, 0x64, 0x49, 0x36, 0x34, 0x00,
+    0x00, 0x06, 0x61, 0x64, 0x64, 0x49, 0x33, 0x32, 0x00, 0x01, 0x06, 0x61,
+    0x64, 0x64, 0x46, 0x36, 0x34, 0x00, 0x02, 0x06, 0x61, 0x64, 0x64, 0x46,
+    0x33, 0x32, 0x00, 0x03, 0x0a, 0x21, 0x04, 0x07, 0x00, 0x20, 0x01, 0x20,
+    0x00, 0x7c, 0x0b, 0x07, 0x00, 0x20, 0x01, 0x20, 0x00, 0x6a, 0x0b, 0x07,
+    0x00, 0x20, 0x00, 0x20, 0x01, 0xa0, 0x0b, 0x07, 0x00, 0x20, 0x00, 0x20,
+    0x01, 0x92, 0x0b,
+  ]);
+
+  var inst = WasmModule(data).instantiate(WasmImports());
+  var addI64 = inst.lookupFunction<Int64 Function(Int64, Int64)>("addI64");
+  var addI32 = inst.lookupFunction<Int32 Function(Int32, Int32)>("addI32");
+  var addF64 = inst.lookupFunction<Double Function(Double, Double)>("addF64");
+  var addF32 = inst.lookupFunction<Float Function(Float, Float)>("addF32");
+
+  int i64 = addI64.call([0x123456789ABCDEF, 0xFEDCBA987654321]);
+  Expect.equals(0x1111111111111110, i64);
+
+  int i32 = addI32.call([0xABCDEF, 0xFEDCBA]);
+  Expect.equals(0x1aaaaa9, i32);
+
+  double f64 = addF64.call([1234.5678, 8765.4321]);
+  Expect.approxEquals(9999.9999, f64, 1e-6);
+
+  double f32 = addF32.call([1234.5678, 8765.4321]);
+  Expect.approxEquals(9999.9999, f32, 1e-3);
+}
diff --git a/tests/lib/wasm/void_test.dart b/tests/lib/wasm/void_test.dart
new file mode 100644
index 0000000..fe3bd94
--- /dev/null
+++ b/tests/lib/wasm/void_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test functions with void return type, and functions that take no args.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // int64_t x = 0;
+  // void set(int64_t a, int64_t b) { x = a + b; }
+  // int64_t get() { return x; }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x02, 0x60,
+    0x02, 0x7e, 0x7e, 0x00, 0x60, 0x00, 0x01, 0x7e, 0x03, 0x03, 0x02, 0x00,
+    0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00,
+    0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41, 0x90, 0x88, 0x04, 0x0b, 0x07,
+    0x16, 0x03, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x03,
+    0x73, 0x65, 0x74, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, 0x01, 0x0a,
+    0x1e, 0x02, 0x10, 0x00, 0x41, 0x00, 0x20, 0x01, 0x20, 0x00, 0x7c, 0x37,
+    0x03, 0x80, 0x88, 0x80, 0x80, 0x00, 0x0b, 0x0b, 0x00, 0x41, 0x00, 0x29,
+    0x03, 0x80, 0x88, 0x80, 0x80, 0x00, 0x0b, 0x0b, 0x0f, 0x01, 0x00, 0x41,
+    0x80, 0x08, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  ]);
+
+  var inst = WasmModule(data).instantiate(WasmImports());
+  var setFn = inst.lookupFunction<Void Function(Int64, Int64)>("set");
+  var getFn = inst.lookupFunction<Int64 Function()>("get");
+  Expect.isNull(setFn.call([123, 456]));
+  int n = getFn.call([]);
+  Expect.equals(123 + 456, n);
+}
diff --git a/tools/VERSION b/tools/VERSION
index bc4e037..0f79813 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
 MAJOR 2
 MINOR 8
 PATCH 0
-PRERELEASE 2
+PRERELEASE 3
 PRERELEASE_PATCH 0
 ABI_VERSION 27
 OLDEST_SUPPORTED_ABI_VERSION 27