Version 2.14.0-358.0.dev

Merge commit '45ae00676adcd36eda411dd6fcec550784128b9a' into 'dev'
diff --git a/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart b/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
index 213fbbb..ddad876 100644
--- a/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
@@ -11,7 +11,6 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(LocalVariableResolutionTest);
-    defineReflectiveTests(LocalVariableResolutionWithNullSafetyTest);
   });
 }
 
@@ -95,11 +94,7 @@
     expect(x.isLate, isFalse);
     expect(x.isStatic, isFalse);
   }
-}
 
-@reflectiveTest
-class LocalVariableResolutionWithNullSafetyTest
-    extends LocalVariableResolutionTest with WithNullSafetyMixin {
   test_element_late() async {
     await assertErrorsInCode(r'''
 void f() {
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 094323e..2c5f443 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -12,13 +12,298 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PostfixExpressionResolutionTest);
-    defineReflectiveTests(PostfixExpressionResolutionWithNullSafetyTest);
+    defineReflectiveTests(PostfixExpressionResolutionWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class PostfixExpressionResolutionTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with PostfixExpressionResolutionTestCases {
+  test_inc_propertyAccess_nullShorting() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int foo = 0;
+}
+
+void f(A? a) {
+  a?.foo++;
+}
+''');
+
+    assertPostfixExpression(
+      findNode.postfix('foo++'),
+      readElement: findElement.getter('foo'),
+      readType: 'int',
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      element: numElement.getMethod('+'),
+      type: 'int?',
+    );
+  }
+
+  test_inc_simpleIdentifier_parameter_depromote() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  Object operator +(int _) => this;
+}
+
+void f(Object x) {
+  if (x is A) {
+    x++;
+    x; // ref
+  }
+}
+''');
+
+    if (hasAssignmentLeftResolution) {
+      assertType(findNode.simple('x++;'), 'A');
+    }
+
+    assertPostfixExpression(
+      findNode.postfix('x++'),
+      readElement: findElement.parameter('x'),
+      readType: 'A',
+      writeElement: findElement.parameter('x'),
+      writeType: 'Object',
+      element: findElement.method('+'),
+      type: 'A',
+    );
+
+    assertType(findNode.simple('x; // ref'), 'Object');
+  }
+
+  test_nullCheck() async {
+    await assertNoErrorsInCode(r'''
+void f(int? x) {
+  x!;
+}
+''');
+
+    assertPostfixExpression(
+      findNode.postfix('x!'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'int',
+    );
+  }
+
+  test_nullCheck_functionExpressionInvocation_rewrite() async {
+    await assertNoErrorsInCode(r'''
+void f(Function f2) {
+  f2(42)!;
+}
+''');
+  }
+
+  test_nullCheck_indexExpression() async {
+    await assertNoErrorsInCode(r'''
+void f(Map<String, int> a) {
+  int v = a['foo']!;
+  v;
+}
+''');
+
+    assertIndexExpression(
+      findNode.index('a['),
+      readElement: elementMatcher(
+        mapElement.getMethod('[]'),
+        substitution: {'K': 'String', 'V': 'int'},
+      ),
+      writeElement: null,
+      type: 'int?',
+    );
+
+    assertPostfixExpression(
+      findNode.postfix(']!'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'int',
+    );
+  }
+
+  test_nullCheck_null() async {
+    await assertErrorsInCode('''
+void f(Null x) {
+  x!;
+}
+''', [
+      error(HintCode.NULL_CHECK_ALWAYS_FAILS, 19, 2),
+    ]);
+
+    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)!'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'int',
+    );
+  }
+
+  /// See https://github.com/dart-lang/language/issues/1163
+  test_nullCheck_participatesNullShorting() async {
+    await assertErrorsInCode('''
+class A {
+  int zero;
+  int? zeroOrNull;
+
+  A(this.zero, [this.zeroOrNull]);
+}
+
+void test1(A? a) => a?.zero!;
+void test2(A? a) => a?.zeroOrNull!;
+void test3(A? a) => a?.zero!.isEven;
+void test4(A? a) => a?.zeroOrNull!.isEven;
+
+class Foo {
+  Bar? bar;
+
+  Foo(this.bar);
+
+  Bar? operator [](int? index) => null;
+}
+
+class Bar {
+  int baz;
+
+  Bar(this.baz);
+
+  int operator [](int index) => index;
+}
+
+void test5(Foo? foo) => foo?.bar!;
+void test6(Foo? foo) => foo?.bar!.baz;
+void test7(Foo? foo, int a) => foo?.bar![a];
+void test8(Foo? foo, int? a) => foo?[a]!;
+void test9(Foo? foo, int? a) => foo?[a]!.baz;
+void test10(Foo? foo, int? a, int b) => foo?[a]![b];
+''', [
+      error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 107, 1),
+      error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 173, 1),
+    ]);
+
+    void assertTestType(int index, String expected) {
+      var function = findNode.functionDeclaration('test$index(');
+      var body = function.functionExpression.body as ExpressionFunctionBody;
+      assertType(body.expression, expected);
+    }
+
+    assertTestType(1, 'int?');
+    assertTestType(2, 'int?');
+    assertTestType(3, 'bool?');
+    assertTestType(4, 'bool?');
+
+    assertTestType(5, 'Bar?');
+    assertTestType(6, 'int?');
+    assertTestType(7, 'int?');
+    assertTestType(8, 'Bar?');
+    assertTestType(9, 'int?');
+    assertTestType(10, 'int?');
+  }
+
+  test_nullCheck_superExpression() async {
+    await assertErrorsInCode(r'''
+class A {
+  int foo() => 0;
+}
+
+class B extends A {
+  void bar() {
+    super!.foo();
+  }
+}
+''', [
+      error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 70, 6),
+    ]);
+
+    assertTypeDynamic(findNode.super_('super!'));
+
+    assertPostfixExpression(
+      findNode.postfix('super!'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'dynamic',
+    );
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('foo();'),
+      element: null,
+      typeArgumentTypes: [],
+      invokeType: 'dynamic',
+      type: 'dynamic',
+    );
+  }
+
+  test_nullCheck_typeParameter() async {
+    await assertNoErrorsInCode(r'''
+void f<T>(T? x) {
+  x!;
+}
+''');
+
+    var postfixExpression = findNode.postfix('x!');
+    assertPostfixExpression(
+      postfixExpression,
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'T & Object',
+    );
+  }
+
+  test_nullCheck_typeParameter_already_promoted() async {
+    await assertNoErrorsInCode('''
+void f<T>(T? x) {
+  if (x is num?) {
+    x!;
+  }
+}
+''');
+
+    var postfixExpression = findNode.postfix('x!');
+    assertPostfixExpression(
+      postfixExpression,
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: null,
+      type: 'T & num',
+    );
+  }
+}
+
+mixin PostfixExpressionResolutionTestCases on PubPackageResolutionTest {
   test_dec_simpleIdentifier_parameter_int() async {
     await assertNoErrorsInCode(r'''
 void f(int x) {
@@ -484,288 +769,6 @@
 }
 
 @reflectiveTest
-class PostfixExpressionResolutionWithNullSafetyTest
-    extends PostfixExpressionResolutionTest with WithNullSafetyMixin {
-  test_inc_propertyAccess_nullShorting() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int foo = 0;
-}
-
-void f(A? a) {
-  a?.foo++;
-}
-''');
-
-    assertPostfixExpression(
-      findNode.postfix('foo++'),
-      readElement: findElement.getter('foo'),
-      readType: 'int',
-      writeElement: findElement.setter('foo'),
-      writeType: 'int',
-      element: numElement.getMethod('+'),
-      type: 'int?',
-    );
-  }
-
-  test_inc_simpleIdentifier_parameter_depromote() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  Object operator +(int _) => this;
-}
-
-void f(Object x) {
-  if (x is A) {
-    x++;
-    x; // ref
-  }
-}
-''');
-
-    if (hasAssignmentLeftResolution) {
-      assertType(findNode.simple('x++;'), 'A');
-    }
-
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.parameter('x'),
-      readType: 'A',
-      writeElement: findElement.parameter('x'),
-      writeType: 'Object',
-      element: findElement.method('+'),
-      type: 'A',
-    );
-
-    assertType(findNode.simple('x; // ref'), 'Object');
-  }
-
-  test_nullCheck() async {
-    await assertNoErrorsInCode(r'''
-void f(int? x) {
-  x!;
-}
-''');
-
-    assertPostfixExpression(
-      findNode.postfix('x!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'int',
-    );
-  }
-
-  test_nullCheck_functionExpressionInvocation_rewrite() async {
-    await assertNoErrorsInCode(r'''
-void f(Function f2) {
-  f2(42)!;
-}
-''');
-  }
-
-  test_nullCheck_indexExpression() async {
-    await assertNoErrorsInCode(r'''
-void f(Map<String, int> a) {
-  int v = a['foo']!;
-  v;
-}
-''');
-
-    assertIndexExpression(
-      findNode.index('a['),
-      readElement: elementMatcher(
-        mapElement.getMethod('[]'),
-        substitution: {'K': 'String', 'V': 'int'},
-      ),
-      writeElement: null,
-      type: 'int?',
-    );
-
-    assertPostfixExpression(
-      findNode.postfix(']!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'int',
-    );
-  }
-
-  test_nullCheck_null() async {
-    await assertErrorsInCode('''
-void f(Null x) {
-  x!;
-}
-''', [
-      error(HintCode.NULL_CHECK_ALWAYS_FAILS, 19, 2),
-    ]);
-
-    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)!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'int',
-    );
-  }
-
-  /// See https://github.com/dart-lang/language/issues/1163
-  test_nullCheck_participatesNullShorting() async {
-    await assertErrorsInCode('''
-class A {
-  int zero;
-  int? zeroOrNull;
-
-  A(this.zero, [this.zeroOrNull]);
-}
-
-void test1(A? a) => a?.zero!;
-void test2(A? a) => a?.zeroOrNull!;
-void test3(A? a) => a?.zero!.isEven;
-void test4(A? a) => a?.zeroOrNull!.isEven;
-
-class Foo {
-  Bar? bar;
-
-  Foo(this.bar);
-
-  Bar? operator [](int? index) => null;
-}
-
-class Bar {
-  int baz;
-
-  Bar(this.baz);
-
-  int operator [](int index) => index;
-}
-
-void test5(Foo? foo) => foo?.bar!;
-void test6(Foo? foo) => foo?.bar!.baz;
-void test7(Foo? foo, int a) => foo?.bar![a];
-void test8(Foo? foo, int? a) => foo?[a]!;
-void test9(Foo? foo, int? a) => foo?[a]!.baz;
-void test10(Foo? foo, int? a, int b) => foo?[a]![b];
-''', [
-      error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 107, 1),
-      error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 173, 1),
-    ]);
-
-    void assertTestType(int index, String expected) {
-      var function = findNode.functionDeclaration('test$index(');
-      var body = function.functionExpression.body as ExpressionFunctionBody;
-      assertType(body.expression, expected);
-    }
-
-    assertTestType(1, 'int?');
-    assertTestType(2, 'int?');
-    assertTestType(3, 'bool?');
-    assertTestType(4, 'bool?');
-
-    assertTestType(5, 'Bar?');
-    assertTestType(6, 'int?');
-    assertTestType(7, 'int?');
-    assertTestType(8, 'Bar?');
-    assertTestType(9, 'int?');
-    assertTestType(10, 'int?');
-  }
-
-  test_nullCheck_superExpression() async {
-    await assertErrorsInCode(r'''
-class A {
-  int foo() => 0;
-}
-
-class B extends A {
-  void bar() {
-    super!.foo();
-  }
-}
-''', [
-      error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 70, 6),
-    ]);
-
-    assertTypeDynamic(findNode.super_('super!'));
-
-    assertPostfixExpression(
-      findNode.postfix('super!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'dynamic',
-    );
-
-    assertMethodInvocation2(
-      findNode.methodInvocation('foo();'),
-      element: null,
-      typeArgumentTypes: [],
-      invokeType: 'dynamic',
-      type: 'dynamic',
-    );
-  }
-
-  test_nullCheck_typeParameter() async {
-    await assertNoErrorsInCode(r'''
-void f<T>(T? x) {
-  x!;
-}
-''');
-
-    var postfixExpression = findNode.postfix('x!');
-    assertPostfixExpression(
-      postfixExpression,
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'T & Object',
-    );
-  }
-
-  test_nullCheck_typeParameter_already_promoted() async {
-    await assertNoErrorsInCode('''
-void f<T>(T? x) {
-  if (x is num?) {
-    x!;
-  }
-}
-''');
-
-    var postfixExpression = findNode.postfix('x!');
-    assertPostfixExpression(
-      postfixExpression,
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'T & num',
-    );
-  }
-}
+class PostfixExpressionResolutionWithoutNullSafetyTest
+    extends PubPackageResolutionTest
+    with PostfixExpressionResolutionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
index 06fd33d..1fa6d56 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
@@ -12,13 +12,140 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PrefixExpressionResolutionTest);
-    defineReflectiveTests(PrefixExpressionResolutionWithNullSafetyTest);
+    defineReflectiveTests(PrefixExpressionResolutionWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class PrefixExpressionResolutionTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with PrefixExpressionResolutionTestCases {
+  test_bang_no_nullShorting() async {
+    await assertErrorsInCode(r'''
+class A {
+  bool get foo => true;
+}
+
+void f(A? a) {
+  !a?.foo;
+}
+''', [
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
+          55, 6),
+    ]);
+
+    assertPrefixExpression(
+      findNode.prefix('!a'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: boolElement.getMethod('!'),
+      type: 'bool',
+    );
+  }
+
+  test_minus_no_nullShorting() async {
+    await assertErrorsInCode(r'''
+class A {
+  int get foo => 0;
+}
+
+void f(A? a) {
+  -a?.foo;
+}
+''', [
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          50, 1),
+    ]);
+
+    assertPrefixExpression(
+      findNode.prefix('-a'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: intElement.getMethod('unary-'),
+      type: 'int',
+    );
+  }
+
+  test_plusPlus_depromote() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  Object operator +(int _) => this;
+}
+
+void f(Object x) {
+  if (x is A) {
+    ++x;
+  }
+}
+''');
+
+    assertPrefixExpression(
+      findNode.prefix('++x'),
+      readElement: findElement.parameter('x'),
+      readType: 'A',
+      writeElement: findElement.parameter('x'),
+      writeType: 'Object',
+      element: findElement.method('+'),
+      type: 'Object',
+    );
+
+    if (hasAssignmentLeftResolution) {
+      assertType(findNode.simple('x;'), 'A');
+    }
+  }
+
+  test_plusPlus_nullShorting() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int foo = 0;
+}
+
+void f(A? a) {
+  ++a?.foo;
+}
+''');
+
+    assertPrefixExpression(
+      findNode.prefix('++a'),
+      readElement: findElement.getter('foo'),
+      readType: 'int',
+      writeElement: findElement.setter('foo'),
+      writeType: 'int',
+      element: numElement.getMethod('+'),
+      type: 'int?',
+    );
+  }
+
+  test_tilde_no_nullShorting() async {
+    await assertErrorsInCode(r'''
+class A {
+  int get foo => 0;
+}
+
+void f(A? a) {
+  ~a?.foo;
+}
+''', [
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          50, 1),
+    ]);
+
+    assertPrefixExpression(
+      findNode.prefix('~a'),
+      readElement: null,
+      readType: null,
+      writeElement: null,
+      writeType: null,
+      element: intElement.getMethod('~'),
+      type: 'int',
+    );
+  }
+}
+
+mixin PrefixExpressionResolutionTestCases on PubPackageResolutionTest {
   test_bang_bool_context() async {
     await assertNoErrorsInCode(r'''
 T f<T>() {
@@ -637,130 +764,6 @@
 }
 
 @reflectiveTest
-class PrefixExpressionResolutionWithNullSafetyTest
-    extends PrefixExpressionResolutionTest with WithNullSafetyMixin {
-  test_bang_no_nullShorting() async {
-    await assertErrorsInCode(r'''
-class A {
-  bool get foo => true;
-}
-
-void f(A? a) {
-  !a?.foo;
-}
-''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
-          55, 6),
-    ]);
-
-    assertPrefixExpression(
-      findNode.prefix('!a'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: boolElement.getMethod('!'),
-      type: 'bool',
-    );
-  }
-
-  test_minus_no_nullShorting() async {
-    await assertErrorsInCode(r'''
-class A {
-  int get foo => 0;
-}
-
-void f(A? a) {
-  -a?.foo;
-}
-''', [
-      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
-          50, 1),
-    ]);
-
-    assertPrefixExpression(
-      findNode.prefix('-a'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: intElement.getMethod('unary-'),
-      type: 'int',
-    );
-  }
-
-  test_plusPlus_depromote() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  Object operator +(int _) => this;
-}
-
-void f(Object x) {
-  if (x is A) {
-    ++x;
-  }
-}
-''');
-
-    assertPrefixExpression(
-      findNode.prefix('++x'),
-      readElement: findElement.parameter('x'),
-      readType: 'A',
-      writeElement: findElement.parameter('x'),
-      writeType: 'Object',
-      element: findElement.method('+'),
-      type: 'Object',
-    );
-
-    if (hasAssignmentLeftResolution) {
-      assertType(findNode.simple('x;'), 'A');
-    }
-  }
-
-  test_plusPlus_nullShorting() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int foo = 0;
-}
-
-void f(A? a) {
-  ++a?.foo;
-}
-''');
-
-    assertPrefixExpression(
-      findNode.prefix('++a'),
-      readElement: findElement.getter('foo'),
-      readType: 'int',
-      writeElement: findElement.setter('foo'),
-      writeType: 'int',
-      element: numElement.getMethod('+'),
-      type: 'int?',
-    );
-  }
-
-  test_tilde_no_nullShorting() async {
-    await assertErrorsInCode(r'''
-class A {
-  int get foo => 0;
-}
-
-void f(A? a) {
-  ~a?.foo;
-}
-''', [
-      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
-          50, 1),
-    ]);
-
-    assertPrefixExpression(
-      findNode.prefix('~a'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: intElement.getMethod('~'),
-      type: 'int',
-    );
-  }
-}
+class PrefixExpressionResolutionWithoutNullSafetyTest
+    extends PubPackageResolutionTest
+    with PrefixExpressionResolutionTestCases, WithoutNullSafetyMixin {}
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 b95d627..e3ef89b 100644
--- a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
@@ -11,13 +11,168 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PropertyAccessResolutionTest);
-    defineReflectiveTests(PropertyAccessResolutionWithNullSafetyTest);
+    defineReflectiveTests(PropertyAccessResolutionWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class PropertyAccessResolutionTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with PropertyAccessResolutionTestCases {
+  test_implicitCall_tearOff_nullable() async {
+    await assertErrorsInCode('''
+class A {
+  int call() => 0;
+}
+
+class B {
+  A? a;
+}
+
+int Function() foo() {
+  return B().a; // ref
+}
+''', [
+      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 85, 5),
+    ]);
+
+    var identifier = findNode.simple('a; // ref');
+    assertElement(identifier, findElement.getter('a'));
+    assertType(identifier, 'A?');
+  }
+
+  test_nullShorting_cascade() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int get foo => 0;
+  int get bar => 0;
+}
+
+void f(A? a) {
+  a?..foo..bar;
+}
+''');
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('..foo'),
+      element: findElement.getter('foo'),
+      type: 'int',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('..bar'),
+      element: findElement.getter('bar'),
+      type: 'int',
+    );
+
+    assertType(findNode.cascade('a?'), 'A?');
+  }
+
+  test_nullShorting_cascade2() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int? get foo => 0;
+}
+
+main() {
+  A a = A()..foo?.isEven;
+  a;
+}
+''');
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('..foo?'),
+      element: findElement.getter('foo'),
+      type: 'int?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.isEven'),
+      element: intElement.getGetter('isEven'),
+      type: 'bool',
+    );
+
+    assertType(findNode.cascade('A()'), 'A');
+  }
+
+  test_nullShorting_cascade3() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A? get foo => this;
+  A? get bar => this;
+  A? get baz => this;
+}
+
+main() {
+  A a = A()..foo?.bar?.baz;
+  a;
+}
+''');
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.foo'),
+      element: findElement.getter('foo'),
+      type: 'A?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.bar'),
+      element: findElement.getter('bar'),
+      type: 'A?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.baz'),
+      element: findElement.getter('baz'),
+      type: 'A?',
+    );
+
+    assertType(findNode.cascade('A()'), 'A');
+  }
+
+  test_nullShorting_cascade4() async {
+    await assertNoErrorsInCode(r'''
+A? get foo => A();
+
+class A {
+  A get bar => this;
+  A? get baz => this;
+  A get baq => this;
+}
+
+main() {
+  foo?.bar?..baz?.baq;
+}
+''');
+
+    assertSimpleIdentifier(
+      findNode.simple('foo?'),
+      element: findElement.topGet('foo'),
+      type: 'A?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.bar'),
+      element: findElement.getter('bar'),
+      type: 'A?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.baz'),
+      element: findElement.getter('baz'),
+      type: 'A?',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('.baq'),
+      element: findElement.getter('baq'),
+      type: 'A',
+    );
+
+    assertType(findNode.cascade('foo?'), 'A?');
+  }
+}
+
+mixin PropertyAccessResolutionTestCases on PubPackageResolutionTest {
   test_extensionOverride_read() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -561,158 +716,6 @@
 }
 
 @reflectiveTest
-class PropertyAccessResolutionWithNullSafetyTest
-    extends PropertyAccessResolutionTest with WithNullSafetyMixin {
-  test_implicitCall_tearOff_nullable() async {
-    await assertErrorsInCode('''
-class A {
-  int call() => 0;
-}
-
-class B {
-  A? a;
-}
-
-int Function() foo() {
-  return B().a; // ref
-}
-''', [
-      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 85, 5),
-    ]);
-
-    var identifier = findNode.simple('a; // ref');
-    assertElement(identifier, findElement.getter('a'));
-    assertType(identifier, 'A?');
-  }
-
-  test_nullShorting_cascade() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int get foo => 0;
-  int get bar => 0;
-}
-
-void f(A? a) {
-  a?..foo..bar;
-}
-''');
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('..foo'),
-      element: findElement.getter('foo'),
-      type: 'int',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('..bar'),
-      element: findElement.getter('bar'),
-      type: 'int',
-    );
-
-    assertType(findNode.cascade('a?'), 'A?');
-  }
-
-  test_nullShorting_cascade2() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  int? get foo => 0;
-}
-
-main() {
-  A a = A()..foo?.isEven;
-  a;
-}
-''');
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('..foo?'),
-      element: findElement.getter('foo'),
-      type: 'int?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.isEven'),
-      element: intElement.getGetter('isEven'),
-      type: 'bool',
-    );
-
-    assertType(findNode.cascade('A()'), 'A');
-  }
-
-  test_nullShorting_cascade3() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  A? get foo => this;
-  A? get bar => this;
-  A? get baz => this;
-}
-
-main() {
-  A a = A()..foo?.bar?.baz;
-  a;
-}
-''');
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.foo'),
-      element: findElement.getter('foo'),
-      type: 'A?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.bar'),
-      element: findElement.getter('bar'),
-      type: 'A?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.baz'),
-      element: findElement.getter('baz'),
-      type: 'A?',
-    );
-
-    assertType(findNode.cascade('A()'), 'A');
-  }
-
-  test_nullShorting_cascade4() async {
-    await assertNoErrorsInCode(r'''
-A? get foo => A();
-
-class A {
-  A get bar => this;
-  A? get baz => this;
-  A get baq => this;
-}
-
-main() {
-  foo?.bar?..baz?.baq;
-}
-''');
-
-    assertSimpleIdentifier(
-      findNode.simple('foo?'),
-      element: findElement.topGet('foo'),
-      type: 'A?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.bar'),
-      element: findElement.getter('bar'),
-      type: 'A?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.baz'),
-      element: findElement.getter('baz'),
-      type: 'A?',
-    );
-
-    assertPropertyAccess2(
-      findNode.propertyAccess('.baq'),
-      element: findElement.getter('baq'),
-      type: 'A',
-    );
-
-    assertType(findNode.cascade('foo?'), 'A?');
-  }
-}
+class PropertyAccessResolutionWithoutNullSafetyTest
+    extends PubPackageResolutionTest
+    with PropertyAccessResolutionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart b/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart
index 1349f39..444c894 100644
--- a/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart
@@ -11,13 +11,32 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(TopLevelVariableTest);
-    defineReflectiveTests(TopLevelVariableWithNullSafetyTest);
+    defineReflectiveTests(TopLevelVariableWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class TopLevelVariableTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with TopLevelVariableTestCases {
+  test_type_inferred_nonNullify() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+var a = 0;
+''');
+
+    await assertErrorsInCode('''
+import 'a.dart';
+
+var v = a;
+''', [
+      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+    ]);
+
+    assertType(findElement.topVar('v').type, 'int');
+  }
+}
+
+mixin TopLevelVariableTestCases on PubPackageResolutionTest {
   test_session_getterSetter() async {
     await resolveTestCode('''
 var v = 0;
@@ -65,22 +84,5 @@
 }
 
 @reflectiveTest
-class TopLevelVariableWithNullSafetyTest extends TopLevelVariableTest
-    with WithNullSafetyMixin {
-  test_type_inferred_nonNullify() async {
-    newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-var a = 0;
-''');
-
-    await assertErrorsInCode('''
-import 'a.dart';
-
-var v = a;
-''', [
-      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
-    ]);
-
-    assertType(findElement.topVar('v').type, 'int');
-  }
-}
+class TopLevelVariableWithoutNullSafetyTest extends PubPackageResolutionTest
+    with TopLevelVariableTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
index 71d74e1..a1531fb 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
@@ -9,27 +9,13 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ConditionalExpressionTest);
-    defineReflectiveTests(ConditionalExpressionWithNullSafetyTest);
+    defineReflectiveTests(ConditionalExpressionWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class ConditionalExpressionTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
-  test_upward() async {
-    await resolveTestCode('''
-void f(bool a, int b, int c) {
-  var d = a ? b : c;
-  print(d);
-}
-''');
-    assertType(findNode.simple('d)'), 'int');
-  }
-}
-
-@reflectiveTest
-class ConditionalExpressionWithNullSafetyTest extends ConditionalExpressionTest
-    with WithNullSafetyMixin {
+    with ConditionalExpressionTestCases {
   @failingTest
   test_downward() async {
     await resolveTestCode('''
@@ -51,3 +37,20 @@
     assertType(findNode.conditionalExpression('b ?'), 'int?');
   }
 }
+
+mixin ConditionalExpressionTestCases on PubPackageResolutionTest {
+  test_upward() async {
+    await resolveTestCode('''
+void f(bool a, int b, int c) {
+  var d = a ? b : c;
+  print(d);
+}
+''');
+    assertType(findNode.simple('d)'), 'int');
+  }
+}
+
+@reflectiveTest
+class ConditionalExpressionWithoutNullSafetyTest
+    extends PubPackageResolutionTest
+    with ConditionalExpressionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
index bcde92b..11676d2 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
@@ -10,13 +10,129 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(FunctionExpressionTest);
-    defineReflectiveTests(FunctionExpressionWithNullSafetyTest);
+    defineReflectiveTests(FunctionExpressionWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class FunctionExpressionTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with FunctionExpressionTestCases {
+  test_contextFunctionType_nonNullify() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+
+int Function(int a) v;
+''');
+
+    await assertErrorsInCode('''
+import 'a.dart';
+
+T foo<T>() => throw 0;
+
+void f() {
+  v = (a) {
+    return foo();
+  };
+}
+''', [
+      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+    ]);
+    assertType(findElement.parameter('a').type, 'int');
+    _assertReturnType('(a) {', 'int');
+  }
+
+  test_contextFunctionType_nonNullify_returnType_takeActual() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+
+void foo(int Function() x) {}
+''');
+    await assertErrorsInCode('''
+import 'a.dart';
+
+void test(int? a) {
+  foo(() => a);
+}
+''', [
+      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+    ]);
+    _assertReturnType('() => a', 'int?');
+  }
+
+  test_contextFunctionType_nonNullify_returnType_takeContext() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+
+void foo(int Function() x) {}
+''');
+    await assertErrorsInCode('''
+import 'a.dart';
+
+void test(dynamic a) {
+  foo(() => a);
+}
+''', [
+      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+    ]);
+    _assertReturnType('() => a', 'int');
+  }
+
+  test_contextFunctionType_returnType_async_blockBody_objectQ() async {
+    await assertNoErrorsInCode('''
+T foo<T>() => throw 0;
+
+Object? Function() v = () async {
+  return foo();
+};
+''');
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('foo();'),
+      ['FutureOr<Object?>'],
+    );
+    _assertReturnType('() async', 'Future<Object?>');
+  }
+
+  test_contextFunctionType_returnType_async_blockBody_objectQ2() async {
+    await assertNoErrorsInCode('''
+T foo<T>() => throw 0;
+
+Object? Function() v = () async {
+  return;
+};
+''');
+    _assertReturnType('() async', 'Future<Null>');
+  }
+
+  test_contextFunctionType_returnType_async_expressionBody_objectQ() async {
+    await assertNoErrorsInCode('''
+T foo<T>() => throw 0;
+
+Object? Function() v = () async => foo();
+''');
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('foo();'),
+      ['FutureOr<Object?>'],
+    );
+    _assertReturnType('() async => foo', 'Future<Object?>');
+  }
+
+  test_optOut_downward_returnType_expressionBody_Null() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+void foo(Map<String, String> Function() f) {}
+''');
+    await resolveTestCode('''
+// @dart = 2.5
+import 'a.dart';
+
+void main() {
+  foo(() => null);
+}
+''');
+    _assertReturnType('() =>', 'Null*');
+  }
+}
+
+mixin FunctionExpressionTestCases on PubPackageResolutionTest {
   test_contextFunctionType_returnType_async_blockBody_futureOrVoid() async {
     var expectedErrors = expectedErrorsByNullability(
       nullable: [
@@ -460,119 +576,5 @@
 }
 
 @reflectiveTest
-class FunctionExpressionWithNullSafetyTest extends FunctionExpressionTest
-    with WithNullSafetyMixin {
-  test_contextFunctionType_nonNullify() async {
-    newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-
-int Function(int a) v;
-''');
-
-    await assertErrorsInCode('''
-import 'a.dart';
-
-T foo<T>() => throw 0;
-
-void f() {
-  v = (a) {
-    return foo();
-  };
-}
-''', [
-      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
-    ]);
-    assertType(findElement.parameter('a').type, 'int');
-    _assertReturnType('(a) {', 'int');
-  }
-
-  test_contextFunctionType_nonNullify_returnType_takeActual() async {
-    newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-
-void foo(int Function() x) {}
-''');
-    await assertErrorsInCode('''
-import 'a.dart';
-
-void test(int? a) {
-  foo(() => a);
-}
-''', [
-      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
-    ]);
-    _assertReturnType('() => a', 'int?');
-  }
-
-  test_contextFunctionType_nonNullify_returnType_takeContext() async {
-    newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-
-void foo(int Function() x) {}
-''');
-    await assertErrorsInCode('''
-import 'a.dart';
-
-void test(dynamic a) {
-  foo(() => a);
-}
-''', [
-      error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
-    ]);
-    _assertReturnType('() => a', 'int');
-  }
-
-  test_contextFunctionType_returnType_async_blockBody_objectQ() async {
-    await assertNoErrorsInCode('''
-T foo<T>() => throw 0;
-
-Object? Function() v = () async {
-  return foo();
-};
-''');
-    assertTypeArgumentTypes(
-      findNode.methodInvocation('foo();'),
-      ['FutureOr<Object?>'],
-    );
-    _assertReturnType('() async', 'Future<Object?>');
-  }
-
-  test_contextFunctionType_returnType_async_blockBody_objectQ2() async {
-    await assertNoErrorsInCode('''
-T foo<T>() => throw 0;
-
-Object? Function() v = () async {
-  return;
-};
-''');
-    _assertReturnType('() async', 'Future<Null>');
-  }
-
-  test_contextFunctionType_returnType_async_expressionBody_objectQ() async {
-    await assertNoErrorsInCode('''
-T foo<T>() => throw 0;
-
-Object? Function() v = () async => foo();
-''');
-    assertTypeArgumentTypes(
-      findNode.methodInvocation('foo();'),
-      ['FutureOr<Object?>'],
-    );
-    _assertReturnType('() async => foo', 'Future<Object?>');
-  }
-
-  test_optOut_downward_returnType_expressionBody_Null() async {
-    newFile('$testPackageLibPath/a.dart', content: r'''
-void foo(Map<String, String> Function() f) {}
-''');
-    await resolveTestCode('''
-// @dart = 2.5
-import 'a.dart';
-
-void main() {
-  foo(() => null);
-}
-''');
-    _assertReturnType('() =>', 'Null*');
-  }
-}
+class FunctionExpressionWithoutNullSafetyTest extends PubPackageResolutionTest
+    with FunctionExpressionTestCases, WithoutNullSafetyMixin {}
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 80aeb15..39f7df5 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
@@ -10,13 +10,98 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ListLiteralTest);
-    defineReflectiveTests(ListLiteralWithNullSafetyTest);
+    defineReflectiveTests(ListLiteralWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class ListLiteralTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with ListLiteralTestCases {
+  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() {
+  [[0], null];
+}
+''');
+    assertType(findNode.listLiteral('[0'), 'List<int>');
+    assertType(findNode.listLiteral('[[0'), 'List<List<int>?>');
+  }
+
+  test_nested_hasNull_2() async {
+    await assertNoErrorsInCode('''
+main() {
+  [[0], [1, null]];
+}
+''');
+    assertType(findNode.listLiteral('[0'), 'List<int>');
+    assertType(findNode.listLiteral('[1,'), 'List<int?>');
+    assertType(findNode.listLiteral('[[0'), 'List<List<int?>>');
+  }
+
+  test_noContext_noTypeArgs_spread_never() async {
+    await assertNoErrorsInCode('''
+void f(Never a) async {
+  // ignore:unused_local_variable
+  var v = [...a];
+}
+''');
+    assertType(findNode.listLiteral('['), 'List<Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_never() async {
+    await assertErrorsInCode('''
+void f(Never a) async {
+  // ignore:unused_local_variable
+  var v = [...?a];
+}
+''', [
+      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 69, 4),
+    ]);
+    assertType(findNode.listLiteral('['), 'List<Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_typeParameter_implementsNever() async {
+    await assertErrorsInCode('''
+void f<T extends Never>(T a) async {
+  // ignore:unused_local_variable
+  var v = [...?a];
+}
+''', [
+      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 82, 4),
+    ]);
+    assertType(findNode.listLiteral('['), 'List<Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_typeParameter_implementsNever() async {
+    await assertNoErrorsInCode('''
+void f<T extends Never>(T a) async {
+  // ignore:unused_local_variable
+  var v = [...a];
+}
+''');
+    assertType(findNode.listLiteral('['), 'List<Never>');
+  }
+}
+
+mixin ListLiteralTestCases on PubPackageResolutionTest {
   test_context_noTypeArgs_expression_conflict() async {
     await assertErrorsInCode('''
 List<int> a = ['a'];
@@ -415,88 +500,5 @@
 }
 
 @reflectiveTest
-class ListLiteralWithNullSafetyTest extends ListLiteralTest
-    with WithNullSafetyMixin {
-  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() {
-  [[0], null];
-}
-''');
-    assertType(findNode.listLiteral('[0'), 'List<int>');
-    assertType(findNode.listLiteral('[[0'), 'List<List<int>?>');
-  }
-
-  test_nested_hasNull_2() async {
-    await assertNoErrorsInCode('''
-main() {
-  [[0], [1, null]];
-}
-''');
-    assertType(findNode.listLiteral('[0'), 'List<int>');
-    assertType(findNode.listLiteral('[1,'), 'List<int?>');
-    assertType(findNode.listLiteral('[[0'), 'List<List<int?>>');
-  }
-
-  test_noContext_noTypeArgs_spread_never() async {
-    await assertNoErrorsInCode('''
-void f(Never a) async {
-  // ignore:unused_local_variable
-  var v = [...a];
-}
-''');
-    assertType(findNode.listLiteral('['), 'List<Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_never() async {
-    await assertErrorsInCode('''
-void f(Never a) async {
-  // ignore:unused_local_variable
-  var v = [...?a];
-}
-''', [
-      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 69, 4),
-    ]);
-    assertType(findNode.listLiteral('['), 'List<Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_typeParameter_implementsNever() async {
-    await assertErrorsInCode('''
-void f<T extends Never>(T a) async {
-  // ignore:unused_local_variable
-  var v = [...?a];
-}
-''', [
-      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 82, 4),
-    ]);
-    assertType(findNode.listLiteral('['), 'List<Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_typeParameter_implementsNever() async {
-    await assertNoErrorsInCode('''
-void f<T extends Never>(T a) async {
-  // ignore:unused_local_variable
-  var v = [...a];
-}
-''');
-    assertType(findNode.listLiteral('['), 'List<Never>');
-  }
-}
+class ListLiteralWithoutNullSafetyTest extends PubPackageResolutionTest
+    with ListLiteralTestCases, WithoutNullSafetyMixin {}
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 e4af4f6..894f8a9 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
@@ -11,13 +11,121 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapLiteralTest);
-    defineReflectiveTests(MapLiteralWithNullSafetyTest);
+    defineReflectiveTests(MapLiteralWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
-class MapLiteralTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+class MapLiteralTest extends PubPackageResolutionTest with MapLiteralTestCases {
+  test_context_noTypeArgs_noEntries_typeParameterNullable() async {
+    await assertNoErrorsInCode('''
+class C<T extends Object?> {
+  Map<String, T> a = {}; // 1
+  Map<String, T>? b = {}; // 2
+  Map<String, T?> c = {}; // 3
+  Map<String, T?>? d = {}; // 4
+}
+''');
+    assertType(setOrMapLiteral('{}; // 1'), 'Map<String, T>');
+    assertType(setOrMapLiteral('{}; // 2'), 'Map<String, T>');
+    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>?',
+    );
+  }
+
+  test_noContext_noTypeArgs_spread_never() async {
+    await assertErrorsInCode('''
+void f(Never a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...a, if (b) throw 0: throw 0};
+}
+''', [
+      error(HintCode.DEAD_CODE, 87, 21),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_never() async {
+    await assertErrorsInCode('''
+void f(Never a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 77, 4),
+      error(HintCode.DEAD_CODE, 88, 21),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_null() async {
+    await assertErrorsInCode('''
+void f(Null a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+      error(HintCode.DEAD_CODE, 99, 9),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_typeParameter_never() async {
+    await assertErrorsInCode('''
+void f<T extends Never>(T a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 90, 4),
+      error(HintCode.DEAD_CODE, 101, 21),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_nullAware_typeParameter_null() async {
+    await assertErrorsInCode('''
+void f<T extends Null>(T a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+      error(HintCode.DEAD_CODE, 112, 9),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+
+  test_noContext_noTypeArgs_spread_typeParameter_never() async {
+    await assertErrorsInCode('''
+void f<T extends Never>(T a, bool b) async {
+  // ignore:unused_local_variable
+  var v = {...a, if (b) throw 0: throw 0};
+}
+''', [
+      error(HintCode.DEAD_CODE, 100, 21),
+    ]);
+    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+  }
+}
+
+mixin MapLiteralTestCases on PubPackageResolutionTest {
   AstNode setOrMapLiteral(String search) => findNode.setOrMapLiteral(search);
 
   test_context_noTypeArgs_entry_conflictingKey() async {
@@ -439,112 +547,5 @@
 }
 
 @reflectiveTest
-class MapLiteralWithNullSafetyTest extends MapLiteralTest
-    with WithNullSafetyMixin {
-  test_context_noTypeArgs_noEntries_typeParameterNullable() async {
-    await assertNoErrorsInCode('''
-class C<T extends Object?> {
-  Map<String, T> a = {}; // 1
-  Map<String, T>? b = {}; // 2
-  Map<String, T?> c = {}; // 3
-  Map<String, T?>? d = {}; // 4
-}
-''');
-    assertType(setOrMapLiteral('{}; // 1'), 'Map<String, T>');
-    assertType(setOrMapLiteral('{}; // 2'), 'Map<String, T>');
-    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>?',
-    );
-  }
-
-  test_noContext_noTypeArgs_spread_never() async {
-    await assertErrorsInCode('''
-void f(Never a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...a, if (b) throw 0: throw 0};
-}
-''', [
-      error(HintCode.DEAD_CODE, 87, 21),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_never() async {
-    await assertErrorsInCode('''
-void f(Never a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
-      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 77, 4),
-      error(HintCode.DEAD_CODE, 88, 21),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_null() async {
-    await assertErrorsInCode('''
-void f(Null a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
-      error(HintCode.DEAD_CODE, 99, 9),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_typeParameter_never() async {
-    await assertErrorsInCode('''
-void f<T extends Never>(T a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
-      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 90, 4),
-      error(HintCode.DEAD_CODE, 101, 21),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_nullAware_typeParameter_null() async {
-    await assertErrorsInCode('''
-void f<T extends Null>(T a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
-      error(HintCode.DEAD_CODE, 112, 9),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-
-  test_noContext_noTypeArgs_spread_typeParameter_never() async {
-    await assertErrorsInCode('''
-void f<T extends Never>(T a, bool b) async {
-  // ignore:unused_local_variable
-  var v = {...a, if (b) throw 0: throw 0};
-}
-''', [
-      error(HintCode.DEAD_CODE, 100, 21),
-    ]);
-    assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
-  }
-}
+class MapLiteralWithoutNullSafetyTest extends PubPackageResolutionTest
+    with MapLiteralTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart b/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart
index cba3c60..7879c8c 100644
--- a/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart
@@ -10,13 +10,15 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AbstractClassMemberTest);
-    defineReflectiveTests(AbstractClassMemberWithNullSafetyTest);
+    defineReflectiveTests(AbstractClassMemberWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class AbstractClassMemberTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+    with AbstractClassMemberTestCases {}
+
+mixin AbstractClassMemberTestCases on PubPackageResolutionTest {
   test_abstract_field_dynamic() async {
     await assertErrorsInCode(
         '''
@@ -55,5 +57,5 @@
 }
 
 @reflectiveTest
-class AbstractClassMemberWithNullSafetyTest extends AbstractClassMemberTest
-    with WithNullSafetyMixin {}
+class AbstractClassMemberWithoutNullSafetyTest extends PubPackageResolutionTest
+    with AbstractClassMemberTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart
index d45f72d..1ef0c33 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart
@@ -10,119 +10,13 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AssignmentToFinalTest);
-    defineReflectiveTests(AssignmentToFinalWithNullSafetyTest);
+    defineReflectiveTests(AssignmentToFinalWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
 class AssignmentToFinalTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
-  test_prefixedIdentifier_instanceField() async {
-    await assertNoErrorsInCode('''
-class A {
-  var x = 0;
-}
-
-void f(A a) {
-  a.x = 0;
-  a.x += 0;
-  ++a.x;
-  a.x++;
-}
-''');
-  }
-
-  test_prefixedIdentifier_instanceField_final() async {
-    await assertErrorsInCode('''
-class A {
-  final x = 0;
-}
-
-void f(A a) {
-  a.x = 0;
-  a.x += 0;
-  ++a.x;
-  a.x++;
-}
-''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 46, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 57, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 71, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 78, 1),
-    ]);
-  }
-
-  test_simpleIdentifier_inheritedSetter_shadowedBy_topLevelGetter() async {
-    await assertErrorsInCode('''
-class A {
-  void set foo(int _) {}
-}
-
-int get foo => 0;
-
-class B extends A {
-  void bar() {
-    foo = 0;
-  }
-}
-''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 96, 3),
-    ]);
-  }
-
-  test_simpleIdentifier_topLevelGetter() async {
-    await assertErrorsInCode('''
-int get x => 0;
-
-void f() {
-  x = 0;
-  x += 0;
-  ++x;
-  x++;
-}
-''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 30, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 39, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 51, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 56, 1),
-    ]);
-  }
-
-  test_simpleIdentifier_topLevelVariable() async {
-    await assertNoErrorsInCode('''
-var x = 0;
-
-void f() {
-  x = 0;
-  x += 0;
-  ++x;
-  x++;
-}
-''');
-  }
-
-  test_simpleIdentifier_topLevelVariable_final() async {
-    await assertErrorsInCode('''
-final x = 0;
-
-void f() {
-  x = 0;
-  x += 0;
-  ++x;
-  x++;
-}
-''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 27, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 36, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 48, 1),
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 53, 1),
-    ]);
-  }
-}
-
-@reflectiveTest
-class AssignmentToFinalWithNullSafetyTest extends AssignmentToFinalTest
-    with WithNullSafetyMixin {
+    with AssignmentToFinalTestCases {
   test_prefixedIdentifier_instanceField_abstract() async {
     await assertNoErrorsInCode('''
 abstract class A {
@@ -450,3 +344,111 @@
     ]);
   }
 }
+
+mixin AssignmentToFinalTestCases on PubPackageResolutionTest {
+  test_prefixedIdentifier_instanceField() async {
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+}
+
+void f(A a) {
+  a.x = 0;
+  a.x += 0;
+  ++a.x;
+  a.x++;
+}
+''');
+  }
+
+  test_prefixedIdentifier_instanceField_final() async {
+    await assertErrorsInCode('''
+class A {
+  final x = 0;
+}
+
+void f(A a) {
+  a.x = 0;
+  a.x += 0;
+  ++a.x;
+  a.x++;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 46, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 57, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 71, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 78, 1),
+    ]);
+  }
+
+  test_simpleIdentifier_inheritedSetter_shadowedBy_topLevelGetter() async {
+    await assertErrorsInCode('''
+class A {
+  void set foo(int _) {}
+}
+
+int get foo => 0;
+
+class B extends A {
+  void bar() {
+    foo = 0;
+  }
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 96, 3),
+    ]);
+  }
+
+  test_simpleIdentifier_topLevelGetter() async {
+    await assertErrorsInCode('''
+int get x => 0;
+
+void f() {
+  x = 0;
+  x += 0;
+  ++x;
+  x++;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 30, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 39, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 51, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 56, 1),
+    ]);
+  }
+
+  test_simpleIdentifier_topLevelVariable() async {
+    await assertNoErrorsInCode('''
+var x = 0;
+
+void f() {
+  x = 0;
+  x += 0;
+  ++x;
+  x++;
+}
+''');
+  }
+
+  test_simpleIdentifier_topLevelVariable_final() async {
+    await assertErrorsInCode('''
+final x = 0;
+
+void f() {
+  x = 0;
+  x += 0;
+  ++x;
+  x++;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 27, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 36, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 48, 1),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 53, 1),
+    ]);
+  }
+}
+
+@reflectiveTest
+class AssignmentToFinalWithoutNullSafetyTest extends PubPackageResolutionTest
+    with AssignmentToFinalTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
index 1fc2927..92f1995 100644
--- a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
@@ -10,13 +10,139 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(DeadCodeTest);
-    defineReflectiveTests(DeadCodeWithNullSafetyTest);
+    defineReflectiveTests(DeadCodeWithoutNullSafetyTest);
   });
 }
 
 @reflectiveTest
-class DeadCodeTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+class DeadCodeTest extends PubPackageResolutionTest with DeadCodeTestCases {
+  test_assert_dead_message() async {
+    // We don't warn if an assert statement is live but its message is dead,
+    // because this results in nuisance warnings for desirable assertions (e.g.
+    // a `!= null` assertion that is redundant with strong checking but still
+    // useful with weak checking).
+    await assertErrorsInCode('''
+void f(Object waldo) {
+  assert(waldo != null, "Where's Waldo?");
+}
+''', [
+      error(HintCode.UNNECESSARY_NULL_COMPARISON_TRUE, 38, 7),
+    ]);
+  }
+
+  test_flowEnd_tryStatement_body() async {
+    await assertErrorsInCode(r'''
+Never foo() => throw 0;
+
+main() {
+  try {
+    foo();
+    1;
+  } catch (_) {
+    2;
+  }
+  3;
+}
+''', [
+      error(HintCode.DEAD_CODE, 57, 2),
+    ]);
+  }
+
+  test_invokeNever_functionExpressionInvocation_getter_propertyAccess() async {
+    await assertErrorsInCode(r'''
+class A {
+  Never get f => throw 0;
+}
+void g(A a) {
+  a.f(0);
+  print(1);
+}
+''', [
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 54, 3),
+      error(HintCode.DEAD_CODE, 57, 16),
+    ]);
+  }
+
+  test_invokeNever_functionExpressionInvocation_parenthesizedExpression() async {
+    await assertErrorsInCode(r'''
+void g(Never f) {
+  (f)(0);
+  print(1);
+}
+''', [
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 3),
+      error(HintCode.DEAD_CODE, 23, 16),
+    ]);
+  }
+
+  test_invokeNever_functionExpressionInvocation_simpleIdentifier() async {
+    await assertErrorsInCode(r'''
+void g(Never f) {
+  f(0);
+  print(1);
+}
+''', [
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 21, 16),
+    ]);
+  }
+
+  test_returnTypeNever_function() async {
+    await assertErrorsInCode(r'''
+Never foo() => throw 0;
+
+main() {
+  foo();
+  1;
+}
+''', [
+      error(HintCode.DEAD_CODE, 45, 2),
+    ]);
+  }
+
+  test_returnTypeNever_getter() async {
+    await assertErrorsInCode(r'''
+Never get foo => throw 0;
+
+main() {
+  foo;
+  2;
+}
+''', [
+      error(HintCode.DEAD_CODE, 45, 2),
+    ]);
+  }
+
+  @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
+  @override
+  test_statementAfterAlwaysThrowsFunction() async {
+    return super.test_statementAfterAlwaysThrowsFunction();
+  }
+
+  @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
+  @override
+  test_statementAfterAlwaysThrowsMethod() async {
+    return super.test_statementAfterAlwaysThrowsMethod();
+  }
+
+  test_switchStatement_exhaustive() async {
+    await assertErrorsInCode(r'''
+enum Foo { a, b }
+
+int f(Foo foo) {
+  switch (foo) {
+    case Foo.a: return 0;
+    case Foo.b: return 1;
+  }
+  return -1;
+}
+''', [
+      error(HintCode.DEAD_CODE, 111, 10),
+    ]);
+  }
+}
+
+mixin DeadCodeTestCases on PubPackageResolutionTest {
   @override
   void setUp() {
     super.setUp();
@@ -846,129 +972,5 @@
 }
 
 @reflectiveTest
-class DeadCodeWithNullSafetyTest extends DeadCodeTest with WithNullSafetyMixin {
-  test_assert_dead_message() async {
-    // We don't warn if an assert statement is live but its message is dead,
-    // because this results in nuisance warnings for desirable assertions (e.g.
-    // a `!= null` assertion that is redundant with strong checking but still
-    // useful with weak checking).
-    await assertErrorsInCode('''
-void f(Object waldo) {
-  assert(waldo != null, "Where's Waldo?");
-}
-''', [
-      error(HintCode.UNNECESSARY_NULL_COMPARISON_TRUE, 38, 7),
-    ]);
-  }
-
-  test_flowEnd_tryStatement_body() async {
-    await assertErrorsInCode(r'''
-Never foo() => throw 0;
-
-main() {
-  try {
-    foo();
-    1;
-  } catch (_) {
-    2;
-  }
-  3;
-}
-''', [
-      error(HintCode.DEAD_CODE, 57, 2),
-    ]);
-  }
-
-  test_invokeNever_functionExpressionInvocation_getter_propertyAccess() async {
-    await assertErrorsInCode(r'''
-class A {
-  Never get f => throw 0;
-}
-void g(A a) {
-  a.f(0);
-  print(1);
-}
-''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 54, 3),
-      error(HintCode.DEAD_CODE, 57, 16),
-    ]);
-  }
-
-  test_invokeNever_functionExpressionInvocation_parenthesizedExpression() async {
-    await assertErrorsInCode(r'''
-void g(Never f) {
-  (f)(0);
-  print(1);
-}
-''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 3),
-      error(HintCode.DEAD_CODE, 23, 16),
-    ]);
-  }
-
-  test_invokeNever_functionExpressionInvocation_simpleIdentifier() async {
-    await assertErrorsInCode(r'''
-void g(Never f) {
-  f(0);
-  print(1);
-}
-''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
-      error(HintCode.DEAD_CODE, 21, 16),
-    ]);
-  }
-
-  test_returnTypeNever_function() async {
-    await assertErrorsInCode(r'''
-Never foo() => throw 0;
-
-main() {
-  foo();
-  1;
-}
-''', [
-      error(HintCode.DEAD_CODE, 45, 2),
-    ]);
-  }
-
-  test_returnTypeNever_getter() async {
-    await assertErrorsInCode(r'''
-Never get foo => throw 0;
-
-main() {
-  foo;
-  2;
-}
-''', [
-      error(HintCode.DEAD_CODE, 45, 2),
-    ]);
-  }
-
-  @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
-  @override
-  test_statementAfterAlwaysThrowsFunction() async {
-    return super.test_statementAfterAlwaysThrowsFunction();
-  }
-
-  @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
-  @override
-  test_statementAfterAlwaysThrowsMethod() async {
-    return super.test_statementAfterAlwaysThrowsMethod();
-  }
-
-  test_switchStatement_exhaustive() async {
-    await assertErrorsInCode(r'''
-enum Foo { a, b }
-
-int f(Foo foo) {
-  switch (foo) {
-    case Foo.a: return 0;
-    case Foo.b: return 1;
-  }
-  return -1;
-}
-''', [
-      error(HintCode.DEAD_CODE, 111, 10),
-    ]);
-  }
-}
+class DeadCodeWithoutNullSafetyTest extends PubPackageResolutionTest
+    with DeadCodeTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index 12614bb..a6d071f 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -42,7 +42,7 @@
   /// Notice that the component has to include the platform, and that no other
   /// platform will be loaded.
   factory IncrementalKernelGenerator.fromComponent(
-      CompilerOptions options, Uri entryPoint, Component component,
+      CompilerOptions options, Uri entryPoint, Component? component,
       [bool? outlineOnly, IncrementalSerializer? incrementalSerializer]) {
     return new IncrementalCompiler.fromComponent(
         new CompilerContext(
@@ -72,7 +72,7 @@
 
   /// Returns a component whose libraries are the recompiled libraries,
   /// or - in the case of [fullComponent] - a full Component.
-  Future<Component> computeDelta({List<Uri> entryPoints, bool fullComponent});
+  Future<Component> computeDelta({List<Uri>? entryPoints, bool fullComponent});
 
   /// Returns [CoreTypes] used during compilation.
   /// Valid after [computeDelta] is called.
@@ -136,7 +136,7 @@
       List<TypeParameter> typeDefinitions,
       String syntheticProcedureName,
       Uri libraryUri,
-      [String className,
+      [String? className,
       bool isStatic = false]);
 
   /// Sets experimental features.
diff --git a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
index 46566f1..8cf810b 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -58,7 +58,7 @@
 /// Re-uses cached components from [oldState.workerInputCache], and reloads them
 /// as necessary based on [workerInputDigests].
 Future<InitializedCompilerState> initializeIncrementalCompiler(
-    InitializedCompilerState oldState,
+    InitializedCompilerState? oldState,
     Set<String> tags,
     Uri sdkSummary,
     Uri packagesFile,
@@ -99,7 +99,7 @@
 }
 
 Future<InitializedCompilerState> initializeCompiler(
-  InitializedCompilerState oldState,
+  InitializedCompilerState? oldState,
   Uri sdkSummary,
   Uri librariesSpecificationUri,
   Uri packagesFile,
diff --git a/pkg/vm/lib/incremental_compiler.dart b/pkg/vm/lib/incremental_compiler.dart
index 5179a44..a8d3271 100644
--- a/pkg/vm/lib/incremental_compiler.dart
+++ b/pkg/vm/lib/incremental_compiler.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.9
-
 /// Defines wrapper class around incremental compiler to support
 /// the flow, where incremental deltas can be rejected by VM.
 import 'dart:async';
@@ -20,23 +18,23 @@
 /// deltas and combines them together into resultant program until it is
 /// accepted.
 class IncrementalCompiler {
-  IncrementalKernelGenerator _generator;
-  IncrementalSerializer incrementalSerializer;
+  late IncrementalKernelGenerator _generator;
+  IncrementalSerializer? incrementalSerializer;
 
   // Component that reflect the state that was most recently accepted by the
   // client. Is [null], if no compilation results were accepted by the client.
-  Component _lastKnownGood;
-  List<Component> _pendingDeltas;
+  Component? _lastKnownGood;
+  late List<Component> _pendingDeltas;
   CompilerOptions _compilerOptions;
   bool initialized = false;
   bool fullComponent = false;
-  Uri initializeFromDillUri;
+  Uri? initializeFromDillUri;
   Uri _entryPoint;
   final bool forExpressionCompilationOnly;
 
   Uri get entryPoint => _entryPoint;
   IncrementalKernelGenerator get generator => _generator;
-  Component get lastKnownGoodComponent => _lastKnownGood;
+  Component? get lastKnownGoodComponent => _lastKnownGood;
 
   IncrementalCompiler(this._compilerOptions, this._entryPoint,
       {this.initializeFromDillUri, bool incrementalSerialization: true})
@@ -61,12 +59,12 @@
   ///
   /// If [entryPoint] is specified, that points to new entry point for the
   /// compilation. Otherwise, previously set entryPoint is used.
-  Future<Component> compile({Uri entryPoint}) async {
+  Future<Component> compile({Uri? entryPoint}) async {
     final task = new TimelineTask();
     try {
       task.start("IncrementalCompiler.compile");
       _entryPoint = entryPoint ?? _entryPoint;
-      List<Uri> entryPoints;
+      List<Uri>? entryPoints;
       if (entryPoint != null) entryPoints = [entryPoint];
       Component component = await _generator.computeDelta(
           entryPoints: entryPoints, fullComponent: fullComponent);
@@ -80,8 +78,9 @@
   }
 
   _combinePendingDeltas(bool includePlatform) {
-    Procedure mainMethod;
-    NonNullableByDefaultCompiledMode compilationMode;
+    Procedure? mainMethod;
+    NonNullableByDefaultCompiledMode compilationMode =
+        NonNullableByDefaultCompiledMode.Invalid;
     Map<Uri, Library> combined = <Uri, Library>{};
     Map<Uri, Source> uriToSource = new Map<Uri, Source>();
     for (Component delta in _pendingDeltas) {
@@ -104,8 +103,8 @@
       ..setMainMethodAndMode(mainMethod?.reference, true, compilationMode);
   }
 
-  CoreTypes getCoreTypes() => _generator.getCoreTypes();
-  ClassHierarchy getClassHierarchy() => _generator.getClassHierarchy();
+  CoreTypes? getCoreTypes() => _generator.getCoreTypes();
+  ClassHierarchy? getClassHierarchy() => _generator.getClassHierarchy();
 
   /// This lets incremental compiler know that results of last [compile] call
   /// were accepted, don't need to be included into subsequent [compile] calls
@@ -118,13 +117,14 @@
     Map<Uri, Library> combined = <Uri, Library>{};
     Map<Uri, Source> uriToSource = <Uri, Source>{};
 
-    if (_lastKnownGood != null) {
+    Component? lastKnownGood = _lastKnownGood;
+    if (lastKnownGood != null) {
       // TODO(aam): Figure out how to skip no-longer-used libraries from
       // [_lastKnownGood] libraries.
-      for (Library library in _lastKnownGood.libraries) {
+      for (Library library in lastKnownGood.libraries) {
         combined[library.importUri] = library;
       }
-      uriToSource.addAll(_lastKnownGood.uriToSource);
+      uriToSource.addAll(lastKnownGood.uriToSource);
     }
 
     Component candidate = _combinePendingDeltas(true);
@@ -133,13 +133,13 @@
     }
     uriToSource.addAll(candidate.uriToSource);
 
-    _lastKnownGood = new Component(
+    _lastKnownGood = lastKnownGood = new Component(
       libraries: combined.values.toList(),
       uriToSource: uriToSource,
     )..setMainMethodAndMode(
         candidate.mainMethod?.reference, true, candidate.mode);
     for (final repo in candidate.metadata.values) {
-      _lastKnownGood.addMetadataRepository(repo);
+      lastKnownGood.addMetadataRepository(repo);
     }
     _pendingDeltas.clear();
   }
@@ -182,12 +182,12 @@
     fullComponent = true;
   }
 
-  Future<Procedure> compileExpression(
+  Future<Procedure?> compileExpression(
       String expression,
       List<String> definitions,
       List<String> typeDefinitions,
       String libraryUri,
-      String klass,
+      String? klass,
       bool isStatic) {
     Map<String, DartType> completeDefinitions = {};
     for (String name in definitions) {
@@ -202,7 +202,6 @@
     }
 
     Uri library = Uri.parse(libraryUri);
-    if (library == null) return null;
 
     return _generator.compileExpression(expression, completeDefinitions,
         typeParameters, kDebugProcedureName, library, klass, isStatic);
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 43d5a59..51ed004 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -2,10 +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.9
-
 /// Defines the VM-specific translation of Dart source code to kernel binaries.
-library vm.kernel_front_end;
 
 import 'dart:async';
 import 'dart:io' show File, IOSink;
@@ -162,7 +159,7 @@
 /// Run kernel compiler tool with given [options] and [usage]
 /// and return exit code.
 Future<int> runCompiler(ArgResults options, String usage) async {
-  final String platformKernel = options['platform'];
+  final String? platformKernel = options['platform'];
 
   if (options['help']) {
     print(usage);
@@ -176,26 +173,26 @@
 
   final String input = options.rest.single;
   final String outputFileName = options['output'] ?? "$input.dill";
-  final String packages = options['packages'];
+  final String? packages = options['packages'];
   final String targetName = options['target'];
-  final String fileSystemScheme = options['filesystem-scheme'];
-  final String depfile = options['depfile'];
-  final String fromDillFile = options['from-dill'];
-  final List<String> fileSystemRoots = options['filesystem-root'];
+  final String? fileSystemScheme = options['filesystem-scheme'];
+  final String? depfile = options['depfile'];
+  final String? fromDillFile = options['from-dill'];
+  final List<String>? fileSystemRoots = options['filesystem-root'];
   final bool aot = options['aot'];
   final bool tfa = options['tfa'];
   final bool linkPlatform = options['link-platform'];
   final bool embedSources = options['embed-sources'];
   final bool enableAsserts = options['enable-asserts'];
-  final bool nullSafety = options['sound-null-safety'];
+  final bool? nullSafety = options['sound-null-safety'];
   final bool useProtobufTreeShakerV2 = options['protobuf-tree-shaker-v2'];
   final bool splitOutputByPackages = options['split-output-by-packages'];
-  final String manifestFilename = options['manifest'];
-  final String dataDir = options['component-name'] ?? options['data-dir'];
+  final String? manifestFilename = options['manifest'];
+  final String? dataDir = options['component-name'] ?? options['data-dir'];
 
   final bool minimalKernel = options['minimal-kernel'];
   final bool treeShakeWriteOnlyFields = options['tree-shake-write-only-fields'];
-  final List<String> experimentalFlags = options['enable-experiment'];
+  final List<String>? experimentalFlags = options['enable-experiment'];
   final Map<String, String> environmentDefines = {};
 
   if (!parseCommandLineDefines(options['define'], environmentDefines, usage)) {
@@ -217,7 +214,7 @@
   final fileSystem =
       createFrontEndFileSystem(fileSystemScheme, fileSystemRoots);
 
-  final Uri packagesUri = packages != null ? resolveInputUri(packages) : null;
+  final Uri? packagesUri = packages != null ? resolveInputUri(packages) : null;
 
   final platformKernelUri = Uri.base.resolveUri(new Uri.file(platformKernel));
   final List<Uri> additionalDills = <Uri>[];
@@ -232,7 +229,8 @@
 
   final verbosity = Verbosity.parseArgument(options['verbosity']);
   final errorPrinter = new ErrorPrinter(verbosity);
-  final errorDetector = new ErrorDetector(previousErrorHandler: errorPrinter);
+  final errorDetector =
+      new ErrorDetector(previousErrorHandler: errorPrinter.call);
 
   final CompilerOptions compilerOptions = new CompilerOptions()
     ..sdkSummary = platformKernelUri
@@ -280,19 +278,20 @@
 
   errorPrinter.printCompilationMessages();
 
-  if (errorDetector.hasCompilationErrors || (results.component == null)) {
+  final Component? component = results.component;
+  if (errorDetector.hasCompilationErrors || (component == null)) {
     return compileTimeErrorExitCode;
   }
 
   final IOSink sink = new File(outputFileName).openWrite();
   final BinaryPrinter printer = new BinaryPrinter(sink,
       libraryFilter: (lib) => !results.loadedLibraries.contains(lib));
-  printer.writeComponentFile(results.component);
+  printer.writeComponentFile(component);
   await sink.close();
 
   if (depfile != null) {
     await writeDepfile(
-        fileSystem, results.compiledSources, outputFileName, depfile);
+        fileSystem, results.compiledSources!, outputFileName, depfile);
   }
 
   if (splitOutputByPackages) {
@@ -314,14 +313,14 @@
 /// Results of [compileToKernel]: generated kernel [Component] and
 /// collection of compiled sources.
 class KernelCompilationResults {
-  final Component component;
+  final Component? component;
 
   /// Set of libraries loaded from .dill, with or without the SDK depending on
   /// the compilation settings.
   final Set<Library> loadedLibraries;
-  final ClassHierarchy classHierarchy;
-  final CoreTypes coreTypes;
-  final Iterable<Uri> compiledSources;
+  final ClassHierarchy? classHierarchy;
+  final CoreTypes? coreTypes;
+  final Iterable<Uri>? compiledSources;
 
   KernelCompilationResults(this.component, this.loadedLibraries,
       this.classHierarchy, this.coreTypes, this.compiledSources);
@@ -338,29 +337,30 @@
     List<String> deleteToStringPackageUris: const <String>[],
     bool aot: false,
     bool useGlobalTypeFlowAnalysis: false,
-    Map<String, String> environmentDefines,
+    required Map<String, String> environmentDefines,
     bool enableAsserts: true,
     bool useProtobufTreeShakerV2: false,
     bool minimalKernel: false,
     bool treeShakeWriteOnlyFields: false,
-    String fromDillFile: null}) async {
+    String? fromDillFile: null}) async {
   // Replace error handler to detect if there are compilation errors.
   final errorDetector =
       new ErrorDetector(previousErrorHandler: options.onDiagnostic);
-  options.onDiagnostic = errorDetector;
+  options.onDiagnostic = errorDetector.call;
 
+  final target = options.target!;
   options.environmentDefines =
-      options.target.updateEnvironmentDefines(environmentDefines);
+      target.updateEnvironmentDefines(environmentDefines);
 
-  CompilerResult compilerResult;
+  CompilerResult? compilerResult;
   if (fromDillFile != null) {
     compilerResult =
         await loadKernel(options.fileSystem, resolveInputUri(fromDillFile));
   } else {
     compilerResult = await kernelForProgram(source, options);
   }
-  Component component = compilerResult?.component;
-  Iterable<Uri> compiledSources = component?.uriToSource?.keys;
+  final Component? component = compilerResult?.component;
+  Iterable<Uri>? compiledSources = component?.uriToSource.keys;
 
   Set<Library> loadedLibraries = createLoadedLibrariesSet(
       compilerResult?.loadedComponents, compilerResult?.sdkComponent,
@@ -373,13 +373,8 @@
 
   // Run global transformations only if component is correct.
   if ((aot || minimalKernel) && component != null) {
-    await runGlobalTransformations(
-        options.target,
-        component,
-        useGlobalTypeFlowAnalysis,
-        enableAsserts,
-        useProtobufTreeShakerV2,
-        errorDetector,
+    await runGlobalTransformations(target, component, useGlobalTypeFlowAnalysis,
+        enableAsserts, useProtobufTreeShakerV2, errorDetector,
         minimalKernel: minimalKernel,
         treeShakeWriteOnlyFields: treeShakeWriteOnlyFields);
 
@@ -387,7 +382,7 @@
       // compiledSources is component.uriToSource.keys.
       // Make a copy of compiledSources to detach it from
       // component.uriToSource which is cleared below.
-      compiledSources = compiledSources.toList();
+      compiledSources = compiledSources!.toList();
 
       component.metadata.clear();
       component.uriToSource.clear();
@@ -406,7 +401,7 @@
 }
 
 Set<Library> createLoadedLibrariesSet(
-    List<Component> loadedComponents, Component sdkComponent,
+    List<Component>? loadedComponents, Component? sdkComponent,
     {bool includePlatform: false}) {
   final Set<Library> loadedLibraries = {};
   if (loadedComponents != null) {
@@ -481,8 +476,11 @@
 
 /// Runs given [action] with [CompilerContext]. This is needed to
 /// be able to report compile-time errors.
-Future<T> runWithFrontEndCompilerContext<T>(Uri source,
-    CompilerOptions compilerOptions, Component component, T action()) async {
+Future<T> runWithFrontEndCompilerContext<T>(
+    Uri source,
+    CompilerOptions compilerOptions,
+    Component component,
+    Future<T> action()) async {
   final processedOptions =
       new ProcessedOptions(options: compilerOptions, inputs: [source]);
 
@@ -498,7 +496,7 @@
 }
 
 class ErrorDetector {
-  final DiagnosticMessageHandler previousErrorHandler;
+  final DiagnosticMessageHandler? previousErrorHandler;
   bool hasCompilationErrors = false;
 
   ErrorDetector({this.previousErrorHandler});
@@ -514,8 +512,9 @@
 
 class ErrorPrinter {
   final Verbosity verbosity;
-  final DiagnosticMessageHandler previousErrorHandler;
-  final compilationMessages = <Uri, List<DiagnosticMessage>>{};
+  final DiagnosticMessageHandler? previousErrorHandler;
+  final Map<Uri?, List<DiagnosticMessage>> compilationMessages =
+      <Uri?, List<DiagnosticMessage>>{};
 
   ErrorPrinter(this.verbosity, {this.previousErrorHandler});
 
@@ -539,8 +538,8 @@
         }
         return 0;
       });
-    for (final Uri sourceUri in sortedUris) {
-      for (final DiagnosticMessage message in compilationMessages[sourceUri]) {
+    for (final Uri? sourceUri in sortedUris) {
+      for (final DiagnosticMessage message in compilationMessages[sourceUri]!) {
         if (Verbosity.shouldPrint(verbosity, message)) {
           printDiagnosticMessage(message, print);
         }
@@ -576,7 +575,7 @@
 }
 
 /// Create front-end target with given name.
-Target createFrontEndTarget(String targetName,
+Target? createFrontEndTarget(String targetName,
     {bool trackWidgetCreation = false, bool nullSafety = false}) {
   // Make sure VM-specific targets are available.
   installAdditionalTargets();
@@ -591,9 +590,8 @@
 /// If requested, create a virtual mutli-root file system and/or an http aware
 /// file system.
 FileSystem createFrontEndFileSystem(
-    String multiRootFileSystemScheme, List<String> multiRootFileSystemRoots,
-    {bool allowHttp}) {
-  allowHttp ??= false;
+    String? multiRootFileSystemScheme, List<String>? multiRootFileSystemRoots,
+    {bool allowHttp = false}) {
   FileSystem fileSystem = StandardFileSystem.instance;
   if (allowHttp) {
     fileSystem = HttpAwareFileSystem(fileSystem);
@@ -615,7 +613,7 @@
 Future<Uri> asFileUri(FileSystem fileSystem, Uri uri) async {
   FileSystemEntity fse = fileSystem.entityForUri(uri);
   if (fse is MultiRootFileSystemEntity) {
-    fse = await (fse as MultiRootFileSystemEntity).delegate;
+    fse = await fse.delegate;
   }
   return fse.uri;
 }
@@ -645,8 +643,9 @@
 Future writeOutputSplitByPackages(Uri source, CompilerOptions compilerOptions,
     KernelCompilationResults compilationResults, String outputFileName) async {
   final packages = <String>[];
-  await runWithFrontEndCompilerContext(
-      source, compilerOptions, compilationResults.component, () async {
+  final Component component = compilationResults.component!;
+  await runWithFrontEndCompilerContext(source, compilerOptions, component,
+      () async {
     // When loading a kernel file list, flutter_runner and dart_runner expect
     // 'main' to be last.
     await forEachPackage(compilationResults,
@@ -655,12 +654,10 @@
       final String filename = '$outputFileName-$package.dilp';
       final IOSink sink = new File(filename).openWrite();
 
-      Component partComponent = compilationResults.component;
-
       final BinaryPrinter printer = new BinaryPrinter(sink,
           libraryFilter: (lib) =>
               packageFor(lib, compilationResults.loadedLibraries) == package);
-      printer.writeComponentFile(partComponent);
+      printer.writeComponentFile(component);
 
       await sink.close();
     }, mainFirst: false);
@@ -673,7 +670,7 @@
   await packagesList.close();
 }
 
-String packageFor(Library lib, Set<Library> loadedLibraries) {
+String? packageFor(Library lib, Set<Library> loadedLibraries) {
   // Core libraries are not written into any package kernel binaries.
   if (loadedLibraries.contains(lib)) return null;
 
@@ -701,23 +698,25 @@
   }
 }
 
-Future<Null> forEachPackage<T>(KernelCompilationResults results,
-    T action(String package, List<Library> libraries),
-    {bool mainFirst}) async {
-  final Component component = results.component;
+Future<void> forEachPackage(KernelCompilationResults results,
+    Future<void> action(String package, List<Library> libraries),
+    {required bool mainFirst}) async {
+  final Component component = results.component!;
   final Set<Library> loadedLibraries = results.loadedLibraries;
   sortComponent(component);
 
-  final packages = new Map<String, List<Library>>();
+  final Map<String, List<Library>> packages = <String, List<Library>>{};
   packages['main'] = <Library>[]; // Always create 'main'.
   for (Library lib in component.libraries) {
-    packages
-        .putIfAbsent(packageFor(lib, loadedLibraries), () => <Library>[])
-        .add(lib);
+    final String? package = packageFor(lib, loadedLibraries);
+    // Ignore external libraries.
+    if (package == null) {
+      continue;
+    }
+    packages.putIfAbsent(package, () => <Library>[]).add(lib);
   }
-  packages.remove(null); // Ignore external libraries.
 
-  final mainLibraries = packages.remove('main');
+  final mainLibraries = packages.remove('main')!;
   if (mainFirst) {
     await action('main', mainLibraries);
   }
@@ -728,7 +727,7 @@
   component.setMainMethodAndMode(null, true, compilationMode);
   component.problemsAsJson = null;
   for (String package in packages.keys) {
-    await action(package, packages[package]);
+    await action(package, packages[package]!);
   }
   component.setMainMethodAndMode(mainMethod?.reference, true, compilationMode);
   component.problemsAsJson = problemsAsJson;
@@ -750,8 +749,8 @@
   file.write(_escapePath(output));
   file.write(':');
   for (Uri dep in compiledSources) {
-    // Skip empty or corelib dependencies.
-    if (dep == null || dep.scheme == 'org-dartlang-sdk') continue;
+    // Skip corelib dependencies.
+    if (dep.scheme == 'org-dartlang-sdk') continue;
     Uri uri = await asFileUri(fileSystem, dep);
     file.write(' ');
     file.write(_escapePath(uri.toFilePath()));
@@ -761,7 +760,7 @@
 }
 
 Future<void> createFarManifest(
-    String output, String dataDir, String packageManifestFilename) async {
+    String output, String? dataDir, String packageManifestFilename) async {
   List<String> packages = await File('$output-packages').readAsLines();
 
   // Make sure the 'main' package is the last (convention with package loader).
@@ -791,7 +790,7 @@
     'typed_data',
     'vector_math'
   ]) {
-    Digest digest;
+    Digest? digest;
     if (packages.contains(package)) {
       final filenameInBuild = '$output-$package.dilp';
       final bytes = await File(filenameInBuild).readAsBytes();
@@ -813,11 +812,20 @@
 
   CompilerResultLoadedFromKernel(this.component);
 
-  List<int> get summary => null;
+  @override
+  List<int>? get summary => null;
+
+  @override
   List<Component> get loadedComponents => const <Component>[];
+
+  @override
   List<Uri> get deps => const <Uri>[];
-  CoreTypes get coreTypes => null;
-  ClassHierarchy get classHierarchy => null;
+
+  @override
+  CoreTypes? get coreTypes => null;
+
+  @override
+  ClassHierarchy? get classHierarchy => null;
 }
 
 Future<CompilerResult> loadKernel(
diff --git a/pkg/vm/lib/target/dart_runner.dart b/pkg/vm/lib/target/dart_runner.dart
index c1df052..995d484 100644
--- a/pkg/vm/lib/target/dart_runner.dart
+++ b/pkg/vm/lib/target/dart_runner.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.9
-
 import 'package:kernel/target/targets.dart';
 import 'package:vm/target/vm.dart' show VmTarget;
 
diff --git a/pkg/vm/lib/target/flutter.dart b/pkg/vm/lib/target/flutter.dart
index 3ffdc12..1eadf20 100644
--- a/pkg/vm/lib/target/flutter.dart
+++ b/pkg/vm/lib/target/flutter.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.9
-
 import 'package:kernel/ast.dart' show Component, Library;
 import 'package:kernel/core_types.dart' show CoreTypes;
 import 'package:kernel/target/changed_structure_notifier.dart';
@@ -14,7 +12,7 @@
 class FlutterTarget extends VmTarget {
   FlutterTarget(TargetFlags flags) : super(flags);
 
-  WidgetCreatorTracker _widgetTracker;
+  late final WidgetCreatorTracker _widgetTracker = WidgetCreatorTracker();
 
   @override
   String get name => 'flutter';
@@ -57,15 +55,12 @@
       CoreTypes coreTypes,
       List<Library> libraries,
       DiagnosticReporter diagnosticReporter,
-      {void Function(String msg) logger,
-      ChangedStructureNotifier changedStructureNotifier}) {
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
     super.performPreConstantEvaluationTransformations(
         component, coreTypes, libraries, diagnosticReporter,
         logger: logger, changedStructureNotifier: changedStructureNotifier);
     if (flags.trackWidgetCreation) {
-      if (_widgetTracker == null) {
-        _widgetTracker = WidgetCreatorTracker();
-      }
       _widgetTracker.transform(component, libraries, changedStructureNotifier);
     }
   }
diff --git a/pkg/vm/lib/target/flutter_runner.dart b/pkg/vm/lib/target/flutter_runner.dart
index a9c41ac..addd766 100644
--- a/pkg/vm/lib/target/flutter_runner.dart
+++ b/pkg/vm/lib/target/flutter_runner.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.9
-
 import 'package:kernel/target/targets.dart';
 import 'package:vm/target/vm.dart' show VmTarget;
 
diff --git a/pkg/vm/lib/target/install.dart b/pkg/vm/lib/target/install.dart
index d691d28..b22d469 100644
--- a/pkg/vm/lib/target/install.dart
+++ b/pkg/vm/lib/target/install.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.9
-
 import 'package:kernel/target/targets.dart' show targets, TargetFlags;
 import 'package:vm/target/dart_runner.dart' show DartRunnerTarget;
 import 'package:vm/target/flutter.dart' show FlutterTarget;
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index 20cd144..ec6e1b1 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.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.9
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/clone.dart';
 import 'package:kernel/class_hierarchy.dart';
@@ -34,14 +32,14 @@
 class VmTarget extends Target {
   final TargetFlags flags;
 
-  Class _growableList;
-  Class _immutableList;
-  Class _internalLinkedHashMap;
-  Class _immutableMap;
-  Class _oneByteString;
-  Class _twoByteString;
-  Class _smi;
-  Class _double; // _Double, not double.
+  Class? _growableList;
+  Class? _immutableList;
+  Class? _internalLinkedHashMap;
+  Class? _immutableMap;
+  Class? _oneByteString;
+  Class? _twoByteString;
+  Class? _smi;
+  Class? _double; // _Double, not double.
 
   VmTarget(this.flags);
 
@@ -116,7 +114,7 @@
     final Field little =
         coreTypes.index.getField('dart:typed_data', 'Endian', 'little');
     host.isConst = true;
-    host.initializer = new CloneVisitorNotMembers().clone(little.initializer)
+    host.initializer = new CloneVisitorNotMembers().clone(little.initializer!)
       ..parent = host;
   }
 
@@ -126,8 +124,8 @@
       CoreTypes coreTypes,
       List<Library> libraries,
       DiagnosticReporter diagnosticReporter,
-      {void Function(String msg) logger,
-      ChangedStructureNotifier changedStructureNotifier}) {
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
     super.performPreConstantEvaluationTransformations(
         component, coreTypes, libraries, diagnosticReporter,
         logger: logger, changedStructureNotifier: changedStructureNotifier);
@@ -152,11 +150,11 @@
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       List<Library> libraries,
-      Map<String, String> environmentDefines,
+      Map<String, String>? environmentDefines,
       DiagnosticReporter diagnosticReporter,
-      ReferenceFromIndex referenceFromIndex,
-      {void Function(String msg) logger,
-      ChangedStructureNotifier changedStructureNotifier}) {
+      ReferenceFromIndex? referenceFromIndex,
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
     transformMixins.transformLibraries(
         this, coreTypes, hierarchy, libraries, referenceFromIndex);
     logger?.call("Transformed mixin applications");
@@ -184,7 +182,7 @@
     }
 
     // TODO(kmillikin): Make this run on a per-method basis.
-    bool productMode = environmentDefines["dart.vm.product"] == "true";
+    bool productMode = environmentDefines!["dart.vm.product"] == "true";
     transformAsync.transformLibraries(
         new TypeEnvironment(coreTypes, hierarchy), libraries,
         productMode: productMode);
@@ -204,9 +202,9 @@
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       Procedure procedure,
-      Map<String, String> environmentDefines,
-      {void Function(String msg) logger}) {
-    bool productMode = environmentDefines["dart.vm.product"] == "true";
+      Map<String, String>? environmentDefines,
+      {void Function(String msg)? logger}) {
+    bool productMode = environmentDefines!["dart.vm.product"] == "true";
     transformAsync.transformProcedure(
         new TypeEnvironment(coreTypes, hierarchy), procedure,
         productMode: productMode);
@@ -451,7 +449,7 @@
   }
 
   @override
-  Class concreteIntLiteralClass(CoreTypes coreTypes, int value) {
+  Class? concreteIntLiteralClass(CoreTypes coreTypes, int value) {
     const int bitsPerInt32 = 32;
     const int smiBits32 = bitsPerInt32 - 2;
     const int smiMin32 = -(1 << smiBits32);
@@ -490,7 +488,6 @@
   Map<String, String> updateEnvironmentDefines(Map<String, String> map) {
     // TODO(alexmarkov): Call this from the front-end in order to have
     //  the same defines when compiling platform.
-    assert(map != null);
     map['dart.isVM'] = 'true';
     // TODO(dartbug.com/36460): Derive dart.library.* definitions from platform.
     for (String library in extraRequiredLibraries) {
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 83c9a50..75eff47 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -2,10 +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.9
-
 /// Global type flow analysis.
-library kernel.transformations.analysis;
 
 import 'dart:collection';
 import 'dart:core' hide Type;
@@ -51,24 +48,28 @@
 
 /// Maintains set of dependent invocations.
 class _DependencyTracker {
-  Set<_Invocation> _dependentInvocations;
+  Set<_Invocation>? _dependentInvocations;
 
   void addDependentInvocation(_Invocation invocation) {
     if (!identical(invocation, this)) {
-      _dependentInvocations ??= new Set<_Invocation>();
-      _dependentInvocations.add(invocation);
+      var dependentInvocations = _dependentInvocations;
+      if (dependentInvocations == null) {
+        _dependentInvocations = dependentInvocations = Set<_Invocation>();
+      }
+      dependentInvocations.add(invocation);
     }
   }
 
   void invalidateDependentInvocations(_WorkList workList) {
-    if (_dependentInvocations != null) {
+    final dependentInvocations = _dependentInvocations;
+    if (dependentInvocations != null) {
       if (kPrintTrace) {
         tracePrint('   - CHANGED: $this');
-        for (var di in _dependentInvocations) {
+        for (var di in dependentInvocations) {
           tracePrint('     - invalidating $di');
         }
       }
-      _dependentInvocations.forEach(workList.invalidateInvocation);
+      dependentInvocations.forEach(workList.invalidateInvocation);
     }
   }
 }
@@ -83,12 +84,12 @@
   final Selector selector;
   final Args<Type> args;
 
-  Type result;
+  Type? result;
 
   /// Result of the invocation calculated before invocation was invalidated.
   /// Used to check if the re-analysis of the invocation yields the same
   /// result or not (to avoid invalidation of callers if result hasn't changed).
-  Type invalidatedResult;
+  Type? invalidatedResult;
 
   /// Number of times result of this invocation was invalidated.
   int invalidationCounter = 0;
@@ -108,7 +109,7 @@
   /// Returns result of this invocation if its available without
   /// further analysis, or `null` if it's not available.
   /// Used for recursive calls while this invocation is being processed.
-  Type get resultForRecursiveInvocation => result;
+  Type? get resultForRecursiveInvocation => result;
 
   /// Use [type] as a current computed result of this invocation.
   /// If this invocation was invalidated, and the invalidated result is
@@ -116,7 +117,6 @@
   /// Result type may be saturated if this invocation was invalidated
   /// too many times.
   void setResult(TypeFlowAnalysis typeFlowAnalysis, Type type) {
-    assert(type != null);
     result = type;
 
     if (invalidatedResult != null) {
@@ -132,8 +132,8 @@
         // the analysis, result is saturated after invocation is invalidated
         // at least [_Invocation.invalidationLimit] times.
         if (invalidationCounter > _Invocation.invalidationLimit) {
-          result =
-              result.union(invalidatedResult, typeFlowAnalysis.hierarchyCache);
+          result = result!
+              .union(invalidatedResult!, typeFlowAnalysis.hierarchyCache);
         }
       }
       invalidatedResult = null;
@@ -192,11 +192,12 @@
     // they could fail bounds checks.
     //
     // TODO(sjindel): Use [TypeCheck] to avoid bounds checks.
-    if (selector.member.function != null) {
-      typeChecksNeeded = selector.member.function.typeParameters
-          .any((t) => t.isGenericCovariantImpl);
+    final function = selector.member.function;
+    if (function != null) {
+      typeChecksNeeded =
+          function.typeParameters.any((t) => t.isGenericCovariantImpl);
     } else {
-      Field field = selector.member;
+      Field field = selector.member as Field;
       if (selector.callKind == CallKind.PropertySet) {
         // TODO(dartbug.com/40615): Use TFA results to improve this criterion.
         typeChecksNeeded = field.isGenericCovariantImpl;
@@ -277,13 +278,10 @@
         fieldValue.isInitialized = true;
         return const EmptyType();
     }
-
-    // Make dartanalyzer happy.
-    throw 'Unexpected call kind ${selector.callKind}';
   }
 
   Type _processFunction(TypeFlowAnalysis typeFlowAnalysis) {
-    final Member member = selector.member;
+    final Member member = selector.member!;
     if (selector.memberAgreesToCallKind(member)) {
       if (_argumentsValid()) {
         final summary = typeFlowAnalysis.getSummary(member);
@@ -326,13 +324,12 @@
   }
 
   bool _argumentsValid() {
-    final function = selector.member.function;
-    assert(function != null);
-
+    final member = selector.member!;
+    final function = member.function!;
     final int positionalArguments = args.positionalCount;
 
-    final int firstParamIndex = numTypeParams(selector.member) +
-        (hasReceiverArg(selector.member) ? 1 : 0);
+    final int firstParamIndex =
+        numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
     final int requiredParameters =
         firstParamIndex + function.requiredParameterCount;
     if (positionalArguments < requiredParameters) {
@@ -361,9 +358,9 @@
 
 class _DispatchableInvocation extends _Invocation {
   bool _isPolymorphic = false;
-  Set<Call> _callSites; // Populated only if not polymorphic.
-  Member _monomorphicTarget;
-  _DirectInvocation _monomorphicDirectInvocation;
+  Set<Call>? _callSites; // Populated only if not polymorphic.
+  Member? _monomorphicTarget;
+  _DirectInvocation? _monomorphicDirectInvocation;
 
   @override
   set typeChecksNeeded(bool value) {
@@ -434,7 +431,8 @@
 
           if (!_isPolymorphic) {
             assert(target == _monomorphicTarget);
-            _monomorphicDirectInvocation = directInvocation;
+            _monomorphicDirectInvocation =
+                directInvocation as _DirectInvocation;
           }
 
           type = typeFlowAnalysis.workList.processInvocation(directInvocation);
@@ -486,13 +484,13 @@
 
     final bool isNullableReceiver = receiver is NullableType;
     if (isNullableReceiver) {
-      receiver = (receiver as NullableType).baseType;
+      receiver = receiver.baseType;
       assert(receiver is! NullableType);
     }
 
     if (selector is InterfaceSelector) {
       final staticReceiverType = new ConeType(typeFlowAnalysis.hierarchyCache
-          .getTFClass(selector.member.enclosingClass));
+          .getTFClass(selector.member!.enclosingClass!));
       receiver = receiver.intersection(
           staticReceiverType, typeFlowAnalysis.hierarchyCache);
       assert(receiver is! NullableType);
@@ -507,7 +505,7 @@
       // invocation to the receiver class. A new allocated class discovered
       // in the receiver cone will invalidate this invocation.
       receiver = typeFlowAnalysis.hierarchyCache
-          .specializeTypeCone((receiver as ConeType).cls, allowWideCone: false);
+          .specializeTypeCone(receiver.cls, allowWideCone: false);
     }
 
     assert(targets.isEmpty);
@@ -535,7 +533,7 @@
     Class nullClass =
         typeFlowAnalysis.environment.coreTypes.deprecatedNullClass;
 
-    Member target = typeFlowAnalysis.hierarchyCache.hierarchy
+    Member? target = typeFlowAnalysis.hierarchyCache.hierarchy
         .getDispatchTarget(nullClass, selector.name, setter: selector.isSetter);
 
     if (target != null) {
@@ -552,7 +550,7 @@
       TypeFlowAnalysis typeFlowAnalysis) {
     final TFClass cls = receiver.cls;
 
-    Member target =
+    Member? target =
         (cls as _TFClassImpl).getDispatchTarget(selector, typeFlowAnalysis);
 
     if (target != null) {
@@ -647,8 +645,9 @@
     if (_isPolymorphic) {
       callSite.setPolymorphic();
     } else {
-      if (_monomorphicTarget != null) {
-        callSite.addTarget(_monomorphicTarget);
+      final monomorphicTarget = _monomorphicTarget;
+      if (monomorphicTarget != null) {
+        callSite.addTarget(monomorphicTarget);
       }
     }
 
@@ -660,18 +659,20 @@
   /// Notify call sites monitoring this invocation about changes in
   /// polymorphism of this invocation.
   void _notifyCallSites() {
-    if (_callSites != null) {
-      _callSites.forEach(_notifyCallSite);
+    final callSites = _callSites;
+    if (callSites != null) {
+      callSites.forEach(_notifyCallSite);
     }
   }
 
   @override
-  Type get resultForRecursiveInvocation {
+  Type? get resultForRecursiveInvocation {
     if (result != null) {
       return result;
     }
-    if (_monomorphicDirectInvocation != null) {
-      return _monomorphicDirectInvocation.resultForRecursiveInvocation;
+    final monomorphicDirectInvocation = _monomorphicDirectInvocation;
+    if (monomorphicDirectInvocation != null) {
+      return monomorphicDirectInvocation.resultForRecursiveInvocation;
     }
     return null;
   }
@@ -683,30 +684,30 @@
 /// 1) Add 1..N concrete types ordered by classId OR add 1 arbitrary type.
 /// 2) Make type nullable.
 class _ReceiverTypeBuilder {
-  Type _type;
-  List<ConcreteType> _list;
+  Type? _type;
+  List<ConcreteType>? _list;
   bool _nullable = false;
 
   /// Appends a ConcreteType. May be called multiple times.
   /// Should not be used in conjunction with [addType].
   void addConcreteType(ConcreteType type) {
-    if (_list == null) {
-      if (_type == null) {
+    final list = _list;
+    if (list == null) {
+      final Type? t = _type;
+      if (t == null) {
         _type = type;
         return;
       }
+      final ct = t as ConcreteType;
 
-      assert(_type is ConcreteType);
-      assert(_type != type);
-
-      _list = <ConcreteType>[];
-      _list.add(_type);
-
+      assert(ct != type);
+      assert(ct.cls.id < type.cls.id);
+      _list = <ConcreteType>[ct, type];
       _type = null;
+    } else {
+      assert(list.last.cls.id < type.cls.id);
+      list.add(type);
     }
-
-    assert(_list.last.cls.id < type.cls.id);
-    _list.add(type);
   }
 
   /// Appends an arbitrary Type. May be called only once.
@@ -723,12 +724,13 @@
 
   /// Returns union of added types.
   Type toType() {
-    Type t = _type;
+    Type? t = _type;
     if (t == null) {
-      if (_list == null) {
+      final list = _list;
+      if (list == null) {
         t = const EmptyType();
       } else {
-        t = new SetType(_list);
+        t = SetType(list);
       }
     } else {
       assert(_list == null);
@@ -753,7 +755,7 @@
   static const int maxInvocationsPerSelector = 5000;
 
   int count = 0;
-  _Invocation approximation;
+  _Invocation? approximation;
 }
 
 /// Maintains ([Selector], [Args]) => [_Invocation] cache.
@@ -771,7 +773,7 @@
     _Invocation invocation = (selector is DirectSelector)
         ? new _DirectInvocation(selector, args)
         : new _DispatchableInvocation(selector, args);
-    _Invocation result = _invocations.lookup(invocation);
+    _Invocation? result = _invocations.lookup(invocation);
     if (result != null) {
       return result;
     }
@@ -784,14 +786,16 @@
       final sa = (_approximations[selector] ??= new _SelectorApproximation());
 
       if (sa.count >= _SelectorApproximation.maxInvocationsPerSelector) {
-        if (sa.approximation == null) {
+        _Invocation? approximation = sa.approximation;
+        if (approximation == null) {
           final rawArgs =
               _typeFlowAnalysis.summaryCollector.rawArguments(selector);
-          sa.approximation = new _DispatchableInvocation(selector, rawArgs);
+          sa.approximation =
+              approximation = _DispatchableInvocation(selector, rawArgs);
           Statistics.approximateInvocationsCreated++;
         }
         Statistics.approximateInvocationsUsed++;
-        return sa.approximation;
+        return approximation;
       }
 
       ++sa.count;
@@ -809,8 +813,8 @@
 class _FieldValue extends _DependencyTracker {
   final Field field;
   final Type staticType;
-  final Summary typeGuardSummary;
-  Type value;
+  final Summary? typeGuardSummary;
+  Type value = const EmptyType();
 
   /// Flag indicating if field initializer was executed.
   bool isInitialized = false;
@@ -825,8 +829,6 @@
       : staticType = typesBuilder.fromStaticType(field.type, true) {
     if (field.initializer == null && _isDefaultValueOfFieldObservable()) {
       value = new Type.nullable(const EmptyType());
-    } else {
-      value = const EmptyType();
     }
   }
 
@@ -839,8 +841,7 @@
       return true;
     }
 
-    final enclosingClass = field.enclosingClass;
-    assert(enclosingClass != null);
+    final enclosingClass = field.enclosingClass!;
 
     // Default value is not observable if every generative constructor
     // is redirecting or initializes the field.
@@ -856,10 +857,11 @@
     });
   }
 
-  void ensureInitialized(TypeFlowAnalysis typeFlowAnalysis, Type receiverType) {
+  void ensureInitialized(
+      TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) {
     if (field.initializer != null) {
       assert(field.isStatic == (receiverType == null));
-      final args = !field.isStatic ? <Type>[receiverType] : const <Type>[];
+      final args = !field.isStatic ? <Type>[receiverType!] : const <Type>[];
       final initializerInvocation = typeFlowAnalysis._invocationsCache
           .getInvocation(
               new DirectSelector(field, callKind: CallKind.FieldInitializer),
@@ -870,17 +872,18 @@
     }
   }
 
-  Type getValue(TypeFlowAnalysis typeFlowAnalysis, Type receiverType) {
+  Type getValue(TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) {
     ensureInitialized(typeFlowAnalysis, receiverType);
     addDependentInvocation(typeFlowAnalysis.currentInvocation);
+    final typeGuardSummary = this.typeGuardSummary;
     return (typeGuardSummary != null)
-        ? typeGuardSummary.apply(Args([receiverType, value]),
+        ? typeGuardSummary.apply(Args([receiverType!, value]),
             typeFlowAnalysis.hierarchyCache, typeFlowAnalysis)
         : value;
   }
 
   void setValue(
-      Type newValue, TypeFlowAnalysis typeFlowAnalysis, Type receiverType) {
+      Type newValue, TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) {
     // Make sure type cones are specialized before putting them into field
     // value, in order to ensure that dependency is established between
     // cone's base type and corresponding field setter.
@@ -907,10 +910,11 @@
     //
     final hierarchy = typeFlowAnalysis.hierarchyCache;
     // TODO(sjindel/tfa): Perform narrowing inside 'TypeCheck'.
+    final typeGuardSummary = this.typeGuardSummary;
     final narrowedNewValue = typeGuardSummary != null
         ? typeGuardSummary
-            .apply(
-                new Args([receiverType, newValue]), hierarchy, typeFlowAnalysis)
+            .apply(new Args([receiverType!, newValue]), hierarchy,
+                typeFlowAnalysis)
             .intersection(staticType, hierarchy)
         : newValue.specialize(hierarchy).intersection(staticType, hierarchy);
     Type newType =
@@ -952,28 +956,26 @@
   /// Flag indicating if this class has a noSuchMethod() method not inherited
   /// from Object.
   /// Lazy initialized by ClassHierarchyCache.hasNonTrivialNoSuchMethod().
-  bool hasNonTrivialNoSuchMethod;
+  bool? hasNonTrivialNoSuchMethod;
 
   _TFClassImpl(int id, Class classNode, this.supertypes)
       : super(id, classNode) {
     supertypes.add(this);
   }
 
-  ConcreteType _concreteType;
-  ConcreteType get concreteType =>
-      _concreteType ??= new ConcreteType(this, null);
+  late final ConcreteType concreteType = ConcreteType(this, null);
 
-  Type _specializedConeType;
+  Type? _specializedConeType;
   Type get specializedConeType =>
       _specializedConeType ??= _calculateConeTypeSpecialization();
 
   bool get hasWideCone =>
       _allocatedSubtypes.length > maxAllocatedTypesInSetSpecializations;
 
-  WideConeType _wideConeType;
+  late final WideConeType _wideConeType = WideConeType(this);
   WideConeType get wideConeType {
     assert(hasWideCone);
-    return _wideConeType ??= new WideConeType(this);
+    return _wideConeType;
   }
 
   Type _calculateConeTypeSpecialization() {
@@ -999,14 +1001,16 @@
     _specializedConeType = null; // Reset cached specialization.
   }
 
-  Member getDispatchTarget(
+  Member? getDispatchTarget(
       Selector selector, TypeFlowAnalysis typeFlowAnalysis) {
-    Member target = _dispatchTargets[selector];
+    Member? target = _dispatchTargets[selector];
     if (target == null) {
       target = typeFlowAnalysis.hierarchyCache.hierarchy.getDispatchTarget(
           classNode, selector.name,
           setter: selector.isSetter);
-      _dispatchTargets[selector] = target;
+      if (target != null) {
+        _dispatchTargets[selector] = target;
+      }
     }
     return target;
   }
@@ -1021,10 +1025,11 @@
   final cachedFlattenedTypeArgs = <Class, List<DartType>>{};
   final cachedFlattenedTypeArgsForNonGeneric = <Class, List<Type>>{};
 
-  RuntimeTypeTranslatorImpl closedTypeTranslator;
+  late final RuntimeTypeTranslatorImpl closedTypeTranslator;
 
-  GenericInterfacesInfoImpl(this.hierarchy) {
-    closedTypeTranslator = RuntimeTypeTranslatorImpl.forClosedTypes(this);
+  GenericInterfacesInfoImpl(CoreTypes coreTypes, this.hierarchy) {
+    closedTypeTranslator =
+        RuntimeTypeTranslatorImpl.forClosedTypes(coreTypes, this);
   }
 
   List<DartType> flattenedTypeArgumentsFor(Class klass, {bool useCache: true}) {
@@ -1049,7 +1054,7 @@
     if (klass == iface) return 0;
 
     final pair = new SubtypePair(klass, iface);
-    int offset = supertypeOffsetsCache[pair];
+    int? offset = supertypeOffsetsCache[pair];
 
     if (offset != null) return offset;
 
@@ -1064,16 +1069,16 @@
   }
 
   List<Type> flattenedTypeArgumentsForNonGeneric(Class klass) {
-    List<Type> result = cachedFlattenedTypeArgsForNonGeneric[klass];
+    List<Type>? result = cachedFlattenedTypeArgsForNonGeneric[klass];
     if (result != null) return result;
 
     List<DartType> flattenedTypeArgs =
         flattenedTypeArgumentsFor(klass, useCache: false);
-    result = new List<Type>.filled(flattenedTypeArgs.length, null);
-    for (int i = 0; i < flattenedTypeArgs.length; ++i) {
-      final translated = closedTypeTranslator.translate(flattenedTypeArgs[i]);
+    result = <Type>[];
+    for (DartType arg in flattenedTypeArgs) {
+      final translated = closedTypeTranslator.translate(arg);
       assert(translated is RuntimeType || translated is UnknownType);
-      result[i] = translated;
+      result.add(translated as Type);
     }
     cachedFlattenedTypeArgsForNonGeneric[klass] = result;
     return result;
@@ -1108,10 +1113,8 @@
   _ClassHierarchyCache(this._typeFlowAnalysis, this.hierarchy,
       this.genericInterfacesInfo, this.environment, bool nullSafety)
       : objectNoSuchMethod = hierarchy.getDispatchTarget(
-            environment.coreTypes.objectClass, noSuchMethodName),
-        super(environment.coreTypes, nullSafety) {
-    assert(objectNoSuchMethod != null);
-  }
+            environment.coreTypes.objectClass, noSuchMethodName)!,
+        super(environment.coreTypes, nullSafety);
 
   @override
   _TFClassImpl getTFClass(Class c) {
@@ -1198,10 +1201,13 @@
 
   bool hasNonTrivialNoSuchMethod(TFClass c) {
     final classImpl = c as _TFClassImpl;
-    classImpl.hasNonTrivialNoSuchMethod ??=
-        (hierarchy.getDispatchTarget(c.classNode, noSuchMethodName) !=
-            objectNoSuchMethod);
-    return classImpl.hasNonTrivialNoSuchMethod;
+    bool? value = classImpl.hasNonTrivialNoSuchMethod;
+    if (value == null) {
+      classImpl.hasNonTrivialNoSuchMethod = value =
+          (hierarchy.getDispatchTarget(c.classNode, noSuchMethodName) !=
+              objectNoSuchMethod);
+    }
+    return value;
   }
 
   _DynamicTargetSet getDynamicTargetSet(DynamicSelector selector) {
@@ -1294,10 +1300,11 @@
   }
 
   bool invalidateProtobufFields() {
-    if (_typeFlowAnalysis.protobufHandler == null) {
+    final protobufHandler = _typeFlowAnalysis.protobufHandler;
+    if (protobufHandler == null) {
       return false;
     }
-    final fields = _typeFlowAnalysis.protobufHandler.getInvalidatedFields();
+    final fields = protobufHandler.getInvalidatedFields();
     if (fields.isEmpty) {
       return false;
     }
@@ -1305,7 +1312,7 @@
     for (var field in fields) {
       assert(field.isStatic);
       // Reset summary in order to rebuild it.
-      _typeFlowAnalysis._summaries[field] = null;
+      _typeFlowAnalysis._summaries.remove(field);
       // Invalidate (and enqueue) field initializer invocation.
       final initializerInvocation = _typeFlowAnalysis._invocationsCache
           .getInvocation(
@@ -1328,10 +1335,11 @@
   }
 
   Type processInvocation(_Invocation invocation) {
-    if (invocation.result != null) {
+    Type? result = invocation.result;
+    if (result != null) {
       // Already processed.
       Statistics.usedCachedResultsOfInvocations++;
-      return invocation.result;
+      return result;
     }
 
     // Test if tracing is enabled to avoid expensive message formatting.
@@ -1374,18 +1382,18 @@
               -1);
         }
         processing.remove(invocation);
-        return invocation.invalidatedResult;
+        return invocation.invalidatedResult!;
       }
 
       callStack.add(invocation);
       pending.remove(invocation);
 
-      Type result = invocation.process(_typeFlowAnalysis);
+      result = invocation.process(_typeFlowAnalysis);
 
       invocation.setResult(_typeFlowAnalysis, result);
 
       // setResult may saturate result to ensure convergence.
-      result = invocation.result;
+      result = invocation.result!;
 
       // Invocation is still pending - it was invalidated while being processed.
       // Move result to invalidatedResult.
@@ -1434,12 +1442,12 @@
   final TypeEnvironment environment;
   final LibraryIndex libraryIndex;
   final PragmaAnnotationParser annotationMatcher;
-  final ProtobufHandler protobufHandler;
-  NativeCodeOracle nativeCodeOracle;
-  _ClassHierarchyCache hierarchyCache;
-  SummaryCollector summaryCollector;
-  _InvocationsCache _invocationsCache;
-  _WorkList workList;
+  final ProtobufHandler? protobufHandler;
+  late NativeCodeOracle nativeCodeOracle;
+  late _ClassHierarchyCache hierarchyCache;
+  late SummaryCollector summaryCollector;
+  late _InvocationsCache _invocationsCache;
+  late _WorkList workList;
   GenericInterfacesInfo _genericInterfacesInfo;
 
   final Map<Member, Summary> _summaries = <Member, Summary>{};
@@ -1459,7 +1467,7 @@
       this.environment,
       this.libraryIndex,
       this.protobufHandler,
-      PragmaAnnotationParser matcher)
+      PragmaAnnotationParser? matcher)
       : annotationMatcher =
             matcher ?? new ConstantPragmaAnnotationParser(coreTypes) {
     nativeCodeOracle = new NativeCodeOracle(libraryIndex, annotationMatcher);
@@ -1488,9 +1496,9 @@
   }
 
   _FieldValue getFieldValue(Field field) {
-    _FieldValue fieldValue = _fieldValues[field];
+    _FieldValue? fieldValue = _fieldValues[field];
     if (fieldValue == null) {
-      Summary typeGuardSummary = null;
+      Summary? typeGuardSummary = null;
       if (field.isGenericCovariantImpl) {
         typeGuardSummary = summaryCollector.createSummary(field,
             fieldSummaryType: FieldSummaryType.kFieldGuard);
@@ -1548,24 +1556,24 @@
 
   bool isClassAllocated(Class c) => hierarchyCache.allocatedClasses.contains(c);
 
-  Call callSite(TreeNode node) => summaryCollector.callSites[node];
+  Call? callSite(TreeNode node) => summaryCollector.callSites[node];
 
-  TypeCheck explicitCast(AsExpression cast) =>
+  TypeCheck? explicitCast(AsExpression cast) =>
       summaryCollector.explicitCasts[cast];
 
-  TypeCheck isTest(IsExpression node) => summaryCollector.isTests[node];
+  TypeCheck? isTest(IsExpression node) => summaryCollector.isTests[node];
 
-  NarrowNotNull nullTest(TreeNode node) => summaryCollector.nullTests[node];
+  NarrowNotNull? nullTest(TreeNode node) => summaryCollector.nullTests[node];
 
-  Type fieldType(Field field) => _fieldValues[field]?.value;
+  Type? fieldType(Field field) => _fieldValues[field]?.value;
 
-  Args<Type> argumentTypes(Member member) => _summaries[member]?.argumentTypes;
+  Args<Type>? argumentTypes(Member member) => _summaries[member]?.argumentTypes;
 
-  Type argumentType(Member member, VariableDeclaration memberParam) {
+  Type? argumentType(Member member, VariableDeclaration memberParam) {
     return _summaries[member]?.argumentType(member, memberParam);
   }
 
-  List<VariableDeclaration> uncheckedParameters(Member member) =>
+  List<VariableDeclaration>? uncheckedParameters(Member member) =>
       _summaries[member]?.uncheckedParameters;
 
   bool isTearOffTaken(Member member) => _tearOffTaken.contains(member);
@@ -1599,7 +1607,7 @@
   /// ---- Implementation of [CallHandler] interface. ----
 
   @override
-  Type applyCall(Call callSite, Selector selector, Args<Type> args,
+  Type applyCall(Call? callSite, Selector selector, Args<Type> args,
       {bool isResultUsed: true, bool processImmediately: true}) {
     _Invocation invocation = _invocationsCache.getInvocation(selector, args);
 
@@ -1629,7 +1637,7 @@
         workList.enqueueInvocation(invocation);
       }
 
-      return null;
+      return const EmptyType();
     }
   }
 
@@ -1680,7 +1688,7 @@
   }
 
   @override
-  void recordTearOff(Procedure target) {
+  void recordTearOff(Member target) {
     _tearOffTaken.add(target);
   }
 }
diff --git a/pkg/vm/lib/transformations/type_flow/calls.dart b/pkg/vm/lib/transformations/type_flow/calls.dart
index 060500a..dd16279d 100644
--- a/pkg/vm/lib/transformations/type_flow/calls.dart
+++ b/pkg/vm/lib/transformations/type_flow/calls.dart
@@ -2,10 +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.9
-
 /// Declares classes which describe a call: selectors and arguments.
-library vm.transformations.type_flow.calls;
 
 import 'dart:core' hide Type;
 
@@ -30,10 +27,10 @@
   Selector(this.callKind);
 
   /// Interface or concrete target, may be null.
-  Member get member;
+  Member? get member;
 
   /// Selector name.
-  Name get name => member.name;
+  Name get name => member!.name;
 
   bool get isSetter => (callKind == CallKind.PropertySet);
 
@@ -46,6 +43,7 @@
 
   /// Static approximation of Dart return type.
   DartType get staticReturnType {
+    final member = this.member;
     if (member == null) {
       return const DynamicType();
     }
@@ -61,7 +59,6 @@
       case CallKind.SetFieldInConstructor:
         return const NeverType.nonNullable();
     }
-    return null;
   }
 
   bool memberAgreesToCallKind(Member member) {
@@ -79,7 +76,6 @@
       case CallKind.SetFieldInConstructor:
         return member is Field;
     }
-    return false;
   }
 
   String get _callKindPrefix {
@@ -94,7 +90,6 @@
       case CallKind.FieldInitializer:
         return 'init ';
     }
-    return '';
   }
 }
 
@@ -169,7 +164,7 @@
   DynamicSelector(CallKind callKind, this.name) : super(callKind);
 
   @override
-  Member get member => null;
+  Member? get member => null;
 
   @override
   int get hashCode => (super.hashCode ^ name.hashCode + 37) & kHashMask;
@@ -189,7 +184,8 @@
   final List<T> values;
   final List<String> names;
 
-  int _hashCode;
+  @override
+  late final int hashCode = _computeHashCode();
 
   Args(this.values, {this.names = const <String>[]}) {
     assert(isSorted(names));
@@ -206,9 +202,6 @@
 
   T get receiver => values[0];
 
-  @override
-  int get hashCode => _hashCode ??= _computeHashCode();
-
   int _computeHashCode() {
     int hash = 1231;
     for (var v in values) {
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index 7a5baf9..0611379 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -2,10 +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.9
-
 /// Handling of native code and entry points.
-library vm.transformations.type_flow.native_code;
 
 import 'dart:core' hide Type;
 
@@ -35,24 +32,21 @@
   /// Record the fact that given member is called from this.
   void recordMemberCalledViaThis(Member target);
 
-  /// Record the fact that given method is torn off.
-  void recordTearOff(Procedure target) {}
+  /// Record the fact that given member is torn off.
+  void recordTearOff(Member target) {}
 }
 
 class PragmaEntryPointsVisitor extends RecursiveVisitor {
   final EntryPointsListener entryPoints;
   final NativeCodeOracle nativeCodeOracle;
   final PragmaAnnotationParser matcher;
-  Class currentClass = null;
 
   PragmaEntryPointsVisitor(
-      this.entryPoints, this.nativeCodeOracle, this.matcher) {
-    assert(matcher != null);
-  }
+      this.entryPoints, this.nativeCodeOracle, this.matcher);
 
-  PragmaEntryPointType _annotationsDefineRoot(List<Expression> annotations) {
+  PragmaEntryPointType? _annotationsDefineRoot(List<Expression> annotations) {
     for (var annotation in annotations) {
-      ParsedPragma pragma = matcher.parsePragma(annotation);
+      ParsedPragma? pragma = matcher.parsePragma(annotation);
       if (pragma == null) continue;
       if (pragma is ParsedEntryPointPragma) return pragma.type;
     }
@@ -72,7 +66,6 @@
       }
       nativeCodeOracle.addClassReferencedFromNativeCode(klass);
     }
-    currentClass = klass;
     klass.visitChildren(this);
   }
 
@@ -88,8 +81,7 @@
       }
       Member target = proc;
       while (target is Procedure && target.isRedirectingFactory) {
-        target = getRedirectingFactoryBody(target).target;
-        assert(target != null);
+        target = getRedirectingFactoryBody(target)!.target!;
         assert(
             (target is Procedure && target.isFactory) || target is Constructor);
       }
@@ -152,7 +144,7 @@
       }
       entryPoints
           .addRawCall(new DirectSelector(ctor, callKind: CallKind.Method));
-      entryPoints.addAllocatedClass(currentClass);
+      entryPoints.addAllocatedClass(ctor.enclosingClass);
       nativeCodeOracle.setMemberReferencedFromNativeCode(ctor);
     }
   }
@@ -201,9 +193,7 @@
   final Set<Class> _classesReferencedFromNativeCode = new Set<Class>();
   final PragmaAnnotationParser _matcher;
 
-  NativeCodeOracle(this._libraryIndex, this._matcher) {
-    assert(_matcher != null);
-  }
+  NativeCodeOracle(this._libraryIndex, this._matcher);
 
   void addClassReferencedFromNativeCode(Class klass) {
     _classesReferencedFromNativeCode.add(klass);
@@ -219,9 +209,9 @@
   bool isMemberReferencedFromNativeCode(Member member) =>
       _membersReferencedFromNativeCode.contains(member);
 
-  PragmaRecognizedType recognizedType(Member member) {
+  PragmaRecognizedType? recognizedType(Member member) {
     for (var annotation in member.annotations) {
-      ParsedPragma pragma = _matcher.parsePragma(annotation);
+      ParsedPragma? pragma = _matcher.parsePragma(annotation);
       if (pragma is ParsedRecognized) {
         return pragma.type;
       }
@@ -229,15 +219,16 @@
     return null;
   }
 
-  bool isRecognized(Member member, [List<PragmaRecognizedType> expectedTypes]) {
-    PragmaRecognizedType type = recognizedType(member);
+  bool isRecognized(Member member,
+      [List<PragmaRecognizedType>? expectedTypes]) {
+    PragmaRecognizedType? type = recognizedType(member);
     return type != null &&
         (expectedTypes == null || expectedTypes.contains(type));
   }
 
   bool hasDisableUnboxedParameters(Member member) {
     for (var annotation in member.annotations) {
-      ParsedPragma pragma = _matcher.parsePragma(annotation);
+      ParsedPragma? pragma = _matcher.parsePragma(annotation);
       if (pragma is ParsedDisableUnboxedParameters) {
         if (member.enclosingLibrary.importUri.scheme != "dart") {
           throw "ERROR: Cannot use @pragma(vm:disable-unboxed-parameters) outside core libraries.";
@@ -255,11 +246,11 @@
       EntryPointsListener entryPointsListener,
       TypesBuilder typesBuilder,
       RuntimeTypeTranslator translator) {
-    TypeExpr returnType = null;
-    bool nullable = null;
+    TypeExpr? returnType = null;
+    bool? nullable = null;
 
     for (var annotation in member.annotations) {
-      ParsedPragma pragma = _matcher.parsePragma(annotation);
+      ParsedPragma? pragma = _matcher.parsePragma(annotation);
       if (pragma == null) continue;
       if (pragma is ParsedResultTypeByTypePragma ||
           pragma is ParsedResultTypeByPathPragma ||
@@ -278,8 +269,8 @@
           returnType = entryPointsListener.addAllocatedClass(type.classNode);
           if (pragma.resultTypeUsesPassedTypeArguments) {
             returnType = translator.instantiateConcreteType(
-                returnType,
-                member.function.typeParameters
+                returnType as ConcreteType,
+                member.function!.typeParameters
                     .map((t) => TypeParameterType(
                         t, TypeParameterType.computeNullabilityFromBound(t)))
                     .toList());
@@ -314,7 +305,7 @@
       return returnType;
     } else {
       return typesBuilder.fromStaticType(
-          member.function.returnType, nullable ?? true);
+          member.function!.returnType, nullable ?? true);
     }
   }
 }
diff --git a/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart b/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
index a4b0bbc..c0175a4 100644
--- a/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
+++ b/pkg/vm/lib/transformations/type_flow/protobuf_handler.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.9
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
 import 'package:kernel/core_types.dart' show CoreTypes;
@@ -47,14 +45,14 @@
   final Procedure _builderInfoAddMethod;
 
   // Type of BuilderInfo.add<Null>().
-  FunctionType _typeOfBuilderInfoAddOfNull;
+  late FunctionType _typeOfBuilderInfoAddOfNull;
 
   final _messageClasses = <Class, _MessageClass>{};
   final _invalidatedClasses = <_MessageClass>{};
 
   /// Creates [ProtobufHandler] instance for [component].
   /// Returns null if protobuf library is not used.
-  static ProtobufHandler forComponent(
+  static ProtobufHandler? forComponent(
       Component component, CoreTypes coreTypes) {
     final libraryIndex = LibraryIndex(component, [protobufLibraryUri]);
     if (!libraryIndex.containsLibrary(protobufLibraryUri)) {
@@ -68,12 +66,12 @@
             libraryIndex.getClass(protobufLibraryUri, 'GeneratedMessage'),
         _tagNumberClass =
             libraryIndex.getClass(protobufLibraryUri, 'TagNumber'),
-        _tagNumberField = libraryIndex.getMember(
-            protobufLibraryUri, 'TagNumber', 'tagNumber'),
+        _tagNumberField =
+            libraryIndex.getField(protobufLibraryUri, 'TagNumber', 'tagNumber'),
         _builderInfoClass =
             libraryIndex.getClass(protobufLibraryUri, 'BuilderInfo'),
-        _builderInfoAddMethod =
-            libraryIndex.getMember(protobufLibraryUri, 'BuilderInfo', 'add') {
+        _builderInfoAddMethod = libraryIndex.getProcedure(
+            protobufLibraryUri, 'BuilderInfo', 'add') {
     final functionType = _builderInfoAddMethod.getterType as FunctionType;
     _typeOfBuilderInfoAddOfNull = Substitution.fromPairs(
             functionType.typeParameters, const <DartType>[NullType()])
@@ -130,8 +128,9 @@
   List<Field> getInvalidatedFields() {
     final fields = <Field>[];
     for (var cls in _invalidatedClasses) {
-      if (cls._metadataField != null) {
-        fields.add(cls._metadataField);
+      final field = cls._metadataField;
+      if (field != null) {
+        fields.add(field);
       }
     }
     _invalidatedClasses.clear();
@@ -143,14 +142,15 @@
     ++Statistics.protobufMetadataInitializersUpdated;
     Statistics.protobufMetadataFieldsPruned -= cls.numberOfFieldsPruned;
 
-    final field = cls._metadataField;
-    if (cls._originalInitializer == null) {
-      cls._originalInitializer = field.initializer;
+    final field = cls._metadataField!;
+    Expression? originalInitializer = cls._originalInitializer;
+    if (originalInitializer == null) {
+      cls._originalInitializer = originalInitializer = field.initializer!;
     }
     final cloner = CloneVisitorNotMembers();
-    field.initializer = cloner.clone(cls._originalInitializer)..parent = field;
+    field.initializer = cloner.clone(originalInitializer)..parent = field;
     final transformer = _MetadataTransformer(this, cls);
-    field.initializer.accept(transformer);
+    field.initializer!.accept(transformer);
     _invalidatedClasses.remove(cls);
 
     cls.numberOfFieldsPruned = transformer.numberOfFieldsPruned;
@@ -168,8 +168,8 @@
 }
 
 class _MessageClass {
-  Field _metadataField;
-  Expression _originalInitializer;
+  Field? _metadataField;
+  Expression? _originalInitializer;
   final _usedTags = <int>{};
   int numberOfFieldsPruned = 0;
 }
diff --git a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
index a61e222..5ae2e16 100644
--- a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
+++ b/pkg/vm/lib/transformations/type_flow/signature_shaking.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.9
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/external_name.dart';
 import 'package:kernel/type_environment.dart';
@@ -57,7 +55,7 @@
 
   SignatureShaker(this.typeFlowAnalysis, this.tableSelectorAssigner);
 
-  _ProcedureInfo _infoForMember(Member member) {
+  _ProcedureInfo? _infoForMember(Member member) {
     if (!(member is Procedure &&
             (member.kind == ProcedureKind.Method ||
                 member.kind == ProcedureKind.Factory) ||
@@ -89,7 +87,7 @@
     }
     while (worklist.isNotEmpty) {
       _ParameterInfo param = worklist.removeLast();
-      for (_ParameterInfo dependencyParam in param.useDependencies) {
+      for (_ParameterInfo dependencyParam in param.useDependencies!) {
         if (!dependencyParam.isRead) {
           dependencyParam.isRead = true;
           if (dependencyParam.useDependencies != null) {
@@ -141,7 +139,7 @@
     return positional.any((param) =>
             param.canBeEliminated ||
             (param.isAlwaysPassed &&
-                param.index >= function.requiredParameterCount)) ||
+                param.index! >= function.requiredParameterCount)) ||
         named.values
             .any((param) => param.canBeEliminated || param.isAlwaysPassed);
   }
@@ -149,7 +147,7 @@
 
 class _ParameterInfo {
   final _ProcedureInfo info;
-  final int index;
+  final int? index;
 
   int passCount = 0;
   bool isRead = false;
@@ -160,7 +158,7 @@
   /// List of parameter variables which were passed as arguments via this
   /// parameter. When this parameter is considered used, all [useDependencies]
   /// parameters should be transitively marked as read.
-  List<_ParameterInfo> useDependencies = null;
+  List<_ParameterInfo>? useDependencies = null;
 
   _ParameterInfo(this.info, this.index);
 
@@ -177,7 +175,7 @@
 
   void observeParameter(
       Member member, VariableDeclaration param, SignatureShaker shaker) {
-    final Type type = shaker.typeFlowAnalysis.argumentType(member, param);
+    final Type? type = shaker.typeFlowAnalysis.argumentType(member, param);
 
     // A parameter is considered constant if the TFA has inferred it to have a
     // constant value in every implementation. The constant value inferred does
@@ -214,19 +212,19 @@
   _Collect(this.shaker);
 
   void enterFunction(Member member) {
-    final _ProcedureInfo info = shaker._infoForMember(member);
+    final _ProcedureInfo? info = shaker._infoForMember(member);
     if (info == null) return;
 
     localParameters.clear();
     useDependencies.clear();
-    final FunctionNode fun = member.function;
+    final FunctionNode fun = member.function!;
     for (int i = 0; i < fun.positionalParameters.length; i++) {
       final VariableDeclaration param = fun.positionalParameters[i];
       localParameters[param] = info.ensurePositional(i)
         ..observeParameter(member, param, shaker);
     }
     for (VariableDeclaration param in fun.namedParameters) {
-      localParameters[param] = info.ensureNamed(param.name)
+      localParameters[param] = info.ensureNamed(param.name!)
         ..observeParameter(member, param, shaker);
     }
 
@@ -270,19 +268,22 @@
 
   void addUseDependency(Expression arg, _ParameterInfo param) {
     if (arg is VariableGet) {
-      _ParameterInfo localParam = localParameters[arg.variable];
+      _ParameterInfo? localParam = localParameters[arg.variable];
       if (localParam != null && !localParam.isUsed) {
         // This is a parameter passed as an argument. Mark it as a use
         // dependency.
-        param.useDependencies ??= [];
-        param.useDependencies.add(localParam);
+        var paramUseDependencies = param.useDependencies;
+        if (paramUseDependencies == null) {
+          param.useDependencies = paramUseDependencies = [];
+        }
+        paramUseDependencies.add(localParam);
         useDependencies.add(arg);
       }
     }
   }
 
   void collectCall(Member member, Arguments args) {
-    final _ProcedureInfo info = shaker._infoForMember(member);
+    final _ProcedureInfo? info = shaker._infoForMember(member);
     if (info == null) return;
 
     for (int i = 0; i < args.positional.length; i++) {
@@ -306,7 +307,10 @@
 
   @override
   void visitSuperMethodInvocation(SuperMethodInvocation node) {
-    collectCall(node.interfaceTarget, node.arguments);
+    final interfaceTarget = node.interfaceTarget;
+    if (interfaceTarget != null) {
+      collectCall(interfaceTarget, node.arguments);
+    }
     super.visitSuperMethodInvocation(node);
   }
 
@@ -338,7 +342,7 @@
 class _Transform extends RecursiveVisitor {
   final SignatureShaker shaker;
 
-  StaticTypeContext typeContext;
+  late StaticTypeContext typeContext;
   final Map<VariableDeclaration, Constant> eliminatedParams = {};
   final Set<VariableDeclaration> unusedParams = {};
   final List<LocalInitializer> addedInitializers = [];
@@ -349,16 +353,15 @@
       Member member, _ParameterInfo param, VariableDeclaration variable) {
     Constant value;
     if (param.isConstant) {
-      Type type = shaker.typeFlowAnalysis.argumentType(member, variable);
+      Type type = shaker.typeFlowAnalysis.argumentType(member, variable)!;
       if (type is ConcreteType) {
-        assert(type.constant != null);
-        value = type.constant;
+        value = type.constant!;
       } else {
         assert(type is NullableType && type.baseType is EmptyType);
         value = NullConstant();
       }
     } else {
-      value = (variable.initializer as ConstantExpression)?.constant ??
+      value = (variable.initializer as ConstantExpression?)?.constant ??
           NullConstant();
     }
     eliminatedParams[variable] = value;
@@ -370,10 +373,10 @@
     eliminatedParams.clear();
     unusedParams.clear();
 
-    final _ProcedureInfo info = shaker._infoForMember(member);
+    final _ProcedureInfo? info = shaker._infoForMember(member);
     if (info == null || !info.eligible || info.callCount == 0) return;
 
-    final FunctionNode function = member.function;
+    final FunctionNode function = member.function!;
 
     if (!info.transformNeeded(function)) return;
 
@@ -404,9 +407,9 @@
     //    as required positional parameters, alphabetically by name.
     final List<VariableDeclaration> sortedNamed = function.namedParameters
         .toList()
-      ..sort((var1, var2) => var1.name.compareTo(var2.name));
+      ..sort((var1, var2) => var1.name!.compareTo(var2.name!));
     for (VariableDeclaration variable in sortedNamed) {
-      final _ParameterInfo param = info.named[variable.name];
+      final _ParameterInfo param = info.named[variable.name!]!;
       if (param.isAlwaysPassed) {
         if (param.isUsed) {
           if (param.canBeEliminated) {
@@ -451,7 +454,7 @@
     // 4. All named parameters that are not always passed and can't be
     //    eliminated, as named parameters in alphabetical order.
     for (VariableDeclaration variable in sortedNamed) {
-      final _ParameterInfo param = info.named[variable.name];
+      final _ParameterInfo param = info.named[variable.name!]!;
       if (!param.isAlwaysPassed) {
         if (param.isUsed) {
           if (param.canBeEliminated) {
@@ -475,7 +478,7 @@
 
   @override
   void visitVariableGet(VariableGet node) {
-    Constant constantValue = eliminatedParams[node.variable];
+    Constant? constantValue = eliminatedParams[node.variable];
     if (constantValue != null) {
       node.replaceWith(ConstantExpression(constantValue));
     }
@@ -511,7 +514,7 @@
       void Function(Expression, _ParameterInfo) fun) {
     for (int i = args.named.length - 1; i >= 0; i--) {
       final NamedExpression namedExp = args.named[i];
-      fun(namedExp.value, info.named[namedExp.name]);
+      fun(namedExp.value, info.named[namedExp.name]!);
     }
     for (int i = args.positional.length - 1; i >= 0; i--) {
       fun(args.positional[i], info.positional[i]);
@@ -519,8 +522,8 @@
   }
 
   void transformCall(
-      Member target, TreeNode call, Expression receiver, Arguments args) {
-    final _ProcedureInfo info = shaker._infoForMember(target);
+      Member target, TreeNode call, Expression? receiver, Arguments args) {
+    final _ProcedureInfo? info = shaker._infoForMember(target);
     if (info == null || !info.eligible) return;
 
     bool transformNeeded = false;
@@ -544,7 +547,7 @@
     Map<Expression, VariableDeclaration> hoisted = {};
     if (hoistingNeeded) {
       if (call is Initializer) {
-        final Constructor constructor = call.parent;
+        final Constructor constructor = call.parent as Constructor;
         forEachArgumentRev(args, info, (Expression arg, _ParameterInfo param) {
           if (mayHaveOrSeeSideEffects(arg) && !isUnusedParam(arg)) {
             VariableDeclaration argVar = VariableDeclaration(null,
@@ -557,8 +560,8 @@
           }
         });
       } else {
-        final TreeNode parent = call.parent;
-        Expression current = call;
+        final TreeNode parent = call.parent!;
+        Expression current = call as Expression;
         forEachArgumentRev(args, info, (Expression arg, _ParameterInfo param) {
           if (mayHaveOrSeeSideEffects(arg) && !isUnusedParam(arg)) {
             VariableDeclaration argVar = VariableDeclaration(null,
@@ -606,7 +609,7 @@
     final List<NamedExpression> sortedNamed = args.named.toList()
       ..sort((var1, var2) => var1.name.compareTo(var2.name));
     for (NamedExpression arg in sortedNamed) {
-      final _ParameterInfo param = info.named[arg.name];
+      final _ParameterInfo param = info.named[arg.name]!;
       if (param.isAlwaysPassed && !param.canBeEliminated) {
         positional.add(getMaybeHoistedArg(arg.value));
       }
@@ -625,7 +628,7 @@
     //    eliminated, as named parameters in alphabetical order.
     //    (Arguments are kept in original order.)
     for (NamedExpression arg in args.named) {
-      final _ParameterInfo param = info.named[arg.name];
+      final _ParameterInfo param = info.named[arg.name]!;
       if (!param.isAlwaysPassed && !param.canBeEliminated) {
         arg.value = getMaybeHoistedArg(arg.value)..parent = arg;
         named.add(arg);
@@ -644,7 +647,10 @@
   @override
   void visitSuperMethodInvocation(SuperMethodInvocation node) {
     super.visitSuperMethodInvocation(node);
-    transformCall(node.interfaceTarget, node, null, node.arguments);
+    final interfaceTarget = node.interfaceTarget;
+    if (interfaceTarget != null) {
+      transformCall(interfaceTarget, node, null, node.arguments);
+    }
   }
 
   @override
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index dcae2df..fb18cec 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -2,10 +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.9
-
 /// Type flow summary of a member, function or initializer.
-library vm.transformations.type_flow.summary;
 
 import 'dart:core' hide Type;
 
@@ -18,7 +15,7 @@
 
 abstract class CallHandler {
   Type applyCall(Call callSite, Selector selector, Args<Type> args,
-      {bool isResultUsed});
+      {required bool isResultUsed});
   void typeCheckTriggered();
   void addAllocatedClass(Class c);
 }
@@ -27,14 +24,10 @@
 abstract class Statement extends TypeExpr {
   /// Index of this statement in the [Summary].
   int index = -1;
-  Summary summary;
+  late Summary summary;
 
   @override
-  Type getComputedType(List<Type> types) {
-    final type = types[index];
-    assert(type != null);
-    return type;
-  }
+  Type getComputedType(List<Type?> types) => types[index]!;
 
   String get label => "t$index";
 
@@ -48,7 +41,7 @@
   void accept(StatementVisitor visitor);
 
   /// Execute this statement and compute its resulting type.
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler);
 }
 
@@ -74,9 +67,9 @@
   // [staticType] is null if no narrowing should be performed. This happens for
   // type parameters and for parameters whose type is narrowed by a [TypeCheck]
   // statement.
-  final Type staticTypeForNarrowing;
+  final Type? staticTypeForNarrowing;
 
-  Type defaultValue;
+  Type? defaultValue;
   Type _argumentType = const EmptyType();
 
   Parameter(this.name, this.staticTypeForNarrowing);
@@ -97,7 +90,7 @@
   }
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
           CallHandler callHandler) =>
       throw 'Unable to apply _Parameter';
 
@@ -110,7 +103,7 @@
   }
 
   Type _observeNotPassed(TypeHierarchy typeHierarchy) {
-    final Type argType = defaultValue.specialize(typeHierarchy);
+    final Type argType = defaultValue!.specialize(typeHierarchy);
     _observeArgumentType(argType, typeHierarchy);
     return argType;
   }
@@ -130,7 +123,7 @@
   String dump() => "$label = _Narrow ($arg to $type)";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
           CallHandler callHandler) =>
       arg.getComputedType(computedTypes).intersection(type, typeHierarchy);
 }
@@ -147,11 +140,11 @@
 
   // Shared NarrowNotNull instances which are used when the outcome is
   // known at summary creation time.
-  static final NarrowNotNull alwaysNotNull = NarrowNotNull(null)
+  static final NarrowNotNull alwaysNotNull = NarrowNotNull(const EmptyType())
     .._flags = canBeNotNullFlag;
-  static final NarrowNotNull alwaysNull = NarrowNotNull(null)
+  static final NarrowNotNull alwaysNull = NarrowNotNull(const EmptyType())
     .._flags = canBeNullFlag;
-  static final NarrowNotNull unknown = NarrowNotNull(null)
+  static final NarrowNotNull unknown = NarrowNotNull(const EmptyType())
     .._flags = canBeNullFlag | canBeNotNullFlag;
 
   bool get isAlwaysNull => (_flags & canBeNotNullFlag) == 0;
@@ -173,14 +166,14 @@
   }
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
           CallHandler callHandler) =>
       handleArgument(arg.getComputedType(computedTypes));
 }
 
 /// Joins values from multiple sources. Its type is a union of [values].
 class Join extends Statement {
-  final String _name;
+  final String? _name;
   final DartType staticType;
   final List<TypeExpr> values = <TypeExpr>[]; // TODO(alexmarkov): Set
 
@@ -197,15 +190,14 @@
       " (${values.join(", ")})";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
-    Type type = null;
-    assert(values.isNotEmpty);
+    Type? type = null;
     for (var value in values) {
       final valueType = value.getComputedType(computedTypes);
       type = type != null ? type.union(valueType, typeHierarchy) : valueType;
     }
-    return type;
+    return type!;
   }
 }
 
@@ -222,7 +214,7 @@
   String dump() => "$label = _Use ($arg)";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
           CallHandler callHandler) =>
       throw 'Use statements should be removed during summary normalization';
 }
@@ -231,7 +223,7 @@
 class Call extends Statement {
   final Selector selector;
   final Args<TypeExpr> args;
-  final Type staticResultType;
+  final Type? staticResultType;
 
   Call(this.selector, this.args, this.staticResultType,
       bool isInstanceCreation) {
@@ -252,9 +244,10 @@
   String dump() => "$label${isResultUsed ? '*' : ''} = _Call $selector $args";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
-    final List<Type> argTypes = new List<Type>.filled(args.values.length, null);
+    final List<Type> argTypes =
+        new List<Type>.filled(args.values.length, const EmptyType());
     for (int i = 0; i < args.values.length; i++) {
       final Type type = args.values[i].getComputedType(computedTypes);
       if (type == const EmptyType()) {
@@ -271,14 +264,15 @@
       callHandler
           .addAllocatedClass((argTypes[0] as ConcreteType).cls.classNode);
     }
-    final Stopwatch timer = kPrintTimings ? (new Stopwatch()..start()) : null;
+    final Stopwatch? timer = kPrintTimings ? (new Stopwatch()..start()) : null;
     Type result = callHandler.applyCall(
         this, selector, new Args<Type>(argTypes, names: args.names),
         isResultUsed: isResultUsed);
-    summary.calleeTime += kPrintTimings ? timer.elapsedMicroseconds : 0;
+    summary.calleeTime += kPrintTimings ? timer!.elapsedMicroseconds : 0;
     if (isInstanceCreation) {
       result = argTypes[0];
     } else if (isResultUsed) {
+      final staticResultType = this.staticResultType;
       if (staticResultType != null) {
         result = result.intersection(staticResultType, typeHierarchy);
       }
@@ -302,9 +296,9 @@
   static const int kReceiverMayBeInt = (1 << 6);
   static const int kInstanceCreation = (1 << 7);
 
-  Member _monomorphicTarget;
+  Member? _monomorphicTarget;
 
-  Member get monomorphicTarget => _monomorphicTarget;
+  Member? get monomorphicTarget => _monomorphicTarget;
 
   bool get isMonomorphic => (_flags & kMonomorphic) != 0;
 
@@ -396,18 +390,19 @@
       "/$paramIndex]${nullability.suffix})";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
     Type argType = arg.getComputedType(computedTypes);
-    Type extractedType;
+    Type? extractedType;
 
     void extractType(ConcreteType c) {
-      if (c.typeArgs == null) {
+      final typeArgs = c.typeArgs;
+      if (typeArgs == null) {
         extractedType = const UnknownType();
       } else {
         final interfaceOffset = typeHierarchy.genericInterfaceOffsetFor(
             c.cls.classNode, referenceClass);
-        final typeArg = c.typeArgs[interfaceOffset + paramIndex];
+        final typeArg = typeArgs[interfaceOffset + paramIndex];
         Type extracted = typeArg;
         if (typeArg is RuntimeType) {
           final argNullability = typeArg.nullability;
@@ -472,16 +467,15 @@
   }
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
     bool hasRuntimeType = false;
-    final types = new List<Type>.filled(flattenedTypeArgs.length, null);
-    for (int i = 0; i < types.length; ++i) {
+    final types = List<Type>.generate(flattenedTypeArgs.length, (int i) {
       final computed = flattenedTypeArgs[i].getComputedType(computedTypes);
       assert(computed is RuntimeType || computed is UnknownType);
       if (computed is RuntimeType) hasRuntimeType = true;
-      types[i] = computed;
-    }
+      return computed;
+    });
     return new ConcreteType(cls, hasRuntimeType ? types : null);
   }
 }
@@ -505,14 +499,13 @@
       "${nullability.suffix})";
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
-    final types = new List<RuntimeType>.filled(flattenedTypeArgs.length, null);
-    for (int i = 0; i < types.length; ++i) {
-      final computed = flattenedTypeArgs[i].getComputedType(computedTypes);
-      assert(computed is RuntimeType || computed is UnknownType);
+    final types = <RuntimeType>[];
+    for (TypeExpr arg in flattenedTypeArgs) {
+      final computed = arg.getComputedType(computedTypes);
       if (computed is UnknownType) return const UnknownType();
-      types[i] = computed;
+      types.add(computed as RuntimeType);
     }
     DartType dartType;
     if (klass == typeHierarchy.coreTypes.deprecatedFutureOrClass) {
@@ -545,17 +538,15 @@
   // "unchecked" entrypoint.
   bool isTestedOnlyOnCheckedEntryPoint;
 
-  VariableDeclaration get parameter =>
-      node is VariableDeclaration ? node : null;
+  bool get isParameterCheck => node is VariableDeclaration;
+  VariableDeclaration get parameterVariable => node as VariableDeclaration;
 
   bool alwaysPass = true;
   bool alwaysFail = true;
 
-  TypeCheck(this.arg, this.type, this.node, this.staticType, this.kind) {
-    assert(node != null);
-    isTestedOnlyOnCheckedEntryPoint =
-        parameter != null && !parameter.isCovariant;
-  }
+  TypeCheck(this.arg, this.type, this.node, this.staticType, this.kind)
+      : isTestedOnlyOnCheckedEntryPoint =
+            node is VariableDeclaration && !node.isCovariant;
 
   @override
   void accept(StatementVisitor visitor) => visitor.visitTypeCheck(this);
@@ -568,7 +559,7 @@
   }
 
   @override
-  Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+  Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
     Type argType = arg.getComputedType(computedTypes);
     Type checkType = type.getComputedType(computedTypes);
@@ -624,11 +615,11 @@
   int requiredParameterCount;
 
   List<Statement> _statements = <Statement>[];
-  TypeExpr result = null;
-  Type resultType = EmptyType();
+  TypeExpr result = const EmptyType();
+  Type resultType = const EmptyType();
 
   // Analysis time of callees. Populated only if kPrintTimings.
-  int calleeTime;
+  int calleeTime = 0;
 
   Summary(this.name,
       {this.parameterCount: 0,
@@ -658,7 +649,7 @@
   /// Apply this summary to the given arguments and return the resulting type.
   Type apply(Args<Type> arguments, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
-    final Stopwatch timer = kPrintTimings ? (new Stopwatch()..start()) : null;
+    final Stopwatch? timer = kPrintTimings ? (new Stopwatch()..start()) : null;
     final int oldCalleeTime = calleeTime;
     calleeTime = 0;
     final args = arguments.values;
@@ -677,7 +668,7 @@
     //
     // The first `parameterCount` statements are Parameters.
 
-    List<Type> types = new List<Type>.filled(_statements.length, null);
+    List<Type?> types = new List<Type?>.filled(_statements.length, null);
 
     for (int i = 0; i < positionalArgCount; i++) {
       final Parameter param = _statements[i] as Parameter;
@@ -687,9 +678,9 @@
       }
       final argType = args[i].specialize(typeHierarchy);
       param._observeArgumentType(argType, typeHierarchy);
-      if (param.staticTypeForNarrowing != null) {
-        types[i] =
-            argType.intersection(param.staticTypeForNarrowing, typeHierarchy);
+      final staticTypeForNarrowing = param.staticTypeForNarrowing;
+      if (staticTypeForNarrowing != null) {
+        types[i] = argType.intersection(staticTypeForNarrowing, typeHierarchy);
       } else {
         // TODO(sjindel/tfa): Narrowing is performed inside a [TypeCheck] later.
         types[i] = args[i];
@@ -710,9 +701,10 @@
             args[positionalArgCount + argIndex].specialize(typeHierarchy);
         argIndex++;
         param._observeArgumentType(argType, typeHierarchy);
-        if (param.staticTypeForNarrowing != null) {
+        final staticTypeForNarrowing = param.staticTypeForNarrowing;
+        if (staticTypeForNarrowing != null) {
           types[i] =
-              argType.intersection(param.staticTypeForNarrowing, typeHierarchy);
+              argType.intersection(staticTypeForNarrowing, typeHierarchy);
         } else {
           types[i] = argType;
         }
@@ -741,7 +733,7 @@
     resultType = resultType.union(computedType, typeHierarchy);
 
     if (kPrintTimings) {
-      final dirtyTime = timer.elapsedMicroseconds;
+      final dirtyTime = timer!.elapsedMicroseconds;
       final pureTime = dirtyTime < calleeTime ? 0 : (dirtyTime - calleeTime);
       Statistics.numSummaryApplications.add(name);
       Statistics.dirtySummaryAnalysisTime.add(name, dirtyTime);
@@ -753,9 +745,9 @@
   }
 
   Args<Type> get argumentTypes {
-    final argTypes = new List<Type>.filled(parameterCount, null);
-    final argNames = new List<String>.filled(
-        parameterCount - positionalParameterCount, null);
+    final argTypes = new List<Type>.filled(parameterCount, const EmptyType());
+    final argNames =
+        new List<String>.filled(parameterCount - positionalParameterCount, '');
     for (int i = 0; i < parameterCount; i++) {
       Parameter param = _statements[i] as Parameter;
       argTypes[i] = param.argumentType;
@@ -769,7 +761,7 @@
   Type argumentType(Member member, VariableDeclaration memberParam) {
     final int firstParamIndex =
         numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
-    final positional = member.function.positionalParameters;
+    final positional = member.function!.positionalParameters;
     for (int i = 0; i < positional.length; i++) {
       if (positional[i] == memberParam) {
         final Parameter param = _statements[firstParamIndex + i] as Parameter;
@@ -791,8 +783,8 @@
     for (Statement statement in _statements) {
       if (statement is TypeCheck &&
           statement.alwaysPass &&
-          statement.parameter != null) {
-        params.add(statement.parameter);
+          statement.isParameterCheck) {
+        params.add(statement.parameterVariable);
       }
     }
     return params;
@@ -808,17 +800,17 @@
         (hasReceiverArg(member) ? 1 : 0) + numTypeParams(member);
     final Map<String, Parameter> paramsByName = {};
     for (int i = implicit; i < parameterCount; i++) {
-      final Parameter param = statements[i];
+      final Parameter param = statements[i] as Parameter;
       paramsByName[param.name] = param;
     }
-    FunctionNode function = member.function;
+    FunctionNode function = member.function!;
     statements.length = implicit;
     for (VariableDeclaration param in function.positionalParameters) {
-      statements.add(paramsByName[param.name]);
+      statements.add(paramsByName[param.name]!);
     }
     positionalParameterCount = statements.length;
     for (VariableDeclaration param in function.namedParameters) {
-      statements.add(paramsByName[param.name]);
+      statements.add(paramsByName[param.name]!);
     }
     parameterCount = statements.length;
     requiredParameterCount = implicit + function.requiredParameterCount;
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index cd78792..d2157f7 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -2,10 +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.9
-
 /// Creation of type flow summaries out of kernel AST.
-library vm.transformations.type_flow.summary_collector;
 
 import 'dart:core' hide Type;
 
@@ -14,6 +11,7 @@
 import 'package:kernel/ast.dart' as ast show Statement, StatementVisitor;
 import 'package:kernel/class_hierarchy.dart'
     show ClassHierarchy, ClosedWorldClassHierarchy;
+import 'package:kernel/core_types.dart' show CoreTypes;
 import 'package:kernel/type_environment.dart'
     show StaticTypeContext, SubtypeCheckMode, TypeEnvironment;
 import 'package:kernel/type_algebra.dart' show Substitution;
@@ -239,7 +237,7 @@
   // function and checks if control can fall through them or not.
 
   bool controlCanFallThrough(FunctionNode function) {
-    return function.body.accept(this);
+    return function.body!.accept(this);
   }
 
   @override
@@ -285,11 +283,11 @@
   bool visitContinueSwitchStatement(ContinueSwitchStatement node) => false;
 
   @override
-  bool visitIfStatement(IfStatement node) =>
-      node.then == null ||
-      node.otherwise == null ||
-      node.then.accept(this) ||
-      node.otherwise.accept(this);
+  bool visitIfStatement(IfStatement node) {
+    final otherwise = node.otherwise;
+    if (otherwise == null) return true;
+    return node.then.accept(this) || otherwise.accept(this);
+  }
 
   @override
   bool visitReturnStatement(ReturnStatement node) => false;
@@ -323,7 +321,7 @@
   final List<VariableDeclaration> varDeclarations = <VariableDeclaration>[];
 
   /// Set of captured variables.
-  Set<VariableDeclaration> captured;
+  Set<VariableDeclaration>? captured;
 
   /// Set of variables which were modified for each loop, switch statement
   /// and try block statement. Doesn't include captured variables and
@@ -334,10 +332,10 @@
   int numVariablesAtFunctionEntry = 0;
 
   /// Active loops, switch statements and try blocks.
-  List<ast.Statement> activeStatements;
+  List<ast.Statement>? activeStatements;
 
   /// Number of variables at entry of active statements.
-  List<int> numVariablesAtActiveStatements;
+  List<int>? numVariablesAtActiveStatements;
 
   _VariablesInfoCollector(Member member) {
     member.accept(this);
@@ -345,8 +343,10 @@
 
   int get numVariables => varDeclarations.length;
 
-  bool isCaptured(VariableDeclaration variable) =>
-      captured != null && captured.contains(variable);
+  bool isCaptured(VariableDeclaration variable) {
+    final captured = this.captured;
+    return captured != null && captured.contains(variable);
+  }
 
   Set<int> getModifiedVariables(ast.Statement st) {
     return modifiedSets[st] ?? const <int>{};
@@ -387,14 +387,15 @@
   }
 
   void _useVariable(VariableDeclaration variable, bool isVarAssignment) {
-    final index = varIndex[variable];
+    final index = varIndex[variable]!;
     if (_isDeclaredBefore(index, numVariablesAtFunctionEntry)) {
       _captureVariable(variable);
       return;
     }
+    final activeStatements = this.activeStatements;
     if (isVarAssignment && activeStatements != null) {
       for (int i = activeStatements.length - 1; i >= 0; --i) {
-        if (_isDeclaredBefore(index, numVariablesAtActiveStatements[i])) {
+        if (_isDeclaredBefore(index, numVariablesAtActiveStatements![i])) {
           final st = activeStatements[i];
           (modifiedSets[st] ??= <int>{}).add(index);
         } else {
@@ -410,8 +411,8 @@
   }
 
   void _endCollectingModifiedVariables() {
-    activeStatements.removeLast();
-    numVariablesAtActiveStatements.removeLast();
+    activeStatements!.removeLast();
+    numVariablesAtActiveStatements!.removeLast();
   }
 
   @override
@@ -457,7 +458,7 @@
   @override
   visitTryCatch(TryCatch node) {
     _startCollectingModifiedVariables(node);
-    node.body?.accept(this);
+    node.body.accept(this);
     _endCollectingModifiedVariables();
     visitList(node.catches, this);
   }
@@ -465,9 +466,9 @@
   @override
   visitTryFinally(TryFinally node) {
     _startCollectingModifiedVariables(node);
-    node.body?.accept(this);
+    node.body.accept(this);
     _endCollectingModifiedVariables();
-    node.finalizer?.accept(this);
+    node.finalizer.accept(this);
   }
 
   @override
@@ -489,7 +490,7 @@
     visitList(node.variables, this);
     _startCollectingModifiedVariables(node);
     node.condition?.accept(this);
-    node.body?.accept(this);
+    node.body.accept(this);
     visitList(node.updates, this);
     _endCollectingModifiedVariables();
   }
@@ -521,7 +522,7 @@
 enum FieldSummaryType { kFieldGuard, kInitializer }
 
 /// Create a type flow summary for a member from the kernel AST.
-class SummaryCollector extends RecursiveResultVisitor<TypeExpr> {
+class SummaryCollector extends RecursiveResultVisitor<TypeExpr?> {
   final Target target;
   final TypeEnvironment _environment;
   final ClosedWorldClassHierarchy _hierarchy;
@@ -529,7 +530,7 @@
   final TypesBuilder _typesBuilder;
   final NativeCodeOracle _nativeCodeOracle;
   final GenericInterfacesInfo _genericInterfacesInfo;
-  final ProtobufHandler _protobufHandler;
+  final ProtobufHandler? _protobufHandler;
 
   final Map<TreeNode, Call> callSites = <TreeNode, Call>{};
   final Map<AsExpression, TypeCheck> explicitCasts =
@@ -540,13 +541,13 @@
   final Set<Name> _nullMethodsAndGetters = <Name>{};
   final Set<Name> _nullSetters = <Name>{};
 
-  Summary _summary;
-  _VariablesInfoCollector _variablesInfo;
+  Summary _summary = Summary('<unused>');
+  late _VariablesInfoCollector _variablesInfo;
 
   // Current value of each variable. May contain null if variable is not
   // declared yet, or EmptyType if current location is unreachable
   // (e.g. after return or throw).
-  List<TypeExpr> _variableValues;
+  List<TypeExpr?> _variableValues = const <TypeExpr?>[];
 
   // Contains Joins which accumulate all values of certain variables.
   // Used only when all variable values should be merged regardless of control
@@ -558,30 +559,30 @@
   // If _variableCells[i] != null, then all values are accumulated in the
   // _variableCells[i]. _variableValues[i] does not change and remains equal
   // to _variableCells[i].
-  List<Join> _variableCells;
+  List<Join?> _variableCells = const <Join?>[];
 
   // Counts number of Joins inserted for each variable. Only used to set
   // readable names for such joins (foo_0, foo_1 etc.)
-  List<int> _variableVersions;
+  List<int> _variableVersions = const <int>[];
 
   // State of variables after corresponding LabeledStatement.
   // Used to collect states from BreakStatements.
-  Map<LabeledStatement, List<TypeExpr>> _variableValuesAfterLabeledStatements;
+  Map<LabeledStatement, List<TypeExpr?>>? _variableValuesAfterLabeledStatements;
 
   // Joins corresponding to variables on entry to switch cases.
   // Used to propagate state from ContinueSwitchStatement to a target case.
-  Map<SwitchCase, List<Join>> _joinsAtSwitchCases;
+  Map<SwitchCase, List<Join?>>? _joinsAtSwitchCases;
 
   // Join which accumulates all return values.
-  Join _returnValue;
+  Join? _returnValue;
 
-  Parameter _receiver;
-  ConstantAllocationCollector constantAllocationCollector;
-  RuntimeTypeTranslatorImpl _translator;
-  StaticTypeContext _staticTypeContext;
+  Parameter? _receiver;
+  late ConstantAllocationCollector constantAllocationCollector;
+  late RuntimeTypeTranslatorImpl _translator;
+  StaticTypeContext? _staticTypeContext;
 
   // Currently only used for factory constructors.
-  Map<TypeParameter, TypeExpr> _fnTypeVariables;
+  Map<TypeParameter, TypeExpr>? _fnTypeVariables;
 
   SummaryCollector(
       this.target,
@@ -592,7 +593,6 @@
       this._nativeCodeOracle,
       this._genericInterfacesInfo,
       this._protobufHandler) {
-    assert(_genericInterfacesInfo != null);
     constantAllocationCollector = new ConstantAllocationCollector(this);
     _nullMethodsAndGetters.addAll(getSelectors(
         _hierarchy, _environment.coreTypes.deprecatedNullClass,
@@ -615,8 +615,8 @@
     _staticTypeContext = new StaticTypeContext(member, _environment);
     _variablesInfo = new _VariablesInfoCollector(member);
     _variableValues =
-        new List<TypeExpr>.filled(_variablesInfo.numVariables, null);
-    _variableCells = new List<Join>.filled(_variablesInfo.numVariables, null);
+        new List<TypeExpr?>.filled(_variablesInfo.numVariables, null);
+    _variableCells = new List<Join?>.filled(_variablesInfo.numVariables, null);
     _variableVersions = new List<int>.filled(_variablesInfo.numVariables, 0);
     _variableValuesAfterLabeledStatements = null;
     _joinsAtSwitchCases = null;
@@ -633,25 +633,24 @@
             parameterCount: numArgs, positionalParameterCount: numArgs);
         // TODO(alexmarkov): subclass cone
         _receiver = _declareParameter("this",
-            _environment.coreTypes.legacyRawType(member.enclosingClass), null,
+            _environment.coreTypes.legacyRawType(member.enclosingClass!), null,
             isReceiver: true);
       } else {
         _summary = new Summary(summaryName);
       }
 
-      _translator = new RuntimeTypeTranslatorImpl(
-          this, _summary, _receiver, null, _genericInterfacesInfo);
+      _translator = new RuntimeTypeTranslatorImpl(_environment.coreTypes,
+          _summary, _receiver, null, _genericInterfacesInfo);
 
       if (fieldSummaryType == FieldSummaryType.kInitializer) {
-        assert(member.initializer != null);
-        _summary.result = _visit(member.initializer);
+        _summary.result = _visit(member.initializer!);
       } else {
         final Parameter valueParam =
             _declareParameter("value", member.type, null);
         _summary.result = _typeCheck(valueParam, member.type, member);
       }
     } else {
-      FunctionNode function = member.function;
+      final FunctionNode function = member.function!;
 
       final numTypeParameters = numTypeParams(member);
       final firstParamIndex = (hasReceiver ? 1 : 0) + numTypeParameters;
@@ -666,43 +665,42 @@
               firstParamIndex + function.requiredParameterCount);
 
       if (numTypeParameters > 0) {
-        _fnTypeVariables = <TypeParameter, TypeExpr>{};
-        for (int i = 0; i < numTypeParameters; ++i) {
-          _fnTypeVariables[function.typeParameters[i]] =
-              _declareParameter(function.typeParameters[i].name, null, null);
-        }
+        _fnTypeVariables = <TypeParameter, TypeExpr>{
+          for (TypeParameter tp in function.typeParameters)
+            tp: _declareParameter(tp.name!, null, null)
+        };
       }
 
       if (hasReceiver) {
         // TODO(alexmarkov): subclass cone
         _receiver = _declareParameter("this",
-            _environment.coreTypes.legacyRawType(member.enclosingClass), null,
+            _environment.coreTypes.legacyRawType(member.enclosingClass!), null,
             isReceiver: true);
       }
 
-      _translator = new RuntimeTypeTranslatorImpl(
-          this, _summary, _receiver, _fnTypeVariables, _genericInterfacesInfo);
+      _translator = new RuntimeTypeTranslatorImpl(_environment.coreTypes,
+          _summary, _receiver, _fnTypeVariables, _genericInterfacesInfo);
 
       // Handle forwarding stubs. We need to check types against the types of
       // the forwarding stub's target, [member.concreteForwardingStubTarget].
-      FunctionNode useTypesFrom = member.function;
-      if (member is Procedure &&
-          member.isForwardingStub &&
-          member.concreteForwardingStubTarget != null) {
+      FunctionNode useTypesFrom = function;
+      if (member is Procedure && member.isForwardingStub) {
         final target = member.concreteForwardingStubTarget;
-        if (target is Field) {
-          useTypesFrom = FunctionNode(null, positionalParameters: [
-            VariableDeclaration("value", type: target.type)
-          ]);
-        } else {
-          useTypesFrom = member.concreteForwardingStubTarget.function;
+        if (target != null) {
+          if (target is Field) {
+            useTypesFrom = FunctionNode(null, positionalParameters: [
+              VariableDeclaration("value", type: target.type)
+            ]);
+          } else {
+            useTypesFrom = target.function!;
+          }
         }
       }
 
       for (int i = 0; i < function.positionalParameters.length; ++i) {
         final decl = function.positionalParameters[i];
         _declareParameter(
-            decl.name,
+            decl.name!,
             _useTypeCheckForParameter(decl)
                 ? null
                 : useTypesFrom.positionalParameters[i].type,
@@ -711,7 +709,7 @@
       for (int i = 0; i < function.namedParameters.length; ++i) {
         final decl = function.namedParameters[i];
         _declareParameter(
-            decl.name,
+            decl.name!,
             _useTypeCheckForParameter(decl)
                 ? null
                 : useTypesFrom.namedParameters[i].type,
@@ -740,7 +738,7 @@
       assert(count == _summary.parameterCount);
 
       _returnValue = new Join("%result", function.returnType);
-      _summary.add(_returnValue);
+      _summary.add(_returnValue!);
 
       if (member is Constructor) {
         // Make sure instance field initializers are visited.
@@ -750,7 +748,7 @@
                 new DirectSelector(f, callKind: CallKind.FieldInitializer));
           }
         }
-        member.initializers.forEach(_visit);
+        member.initializers.forEach(_visitWithoutResult);
       }
 
       if (function.body == null) {
@@ -760,15 +758,15 @@
           // Runtime type could be more precise than static type, so
           // calculate intersection.
           final typeCheck = _typeCheck(type, function.returnType, function);
-          _returnValue.values.add(typeCheck);
+          _returnValue!.values.add(typeCheck);
         } else {
-          _returnValue.values.add(type);
+          _returnValue!.values.add(type);
         }
       } else {
-        _visit(function.body);
+        _visitWithoutResult(function.body!);
 
         if (_fallthroughDetector.controlCanFallThrough(function)) {
-          _returnValue.values.add(_nullType);
+          _returnValue!.values.add(_nullType);
         }
       }
 
@@ -776,15 +774,15 @@
         // In addition to what is returned from the function body,
         // operator == performs implicit comparison with null
         // and returns bool.
-        _returnValue.values.add(_boolType);
+        _returnValue!.values.add(_boolType);
       }
 
-      _summary.result = _returnValue;
+      _summary.result = _returnValue!;
     }
 
     member.annotations.forEach(_visit);
-    member.enclosingClass?.annotations?.forEach(_visit);
-    member.enclosingLibrary?.annotations?.forEach(_visit);
+    member.enclosingClass?.annotations.forEach(_visit);
+    member.enclosingLibrary.annotations.forEach(_visit);
 
     _staticTypeContext = null;
 
@@ -808,9 +806,7 @@
   }
 
   Args<Type> rawArguments(Selector selector) {
-    final member = selector.member;
-    assert(member != null);
-
+    final member = selector.member!;
     final List<Type> args = <Type>[];
     final List<String> names = <String>[];
 
@@ -822,15 +818,14 @@
     if (hasReceiverArg(member)) {
       assert(member.enclosingClass != null);
       final receiver =
-          new ConeType(_typesBuilder.getTFClass(member.enclosingClass));
+          new ConeType(_typesBuilder.getTFClass(member.enclosingClass!));
       args.add(receiver);
     }
 
     switch (selector.callKind) {
       case CallKind.Method:
         if (member is! Field) {
-          final function = member.function;
-          assert(function != null);
+          final function = member.function!;
 
           final int paramCount = function.positionalParameters.length +
               function.namedParameters.length;
@@ -840,7 +835,7 @@
 
           if (function.namedParameters.isNotEmpty) {
             for (var param in function.namedParameters) {
-              names.add(param.name);
+              names.add(param.name!);
             }
             // TODO(dartbug.com/32292): make sure parameters are sorted in
             // kernel AST and remove this sorting.
@@ -864,11 +859,15 @@
     return new Args<Type>(args, names: names);
   }
 
-  TypeExpr _visit(TreeNode node) => node.accept(this);
+  TypeExpr _visit(Expression node) => node.accept(this)!;
 
-  Args<TypeExpr> _visitArguments(TypeExpr receiver, Arguments arguments,
+  void _visitWithoutResult(TreeNode node) {
+    node.accept(this);
+  }
+
+  Args<TypeExpr> _visitArguments(TypeExpr? receiver, Arguments arguments,
       {bool passTypeArguments: false}) {
-    final args = <TypeExpr>[];
+    final List<TypeExpr> args = <TypeExpr>[];
     if (passTypeArguments) {
       for (var type in arguments.types) {
         args.add(_translator.translate(type));
@@ -890,7 +889,7 @@
       }
       names.sort();
       for (var name in names) {
-        args.add(map[name]);
+        args.add(map[name]!);
       }
       return new Args<TypeExpr>(args, names: names);
     } else {
@@ -899,9 +898,9 @@
   }
 
   Parameter _declareParameter(
-      String name, DartType type, Expression initializer,
+      String name, DartType? type, Expression? initializer,
       {bool isReceiver: false}) {
-    Type staticType;
+    Type? staticType;
     if (type != null) {
       staticType = _typesBuilder.fromStaticType(type, !isReceiver);
     }
@@ -916,7 +915,7 @@
         } else if (initializer is BasicLiteral ||
             initializer is SymbolLiteral ||
             initializer is TypeLiteral) {
-          param.defaultValue = _visit(initializer);
+          param.defaultValue = _visit(initializer) as Type;
         } else {
           throw 'Unexpected parameter $name default value ${initializer.runtimeType} $initializer';
         }
@@ -930,8 +929,7 @@
   }
 
   void _declareVariable(VariableDeclaration decl, TypeExpr initialValue) {
-    final int varIndex = _variablesInfo.varIndex[decl];
-    assert(varIndex != null);
+    final int varIndex = _variablesInfo.varIndex[decl]!;
     assert(_variablesInfo.varDeclarations[varIndex] == decl);
     assert(_variableValues[varIndex] == null);
     if (_variablesInfo.isCaptured(decl)) {
@@ -944,8 +942,8 @@
   }
 
   void _writeVariable(VariableDeclaration variable, TypeExpr value) {
-    final int varIndex = _variablesInfo.varIndex[variable];
-    final Join join = _variableCells[varIndex];
+    final int varIndex = _variablesInfo.varIndex[variable]!;
+    final Join? join = _variableCells[varIndex];
     if (join != null) {
       join.values.add(value);
     } else {
@@ -953,11 +951,12 @@
     }
   }
 
-  List<TypeExpr> _cloneVariableValues(List<TypeExpr> values) =>
-      new List<TypeExpr>.from(values);
+  List<TypeExpr?> _cloneVariableValues(List<TypeExpr?> values) =>
+      new List<TypeExpr?>.from(values);
 
-  List<TypeExpr> _makeEmptyVariableValues() {
-    final values = new List<TypeExpr>.filled(_variablesInfo.numVariables, null);
+  List<TypeExpr?> _makeEmptyVariableValues() {
+    final values =
+        new List<TypeExpr?>.filled(_variablesInfo.numVariables, null);
     for (int i = 0; i < values.length; ++i) {
       if (_variableCells[i] != null) {
         values[i] = _variableValues[i];
@@ -978,11 +977,11 @@
     return join;
   }
 
-  void _mergeVariableValues(List<TypeExpr> dst, List<TypeExpr> src) {
+  void _mergeVariableValues(List<TypeExpr?> dst, List<TypeExpr?> src) {
     assert(dst.length == src.length);
     for (int i = 0; i < dst.length; ++i) {
-      final TypeExpr dstValue = dst[i];
-      final TypeExpr srcValue = src[i];
+      final TypeExpr? dstValue = dst[i];
+      final TypeExpr? srcValue = src[i];
       if (identical(dstValue, srcValue)) {
         continue;
       }
@@ -997,21 +996,21 @@
       } else if (srcValue is Join && srcValue.values.contains(dstValue)) {
         dst[i] = srcValue;
       } else {
-        final Join join = _makeJoin(i, dst[i]);
-        join.values.add(src[i]);
+        final Join join = _makeJoin(i, dstValue);
+        join.values.add(srcValue);
         dst[i] = join;
       }
     }
   }
 
-  void _copyVariableValues(List<TypeExpr> dst, List<TypeExpr> src) {
+  void _copyVariableValues(List<TypeExpr?> dst, List<TypeExpr?> src) {
     assert(dst.length == src.length);
     for (int i = 0; i < dst.length; ++i) {
       dst[i] = src[i];
     }
   }
 
-  bool _isIdenticalState(List<TypeExpr> state1, List<TypeExpr> state2) {
+  bool _isIdenticalState(List<TypeExpr?> state1, List<TypeExpr?> state2) {
     assert(state1.length == state2.length);
     for (int i = 0; i < state1.length; ++i) {
       if (!identical(state1[i], state2[i])) {
@@ -1021,14 +1020,14 @@
     return true;
   }
 
-  List<Join> _insertJoinsForModifiedVariables(TreeNode node, bool isTry) {
-    final List<Join> joins =
-        new List<Join>.filled(_variablesInfo.numVariables, null);
+  List<Join?> _insertJoinsForModifiedVariables(ast.Statement node, bool isTry) {
+    final List<Join?> joins =
+        new List<Join?>.filled(_variablesInfo.numVariables, null);
     for (var i in _variablesInfo.getModifiedVariables(node)) {
       if (_variableCells[i] != null) {
         assert(_variableCells[i] == _variableValues[i]);
       } else {
-        final join = _makeJoin(i, _variableValues[i]);
+        final join = _makeJoin(i, _variableValues[i]!);
         joins[i] = join;
         _variableValues[i] = join;
         if (isTry) {
@@ -1044,7 +1043,7 @@
 
   /// Stops accumulating values in [joins] by removing them from
   /// _variableCells.
-  void _restoreVariableCellsAfterTry(List<Join> joins) {
+  void _restoreVariableCellsAfterTry(List<Join?> joins) {
     for (int i = 0; i < joins.length; ++i) {
       if (joins[i] != null) {
         assert(_variableCells[i] == joins[i]);
@@ -1053,14 +1052,14 @@
     }
   }
 
-  void _mergeVariableValuesToJoins(List<TypeExpr> values, List<Join> joins) {
+  void _mergeVariableValuesToJoins(List<TypeExpr?> values, List<Join?> joins) {
     for (int i = 0; i < joins.length; ++i) {
       final join = joins[i];
       final value = values[i];
       if (join != null &&
           !identical(join, value) &&
           !identical(join.values.first, value)) {
-        join.values.add(value);
+        join.values.add(value!);
       }
     }
   }
@@ -1079,16 +1078,17 @@
 
   // TODO(alexmarkov): Avoid declaring variables with static types.
   void _declareVariableWithStaticType(VariableDeclaration decl) {
-    if (decl.initializer != null) {
-      _visit(decl.initializer);
+    final initializer = decl.initializer;
+    if (initializer != null) {
+      _visit(initializer);
     }
     _declareVariable(decl, _typesBuilder.fromStaticType(decl.type, true));
   }
 
   Call _makeCall(TreeNode node, Selector selector, Args<TypeExpr> args,
       {bool isInstanceCreation = false}) {
-    Type staticResultType = null;
-    Member target;
+    Type? staticResultType = null;
+    Member? target;
     if (selector is DirectSelector) {
       target = selector.member;
     } else if (selector is InterfaceSelector) {
@@ -1101,9 +1101,7 @@
     }
     Call call = new Call(selector, args, staticResultType, isInstanceCreation);
     _summary.add(call);
-    if (node != null) {
-      callSites[node] = call;
-    }
+    callSites[node] = call;
     return call;
   }
 
@@ -1189,53 +1187,43 @@
   }
 
   DartType _staticDartType(Expression node) =>
-      node.getStaticType(_staticTypeContext);
+      node.getStaticType(_staticTypeContext!);
 
   Type _staticType(Expression node) =>
       _typesBuilder.fromStaticType(_staticDartType(node), true);
 
-  ConcreteType _cachedBoolType;
-  ConcreteType get _boolType => _cachedBoolType ??=
+  late final ConcreteType _boolType =
       _entryPointsListener.addAllocatedClass(_environment.coreTypes.boolClass);
 
-  ConcreteType _cachedBoolTrue;
-  ConcreteType get _boolTrue => _cachedBoolTrue ??=
-      new ConcreteType(_boolType.cls, null, BoolConstant(true));
+  late final ConcreteType _boolTrue =
+      ConcreteType(_boolType.cls, null, BoolConstant(true));
 
-  ConcreteType _cachedBoolFalse;
-  ConcreteType get _boolFalse => _cachedBoolFalse ??=
-      new ConcreteType(_boolType.cls, null, BoolConstant(false));
+  late final ConcreteType _boolFalse =
+      ConcreteType(_boolType.cls, null, BoolConstant(false));
 
-  Type _cachedDoubleType;
-  Type get _doubleType => _cachedDoubleType ??= new ConeType(
-      _typesBuilder.getTFClass(_environment.coreTypes.doubleClass));
+  late final Type _doubleType =
+      ConeType(_typesBuilder.getTFClass(_environment.coreTypes.doubleClass));
 
-  Type _cachedIntType;
-  Type get _intType => _cachedIntType ??=
-      new ConeType(_typesBuilder.getTFClass(_environment.coreTypes.intClass));
+  late final Type _intType =
+      ConeType(_typesBuilder.getTFClass(_environment.coreTypes.intClass));
 
-  Type _cachedStringType;
-  Type get _stringType => _cachedStringType ??= new ConeType(
-      _typesBuilder.getTFClass(_environment.coreTypes.stringClass));
+  late final Type _stringType =
+      ConeType(_typesBuilder.getTFClass(_environment.coreTypes.stringClass));
 
-  Type _cachedSymbolType;
-  Type get _symbolType => _cachedSymbolType ??= new ConeType(
-      _typesBuilder.getTFClass(_environment.coreTypes.symbolClass));
+  late final Type _symbolType =
+      ConeType(_typesBuilder.getTFClass(_environment.coreTypes.symbolClass));
 
-  Type _cachedTypeType;
-  Type get _typeType => _cachedTypeType ??=
-      new ConeType(_typesBuilder.getTFClass(_environment.coreTypes.typeClass));
+  late final Type _typeType =
+      ConeType(_typesBuilder.getTFClass(_environment.coreTypes.typeClass));
 
-  Type _cachedNullType;
-  Type get _nullType =>
-      _cachedNullType ??= new Type.nullable(const EmptyType());
+  late final Type _nullType = Type.nullable(const EmptyType());
 
-  Class get _superclass => _staticTypeContext.thisType.classNode.superclass;
+  Class get _superclass => _staticTypeContext!.thisType!.classNode.superclass!;
 
   Type _boolLiteralType(bool value) => value ? _boolTrue : _boolFalse;
 
-  Type _intLiteralType(int value, Constant constant) {
-    final Class concreteClass =
+  Type _intLiteralType(int value, Constant? constant) {
+    final Class? concreteClass =
         target.concreteIntLiteralClass(_environment.coreTypes, value);
     if (concreteClass != null) {
       constant ??= IntConstant(value);
@@ -1247,8 +1235,8 @@
     return _intType;
   }
 
-  Type _doubleLiteralType(double value, Constant constant) {
-    final Class concreteClass =
+  Type _doubleLiteralType(double value, Constant? constant) {
+    final Class? concreteClass =
         target.concreteDoubleLiteralClass(_environment.coreTypes, value);
     if (concreteClass != null) {
       constant ??= DoubleConstant(value);
@@ -1260,8 +1248,8 @@
     return _doubleType;
   }
 
-  Type _stringLiteralType(String value, Constant constant) {
-    final Class concreteClass =
+  Type _stringLiteralType(String value, Constant? constant) {
+    final Class? concreteClass =
         target.concreteStringLiteralClass(_environment.coreTypes, value);
     if (concreteClass != null) {
       constant ??= StringConstant(value);
@@ -1284,7 +1272,7 @@
     node.positionalParameters.forEach(_declareVariableWithStaticType);
     node.namedParameters.forEach(_declareVariableWithStaticType);
 
-    _visit(node.body);
+    _visitWithoutResult(node.body!);
 
     _variableValues = savedVariableValues;
     _returnValue = savedReturn;
@@ -1307,8 +1295,7 @@
       for (Class c
           in _hierarchy.computeSubtypesInformation().getSubtypesOf(cls)) {
         if (!c.isAbstract) {
-          final candidate = _hierarchy.getDispatchTarget(c, _equalsName);
-          assert(candidate != null);
+          final candidate = _hierarchy.getDispatchTarget(c, _equalsName)!;
           assert(!candidate.isAbstract);
           if (candidate != _environment.coreTypes.objectEquals) {
             _cachedHasOverriddenEquals[cls] = true;
@@ -1328,12 +1315,12 @@
   // On exit _variableValues is null, so caller should explicitly pick
   // either trueState or falseState.
   void _visitCondition(
-      Expression node, List<TypeExpr> trueState, List<TypeExpr> falseState) {
+      Expression node, List<TypeExpr?> trueState, List<TypeExpr?> falseState) {
     assert(_isIdenticalState(_variableValues, trueState));
     assert(_isIdenticalState(_variableValues, falseState));
     if (node is Not) {
       _visitCondition(node.operand, falseState, trueState);
-      _variableValues = null;
+      _variableValues = const <TypeExpr?>[]; // Should not be used.
       return;
     } else if (node is LogicalExpression) {
       final isOR = (node.operatorEnum == LogicalExpressionOperator.OR);
@@ -1351,7 +1338,7 @@
         _visitCondition(node.right, trueState, falseStateAfterRHS);
         _mergeVariableValues(falseState, falseStateAfterRHS);
       }
-      _variableValues = null;
+      _variableValues = const <TypeExpr?>[]; // Should not be used.
       return;
     } else if (node is VariableGet ||
         (node is AsExpression && node.operand is VariableGet)) {
@@ -1359,12 +1346,12 @@
       _addUse(_visit(node));
       final variableGet =
           (node is AsExpression ? node.operand : node) as VariableGet;
-      final int varIndex = _variablesInfo.varIndex[variableGet.variable];
+      final int varIndex = _variablesInfo.varIndex[variableGet.variable]!;
       if (_variableCells[varIndex] == null) {
         trueState[varIndex] = _boolTrue;
         falseState[varIndex] = _boolFalse;
       }
-      _variableValues = null;
+      _variableValues = const <TypeExpr?>[]; // Should not be used.
       return;
     } else if (node is EqualsCall && node.left is VariableGet) {
       final lhs = node.left as VariableGet;
@@ -1379,11 +1366,11 @@
               !_hasOverriddenEquals(lhs.variable.type))) {
         // 'x == c', where x is a variable and c is a constant.
         _addUse(_visit(node));
-        final int varIndex = _variablesInfo.varIndex[lhs.variable];
+        final int varIndex = _variablesInfo.varIndex[lhs.variable]!;
         if (_variableCells[varIndex] == null) {
           trueState[varIndex] = _visit(rhs);
         }
-        _variableValues = null;
+        _variableValues = const <TypeExpr?>[]; // Should not be used.
         return;
       }
     } else if (node is EqualsNull && node.expression is VariableGet) {
@@ -1393,12 +1380,12 @@
       _makeCall(node, DirectSelector(_environment.coreTypes.objectEquals),
           Args<TypeExpr>([expr, _nullType]));
       final narrowedNotNull = _makeNarrowNotNull(node, expr);
-      final int varIndex = _variablesInfo.varIndex[lhs.variable];
+      final int varIndex = _variablesInfo.varIndex[lhs.variable]!;
       if (_variableCells[varIndex] == null) {
         trueState[varIndex] = _nullType;
         falseState[varIndex] = narrowedNotNull;
       }
-      _variableValues = null;
+      _variableValues = const <TypeExpr?>[]; // Should not be used.
       return;
     } else if (node is IsExpression && node.operand is VariableGet) {
       // Handle 'x is T', where x is a variable.
@@ -1406,17 +1393,17 @@
       final TypeCheck typeCheck =
           _typeCheck(_visit(operand), node.type, node, SubtypeTestKind.IsTest);
       isTests[node] = typeCheck;
-      final int varIndex = _variablesInfo.varIndex[operand.variable];
+      final int varIndex = _variablesInfo.varIndex[operand.variable]!;
       if (_variableCells[varIndex] == null) {
         trueState[varIndex] = typeCheck;
       }
-      _variableValues = null;
+      _variableValues = const <TypeExpr?>[]; // Should not be used.
       return;
     }
     _addUse(_visit(node));
     _copyVariableValues(trueState, _variableValues);
     _copyVariableValues(falseState, _variableValues);
-    _variableValues = null;
+    _variableValues = const <TypeExpr?>[]; // Should not be used.
   }
 
   void _updateReceiverAfterCall(
@@ -1425,7 +1412,7 @@
     if (receiverNode is VariableGet) {
       final nullSelectors = isSetter ? _nullSetters : _nullMethodsAndGetters;
       if (!nullSelectors.contains(selector)) {
-        final int varIndex = _variablesInfo.varIndex[receiverNode.variable];
+        final int varIndex = _variablesInfo.varIndex[receiverNode.variable]!;
         if (_variableCells[varIndex] == null) {
           _variableValues[varIndex] =
               _makeNarrow(receiverValue, const AnyType());
@@ -1434,9 +1421,8 @@
     }
   }
 
-  Procedure _cachedUnsafeCast;
-  Procedure get unsafeCast => _cachedUnsafeCast ??= _environment.coreTypes.index
-      .getTopLevelMember('dart:_internal', 'unsafeCast');
+  late final Procedure unsafeCast = _environment.coreTypes.index
+      .getTopLevelProcedure('dart:_internal', 'unsafeCast');
 
   @override
   defaultTreeNode(TreeNode node) =>
@@ -1446,10 +1432,10 @@
   TypeExpr visitAsExpression(AsExpression node) {
     final operandNode = node.operand;
     final TypeExpr operand = _visit(operandNode);
-    final TypeExpr result = _typeCheck(operand, node.type, node);
+    final TypeCheck result = _typeCheck(operand, node.type, node);
     explicitCasts[node] = result;
     if (operandNode is VariableGet) {
-      final int varIndex = _variablesInfo.varIndex[operandNode.variable];
+      final int varIndex = _variablesInfo.varIndex[operandNode.variable]!;
       if (_variableCells[varIndex] == null) {
         _variableValues[varIndex] = result;
       }
@@ -1462,7 +1448,7 @@
     final operandNode = node.operand;
     final TypeExpr result = _makeNarrowNotNull(node, _visit(operandNode));
     if (operandNode is VariableGet) {
-      final int varIndex = _variablesInfo.varIndex[operandNode.variable];
+      final int varIndex = _variablesInfo.varIndex[operandNode.variable]!;
       if (_variableCells[varIndex] == null) {
         _variableValues[varIndex] = result;
       }
@@ -1549,20 +1535,20 @@
 
   @override
   TypeExpr visitLet(Let node) {
-    _declareVariable(node.variable, _visit(node.variable.initializer));
+    _declareVariable(node.variable, _visit(node.variable.initializer!));
     return _visit(node.body);
   }
 
   @override
   TypeExpr visitBlockExpression(BlockExpression node) {
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     return _visit(node.value);
   }
 
   @override
   TypeExpr visitListLiteral(ListLiteral node) {
     node.expressions.forEach(_visit);
-    Class concreteClass =
+    Class? concreteClass =
         target.concreteListLiteralClass(_environment.coreTypes);
     if (concreteClass != null) {
       return _translator.instantiateConcreteType(
@@ -1588,7 +1574,7 @@
       _visit(entry.key);
       _visit(entry.value);
     }
-    Class concreteClass =
+    Class? concreteClass =
         target.concreteMapLiteralClass(_environment.coreTypes);
     if (concreteClass != null) {
       return _translator.instantiateConcreteType(
@@ -1690,7 +1676,7 @@
   }
 
   TypeExpr _handlePropertyGet(
-      TreeNode node, Expression receiverNode, Member target, Name selector) {
+      TreeNode node, Expression receiverNode, Member? target, Name selector) {
     var receiver = _visit(receiverNode);
     var args = new Args<TypeExpr>([receiver]);
     TypeExpr result;
@@ -1779,8 +1765,7 @@
   @override
   TypeExpr visitSuperPropertyGet(SuperPropertyGet node) {
     assert(kPartialMixinResolution);
-    assert(_receiver != null, "Should have receiver. Node: $node");
-    final args = new Args<TypeExpr>([_receiver]);
+    final args = new Args<TypeExpr>([_receiver!]);
     // Re-resolve target due to partial mixin resolution.
     final target = _hierarchy.getDispatchTarget(_superclass, node.name);
     if (target == null) {
@@ -1794,9 +1779,8 @@
   @override
   TypeExpr visitSuperPropertySet(SuperPropertySet node) {
     assert(kPartialMixinResolution);
-    assert(_receiver != null, "Should have receiver. Node: $node");
     final value = _visit(node.value);
-    final args = new Args<TypeExpr>([_receiver, value]);
+    final args = new Args<TypeExpr>([_receiver!, value]);
     // Re-resolve target due to partial mixin resolution.
     final target =
         _hierarchy.getDispatchTarget(_superclass, node.name, setter: true);
@@ -1882,8 +1866,7 @@
 
   @override
   TypeExpr visitThisExpression(ThisExpression node) {
-    assert(_receiver != null, "Should have receiver. Node: $node");
-    return _receiver;
+    return _receiver!;
   }
 
   @override
@@ -1900,7 +1883,7 @@
 
   @override
   TypeExpr visitVariableGet(VariableGet node) {
-    final v = _variableValues[_variablesInfo.varIndex[node.variable]];
+    final v = _variableValues[_variablesInfo.varIndex[node.variable]!];
     if (v == null) {
       throw 'Unable to find variable ${node.variable} at ${node.location}';
     }
@@ -1925,56 +1908,60 @@
   }
 
   @override
-  TypeExpr visitAssertStatement(AssertStatement node) {
+  TypeExpr? visitAssertStatement(AssertStatement node) {
     if (!kRemoveAsserts) {
       _addUse(_visit(node.condition));
-      if (node.message != null) {
-        _visit(node.message);
+      final message = node.message;
+      if (message != null) {
+        _visit(message);
       }
     }
     return null;
   }
 
   @override
-  TypeExpr visitBlock(Block node) {
-    node.statements.forEach(_visit);
+  TypeExpr? visitBlock(Block node) {
+    node.statements.forEach(_visitWithoutResult);
     return null;
   }
 
   @override
-  TypeExpr visitAssertBlock(AssertBlock node) {
+  TypeExpr? visitAssertBlock(AssertBlock node) {
     if (!kRemoveAsserts) {
-      node.statements.forEach(_visit);
+      node.statements.forEach(_visitWithoutResult);
     }
     return null;
   }
 
   @override
-  TypeExpr visitBreakStatement(BreakStatement node) {
-    _variableValuesAfterLabeledStatements ??=
-        <LabeledStatement, List<TypeExpr>>{};
-    final state = _variableValuesAfterLabeledStatements[node.target];
+  TypeExpr? visitBreakStatement(BreakStatement node) {
+    var afterLabels = _variableValuesAfterLabeledStatements;
+    if (afterLabels == null) {
+      _variableValuesAfterLabeledStatements =
+          afterLabels = <LabeledStatement, List<TypeExpr?>>{};
+    }
+    final state = afterLabels[node.target];
     if (state != null) {
       _mergeVariableValues(state, _variableValues);
     } else {
-      _variableValuesAfterLabeledStatements[node.target] = _variableValues;
+      afterLabels[node.target] = _variableValues;
     }
     _variableValues = _makeEmptyVariableValues();
     return null;
   }
 
   @override
-  TypeExpr visitContinueSwitchStatement(ContinueSwitchStatement node) {
+  TypeExpr? visitContinueSwitchStatement(ContinueSwitchStatement node) {
     _mergeVariableValuesToJoins(
-        _variableValues, _joinsAtSwitchCases[node.target]);
+        _variableValues, _joinsAtSwitchCases![node.target]!);
     _variableValues = _makeEmptyVariableValues();
     return null;
   }
 
   @override
-  TypeExpr visitDoStatement(DoStatement node) {
-    final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
-    _visit(node.body);
+  TypeExpr? visitDoStatement(DoStatement node) {
+    final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
+    _visitWithoutResult(node.body);
     final trueState = _cloneVariableValues(_variableValues);
     final falseState = _cloneVariableValues(_variableValues);
     _visitCondition(node.condition, trueState, falseState);
@@ -1988,39 +1975,39 @@
   }
 
   @override
-  TypeExpr visitEmptyStatement(EmptyStatement node) => null;
+  TypeExpr? visitEmptyStatement(EmptyStatement node) => null;
 
   @override
-  TypeExpr visitExpressionStatement(ExpressionStatement node) {
+  TypeExpr? visitExpressionStatement(ExpressionStatement node) {
     _visit(node.expression);
     return null;
   }
 
   @override
-  TypeExpr visitForInStatement(ForInStatement node) {
+  TypeExpr? visitForInStatement(ForInStatement node) {
     _visit(node.iterable);
     // TODO(alexmarkov): try to infer more precise type from 'iterable'
     _declareVariableWithStaticType(node.variable);
 
-    final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
+    final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
     final stateAfterLoop = _cloneVariableValues(_variableValues);
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     _mergeVariableValuesToJoins(_variableValues, joins);
     _variableValues = stateAfterLoop;
     return null;
   }
 
   @override
-  TypeExpr visitForStatement(ForStatement node) {
+  TypeExpr? visitForStatement(ForStatement node) {
     node.variables.forEach(visitVariableDeclaration);
-    final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
+    final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
     final trueState = _cloneVariableValues(_variableValues);
     final falseState = _cloneVariableValues(_variableValues);
     if (node.condition != null) {
-      _visitCondition(node.condition, trueState, falseState);
+      _visitCondition(node.condition!, trueState, falseState);
     }
     _variableValues = trueState;
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     node.updates.forEach(_visit);
     _mergeVariableValuesToJoins(_variableValues, joins);
     // Kernel represents 'break;' as a BreakStatement referring to a
@@ -2032,7 +2019,7 @@
   }
 
   @override
-  TypeExpr visitFunctionDeclaration(FunctionDeclaration node) {
+  TypeExpr? visitFunctionDeclaration(FunctionDeclaration node) {
     // TODO(alexmarkov): support function types.
     node.variable.annotations.forEach(_visit);
     _declareVariableWithStaticType(node.variable);
@@ -2041,18 +2028,18 @@
   }
 
   @override
-  TypeExpr visitIfStatement(IfStatement node) {
+  TypeExpr? visitIfStatement(IfStatement node) {
     final trueState = _cloneVariableValues(_variableValues);
     final falseState = _cloneVariableValues(_variableValues);
     _visitCondition(node.condition, trueState, falseState);
 
     _variableValues = trueState;
-    _visit(node.then);
+    _visitWithoutResult(node.then);
     final stateAfter = _variableValues;
 
     _variableValues = falseState;
     if (node.otherwise != null) {
-      _visit(node.otherwise);
+      _visitWithoutResult(node.otherwise!);
     }
 
     _mergeVariableValues(stateAfter, _variableValues);
@@ -2061,8 +2048,8 @@
   }
 
   @override
-  TypeExpr visitLabeledStatement(LabeledStatement node) {
-    _visit(node.body);
+  TypeExpr? visitLabeledStatement(LabeledStatement node) {
+    _visitWithoutResult(node.body);
     final state = _variableValuesAfterLabeledStatements?.remove(node);
     if (state != null) {
       _mergeVariableValues(_variableValues, state);
@@ -2071,34 +2058,35 @@
   }
 
   @override
-  TypeExpr visitReturnStatement(ReturnStatement node) {
-    TypeExpr ret =
-        (node.expression != null) ? _visit(node.expression) : _nullType;
-    if (_returnValue != null) {
-      _returnValue.values.add(ret);
-    }
+  TypeExpr? visitReturnStatement(ReturnStatement node) {
+    final expression = node.expression;
+    TypeExpr ret = (expression != null) ? _visit(expression) : _nullType;
+    _returnValue?.values.add(ret);
     _variableValues = _makeEmptyVariableValues();
     return null;
   }
 
   @override
-  TypeExpr visitSwitchStatement(SwitchStatement node) {
+  TypeExpr? visitSwitchStatement(SwitchStatement node) {
     _visit(node.expression);
     // Insert joins at each case in case there are 'continue' statements.
     final stateOnEntry = _variableValues;
-    final variableValuesAtCaseEntry = <SwitchCase, List<TypeExpr>>{};
-    _joinsAtSwitchCases ??= <SwitchCase, List<Join>>{};
+    final variableValuesAtCaseEntry = <SwitchCase, List<TypeExpr?>>{};
+    Map<SwitchCase, List<Join?>>? joinsAtSwitchCases = _joinsAtSwitchCases;
+    if (joinsAtSwitchCases == null) {
+      _joinsAtSwitchCases = joinsAtSwitchCases = <SwitchCase, List<Join?>>{};
+    }
     for (var switchCase in node.cases) {
       _variableValues = _cloneVariableValues(stateOnEntry);
-      _joinsAtSwitchCases[switchCase] =
+      joinsAtSwitchCases[switchCase] =
           _insertJoinsForModifiedVariables(node, false);
       variableValuesAtCaseEntry[switchCase] = _variableValues;
     }
     bool hasDefault = false;
     for (var switchCase in node.cases) {
-      _variableValues = variableValuesAtCaseEntry[switchCase];
+      _variableValues = variableValuesAtCaseEntry[switchCase]!;
       switchCase.expressions.forEach(_visit);
-      _visit(switchCase.body);
+      _visitWithoutResult(switchCase.body);
       hasDefault = hasDefault || switchCase.isDefault;
     }
     if (!hasDefault) {
@@ -2108,21 +2096,21 @@
   }
 
   @override
-  TypeExpr visitTryCatch(TryCatch node) {
+  TypeExpr? visitTryCatch(TryCatch node) {
     final joins = _insertJoinsForModifiedVariables(node, true);
     final stateAfterTry = _cloneVariableValues(_variableValues);
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     _restoreVariableCellsAfterTry(joins);
-    List<TypeExpr> stateAfterCatch;
+    List<TypeExpr?>? stateAfterCatch;
     for (var catchClause in node.catches) {
       _variableValues = _cloneVariableValues(stateAfterTry);
       if (catchClause.exception != null) {
-        _declareVariableWithStaticType(catchClause.exception);
+        _declareVariableWithStaticType(catchClause.exception!);
       }
       if (catchClause.stackTrace != null) {
-        _declareVariableWithStaticType(catchClause.stackTrace);
+        _declareVariableWithStaticType(catchClause.stackTrace!);
       }
-      _visit(catchClause.body);
+      _visitWithoutResult(catchClause.body);
       if (stateAfterCatch == null) {
         stateAfterCatch = _variableValues;
       } else {
@@ -2130,38 +2118,39 @@
       }
     }
     _variableValues = stateAfterTry;
-    _mergeVariableValues(_variableValues, stateAfterCatch);
+    _mergeVariableValues(_variableValues, stateAfterCatch!);
     return null;
   }
 
   @override
-  TypeExpr visitTryFinally(TryFinally node) {
+  TypeExpr? visitTryFinally(TryFinally node) {
     final joins = _insertJoinsForModifiedVariables(node, true);
     final stateAfterTry = _cloneVariableValues(_variableValues);
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     _restoreVariableCellsAfterTry(joins);
     _variableValues = stateAfterTry;
-    _visit(node.finalizer);
+    _visitWithoutResult(node.finalizer);
     return null;
   }
 
   @override
-  TypeExpr visitVariableDeclaration(VariableDeclaration node) {
+  TypeExpr? visitVariableDeclaration(VariableDeclaration node) {
     node.annotations.forEach(_visit);
+    final initializer = node.initializer;
     final TypeExpr initialValue =
-        node.initializer == null ? _nullType : _visit(node.initializer);
+        initializer == null ? _nullType : _visit(initializer);
     _declareVariable(node, initialValue);
     return null;
   }
 
   @override
-  TypeExpr visitWhileStatement(WhileStatement node) {
-    final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
+  TypeExpr? visitWhileStatement(WhileStatement node) {
+    final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
     final trueState = _cloneVariableValues(_variableValues);
     final falseState = _cloneVariableValues(_variableValues);
     _visitCondition(node.condition, trueState, falseState);
     _variableValues = trueState;
-    _visit(node.body);
+    _visitWithoutResult(node.body);
     _mergeVariableValuesToJoins(_variableValues, joins);
     // Kernel represents 'break;' as a BreakStatement referring to a
     // LabeledStatement. We are therefore guaranteed to always have the
@@ -2172,15 +2161,15 @@
   }
 
   @override
-  TypeExpr visitYieldStatement(YieldStatement node) {
+  TypeExpr? visitYieldStatement(YieldStatement node) {
     _visit(node.expression);
     return null;
   }
 
   @override
-  TypeExpr visitFieldInitializer(FieldInitializer node) {
+  TypeExpr? visitFieldInitializer(FieldInitializer node) {
     final value = _visit(node.value);
-    final args = new Args<TypeExpr>([_receiver, value]);
+    final args = new Args<TypeExpr>([_receiver!, value]);
     _makeCall(
         node,
         new DirectSelector(node.field,
@@ -2190,17 +2179,17 @@
   }
 
   @override
-  TypeExpr visitRedirectingInitializer(RedirectingInitializer node) {
+  TypeExpr? visitRedirectingInitializer(RedirectingInitializer node) {
     final args = _visitArguments(_receiver, node.arguments);
     _makeCall(node, new DirectSelector(node.target), args);
     return null;
   }
 
   @override
-  TypeExpr visitSuperInitializer(SuperInitializer node) {
+  TypeExpr? visitSuperInitializer(SuperInitializer node) {
     final args = _visitArguments(_receiver, node.arguments);
 
-    Constructor target = null;
+    Constructor? target = null;
     if (kPartialMixinResolution) {
       // Re-resolve target due to partial mixin resolution.
       for (var replacement in _superclass.constructors) {
@@ -2212,27 +2201,26 @@
     } else {
       target = node.target;
     }
-    assert(target != null);
-    _makeCall(node, new DirectSelector(target), args);
+    _makeCall(node, new DirectSelector(target!), args);
     return null;
   }
 
   @override
-  TypeExpr visitLocalInitializer(LocalInitializer node) {
+  TypeExpr? visitLocalInitializer(LocalInitializer node) {
     visitVariableDeclaration(node.variable);
     return null;
   }
 
   @override
-  TypeExpr visitAssertInitializer(AssertInitializer node) {
+  TypeExpr? visitAssertInitializer(AssertInitializer node) {
     if (!kRemoveAsserts) {
-      _visit(node.statement);
+      _visitWithoutResult(node.statement);
     }
     return null;
   }
 
   @override
-  TypeExpr visitInvalidInitializer(InvalidInitializer node) {
+  TypeExpr? visitInvalidInitializer(InvalidInitializer node) {
     return null;
   }
 
@@ -2244,21 +2232,21 @@
 
 class RuntimeTypeTranslatorImpl extends DartTypeVisitor<TypeExpr>
     implements RuntimeTypeTranslator {
-  final Summary summary;
-  final Map<TypeParameter, TypeExpr> functionTypeVariables;
+  final CoreTypes coreTypes;
+  final Summary? summary;
+  final Map<TypeParameter, TypeExpr>? functionTypeVariables;
   final Map<DartType, TypeExpr> typesCache = <DartType, TypeExpr>{};
-  final TypeExpr receiver;
+  final TypeExpr? receiver;
   final GenericInterfacesInfo genericInterfacesInfo;
-  final SummaryCollector summaryCollector;
 
-  RuntimeTypeTranslatorImpl(this.summaryCollector, this.summary, this.receiver,
+  RuntimeTypeTranslatorImpl(this.coreTypes, this.summary, this.receiver,
       this.functionTypeVariables, this.genericInterfacesInfo) {}
 
   // Create a type translator which can be used only for types with no free type
   // variables.
-  RuntimeTypeTranslatorImpl.forClosedTypes(this.genericInterfacesInfo)
-      : summaryCollector = null,
-        summary = null,
+  RuntimeTypeTranslatorImpl.forClosedTypes(
+      this.coreTypes, this.genericInterfacesInfo)
+      : summary = null,
         functionTypeVariables = null,
         receiver = null {}
 
@@ -2271,8 +2259,7 @@
     final substitution = Substitution.fromPairs(klass.typeParameters, typeArgs);
     final flattenedTypeArgs =
         genericInterfacesInfo.flattenedTypeArgumentsFor(klass);
-    final flattenedTypeExprs =
-        new List<TypeExpr>.filled(flattenedTypeArgs.length, null);
+    final flattenedTypeExprs = <TypeExpr>[];
 
     bool createConcreteType = true;
     bool allUnknown = true;
@@ -2281,7 +2268,7 @@
           translate(substitution.substituteType(flattenedTypeArgs[i]));
       if (typeExpr is! UnknownType) allUnknown = false;
       if (typeExpr is Statement) createConcreteType = false;
-      flattenedTypeExprs[i] = typeExpr;
+      flattenedTypeExprs.add(typeExpr);
     }
 
     if (allUnknown) return type;
@@ -2291,7 +2278,7 @@
           type.cls, new List<Type>.from(flattenedTypeExprs));
     } else {
       final instantiate = new CreateConcreteType(type.cls, flattenedTypeExprs);
-      summary.add(instantiate);
+      summary!.add(instantiate);
       return instantiate;
     }
   }
@@ -2341,8 +2328,7 @@
         type.classNode.typeParameters, type.typeArguments);
     final flattenedTypeArgs =
         genericInterfacesInfo.flattenedTypeArgumentsFor(type.classNode);
-    final flattenedTypeExprs =
-        new List<TypeExpr>.filled(flattenedTypeArgs.length, null);
+    final flattenedTypeExprs = <TypeExpr>[];
 
     bool createRuntimeType = true;
     for (var i = 0; i < flattenedTypeArgs.length; ++i) {
@@ -2350,7 +2336,7 @@
           translate(substitution.substituteType(flattenedTypeArgs[i]));
       if (typeExpr == const UnknownType()) return const UnknownType();
       if (typeExpr is! RuntimeType) createRuntimeType = false;
-      flattenedTypeExprs[i] = typeExpr;
+      flattenedTypeExprs.add(typeExpr);
     }
 
     if (createRuntimeType) {
@@ -2360,7 +2346,7 @@
     } else {
       final instantiate = new CreateRuntimeType(
           type.classNode, type.nullability, flattenedTypeExprs);
-      summary.add(instantiate);
+      summary!.add(instantiate);
       return instantiate;
     }
   }
@@ -2375,32 +2361,32 @@
           <RuntimeType>[typeArg]);
     } else {
       final instantiate = new CreateRuntimeType(
-          summaryCollector._environment.coreTypes.deprecatedFutureOrClass,
+          coreTypes.deprecatedFutureOrClass,
           type.nullability,
           <TypeExpr>[typeArg]);
-      summary.add(instantiate);
+      summary!.add(instantiate);
       return instantiate;
     }
   }
 
   @override
   visitTypeParameterType(TypeParameterType type) {
+    final functionTypeVariables = this.functionTypeVariables;
     if (functionTypeVariables != null) {
       final result = functionTypeVariables[type.parameter];
       if (result != null) return result;
     }
     if (type.parameter.parent is! Class) return const UnknownType();
     final interfaceClass = type.parameter.parent as Class;
-    assert(receiver != null);
     // Undetermined nullability is equivalent to nonNullable when
     // instantiating type parameter, so convert it right away.
     Nullability nullability = type.nullability;
     if (nullability == Nullability.undetermined) {
       nullability = Nullability.nonNullable;
     }
-    final extract = new Extract(receiver, interfaceClass,
+    final extract = new Extract(receiver!, interfaceClass,
         interfaceClass.typeParameters.indexOf(type.parameter), nullability);
-    summary.add(extract);
+    summary!.add(extract);
     return extract;
   }
 }
@@ -2420,7 +2406,7 @@
 
   Type _getStaticType(Constant constant) =>
       summaryCollector._typesBuilder.fromStaticType(
-          constant.getType(summaryCollector._staticTypeContext), false);
+          constant.getType(summaryCollector._staticTypeContext!), false);
 
   @override
   defaultConstant(Constant constant) {
@@ -2467,7 +2453,7 @@
     for (final Constant entry in constant.entries) {
       typeFor(entry);
     }
-    final Class concreteClass = summaryCollector.target
+    final Class? concreteClass = summaryCollector.target
         .concreteConstListLiteralClass(summaryCollector._environment.coreTypes);
     if (concreteClass != null) {
       return new ConcreteType(
diff --git a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
index f1901e7..0080748 100644
--- a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
+++ b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.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.9
-
 import 'package:kernel/ast.dart';
 
 import 'utils.dart' show UnionFind;
@@ -18,7 +16,7 @@
   final Map<Class, Map<Name, int>> _methodOrSetterMemberIds = {};
 
   final UnionFind _unionFind = UnionFind();
-  List<int> _selectorIdForMemberId;
+  late List<int?> _selectorIdForMemberId;
 
   TableSelectorAssigner(Component component) {
     for (Library library in component.libraries) {
@@ -44,20 +42,21 @@
     }
   }
 
-  Map<Name, int> _memberIdsForClass(Class cls, {bool getter}) {
+  Map<Name, int> _memberIdsForClass(Class? cls, {required bool getter}) {
     if (cls == null) return {};
 
     final cache = getter ? _getterMemberIds : _methodOrSetterMemberIds;
 
     // Already computed for this class?
-    Map<Name, int> memberIds = cache[cls];
-    if (memberIds != null) return memberIds;
+    final cachedMemberIds = cache[cls];
+    if (cachedMemberIds != null) return cachedMemberIds;
 
     // Merge maps from supertypes.
-    memberIds = Map.from(_memberIdsForClass(cls.superclass, getter: getter));
+    final memberIds =
+        Map<Name, int>.from(_memberIdsForClass(cls.superclass, getter: getter));
     for (Supertype impl in cls.implementedTypes) {
       _memberIdsForClass(impl.classNode, getter: getter).forEach((name, id) {
-        final int firstId = memberIds[name];
+        final int? firstId = memberIds[name];
         if (firstId == null) {
           memberIds[name] = id;
         } else if (firstId != id) {
@@ -99,9 +98,9 @@
     return cache[cls] = memberIds;
   }
 
-  int _selectorIdForMember(Member member, {bool getter}) {
+  int _selectorIdForMember(Member member, {required bool getter}) {
     final map = getter ? _getterMemberIds : _methodOrSetterMemberIds;
-    int memberId = map[member.enclosingClass][member.name];
+    int? memberId = map[member.enclosingClass!]![member.name];
     if (memberId == null) {
       assert(member is Procedure &&
               ((identical(map, _getterMemberIds) &&
@@ -115,7 +114,7 @@
       return ProcedureAttributesMetadata.kInvalidSelectorId;
     }
     memberId = _unionFind.find(memberId);
-    int selectorId = _selectorIdForMemberId[memberId];
+    int? selectorId = _selectorIdForMemberId[memberId];
     if (selectorId == null) {
       _selectorIdForMemberId[memberId] = selectorId = metadata.addSelector();
     }
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index feb185d..82bebec 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -2,10 +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.9
-
 /// Transformations based on type flow analysis.
-library vm.transformations.type_flow.transformer;
 
 import 'dart:core' hide Type;
 
@@ -14,7 +11,8 @@
 import 'package:kernel/ast.dart' as ast show Statement;
 import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
 import 'package:kernel/core_types.dart' show CoreTypes;
-import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+import 'package:kernel/class_hierarchy.dart'
+    show ClassHierarchy, ClosedWorldClassHierarchy;
 import 'package:kernel/library_index.dart' show LibraryIndex;
 import 'package:kernel/type_environment.dart';
 
@@ -43,16 +41,18 @@
 /// Assumes strong mode and closed world.
 Component transformComponent(
     Target target, CoreTypes coreTypes, Component component,
-    {PragmaAnnotationParser matcher,
+    {PragmaAnnotationParser? matcher,
     bool treeShakeSignatures: true,
     bool treeShakeWriteOnlyFields: true,
     bool treeShakeProtobufs: false}) {
   void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
   final hierarchy = new ClassHierarchy(component, coreTypes,
-      onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
+          onAmbiguousSupertypes: ignoreAmbiguousSupertypes)
+      as ClosedWorldClassHierarchy;
   final types = new TypeEnvironment(coreTypes, hierarchy);
   final libraryIndex = new LibraryIndex.all(component);
-  final genericInterfacesInfo = new GenericInterfacesInfoImpl(hierarchy);
+  final genericInterfacesInfo =
+      new GenericInterfacesInfoImpl(coreTypes, hierarchy);
   final protobufHandler = treeShakeProtobufs
       ? ProtobufHandler.forComponent(component, coreTypes)
       : null;
@@ -73,7 +73,7 @@
       protobufHandler,
       matcher);
 
-  Procedure main = component.mainMethod;
+  Procedure? main = component.mainMethod;
 
   // `main` can be null, roots can also come from @pragma("vm:entry-point").
   if (main != null) {
@@ -149,7 +149,7 @@
         if (!f.isStatic &&
             !f.isLate &&
             f.initializer != null &&
-            mayHaveSideEffects(f.initializer))
+            mayHaveSideEffects(f.initializer!))
           f
     ];
     if (fields.isEmpty) return;
@@ -173,7 +173,7 @@
       };
       final List<Initializer> newInitializers = [];
       for (Field f in fields) {
-        Expression initExpr = f.initializer;
+        Expression initExpr = f.initializer!;
         if (!isFirst) {
           initExpr = CloneVisitorNotMembers().clone(initExpr);
         }
@@ -204,7 +204,7 @@
 class CleanupAnnotations extends RecursiveVisitor {
   final Class externalNameClass;
   final Class pragmaClass;
-  final ProtobufHandler protobufHandler;
+  final ProtobufHandler? protobufHandler;
 
   CleanupAnnotations(
       CoreTypes coreTypes, LibraryIndex index, this.protobufHandler)
@@ -238,7 +238,7 @@
         return (cls == externalNameClass) ||
             (cls == pragmaClass) ||
             (protobufHandler != null &&
-                protobufHandler.usesAnnotationClass(cls));
+                protobufHandler!.usesAnnotationClass(cls));
       }
     }
     return false;
@@ -255,11 +255,11 @@
       : super(_typeFlowAnalysis.environment.coreTypes, component, hierarchy);
 
   @override
-  DirectCallMetadata getDirectCall(TreeNode node, Member interfaceTarget,
+  DirectCallMetadata? getDirectCall(TreeNode node, Member? interfaceTarget,
       {bool setter = false}) {
     final callSite = _typeFlowAnalysis.callSite(node);
     if (callSite != null) {
-      final Member singleTarget = fieldMorpher
+      final Member? singleTarget = fieldMorpher
           .getMorphedMember(callSite.monomorphicTarget, isSetter: setter);
       if (singleTarget != null) {
         return new DirectCallMetadata(
@@ -283,12 +283,13 @@
   final UnboxingInfoMetadataRepository _unboxingInfoMetadata;
   final UnboxingInfoManager _unboxingInfo;
   final Class _intClass;
-  Constant _nullConstant;
+  late final Constant _nullConstant = NullConstant();
 
   AnnotateKernel(Component component, this._typeFlowAnalysis, this.fieldMorpher,
       this._tableSelectorAssigner, this._unboxingInfo)
       : _directCallMetadataRepository =
-            component.metadata[DirectCallMetadataRepository.repositoryTag],
+            component.metadata[DirectCallMetadataRepository.repositoryTag]
+                as DirectCallMetadataRepository,
         _inferredTypeMetadata = new InferredTypeMetadataRepository(),
         _unreachableNodeMetadata = new UnreachableNodeMetadataRepository(),
         _procedureAttributesMetadata =
@@ -308,12 +309,10 @@
     return _directCallMetadataRepository.mapping.containsKey(node);
   }
 
-  InferredType _convertType(Type type,
+  InferredType? _convertType(Type type,
       {bool skipCheck: false, bool receiverNotInt: false}) {
-    assert(type != null);
-
-    Class concreteClass;
-    Constant constantValue;
+    Class? concreteClass;
+    Constant? constantValue;
     bool isInt = false;
 
     final nullable = type is NullableType;
@@ -324,7 +323,7 @@
     if (nullable && type == const EmptyType()) {
       concreteClass =
           _typeFlowAnalysis.environment.coreTypes.deprecatedNullClass;
-      constantValue = _nullConstant ??= new NullConstant();
+      constantValue = _nullConstant;
     } else {
       concreteClass = type.getConcreteClass(_typeFlowAnalysis.hierarchyCache);
 
@@ -337,9 +336,9 @@
       }
     }
 
-    List<DartType> typeArgs;
+    List<DartType?>? typeArgs;
     if (type is ConcreteType && type.typeArgs != null) {
-      typeArgs = type.typeArgs
+      typeArgs = type.typeArgs!
           .take(type.numImmediateTypeArgs)
           .map((t) =>
               t is UnknownType ? null : (t as RuntimeType).representedType)
@@ -374,7 +373,7 @@
     _unreachableNodeMetadata.mapping[node] = const UnreachableNode();
   }
 
-  void _annotateCallSite(TreeNode node, Member interfaceTarget) {
+  void _annotateCallSite(TreeNode node, Member? interfaceTarget) {
     final callSite = _typeFlowAnalysis.callSite(node);
     if (callSite == null) return;
     if (!callSite.isReachable) {
@@ -405,7 +404,7 @@
         if (interfaceTarget == null ||
             _typeFlowAnalysis.hierarchyCache.hierarchy.isSubtypeOf(
                 _typeFlowAnalysis.hierarchyCache.coreTypes.intClass,
-                interfaceTarget.enclosingClass)) {
+                interfaceTarget.enclosingClass!)) {
           markReceiverNotInt = true;
         }
       }
@@ -446,35 +445,33 @@
   void _annotateMember(Member member) {
     if (_typeFlowAnalysis.isMemberUsed(member)) {
       if (member is Field) {
-        _setInferredType(member, _typeFlowAnalysis.fieldType(member));
+        _setInferredType(member, _typeFlowAnalysis.fieldType(member)!);
       } else {
-        Args<Type> argTypes = _typeFlowAnalysis.argumentTypes(member);
+        Args<Type> argTypes = _typeFlowAnalysis.argumentTypes(member)!;
         final uncheckedParameters =
             _typeFlowAnalysis.uncheckedParameters(member);
-        assert(argTypes != null);
 
         final int firstParamIndex =
             numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
 
-        final positionalParams = member.function.positionalParameters;
+        final positionalParams = member.function!.positionalParameters;
         assert(argTypes.positionalCount ==
             firstParamIndex + positionalParams.length);
 
         for (int i = 0; i < positionalParams.length; i++) {
           _setInferredType(
               positionalParams[i], argTypes.values[firstParamIndex + i],
-              skipCheck: uncheckedParameters.contains(positionalParams[i]));
+              skipCheck: uncheckedParameters!.contains(positionalParams[i]));
         }
 
         // TODO(dartbug.com/32292): make sure parameters are sorted in kernel
         // AST and iterate parameters in parallel, without lookup.
         final names = argTypes.names;
         for (int i = 0; i < names.length; i++) {
-          final param = findNamedParameter(member.function, names[i]);
-          assert(param != null);
+          final param = findNamedParameter(member.function!, names[i])!;
           _setInferredType(param,
               argTypes.values[firstParamIndex + positionalParams.length + i],
-              skipCheck: uncheckedParameters.contains(param));
+              skipCheck: uncheckedParameters!.contains(param));
         }
 
         // TODO(alexmarkov): figure out how to pass receiver type.
@@ -521,7 +518,7 @@
     // interface target, and table dispatch calls need selector IDs for all
     // interface targets.
     if (member.isInstanceMember) {
-      final original = fieldMorpher.getOriginalMember(member);
+      final original = fieldMorpher.getOriginalMember(member)!;
       final attrs = new ProcedureAttributesMetadata(
           methodOrSetterCalledDynamically:
               _typeFlowAnalysis.isCalledDynamically(original),
@@ -689,11 +686,11 @@
   final Set<Member> _usedMembers = new Set<Member>();
   final Set<Extension> _usedExtensions = new Set<Extension>();
   final Set<Typedef> _usedTypedefs = new Set<Typedef>();
-  FieldMorpher fieldMorpher;
-  _TreeShakerTypeVisitor typeVisitor;
-  _TreeShakerConstantVisitor constantVisitor;
-  _TreeShakerPass1 _pass1;
-  _TreeShakerPass2 _pass2;
+  late final FieldMorpher fieldMorpher;
+  late final _TreeShakerTypeVisitor typeVisitor;
+  late final _TreeShakerConstantVisitor constantVisitor;
+  late final _TreeShakerPass1 _pass1;
+  late final _TreeShakerPass2 _pass2;
 
   TreeShaker(Component component, this.typeFlowAnalysis,
       {this.treeShakeWriteOnlyFields: true}) {
@@ -734,7 +731,7 @@
               (!f.isStatic &&
                   f.initializer != null &&
                   isFieldInitializerReachable(f) &&
-                  mayHaveSideEffects(f.initializer)) ||
+                  mayHaveSideEffects(f.initializer!)) ||
               (f.isLate && f.isFinal)) ||
       isMemberReferencedFromNativeCode(f) ||
       _isInstanceFieldOfAllocatedEnum(f);
@@ -745,8 +742,8 @@
   bool _isInstanceFieldOfAllocatedEnum(Field node) =>
       !node.isStatic &&
       node.enclosingClass != null &&
-      node.enclosingClass.isEnum &&
-      isClassAllocated(node.enclosingClass);
+      node.enclosingClass!.isEnum &&
+      isClassAllocated(node.enclosingClass!);
 
   void addClassUsedInType(Class c) {
     if (_classesUsedInType.add(c)) {
@@ -777,7 +774,7 @@
         _usedClasses.add(enclosingClass);
       }
 
-      FunctionNode func = null;
+      FunctionNode? func = null;
       if (m is Field) {
         m.type.accept(typeVisitor);
       } else if (m is Procedure) {
@@ -786,19 +783,19 @@
           m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
               m.concreteForwardingStubTarget,
               isSetter: m.isSetter);
-          addUsedMember(m.concreteForwardingStubTarget);
+          addUsedMember(m.concreteForwardingStubTarget!);
         }
         if (m.abstractForwardingStubTarget != null) {
           m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
               m.abstractForwardingStubTarget,
               isSetter: m.isSetter);
-          addUsedMember(m.abstractForwardingStubTarget);
+          addUsedMember(m.abstractForwardingStubTarget!);
         }
         if (m.memberSignatureOrigin != null) {
           m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
               m.memberSignatureOrigin,
               isSetter: m.isSetter);
-          addUsedMember(m.memberSignatureOrigin);
+          addUsedMember(m.memberSignatureOrigin!);
         }
       } else if (m is Constructor) {
         func = m.function;
@@ -821,8 +818,7 @@
         final extension = m.enclosingLibrary.extensions.firstWhere((extension) {
           return extension.members
               .any((descriptor) => descriptor.member.asMember == m);
-        }, orElse: () => null);
-        assert(extension != null);
+        });
 
         // Ensure we retain the [Extension] itself (though members might be
         // shaken)
@@ -844,7 +840,7 @@
     if (_usedExtensions.add(node)) {
       node.annotations = const <Expression>[];
       _pass1.transformTypeParameterList(node.typeParameters, node);
-      node.onType?.accept(typeVisitor);
+      node.onType.accept(typeVisitor);
     }
   }
 
@@ -898,7 +894,7 @@
           isAbstract: true, fileUri: field.fileUri);
     }
     accessor.fileOffset = field.fileOffset;
-    field.enclosingClass.addProcedure(accessor);
+    field.enclosingClass!.addProcedure(accessor);
     _removedFields[accessor] = field;
     shaker.addUsedMember(accessor);
     return accessor;
@@ -908,7 +904,7 @@
   /// If necessary, creates a getter or setter as a replacement if target is a
   /// field which is going to be removed by the tree shaker.
   /// This method is used during tree shaker pass 1.
-  Member adjustInstanceCallTarget(Member target, {bool isSetter = false}) {
+  Member? adjustInstanceCallTarget(Member? target, {bool isSetter = false}) {
     if (target is Field && !shaker.retainField(target)) {
       final targets =
           isSetter ? _settersForRemovedFields : _gettersForRemovedFields;
@@ -923,9 +919,9 @@
 
   /// Return a member which replaced [target] in instance calls.
   /// This method can be used after tree shaking to discover replacement.
-  Member getMorphedMember(Member target, {bool isSetter = false}) {
-    if (target == null) {
-      return null;
+  Member? getMorphedMember(Member? target, {bool isSetter = false}) {
+    if (target is! Field) {
+      return target;
     }
     final targets =
         isSetter ? _settersForRemovedFields : _gettersForRemovedFields;
@@ -934,7 +930,7 @@
 
   /// Return original member which was replaced by [target] in instance calls.
   /// This method can be used after tree shaking.
-  Member getOriginalMember(Member target) {
+  Member? getOriginalMember(Member? target) {
     if (target == null) {
       return null;
     }
@@ -994,16 +990,15 @@
   final TreeShaker shaker;
   final FieldMorpher fieldMorpher;
   final TypeEnvironment environment;
-  Procedure _unsafeCast;
 
-  StaticTypeContext _staticTypeContext;
-  Member _currentMember;
+  StaticTypeContext? _staticTypeContext;
+  Member? _currentMember;
 
   StaticTypeContext get staticTypeContext =>
       _staticTypeContext ??= StaticTypeContext(currentMember, environment);
 
-  Member get currentMember => _currentMember;
-  set currentMember(Member m) {
+  Member get currentMember => _currentMember!;
+  set currentMember(Member? m) {
     _currentMember = m;
     _staticTypeContext = null;
   }
@@ -1022,7 +1017,7 @@
   }
 
   List<Expression> _flattenArguments(Arguments arguments,
-      {Expression receiver}) {
+      {Expression? receiver}) {
     final args = <Expression>[];
     if (receiver != null) {
       args.add(receiver);
@@ -1035,9 +1030,9 @@
   bool _isThrowExpression(Expression expr) {
     for (;;) {
       if (expr is Let) {
-        expr = (expr as Let).body;
+        expr = expr.body;
       } else if (expr is BlockExpression) {
-        expr = (expr as BlockExpression).value;
+        expr = expr.value;
       } else {
         break;
       }
@@ -1068,7 +1063,7 @@
     return BlockExpression(Block(statements), value);
   }
 
-  TreeNode _makeUnreachableCall(List<Expression> args) {
+  Expression _makeUnreachableCall(List<Expression> args) {
     Expression node;
     final int last = args.indexWhere(_isThrowExpression);
     if (last >= 0) {
@@ -1090,12 +1085,12 @@
         new VariableDeclaration(null, initializer: _makeUnreachableCall(args)));
   }
 
-  NarrowNotNull _getNullTest(TreeNode node) =>
+  NarrowNotNull? _getNullTest(TreeNode node) =>
       shaker.typeFlowAnalysis.nullTest(node);
 
-  TreeNode _visitAssertNode(TreeNode node, TreeNode removalSentinel) {
+  TreeNode _visitAssertNode(TreeNode node, TreeNode? removalSentinel) {
     if (kRemoveAsserts) {
-      return removalSentinel;
+      return removalSentinel!;
     } else {
       node.transformOrRemoveChildren(this);
       return node;
@@ -1103,31 +1098,31 @@
   }
 
   @override
-  DartType visitDartType(DartType node, DartType removalSentinel) {
+  DartType visitDartType(DartType node, DartType? removalSentinel) {
     node.accept(shaker.typeVisitor);
     return node;
   }
 
   @override
-  Supertype visitSupertype(Supertype node, Supertype removalSentinel) {
+  Supertype visitSupertype(Supertype node, Supertype? removalSentinel) {
     node.accept(shaker.typeVisitor);
     return node;
   }
 
   @override
-  TreeNode visitTypedef(Typedef node, TreeNode removalSentinel) {
+  TreeNode visitTypedef(Typedef node, TreeNode? removalSentinel) {
     return node; // Do not go deeper.
   }
 
   @override
-  Extension visitExtension(Extension node, TreeNode removalSentinel) {
+  TreeNode visitExtension(Extension node, TreeNode? removalSentinel) {
     // The extension can be considered a weak node, we'll only retain it if
     // normal code references any of it's members.
     return node;
   }
 
   @override
-  TreeNode visitClass(Class node, TreeNode removalSentinel) {
+  TreeNode visitClass(Class node, TreeNode? removalSentinel) {
     if (shaker.isClassAllocated(node) ||
         shaker.isClassReferencedFromNativeCode(node)) {
       shaker.addClassUsedInType(node);
@@ -1140,7 +1135,7 @@
   }
 
   @override
-  TreeNode defaultMember(Member node, TreeNode removalSentinel) {
+  TreeNode defaultMember(Member node, TreeNode? removalSentinel) {
     currentMember = node;
     if (shaker.isMemberBodyReachable(node)) {
       if (kPrintTrace) {
@@ -1160,7 +1155,7 @@
   }
 
   @override
-  TreeNode visitField(Field node, TreeNode removalSentinel) {
+  TreeNode visitField(Field node, TreeNode? removalSentinel) {
     currentMember = node;
     if (shaker.retainField(node)) {
       if (kPrintTrace) {
@@ -1185,21 +1180,21 @@
 
   @override
   TreeNode visitInstanceInvocation(
-      InstanceInvocation node, TreeNode removalSentinel) {
+      InstanceInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(
           _flattenArguments(node.arguments, receiver: node.receiver));
     }
-    node.interfaceTarget =
-        fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+    node.interfaceTarget = fieldMorpher
+        .adjustInstanceCallTarget(node.interfaceTarget) as Procedure;
     shaker.addUsedMember(node.interfaceTarget);
     return node;
   }
 
   @override
   TreeNode visitDynamicInvocation(
-      DynamicInvocation node, TreeNode removalSentinel) {
+      DynamicInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(
@@ -1210,7 +1205,7 @@
 
   @override
   TreeNode visitLocalFunctionInvocation(
-      LocalFunctionInvocation node, TreeNode removalSentinel) {
+      LocalFunctionInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(_flattenArguments(node.arguments));
@@ -1220,7 +1215,7 @@
 
   @override
   TreeNode visitFunctionInvocation(
-      FunctionInvocation node, TreeNode removalSentinel) {
+      FunctionInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(
@@ -1230,24 +1225,24 @@
   }
 
   @override
-  TreeNode visitEqualsCall(EqualsCall node, TreeNode removalSentinel) {
+  TreeNode visitEqualsCall(EqualsCall node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.left, node.right]);
     }
-    node.interfaceTarget =
-        fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+    node.interfaceTarget = fieldMorpher
+        .adjustInstanceCallTarget(node.interfaceTarget) as Procedure;
     shaker.addUsedMember(node.interfaceTarget);
     return node;
   }
 
   @override
-  TreeNode visitEqualsNull(EqualsNull node, TreeNode removalSentinel) {
+  TreeNode visitEqualsNull(EqualsNull node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.expression]);
     }
-    final nullTest = _getNullTest(node);
+    final nullTest = _getNullTest(node)!;
     if (nullTest.isAlwaysNull || nullTest.isAlwaysNotNull) {
       return _evaluateArguments([node.expression],
           BoolLiteral(nullTest.isAlwaysNull)..fileOffset = node.fileOffset);
@@ -1256,13 +1251,13 @@
   }
 
   @override
-  TreeNode visitInstanceGet(InstanceGet node, TreeNode removalSentinel) {
+  TreeNode visitInstanceGet(InstanceGet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver]);
     } else {
       node.interfaceTarget =
-          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget)!;
       shaker.addUsedMember(node.interfaceTarget);
       return node;
     }
@@ -1270,20 +1265,20 @@
 
   @override
   TreeNode visitInstanceTearOff(
-      InstanceTearOff node, TreeNode removalSentinel) {
+      InstanceTearOff node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver]);
     } else {
-      node.interfaceTarget =
-          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+      node.interfaceTarget = fieldMorpher
+          .adjustInstanceCallTarget(node.interfaceTarget) as Procedure;
       shaker.addUsedMember(node.interfaceTarget);
       return node;
     }
   }
 
   @override
-  TreeNode visitDynamicGet(DynamicGet node, TreeNode removalSentinel) {
+  TreeNode visitDynamicGet(DynamicGet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver]);
@@ -1294,7 +1289,7 @@
 
   @override
   TreeNode visitFunctionTearOff(
-      FunctionTearOff node, TreeNode removalSentinel) {
+      FunctionTearOff node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver]);
@@ -1304,20 +1299,20 @@
   }
 
   @override
-  TreeNode visitInstanceSet(InstanceSet node, TreeNode removalSentinel) {
+  TreeNode visitInstanceSet(InstanceSet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver, node.value]);
     } else {
       node.interfaceTarget = fieldMorpher
-          .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true);
+          .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true)!;
       shaker.addUsedMember(node.interfaceTarget);
       return node;
     }
   }
 
   @override
-  TreeNode visitDynamicSet(DynamicSet node, TreeNode removalSentinel) {
+  TreeNode visitDynamicSet(DynamicSet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.receiver, node.value]);
@@ -1328,15 +1323,15 @@
 
   @override
   TreeNode visitSuperMethodInvocation(
-      SuperMethodInvocation node, TreeNode removalSentinel) {
+      SuperMethodInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(_flattenArguments(node.arguments));
     } else {
-      node.interfaceTarget =
-          fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+      node.interfaceTarget = fieldMorpher
+          .adjustInstanceCallTarget(node.interfaceTarget) as Procedure?;
       if (node.interfaceTarget != null) {
-        shaker.addUsedMember(node.interfaceTarget);
+        shaker.addUsedMember(node.interfaceTarget!);
       }
       return node;
     }
@@ -1344,7 +1339,7 @@
 
   @override
   TreeNode visitSuperPropertyGet(
-      SuperPropertyGet node, TreeNode removalSentinel) {
+      SuperPropertyGet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([]);
@@ -1352,7 +1347,7 @@
       node.interfaceTarget =
           fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
       if (node.interfaceTarget != null) {
-        shaker.addUsedMember(node.interfaceTarget);
+        shaker.addUsedMember(node.interfaceTarget!);
       }
       return node;
     }
@@ -1360,7 +1355,7 @@
 
   @override
   TreeNode visitSuperPropertySet(
-      SuperPropertySet node, TreeNode removalSentinel) {
+      SuperPropertySet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.value]);
@@ -1368,7 +1363,7 @@
       node.interfaceTarget = fieldMorpher
           .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true);
       if (node.interfaceTarget != null) {
-        shaker.addUsedMember(node.interfaceTarget);
+        shaker.addUsedMember(node.interfaceTarget!);
       }
       return node;
     }
@@ -1376,7 +1371,7 @@
 
   @override
   TreeNode visitStaticInvocation(
-      StaticInvocation node, TreeNode removalSentinel) {
+      StaticInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(_flattenArguments(node.arguments));
@@ -1390,7 +1385,7 @@
   }
 
   @override
-  TreeNode visitStaticGet(StaticGet node, TreeNode removalSentinel) {
+  TreeNode visitStaticGet(StaticGet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([]);
@@ -1405,13 +1400,13 @@
   }
 
   @override
-  Constant visitConstant(Constant node, Constant removalSentinel) {
+  Constant visitConstant(Constant node, Constant? removalSentinel) {
     shaker.constantVisitor.analyzeConstant(node);
     return node;
   }
 
   @override
-  TreeNode visitStaticSet(StaticSet node, TreeNode removalSentinel) {
+  TreeNode visitStaticSet(StaticSet node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall([node.value]);
@@ -1428,7 +1423,7 @@
 
   @override
   TreeNode visitConstructorInvocation(
-      ConstructorInvocation node, TreeNode removalSentinel) {
+      ConstructorInvocation node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(_flattenArguments(node.arguments));
@@ -1444,7 +1439,7 @@
 
   @override
   TreeNode visitRedirectingInitializer(
-      RedirectingInitializer node, TreeNode removalSentinel) {
+      RedirectingInitializer node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableInitializer(_flattenArguments(node.arguments));
@@ -1457,7 +1452,7 @@
 
   @override
   TreeNode visitSuperInitializer(
-      SuperInitializer node, TreeNode removalSentinel) {
+      SuperInitializer node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableInitializer(_flattenArguments(node.arguments));
@@ -1469,7 +1464,7 @@
 
   @override
   TreeNode visitFieldInitializer(
-      FieldInitializer node, TreeNode removalSentinel) {
+      FieldInitializer node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableInitializer([node.value]);
@@ -1482,7 +1477,7 @@
           return LocalInitializer(
               VariableDeclaration(null, initializer: node.value));
         } else {
-          return removalSentinel;
+          return removalSentinel!;
         }
       }
       return node;
@@ -1491,18 +1486,18 @@
 
   @override
   TreeNode visitAssertStatement(
-      AssertStatement node, TreeNode removalSentinel) {
+      AssertStatement node, TreeNode? removalSentinel) {
     return _visitAssertNode(node, removalSentinel);
   }
 
   @override
-  TreeNode visitAssertBlock(AssertBlock node, TreeNode removalSentinel) {
+  TreeNode visitAssertBlock(AssertBlock node, TreeNode? removalSentinel) {
     return _visitAssertNode(node, removalSentinel);
   }
 
   @override
   TreeNode visitAssertInitializer(
-      AssertInitializer node, TreeNode removalSentinel) {
+      AssertInitializer node, TreeNode? removalSentinel) {
     return _visitAssertNode(node, removalSentinel);
   }
 
@@ -1520,21 +1515,21 @@
 
   // Returns Block corresponding to the given extended bool literal,
   // or null if the expression is a simple bool literal.
-  Block _getExtendedBoolLiteralBlock(Expression expr) =>
+  Block? _getExtendedBoolLiteralBlock(Expression expr) =>
       (expr is BoolLiteral) ? null : (expr as BlockExpression).body;
 
   @override
-  TreeNode visitIfStatement(IfStatement node, TreeNode removalSentinel) {
+  TreeNode visitIfStatement(IfStatement node, TreeNode? removalSentinel) {
     final condition = transform(node.condition);
     if (_isExtendedBoolLiteral(condition)) {
       final bool conditionValue = _getExtendedBoolLiteralValue(condition);
-      final Block conditionBlock = _getExtendedBoolLiteralBlock(condition);
-      ast.Statement body;
+      final Block? conditionBlock = _getExtendedBoolLiteralBlock(condition);
+      ast.Statement? body;
       if (conditionValue) {
         body = transform(node.then);
       } else {
         if (node.otherwise != null) {
-          body = transformOrRemoveStatement(node.otherwise);
+          body = transformOrRemoveStatement(node.otherwise!);
         }
       }
       if (conditionBlock != null) {
@@ -1549,7 +1544,7 @@
     node.condition = condition..parent = node;
     node.then = transform(node.then)..parent = node;
     if (node.otherwise != null) {
-      node.otherwise = transformOrRemoveStatement(node.otherwise);
+      node.otherwise = transformOrRemoveStatement(node.otherwise!);
       node.otherwise?.parent = node;
     }
     return node;
@@ -1557,7 +1552,7 @@
 
   @override
   visitConditionalExpression(
-      ConditionalExpression node, TreeNode removalSentinel) {
+      ConditionalExpression node, TreeNode? removalSentinel) {
     final condition = transform(node.condition);
     if (_isExtendedBoolLiteral(condition)) {
       final bool value = _getExtendedBoolLiteralValue(condition);
@@ -1578,7 +1573,7 @@
   }
 
   @override
-  TreeNode visitNot(Not node, TreeNode removalSentinel) {
+  TreeNode visitNot(Not node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     final operand = node.operand;
     if (_isExtendedBoolLiteral(operand)) {
@@ -1595,7 +1590,7 @@
 
   @override
   TreeNode visitLogicalExpression(
-      LogicalExpression node, TreeNode removalSentinel) {
+      LogicalExpression node, TreeNode? removalSentinel) {
     final left = transform(node.left);
     final operatorEnum = node.operatorEnum;
     if (_isExtendedBoolLiteral(left)) {
@@ -1621,8 +1616,8 @@
   }
 
   @override
-  TreeNode visitIsExpression(IsExpression node, TreeNode removalSentinel) {
-    TypeCheck check = shaker.typeFlowAnalysis.isTest(node);
+  TreeNode visitIsExpression(IsExpression node, TreeNode? removalSentinel) {
+    TypeCheck? check = shaker.typeFlowAnalysis.isTest(node);
     if (check != null && (check.alwaysFail || check.alwaysPass)) {
       final operand = transform(node.operand);
       final result = BoolLiteral(!check.alwaysFail)
@@ -1634,9 +1629,9 @@
   }
 
   @override
-  TreeNode visitAsExpression(AsExpression node, TreeNode removalSentinel) {
+  TreeNode visitAsExpression(AsExpression node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
-    TypeCheck check = shaker.typeFlowAnalysis.explicitCast(node);
+    TypeCheck? check = shaker.typeFlowAnalysis.explicitCast(node);
     if (check != null && check.alwaysPass) {
       return StaticInvocation(
           unsafeCast, Arguments([node.operand], types: [node.type]))
@@ -1646,9 +1641,9 @@
   }
 
   @override
-  TreeNode visitNullCheck(NullCheck node, TreeNode removalSentinel) {
+  TreeNode visitNullCheck(NullCheck node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
-    final nullTest = _getNullTest(node);
+    final nullTest = _getNullTest(node)!;
     if (nullTest.isAlwaysNotNull) {
       return StaticInvocation(
           unsafeCast,
@@ -1659,12 +1654,9 @@
     return node;
   }
 
-  Procedure get unsafeCast {
-    _unsafeCast ??= shaker.typeFlowAnalysis.environment.coreTypes.index
-        .getTopLevelMember('dart:_internal', 'unsafeCast');
-    assert(_unsafeCast != null);
-    return _unsafeCast;
-  }
+  late final Procedure unsafeCast = shaker
+      .typeFlowAnalysis.environment.coreTypes.index
+      .getTopLevelProcedure('dart:_internal', 'unsafeCast');
 }
 
 /// The second pass of [TreeShaker]. It is called after set of used
@@ -1680,7 +1672,7 @@
   void transformComponent(Component component) {
     component.transformOrRemoveChildren(this);
     for (Source source in component.uriToSource.values) {
-      source?.constantCoverageConstructors?.removeWhere((Reference reference) {
+      source.constantCoverageConstructors?.removeWhere((Reference reference) {
         Member node = reference.asMember;
         return !shaker.isMemberUsed(node);
       });
@@ -1688,7 +1680,7 @@
   }
 
   @override
-  TreeNode visitLibrary(Library node, TreeNode removalSentinel) {
+  TreeNode visitLibrary(Library node, TreeNode? removalSentinel) {
     node.transformOrRemoveChildren(this);
     // The transformer API does not iterate over `Library.additionalExports`,
     // so we manually delete the references to shaken nodes.
@@ -1708,12 +1700,12 @@
   }
 
   @override
-  Typedef visitTypedef(Typedef node, TreeNode removalSentinel) {
-    return shaker.isTypedefUsed(node) ? node : removalSentinel;
+  TreeNode visitTypedef(Typedef node, TreeNode? removalSentinel) {
+    return shaker.isTypedefUsed(node) ? node : removalSentinel!;
   }
 
   @override
-  Class visitClass(Class node, TreeNode removalSentinel) {
+  TreeNode visitClass(Class node, TreeNode? removalSentinel) {
     if (!shaker.isClassUsed(node)) {
       debugPrint('Dropped class ${node.name}');
       // Ensure that kernel file writer will not be able to
@@ -1724,7 +1716,7 @@
           "been repurposed for ${node.reference.node}.");
       node.reference.canonicalName?.unbind();
       Statistics.classesDropped++;
-      return removalSentinel; // Remove the class.
+      return removalSentinel!; // Remove the class.
     }
 
     if (!shaker.isClassUsedInType(node)) {
@@ -1755,7 +1747,7 @@
   }
 
   @override
-  Member defaultMember(Member node, TreeNode removalSentinel) {
+  TreeNode defaultMember(Member node, TreeNode? removalSentinel) {
     if (!shaker.isMemberUsed(node)) {
       // Ensure that kernel file writer will not be able to
       // write a dangling reference to the deleted member.
@@ -1767,10 +1759,10 @@
         node.getterReference.canonicalName?.unbind();
         if (node.hasSetter) {
           assert(
-              node.setterReference.node == node,
+              node.setterReference!.node == node,
               "Trying to remove canonical name from reference on $node which "
-              "has been repurposed for ${node.setterReference.node}.");
-          node.setterReference.canonicalName?.unbind();
+              "has been repurposed for ${node.setterReference!.node}.");
+          node.setterReference!.canonicalName?.unbind();
         }
       } else {
         assert(
@@ -1780,13 +1772,13 @@
         node.reference.canonicalName?.unbind();
       }
       Statistics.membersDropped++;
-      return removalSentinel;
+      return removalSentinel!;
     }
 
     if (!shaker.isMemberBodyReachable(node)) {
       if (node is Procedure) {
         // Remove body of unused member.
-        if (!node.isStatic && node.enclosingClass.isAbstract) {
+        if (!node.isStatic && node.enclosingClass!.isAbstract) {
           node.isAbstract = true;
           node.function.body = null;
         } else {
@@ -1829,7 +1821,7 @@
   }
 
   @override
-  Extension visitExtension(Extension node, TreeNode removalSentinel) {
+  TreeNode visitExtension(Extension node, TreeNode? removalSentinel) {
     if (shaker.isExtensionUsed(node)) {
       int writeIndex = 0;
       for (int i = 0; i < node.members.length; ++i) {
@@ -1840,7 +1832,7 @@
         // member was already removed or it will be removed later.
         final Reference memberReference = descriptor.member;
         final bool isBound = memberReference.node != null;
-        if (isBound && shaker.isMemberUsed(memberReference.node)) {
+        if (isBound && shaker.isMemberUsed(memberReference.asMember)) {
           node.members[writeIndex++] = descriptor;
         }
       }
@@ -1850,7 +1842,7 @@
       assert(node.members.length > 0);
       return node;
     }
-    return removalSentinel;
+    return removalSentinel!;
   }
 
   void _makeUnreachableBody(FunctionNode function) {
@@ -1871,7 +1863,7 @@
   }
 
   @override
-  TreeNode defaultTreeNode(TreeNode node, TreeNode removalSentinel) {
+  TreeNode defaultTreeNode(TreeNode node, TreeNode? removalSentinel) {
     return node; // Do not traverse into other nodes.
   }
 }
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index 588512c..3ed7b9b 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -2,10 +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.9
-
 /// Declares the type system used by global type flow analysis.
-library vm.transformations.type_flow.types;
 
 import 'dart:core' hide Type;
 
@@ -138,10 +135,7 @@
   /// values can flow through the program.
   Type specializeTypeCone(TFClass base, {bool allowWideCone = false});
 
-  Type _cachedIntType;
-  Type get intType {
-    return _cachedIntType ??= fromStaticType(coreTypes.intLegacyRawType, true);
-  }
+  late final Type intType = fromStaticType(coreTypes.intLegacyRawType, true);
 }
 
 /// Base class for type expressions.
@@ -151,7 +145,7 @@
 
   /// Returns computed type of this type expression.
   /// [types] is the list of types computed for the statements in the summary.
-  Type getComputedType(List<Type> types);
+  Type getComputedType(List<Type?> types);
 }
 
 /// Kind of a subtype test: subtype/cast/'as' test or instance check/'is' test.
@@ -174,7 +168,7 @@
   /// Create a type representing arbitrary nullable object (`dynamic`).
   factory Type.nullableAny() => new NullableType(const AnyType());
 
-  Class getConcreteClass(TypeHierarchy typeHierarchy) => null;
+  Class? getConcreteClass(TypeHierarchy typeHierarchy) => null;
 
   bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) => false;
 
@@ -185,7 +179,7 @@
       RuntimeType runtimeType, SubtypeTestKind kind);
 
   @override
-  Type getComputedType(List<Type> types) => this;
+  Type getComputedType(List<Type?> types) => this;
 
   /// Order of precedence for evaluation of union/intersection.
   int get order;
@@ -260,7 +254,6 @@
   final Type baseType;
 
   NullableType(this.baseType) {
-    assert(baseType != null);
     assert(baseType is! NullableType);
   }
 
@@ -387,7 +380,9 @@
 class SetType extends Type {
   /// List of concrete types, sorted by classId.
   final List<ConcreteType> types;
-  int _hashCode;
+
+  @override
+  late final int hashCode = _computeHashCode();
 
   /// Creates a new SetType using list of concrete types sorted by classId.
   SetType(this.types) {
@@ -395,9 +390,6 @@
     assert(isSorted(types));
   }
 
-  @override
-  int get hashCode => _hashCode ??= _computeHashCode();
-
   int _computeHashCode() {
     int hash = 1237;
     for (var t in types) {
@@ -470,8 +462,8 @@
     return types;
   }
 
-  static List<ConcreteType> _intersectLists(
-      List<ConcreteType> types1, List<ConcreteType> types2) {
+  static List<ConcreteType> _intersectLists(List<ConcreteType> types1,
+      List<ConcreteType> types2, TypeHierarchy typeHierarchy) {
     int i1 = 0;
     int i2 = 0;
     List<ConcreteType> types = <ConcreteType>[];
@@ -491,9 +483,9 @@
             t2.constant == null) {
           types.add(t1);
         } else {
-          final intersect = t1.intersection(t2, null);
+          final intersect = t1.intersection(t2, typeHierarchy);
           if (intersect is! EmptyType) {
-            types.add(intersect);
+            types.add(intersect as ConcreteType);
           }
         }
         ++i1;
@@ -558,7 +550,8 @@
       return other.intersection(this, typeHierarchy);
     }
     if (other is SetType) {
-      List<ConcreteType> list = _intersectLists(types, other.types);
+      List<ConcreteType> list =
+          _intersectLists(types, other.types, typeHierarchy);
       final size = list.length;
       if (size == 0) {
         return const EmptyType();
@@ -594,7 +587,7 @@
   ConeType(this.cls);
 
   @override
-  Class getConcreteClass(TypeHierarchy typeHierarchy) => typeHierarchy
+  Class? getConcreteClass(TypeHierarchy typeHierarchy) => typeHierarchy
       .specializeTypeCone(cls, allowWideCone: true)
       .getConcreteClass(typeHierarchy);
 
@@ -696,7 +689,7 @@
   WideConeType(TFClass cls) : super(cls);
 
   @override
-  Class getConcreteClass(TypeHierarchy typeHierarchy) => null;
+  Class? getConcreteClass(TypeHierarchy typeHierarchy) => null;
 
   @override
   int get hashCode => (cls.id + 41) & kHashMask;
@@ -783,7 +776,9 @@
 /// or `null` object).
 class ConcreteType extends Type implements Comparable<ConcreteType> {
   final TFClass cls;
-  int _hashCode;
+
+  @override
+  late final int hashCode = _computeHashCode();
 
   // May be null if there are no type arguments constraints. The type arguments
   // should represent type sets, i.e. `UnknownType` or `RuntimeType`. The type
@@ -796,19 +791,19 @@
   // 'numImmediateTypeArgs' is the length of the prefix of 'typeArgs' which
   // holds the type arguments to the class itself.
   final int numImmediateTypeArgs;
-  final List<Type> typeArgs;
+  final List<Type>? typeArgs;
 
   // May be null if constant value is not inferred.
-  final Constant constant;
+  final Constant? constant;
 
-  ConcreteType(this.cls, [List<Type> typeArgs_, this.constant])
+  ConcreteType(this.cls, [List<Type>? typeArgs_, this.constant])
       : typeArgs = typeArgs_,
         numImmediateTypeArgs =
             typeArgs_ != null ? cls.classNode.typeParameters.length : 0 {
     // TODO(alexmarkov): support closures
     assert(!cls.classNode.isAbstract);
     assert(typeArgs == null || cls.classNode.typeParameters.isNotEmpty);
-    assert(typeArgs == null || typeArgs.any((t) => t is RuntimeType));
+    assert(typeArgs == null || typeArgs!.any((t) => t is RuntimeType));
   }
 
   ConcreteType get raw => cls.concreteType;
@@ -839,7 +834,7 @@
 
       if (rhs.typeArguments.isEmpty) return true;
 
-      List<Type> usableTypeArgs = typeArgs;
+      List<Type>? usableTypeArgs = typeArgs;
       if (usableTypeArgs == null) {
         if (cls.classNode.typeParameters.isEmpty) {
           usableTypeArgs =
@@ -862,7 +857,7 @@
         }
         assert(ta is RuntimeType);
         if (!ta.isSubtypeOfRuntimeType(
-            typeHierarchy, runtimeType.typeArgs[i], SubtypeTestKind.Subtype)) {
+            typeHierarchy, runtimeType.typeArgs![i], SubtypeTestKind.Subtype)) {
           return false;
         }
       }
@@ -877,29 +872,26 @@
         } else {
           final interfaceOffset = typeHierarchy.genericInterfaceOffsetFor(
               cls.classNode, typeHierarchy.coreTypes.futureClass);
-          typeArg = typeArgs[interfaceOffset];
+          typeArg = typeArgs![interfaceOffset];
         }
         final RuntimeType lhs =
             typeArg is RuntimeType ? typeArg : RuntimeType(DynamicType(), null);
         return lhs.isSubtypeOfRuntimeType(
-            typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
+            typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
       } else {
         return isSubtypeOfRuntimeType(
-            typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
+            typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
       }
     }
     return false;
   }
 
-  @override
-  int get hashCode => _hashCode ??= _computeHashCode();
-
   int _computeHashCode() {
     int hash = cls.hashCode ^ 0x1234 & kHashMask;
     // We only need to hash the first type arguments vector, since the type
     // arguments of the implemented interfaces are implied by it.
     for (int i = 0; i < numImmediateTypeArgs; ++i) {
-      hash = (((hash * 31) & kHashMask) + typeArgs[i].hashCode) & kHashMask;
+      hash = (((hash * 31) & kHashMask) + typeArgs![i].hashCode) & kHashMask;
     }
     hash = ((hash * 31) & kHashMask) + constant.hashCode;
     return hash;
@@ -915,7 +907,7 @@
       }
       if (this.typeArgs != null) {
         for (int i = 0; i < numImmediateTypeArgs; ++i) {
-          if (this.typeArgs[i] != other.typeArgs[i]) {
+          if (this.typeArgs![i] != other.typeArgs![i]) {
             return false;
           }
         }
@@ -942,10 +934,10 @@
     final StringBuffer buf = new StringBuffer();
     buf.write("_T (${cls}");
     if (typeArgs != null) {
-      buf.write("<${typeArgs.take(numImmediateTypeArgs).join(', ')}>");
+      buf.write("<${typeArgs!.take(numImmediateTypeArgs).join(', ')}>");
     }
     if (constant != null) {
-      buf.write(", ${nodeToText(constant)}");
+      buf.write(", ${nodeToText(constant!)}");
     }
     buf.write(")");
     return buf.toString();
@@ -997,17 +989,21 @@
         return this;
       }
 
-      List<Type> mergedTypeArgs;
-      if (typeArgs == null) {
-        mergedTypeArgs = other.typeArgs;
-      } else if (other.typeArgs == null) {
-        mergedTypeArgs = typeArgs;
+      List<Type>? mergedTypeArgs;
+      final thisTypeArgs = this.typeArgs;
+      final otherTypeArgs = other.typeArgs;
+      if (thisTypeArgs == null) {
+        mergedTypeArgs = otherTypeArgs;
+      } else if (otherTypeArgs == null) {
+        mergedTypeArgs = thisTypeArgs;
       } else {
-        mergedTypeArgs = new List<Type>.filled(typeArgs.length, null);
+        assert(thisTypeArgs.length == otherTypeArgs.length);
+        mergedTypeArgs =
+            new List<Type>.filled(thisTypeArgs.length, const EmptyType());
         bool hasRuntimeType = false;
-        for (int i = 0; i < typeArgs.length; ++i) {
+        for (int i = 0; i < thisTypeArgs.length; ++i) {
           final merged =
-              typeArgs[i].intersection(other.typeArgs[i], typeHierarchy);
+              thisTypeArgs[i].intersection(otherTypeArgs[i], typeHierarchy);
           if (merged is EmptyType) {
             return const EmptyType();
           } else if (merged is RuntimeType) {
@@ -1020,7 +1016,7 @@
         }
       }
 
-      Constant mergedConstant;
+      Constant? mergedConstant;
       if (constant == null) {
         mergedConstant = other.constant;
       } else if (other.constant == null || constant == other.constant) {
@@ -1062,7 +1058,7 @@
   final DartType _type; // Doesn't contain type args.
 
   final int numImmediateTypeArgs;
-  final List<RuntimeType> typeArgs;
+  final List<RuntimeType>? typeArgs;
 
   RuntimeType(DartType type, this.typeArgs)
       : _type = type,
@@ -1070,14 +1066,12 @@
             ? type.classNode.typeParameters.length
             : (type is FutureOrType ? 1 : 0) {
     if (_type is InterfaceType && numImmediateTypeArgs > 0) {
-      assert(typeArgs != null);
-      assert(typeArgs.length >= numImmediateTypeArgs);
+      assert(typeArgs!.length >= numImmediateTypeArgs);
       assert((_type as InterfaceType)
           .typeArguments
           .every((t) => t == const DynamicType()));
     } else if (_type is FutureOrType) {
-      assert(typeArgs != null);
-      assert(typeArgs.length >= numImmediateTypeArgs);
+      assert(typeArgs!.length >= numImmediateTypeArgs);
       DartType typeArgument = (_type as FutureOrType).typeArgument;
       assert(typeArgument == const DynamicType());
     } else {
@@ -1098,25 +1092,27 @@
     final type = _type;
     if (type is InterfaceType && typeArgs != null) {
       final klass = type.classNode;
-      final typeArguments = typeArgs
+      final typeArguments = typeArgs!
           .take(klass.typeParameters.length)
           .map((pt) => pt.representedType)
           .toList();
       return new InterfaceType(klass, type.nullability, typeArguments);
     } else if (type is FutureOrType) {
-      return new FutureOrType(typeArgs[0].representedType, type.nullability);
+      return new FutureOrType(typeArgs![0].representedType, type.nullability);
     } else {
       return type;
     }
   }
 
   @override
-  int get hashCode {
+  late final int hashCode = _computeHashCode();
+
+  int _computeHashCode() {
     int hash = _type.hashCode ^ 0x1234 & kHashMask;
     // Only hash by the type arguments of the class. The type arguments of
     // supertypes are are implied by them.
     for (int i = 0; i < numImmediateTypeArgs; ++i) {
-      hash = (((hash * 31) & kHashMask) + typeArgs[i].hashCode) & kHashMask;
+      hash = (((hash * 31) & kHashMask) + typeArgs![i].hashCode) & kHashMask;
     }
     return hash;
   }
@@ -1127,7 +1123,7 @@
     if (other is RuntimeType) {
       if (other._type != _type) return false;
       assert(numImmediateTypeArgs == other.numImmediateTypeArgs);
-      return typeArgs == null || listEquals(typeArgs, other.typeArgs);
+      return typeArgs == null || listEquals(typeArgs!, other.typeArgs!);
     }
     return false;
   }
@@ -1139,7 +1135,7 @@
         : "${nodeToText(_type)}";
     final typeArgsStrs = (numImmediateTypeArgs == 0)
         ? ""
-        : "<${typeArgs.take(numImmediateTypeArgs).map((t) => "$t").join(", ")}>";
+        : "<${typeArgs!.take(numImmediateTypeArgs).map((t) => "$t").join(", ")}>";
     final nullability = _type.nullability.suffix;
     return "$head$typeArgsStrs$nullability";
   }
@@ -1200,15 +1196,15 @@
       if (_type is InterfaceType) {
         Class thisClass = (_type as InterfaceType).classNode;
         if (thisClass == typeHierarchy.coreTypes.futureClass) {
-          return typeArgs[0].isSubtypeOfRuntimeType(
-              typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
+          return typeArgs![0].isSubtypeOfRuntimeType(
+              typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
         } else {
           return isSubtypeOfRuntimeType(
-              typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
+              typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
         }
       } else if (_type is FutureOrType) {
-        return typeArgs[0].isSubtypeOfRuntimeType(
-            typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype);
+        return typeArgs![0].isSubtypeOfRuntimeType(
+            typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
       }
     }
 
@@ -1236,7 +1232,7 @@
       return true;
     }
 
-    List<Type> usableTypeArgs = typeArgs;
+    List<Type>? usableTypeArgs = typeArgs;
     if (usableTypeArgs == null) {
       assert(thisClass.typeParameters.isEmpty);
       usableTypeArgs =
@@ -1248,7 +1244,7 @@
         runtimeType.numImmediateTypeArgs);
     for (int i = 0; i < runtimeType.numImmediateTypeArgs; ++i) {
       if (!usableTypeArgs[interfaceOffset + i].isSubtypeOfRuntimeType(
-          typeHierarchy, runtimeType.typeArgs[i], SubtypeTestKind.Subtype)) {
+          typeHierarchy, runtimeType.typeArgs![i], SubtypeTestKind.Subtype)) {
         return false;
       }
     }
diff --git a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
index 723e673..682cf58 100644
--- a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
+++ b/pkg/vm/lib/transformations/type_flow/unboxing_info.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.9
-
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/external_name.dart' show getExternalName;
@@ -30,12 +28,12 @@
         _coreTypes = typeFlowAnalysis.environment.coreTypes,
         _nativeCodeOracle = typeFlowAnalysis.nativeCodeOracle;
 
-  UnboxingInfoMetadata getUnboxingInfoOfMember(Member member) {
-    final UnboxingInfoMetadata info = _memberInfo[member];
+  UnboxingInfoMetadata? getUnboxingInfoOfMember(Member member) {
+    final UnboxingInfoMetadata? info = _memberInfo[member];
     if (member is Procedure && member.isGetter) {
       // Remove placeholder parameter info slot for setters that the getter is
       // grouped with.
-      return UnboxingInfoMetadata(0)..returnInfo = info.returnInfo;
+      return UnboxingInfoMetadata(0)..returnInfo = info!.returnInfo;
     }
     return info;
   }
@@ -81,8 +79,8 @@
           ? (member.hasSetter ? 1 : 0)
           : member is Procedure && member.isGetter
               ? 1
-              : member.function.requiredParameterCount;
-      UnboxingInfoMetadata info;
+              : member.function!.requiredParameterCount;
+      UnboxingInfoMetadata? info;
       if (member.isInstanceMember) {
         int selectorId =
             member is Field || member is Procedure && member.isGetter
@@ -121,20 +119,18 @@
   void _updateUnboxingInfoOfMember(
       Member member, TypeFlowAnalysis typeFlowAnalysis) {
     if (typeFlowAnalysis.isMemberUsed(member)) {
-      final UnboxingInfoMetadata unboxingInfo = _memberInfo[member];
+      final UnboxingInfoMetadata unboxingInfo = _memberInfo[member]!;
       if (_cannotUnbox(member)) {
         unboxingInfo.unboxedArgsInfo.length = 0;
         unboxingInfo.returnInfo = UnboxingInfoMetadata.kBoxed;
         return;
       }
       if (member is Procedure || member is Constructor) {
-        final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member);
-        assert(argTypes != null);
-
+        final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member)!;
         final int firstParamIndex =
             numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
 
-        final positionalParams = member.function.positionalParameters;
+        final positionalParams = member.function!.positionalParameters;
         assert(argTypes.positionalCount ==
             firstParamIndex + positionalParams.length);
 
diff --git a/pkg/vm/lib/transformations/type_flow/utils.dart b/pkg/vm/lib/transformations/type_flow/utils.dart
index b04e69e..c85dfc7 100644
--- a/pkg/vm/lib/transformations/type_flow/utils.dart
+++ b/pkg/vm/lib/transformations/type_flow/utils.dart
@@ -2,12 +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.9
-
 /// Declares miscellaneous utility functions and constants for type flow
 /// analysis.
 library vm.transformations.type_flow.utils;
 
+import 'package:collection/collection.dart' show IterableExtension;
 import 'package:kernel/ast.dart';
 import 'package:kernel/src/printer.dart';
 
@@ -123,9 +122,8 @@
   return true;
 }
 
-VariableDeclaration findNamedParameter(FunctionNode function, String name) {
-  return function.namedParameters
-      .firstWhere((p) => p.name == name, orElse: () => null);
+VariableDeclaration? findNamedParameter(FunctionNode function, String name) {
+  return function.namedParameters.firstWhereOrNull((p) => p.name == name);
 }
 
 class Histogram<K> {
@@ -143,7 +141,7 @@
     print(
         '-------------------------------------------------------------------');
     List<K> keys = values.keys.toList();
-    keys.sort((k1, k2) => values[k1].compareTo(values[k2]));
+    keys.sort((k1, k2) => values[k1]!.compareTo(values[k2]!));
     final cut = keys.length < n ? 0 : keys.length - n;
     for (int i = keys.length - 1; i >= cut; --i) {
       final k = keys[i];
@@ -376,7 +374,7 @@
 };
 
 extension NullabilitySuffix on Nullability {
-  String get suffix => nullabilitySuffix[this];
+  String get suffix => nullabilitySuffix[this]!;
 }
 
 bool mayHaveSideEffects(Expression node) {
diff --git a/pkg/vm/pubspec.yaml b/pkg/vm/pubspec.yaml
index f57cf389..0e78a09 100644
--- a/pkg/vm/pubspec.yaml
+++ b/pkg/vm/pubspec.yaml
@@ -18,6 +18,7 @@
   meta:
     path: ../meta
   package_config: any
+  collection: ^1.15.0
 
 dev_dependencies:
   expect:
diff --git a/pkg/vm/test/common_test_utils.dart b/pkg/vm/test/common_test_utils.dart
index 3f8bf9c..1ff586a 100644
--- a/pkg/vm/test/common_test_utils.dart
+++ b/pkg/vm/test/common_test_utils.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.9
-
 import 'dart:async';
 import 'dart:io';
 
@@ -37,11 +35,11 @@
 }
 
 Future<Component> compileTestCaseToKernelProgram(Uri sourceUri,
-    {Target target,
+    {Target? target,
     bool enableSuperMixins = false,
-    List<String> experimentalFlags,
-    Map<String, String> environmentDefines,
-    Uri packagesFileUri}) async {
+    List<String>? experimentalFlags,
+    Map<String, String>? environmentDefines,
+    Uri? packagesFileUri}) async {
   final platformKernel =
       computePlatformBinariesLocation().resolve('vm_platform_strong.dill');
   target ??= new TestingVmTarget(new TargetFlags())
@@ -62,11 +60,11 @@
     };
 
   final Component component =
-      (await kernelForProgram(sourceUri, options)).component;
+      (await kernelForProgram(sourceUri, options))!.component!;
 
   // Make sure the library name is the same and does not depend on the order
   // of test cases.
-  component.mainMethod.enclosingLibrary.name = '#lib';
+  component.mainMethod!.enclosingLibrary.name = '#lib';
 
   return component;
 }
@@ -75,19 +73,19 @@
   final StringBuffer buffer = new StringBuffer();
   final printer = new Printer(buffer, showMetadata: true);
   printer.writeLibraryFile(library);
-  printer.writeConstantTable(library.enclosingComponent);
+  printer.writeConstantTable(library.enclosingComponent!);
   return buffer
       .toString()
-      .replaceAll(library.importUri.toString(), library.name);
+      .replaceAll(library.importUri.toString(), library.name!);
 }
 
 String kernelComponentToString(Component component) {
   final StringBuffer buffer = new StringBuffer();
   new Printer(buffer, showMetadata: true).writeComponentFile(component);
-  final mainLibrary = component.mainMethod.enclosingLibrary;
+  final mainLibrary = component.mainMethod!.enclosingLibrary;
   return buffer
       .toString()
-      .replaceAll(mainLibrary.importUri.toString(), mainLibrary.name);
+      .replaceAll(mainLibrary.importUri.toString(), mainLibrary.name!);
 }
 
 class DevNullSink<T> extends Sink<T> {
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
index f9ea8d7..2e25344 100644
--- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -60,7 +60,7 @@
   void recordMemberCalledViaThis(Member target) {}
 
   @override
-  void recordTearOff(Procedure target) {}
+  void recordTearOff(Member target) {}
 }
 
 class PrintSummaries extends RecursiveVisitor {
@@ -78,7 +78,7 @@
         typesBuilder,
         new NativeCodeOracle(
             null, new ConstantPragmaAnnotationParser(coreTypes)),
-        new GenericInterfacesInfoImpl(hierarchy),
+        new GenericInterfacesInfoImpl(coreTypes, hierarchy),
         /*_protobufHandler=*/ null);
   }
 
diff --git a/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart b/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart
index 0087928..2fa4962 100644
--- a/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart
+++ b/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart
@@ -14,6 +14,7 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
+import 'test_utils.dart' show isArtificialReloadMode;
 import '../../../../../tests/ffi/dylib_utils.dart';
 
 final bool isolateGroupsEnabled =
@@ -240,5 +241,10 @@
     await testNotSupported();
     return;
   }
+
+  // This test should not run in hot-reload because of the way it is written
+  // (embedder related code written in Dart instead of C)
+  if (isArtificialReloadMode) return;
+
   await testJitOrAot();
 }
diff --git a/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart b/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart
index 5ce5984..8b92de1 100644
--- a/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart
@@ -14,6 +14,7 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
+import 'test_utils.dart' show isArtificialReloadMode;
 import '../../../../../tests/ffi/dylib_utils.dart';
 
 final bool isolateGroupsEnabled =
@@ -240,5 +241,10 @@
     await testNotSupported();
     return;
   }
+
+  // This test should not run in hot-reload because of the way it is written
+  // (embedder related code written in Dart instead of C)
+  if (isArtificialReloadMode) return;
+
   await testJitOrAot();
 }
diff --git a/tools/VERSION b/tools/VERSION
index 8235dad..3b8e28a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 357
+PRERELEASE 358
 PRERELEASE_PATCH 0
\ No newline at end of file