Version 2.14.0-345.0.dev

Merge commit '3b1e83387fe7e1b03df9259d2dae3f6f8207abfa' into 'dev'
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index 8339c43..16fbc15 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -678,7 +678,8 @@
   @override
   void handleConstantExpression(ir.ConstantExpression node) {
     ir.LibraryDependency import = getDeferredImport(node);
-    new ConstantImpactVisitor(this, import, node).visitConstant(node.constant);
+    new ConstantImpactVisitor(this, import, node, staticTypeContext)
+        .visitConstant(node.constant);
   }
 }
 
@@ -727,8 +728,10 @@
   final ImpactRegistry registry;
   final ir.LibraryDependency import;
   final ir.ConstantExpression expression;
+  final ir.StaticTypeContext staticTypeContext;
 
-  ConstantImpactVisitor(this.registry, this.import, this.expression);
+  ConstantImpactVisitor(
+      this.registry, this.import, this.expression, this.staticTypeContext);
 
   @override
   void defaultConstant(ir.Constant node) {
@@ -755,9 +758,7 @@
   @override
   void visitInstantiationConstant(ir.InstantiationConstant node) {
     registry.registerGenericInstantiation(
-        node.tearOffConstant.function.computeFunctionType(
-            node.tearOffConstant.target.enclosingLibrary.nonNullable),
-        node.types);
+        node.tearOffConstant.getType(staticTypeContext), node.types);
     visitConstant(node.tearOffConstant);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 08e70bf..653af5c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -714,6 +714,11 @@
   }
 
   @override
+  TreeNode visitTypedefTearOff(TypedefTearOff node, TreeNode? removalSentinel) {
+    return evaluateAndTransformWithContext(node, node);
+  }
+
+  @override
   TreeNode visitInstantiation(Instantiation node, TreeNode? removalSentinel) {
     Instantiation result =
         super.visitInstantiation(node, removalSentinel) as Instantiation;
@@ -3387,43 +3392,38 @@
           new Instantiation(extract(constant),
               node.typeArguments.map((t) => env.substituteType(t)).toList()));
     }
+    List<TypeParameter>? typeParameters;
     if (constant is TearOffConstant) {
       Member target = constant.target;
-      List<TypeParameter>? typeParameters;
       if (target is Procedure) {
         typeParameters = target.function.typeParameters;
       } else if (target is Constructor) {
         typeParameters = target.enclosingClass.typeParameters;
       }
-      if (typeParameters != null) {
-        if (node.typeArguments.length == typeParameters.length) {
-          List<DartType>? types = _evaluateDartTypes(node, node.typeArguments);
-          if (types == null) {
-            AbortConstant error = _gotError!;
-            _gotError = null;
-            return error;
-          }
-          assert(_gotError == null);
-          // ignore: unnecessary_null_comparison
-          assert(types != null);
-
-          final List<DartType> typeArguments = convertTypes(types);
-          return canonicalize(
-              new InstantiationConstant(constant, typeArguments));
-        } else {
-          // Probably unreachable.
-          return createInvalidExpressionConstant(
-              node,
-              'The number of type arguments supplied in the partial '
-              'instantiation does not match the number of type arguments '
-              'of the $constant.');
+    } else if (constant is TypedefTearOffConstant) {
+      typeParameters = constant.parameters;
+    }
+    if (typeParameters != null) {
+      if (node.typeArguments.length == typeParameters.length) {
+        List<DartType>? types = _evaluateDartTypes(node, node.typeArguments);
+        if (types == null) {
+          AbortConstant error = _gotError!;
+          _gotError = null;
+          return error;
         }
+        assert(_gotError == null);
+        // ignore: unnecessary_null_comparison
+        assert(types != null);
+
+        final List<DartType> typeArguments = convertTypes(types);
+        return canonicalize(new InstantiationConstant(constant, typeArguments));
       } else {
         // Probably unreachable.
         return createInvalidExpressionConstant(
             node,
-            "Unsupported kind of a torn off member: "
-            "'${target.runtimeType}'.");
+            'The number of type arguments supplied in the partial '
+            'instantiation does not match the number of type arguments '
+            'of the $constant.');
       }
     }
     // The inner expression in an instantiation can never be null, since
@@ -3445,7 +3445,23 @@
 
   @override
   Constant visitTypedefTearOff(TypedefTearOff node) {
-    return defaultExpression(node);
+    final Constant constant = _evaluateSubexpression(node.expression);
+    if (constant is TearOffConstant) {
+      FreshTypeParameters freshTypeParameters =
+          getFreshTypeParameters(node.typeParameters);
+      List<TypeParameter> typeParameters =
+          freshTypeParameters.freshTypeParameters;
+      List<DartType> typeArguments = new List<DartType>.generate(
+          node.typeArguments.length,
+          (int i) => freshTypeParameters.substitute(node.typeArguments[i]),
+          growable: false);
+      return canonicalize(
+          new TypedefTearOffConstant(typeParameters, constant, typeArguments));
+    } else {
+      // Probably unreachable.
+      return createInvalidExpressionConstant(
+          node, "Unexpected typedef tearoff target: ${constant}.");
+    }
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 7363aa8..a378dec 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -1403,7 +1403,7 @@
 
   KernelDiagnosticReporter(this.loader);
 
-  void report(Message message, int charOffset, int length, Uri fileUri,
+  void report(Message message, int charOffset, int length, Uri? fileUri,
       {List<LocatedMessage>? context}) {
     loader.addProblem(message, charOffset, noLength, fileUri, context: context);
   }
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index 59a5c83..0067517 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -415,7 +415,12 @@
 
   void visitInstantiationConstant(InstantiationConstant node) {
     sb.write('Instantiation(');
-    sb.write(getMemberName(node.tearOffConstant.target));
+    Constant tearOffConstant = node.tearOffConstant;
+    if (tearOffConstant is TearOffConstant) {
+      sb.write(getMemberName(tearOffConstant.target));
+    } else {
+      visit(tearOffConstant);
+    }
     sb.write('<');
     typeToText.visitList(node.types);
     sb.write('>)');
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart
new file mode 100644
index 0000000..e832879f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A<T> {
+  A();
+  factory A.fact() => new A();
+  factory A.redirect() = A;
+}
+
+typedef B<T> = A<T>;
+typedef C<T> = A<int>;
+
+const a = A.new;
+const b = A<int>.new;
+const c = A.fact;
+const d = A<int>.fact;
+const e = A.redirect;
+const f = A<int>.redirect;
+const g = B.new;
+const h = B<int>.new;
+const i = B.fact;
+const j = B<int>.fact;
+const k = B.redirect;
+const l = B<int>.redirect;
+const m = C.new;
+const n = C<int>.new;
+const o = C.fact;
+const p = C<int>.fact;
+const q = C.redirect;
+const r = C<int>.redirect;
+
+main() {
+  var a = A.new;
+  var b = A<int>.new;
+  var c = A.fact;
+  var d = A<int>.fact;
+  var e = A.redirect;
+  var f = A<int>.redirect;
+  var g = B.new;
+  var h = B<int>.new;
+  var i = B.fact;
+  var j = B<int>.fact;
+  var k = B.redirect;
+  var l = B<int>.redirect;
+  var m = C.new;
+  var n = C<int>.new;
+  var o = C.fact;
+  var p = C<int>.fact;
+  var q = C.redirect;
+  var r = C<int>.redirect;
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.expect
new file mode 100644
index 0000000..cfec78a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+  <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+  () → self::A<core::int> b = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+  () → self::A<core::int> d = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+  () → self::A<core::int> f = #C6;
+  <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+  () → self::A<core::int> h = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+  () → self::A<core::int> j = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+  () → self::A<core::int> l = #C6;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+  () → self::A<core::int> n = #C2;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+  () → self::A<core::int> p = #C4;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+  () → self::A<core::int> r = #C6;
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int>
+  #C3 = static-tearoff self::A::fact
+  #C4 = instantiation self::A::fact <core::int>
+  #C5 = redirecting-factory-tearoff self::A::redirect
+  #C6 = instantiation self::A::redirect <core::int>
+  #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+  #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+  #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..d84286f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+  <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+  () → self::A<core::int> b = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+  () → self::A<core::int> d = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+  () → self::A<core::int> f = #C6;
+  <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+  () → self::A<core::int> h = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+  () → self::A<core::int> j = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+  () → self::A<core::int> l = #C6;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+  () → self::A<core::int> n = #C2;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+  () → self::A<core::int> p = #C4;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+  () → self::A<core::int> r = #C6;
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int>
+  #C3 = static-tearoff self::A::fact
+  #C4 = instantiation self::A::fact <core::int>
+  #C5 = redirecting-factory-tearoff self::A::redirect
+  #C6 = instantiation self::A::redirect <core::int>
+  #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+  #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+  #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..a4b6c13
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.textual_outline.expect
@@ -0,0 +1,26 @@
+class A<T> {
+  A();
+  factory A.fact() => new A();
+  factory A.redirect() = A;
+}
+typedef B<T> = A<T>;
+typedef C<T> = A<int>;
+const a = A.new;
+const b = A<int>.new;
+const c = A.fact;
+const d = A<int>.fact;
+const e = A.redirect;
+const f = A<int>.redirect;
+const g = B.new;
+const h = B<int>.new;
+const i = B.fact;
+const j = B<int>.fact;
+const k = B.redirect;
+const l = B<int>.redirect;
+const m = C.new;
+const n = C<int>.new;
+const o = C.fact;
+const p = C<int>.fact;
+const q = C.redirect;
+const r = C<int>.redirect;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.expect
new file mode 100644
index 0000000..7412c43
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+  <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+  () → self::A<core::int> b = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+  () → self::A<core::int> d = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+  () → self::A<core::int> f = #C6;
+  <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+  () → self::A<core::int> h = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+  () → self::A<core::int> j = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+  () → self::A<core::int> l = #C6;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+  () → self::A<core::int> n = #C2;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+  () → self::A<core::int> p = #C4;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+  () → self::A<core::int> r = #C6;
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int*>
+  #C3 = static-tearoff self::A::fact
+  #C4 = instantiation self::A::fact <core::int*>
+  #C5 = redirecting-factory-tearoff self::A::redirect
+  #C6 = instantiation self::A::redirect <core::int*>
+  #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+  #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+  #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..8c8090d
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect
@@ -0,0 +1,57 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    ;
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    ;
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = self::A::•;
+static const field () → self::A<core::int> b = self::A::•<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = self::A::fact;
+static const field () → self::A<core::int> d = self::A::fact<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = self::A::redirect;
+static const field () → self::A<core::int> f = self::A::redirect<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = self::A::•;
+static const field () → self::A<core::int> h = self::A::•<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = self::A::fact;
+static const field () → self::A<core::int> j = self::A::fact<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = self::A::redirect;
+static const field () → self::A<core::int> l = self::A::redirect<core::int>;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = <unrelated T extends core::Object? = dynamic>.(self::A::•<core::int>);
+static const field () → self::A<core::int> n = self::A::•<core::int>;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = <unrelated T extends core::Object? = dynamic>.(self::A::fact<core::int>);
+static const field () → self::A<core::int> p = self::A::fact<core::int>;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = <unrelated T extends core::Object? = dynamic>.(self::A::redirect<core::int>);
+static const field () → self::A<core::int> r = self::A::redirect<core::int>;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///const_tear_off.dart:14:11 -> ConstructorTearOffConstant(A.)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:15:11 -> InstantiationConstant(A.<int*>)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///const_tear_off.dart:16:11 -> StaticTearOffConstant(A.fact)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:17:11 -> InstantiationConstant(A.fact<int*>)
+Evaluated: RedirectingFactoryTearOff @ org-dartlang-testcase:///const_tear_off.dart:18:11 -> RedirectingFactoryTearOffConstant(A.redirect)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:19:11 -> InstantiationConstant(A.redirect<int*>)
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///const_tear_off.dart:20:11 -> ConstructorTearOffConstant(A.)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:21:11 -> InstantiationConstant(A.<int*>)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///const_tear_off.dart:22:11 -> StaticTearOffConstant(A.fact)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:23:11 -> InstantiationConstant(A.fact<int*>)
+Evaluated: RedirectingFactoryTearOff @ org-dartlang-testcase:///const_tear_off.dart:24:11 -> RedirectingFactoryTearOffConstant(A.redirect)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:25:11 -> InstantiationConstant(A.redirect<int*>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:26:11 -> TypedefTearOffConstant(A.<T><int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:27:11 -> InstantiationConstant(A.<int*>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:28:11 -> TypedefTearOffConstant(A.fact<T><int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:29:11 -> InstantiationConstant(A.fact<int*>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:30:11 -> TypedefTearOffConstant(A.redirect<T><int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:31:11 -> InstantiationConstant(A.redirect<int*>)
+Extra constant evaluation: evaluated: 23, effectively constant: 18
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..0a0394c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+  constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+    return new self::A::•<self::A::fact::T%>();
+  static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+    let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+  <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+  () → self::A<core::int> b = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+  () → self::A<core::int> d = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+  () → self::A<core::int> f = #C6;
+  <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+  () → self::A<core::int> h = #C2;
+  <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+  () → self::A<core::int> j = #C4;
+  <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+  () → self::A<core::int> l = #C6;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+  () → self::A<core::int> n = #C2;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+  () → self::A<core::int> p = #C4;
+  <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+  () → self::A<core::int> r = #C6;
+}
+
+constants  {
+  #C1 = constructor-tearoff self::A::•
+  #C2 = instantiation self::A::• <core::int*>
+  #C3 = static-tearoff self::A::fact
+  #C4 = instantiation self::A::fact <core::int*>
+  #C5 = redirecting-factory-tearoff self::A::redirect
+  #C6 = instantiation self::A::redirect <core::int*>
+  #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+  #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+  #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.expect
index 1fc439e..2949323 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.expect
@@ -1,4 +1,21 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -44,9 +61,9 @@
 static method test3() → dynamic
   return #C1;
 static method test4() → dynamic
-  return invalid-expression "Constant evaluation has no support for TypedefTearOff!";
+  return invalid-expression "This assertion failed.";
 static method test5() → dynamic
-  return invalid-expression "Constant evaluation has no support for TypedefTearOff!";
+  return invalid-expression "This assertion failed.";
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.transformed.expect
index 1fc439e..2949323 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.transformed.expect
@@ -1,4 +1,21 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -44,9 +61,9 @@
 static method test3() → dynamic
   return #C1;
 static method test4() → dynamic
-  return invalid-expression "Constant evaluation has no support for TypedefTearOff!";
+  return invalid-expression "This assertion failed.";
 static method test5() → dynamic
-  return invalid-expression "Constant evaluation has no support for TypedefTearOff!";
+  return invalid-expression "This assertion failed.";
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.expect
index 1fc439e..2949323 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.expect
@@ -1,4 +1,21 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -44,9 +61,9 @@
 static method test3() → dynamic
   return #C1;
 static method test4() → dynamic
-  return invalid-expression "Constant evaluation has no support for TypedefTearOff!";
+  return invalid-expression "This assertion failed.";
 static method test5() → dynamic
-  return invalid-expression "Constant evaluation has no support for TypedefTearOff!";
+  return invalid-expression "This assertion failed.";
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.transformed.expect
index 1fc439e..2949323 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.transformed.expect
@@ -1,4 +1,21 @@
 library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+//                  ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+//   const StaticIdentityTest(a, b) : assert(identical(a, b));
+//                                           ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -44,9 +61,9 @@
 static method test3() → dynamic
   return #C1;
 static method test4() → dynamic
-  return invalid-expression "Constant evaluation has no support for TypedefTearOff!";
+  return invalid-expression "This assertion failed.";
 static method test5() → dynamic
-  return invalid-expression "Constant evaluation has no support for TypedefTearOff!";
+  return invalid-expression "This assertion failed.";
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect
index f1d8c77..218d370 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect
@@ -63,36 +63,36 @@
 static method test2() → () → self::A
   return #C1;
 static method test3() → () → self::A
-  return <unrelated X extends core::num>.(#C1)<core::num>;
+  return #C3;
 static method test4() → () → self::A
-  return <unrelated X extends core::num>.(#C1)<core::num>;
+  return #C3;
 static method test5() → () → self::A
   return #C1;
 static method test6() → () → self::A
   return #C1;
 static method test7() → () → self::B<core::String>
-  return #C3;
+  return #C5;
 static method test8() → () → self::B<core::String>
-  return #C3;
+  return #C5;
 static method test9() → () → self::B<core::num>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<num> Function() test9() => DB1.new; // Error.
-                             ^" in (#C3) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+                             ^" in (#C5) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
 static method test10() → () → self::B<core::String>
-  return #C5;
-static method test11() → () → self::B<core::String>
   return #C7;
-static method test12() → () → self::B<core::num>
-  return #C8;
-static method test13() → () → self::B<core::num>
+static method test11() → () → self::B<core::String>
   return #C9;
-static method test14() → () → self::B<core::num>
+static method test12() → () → self::B<core::num>
   return #C10;
+static method test13() → () → self::B<core::num>
+  return #C11;
+static method test14() → () → self::B<core::num>
+  return #C12;
 static method test15() → () → self::B<core::num>
-  return <X extends core::num>.(#C2<X>)<core::num>;
+  return #C14;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return <X extends core::num>.(#C2<X>);
+  return #C13;
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
@@ -100,17 +100,17 @@
                                ^" in (let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (<X extends core::num>.(#C2<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
 static method test18() → () → self::B<core::num>
-  return #C8;
-static method test19() → () → self::B<core::num>
-  return #C9;
-static method test20() → () → self::B<core::num>
   return #C10;
+static method test19() → () → self::B<core::num>
+  return #C11;
+static method test20() → () → self::B<core::num>
+  return #C12;
 static method test21() → () → self::B<core::num>
-  return <X extends core::num, unrelated Y extends core::String>.(#C2<X>)<core::num, core::String>;
+  return #C16;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return <X extends core::num, unrelated Y extends core::String>.(#C2<X>);
+  return #C15;
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
   return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
@@ -118,20 +118,27 @@
                                   ^" in (let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
-                                  ^" in (<X extends core::num, unrelated Y extends core::String>.(#C2<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+                                  ^" in (#C15) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
 static method test24() → () → self::B<core::String>
-  return <X extends core::num>.(#C2<X>)<Never>;
+  return #C17;
 static method main() → dynamic {}
 
 constants  {
   #C1 = constructor-tearoff self::A::•
-  #C2 = constructor-tearoff self::B::•
-  #C3 = instantiation self::B::• <core::String>
-  #C4 = constructor-tearoff self::B::foo
-  #C5 = instantiation self::B::foo <core::String>
-  #C6 = static-tearoff self::B::bar
-  #C7 = instantiation self::B::bar <core::String>
-  #C8 = instantiation self::B::• <core::num>
-  #C9 = instantiation self::B::foo <core::num>
-  #C10 = instantiation self::B::bar <core::num>
+  #C2 = typedef-tearoff <unrelated X extends core::num>.(#C1)
+  #C3 = instantiation #C2 <core::num>
+  #C4 = constructor-tearoff self::B::•
+  #C5 = instantiation self::B::• <core::String>
+  #C6 = constructor-tearoff self::B::foo
+  #C7 = instantiation self::B::foo <core::String>
+  #C8 = static-tearoff self::B::bar
+  #C9 = instantiation self::B::bar <core::String>
+  #C10 = instantiation self::B::• <core::num>
+  #C11 = instantiation self::B::foo <core::num>
+  #C12 = instantiation self::B::bar <core::num>
+  #C13 = typedef-tearoff <X extends core::num>.(#C4<X>)
+  #C14 = instantiation #C13 <core::num>
+  #C15 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C4<X>)
+  #C16 = instantiation #C15 <core::num, core::String>
+  #C17 = instantiation #C13 <Never>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect
index b64fd31..8730f3b 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect
@@ -63,36 +63,36 @@
 static method test2() → () → self::A
   return #C1;
 static method test3() → () → self::A
-  return <unrelated X extends core::num>.(#C1)<core::num>;
+  return #C3;
 static method test4() → () → self::A
-  return <unrelated X extends core::num>.(#C1)<core::num>;
+  return #C3;
 static method test5() → () → self::A
   return #C1;
 static method test6() → () → self::A
   return #C1;
 static method test7() → () → self::B<core::String>
-  return #C3;
+  return #C5;
 static method test8() → () → self::B<core::String>
-  return #C3;
+  return #C5;
 static method test9() → () → self::B<core::num>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<num> Function() test9() => DB1.new; // Error.
-                             ^" in (#C3) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+                             ^" in (#C5) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
 static method test10() → () → self::B<core::String>
-  return #C5;
-static method test11() → () → self::B<core::String>
   return #C7;
-static method test12() → () → self::B<core::num>
-  return #C8;
-static method test13() → () → self::B<core::num>
+static method test11() → () → self::B<core::String>
   return #C9;
-static method test14() → () → self::B<core::num>
+static method test12() → () → self::B<core::num>
   return #C10;
+static method test13() → () → self::B<core::num>
+  return #C11;
+static method test14() → () → self::B<core::num>
+  return #C12;
 static method test15() → () → self::B<core::num>
-  return <X extends core::num>.(#C2<X>)<core::num>;
+  return #C14;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return <X extends core::num>.(#C2<X>);
+  return #C13;
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
@@ -100,17 +100,17 @@
                                ^" in let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (<X extends core::num>.(#C2<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
 static method test18() → () → self::B<core::num>
-  return #C8;
-static method test19() → () → self::B<core::num>
-  return #C9;
-static method test20() → () → self::B<core::num>
   return #C10;
+static method test19() → () → self::B<core::num>
+  return #C11;
+static method test20() → () → self::B<core::num>
+  return #C12;
 static method test21() → () → self::B<core::num>
-  return <X extends core::num, unrelated Y extends core::String>.(#C2<X>)<core::num, core::String>;
+  return #C16;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return <X extends core::num, unrelated Y extends core::String>.(#C2<X>);
+  return #C15;
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
   return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
@@ -118,20 +118,27 @@
                                   ^" in let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
-                                  ^" in (<X extends core::num, unrelated Y extends core::String>.(#C2<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+                                  ^" in (#C15) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
 static method test24() → () → self::B<core::String>
-  return <X extends core::num>.(#C2<X>)<Never>;
+  return #C17;
 static method main() → dynamic {}
 
 constants  {
   #C1 = constructor-tearoff self::A::•
-  #C2 = constructor-tearoff self::B::•
-  #C3 = instantiation self::B::• <core::String>
-  #C4 = constructor-tearoff self::B::foo
-  #C5 = instantiation self::B::foo <core::String>
-  #C6 = static-tearoff self::B::bar
-  #C7 = instantiation self::B::bar <core::String>
-  #C8 = instantiation self::B::• <core::num>
-  #C9 = instantiation self::B::foo <core::num>
-  #C10 = instantiation self::B::bar <core::num>
+  #C2 = typedef-tearoff <unrelated X extends core::num>.(#C1)
+  #C3 = instantiation #C2 <core::num>
+  #C4 = constructor-tearoff self::B::•
+  #C5 = instantiation self::B::• <core::String>
+  #C6 = constructor-tearoff self::B::foo
+  #C7 = instantiation self::B::foo <core::String>
+  #C8 = static-tearoff self::B::bar
+  #C9 = instantiation self::B::bar <core::String>
+  #C10 = instantiation self::B::• <core::num>
+  #C11 = instantiation self::B::foo <core::num>
+  #C12 = instantiation self::B::bar <core::num>
+  #C13 = typedef-tearoff <X extends core::num>.(#C4<X>)
+  #C14 = instantiation #C13 <core::num>
+  #C15 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C4<X>)
+  #C16 = instantiation #C15 <core::num, core::String>
+  #C17 = instantiation #C13 <Never>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect
index 85a026d..ba0758d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect
@@ -63,36 +63,36 @@
 static method test2() → () → self::A
   return #C1;
 static method test3() → () → self::A
-  return <unrelated X extends core::num>.(#C1)<core::num>;
+  return #C3;
 static method test4() → () → self::A
-  return <unrelated X extends core::num>.(#C1)<core::num>;
+  return #C3;
 static method test5() → () → self::A
   return #C1;
 static method test6() → () → self::A
   return #C1;
 static method test7() → () → self::B<core::String>
-  return #C3;
+  return #C5;
 static method test8() → () → self::B<core::String>
-  return #C3;
+  return #C5;
 static method test9() → () → self::B<core::num>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<num> Function() test9() => DB1.new; // Error.
-                             ^" in (#C3) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+                             ^" in (#C5) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
 static method test10() → () → self::B<core::String>
-  return #C5;
-static method test11() → () → self::B<core::String>
   return #C7;
-static method test12() → () → self::B<core::num>
-  return #C8;
-static method test13() → () → self::B<core::num>
+static method test11() → () → self::B<core::String>
   return #C9;
-static method test14() → () → self::B<core::num>
+static method test12() → () → self::B<core::num>
   return #C10;
+static method test13() → () → self::B<core::num>
+  return #C11;
+static method test14() → () → self::B<core::num>
+  return #C12;
 static method test15() → () → self::B<core::num>
-  return <X extends core::num>.(#C2<X>)<core::num>;
+  return #C14;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return <X extends core::num>.(#C2<X>);
+  return #C13;
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
@@ -100,17 +100,17 @@
                                ^" in (let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (<X extends core::num>.(#C2<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
 static method test18() → () → self::B<core::num>
-  return #C8;
-static method test19() → () → self::B<core::num>
-  return #C9;
-static method test20() → () → self::B<core::num>
   return #C10;
+static method test19() → () → self::B<core::num>
+  return #C11;
+static method test20() → () → self::B<core::num>
+  return #C12;
 static method test21() → () → self::B<core::num>
-  return <X extends core::num, unrelated Y extends core::String>.(#C2<X>)<core::num, core::String>;
+  return #C16;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return <X extends core::num, unrelated Y extends core::String>.(#C2<X>);
+  return #C15;
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
   return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
@@ -118,20 +118,27 @@
                                   ^" in (let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
-                                  ^" in (<X extends core::num, unrelated Y extends core::String>.(#C2<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+                                  ^" in (#C15) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
 static method test24() → () → self::B<core::String>
-  return <X extends core::num>.(#C2<X>)<Never>;
+  return #C17;
 static method main() → dynamic {}
 
 constants  {
   #C1 = constructor-tearoff self::A::•
-  #C2 = constructor-tearoff self::B::•
-  #C3 = instantiation self::B::• <core::String*>
-  #C4 = constructor-tearoff self::B::foo
-  #C5 = instantiation self::B::foo <core::String*>
-  #C6 = static-tearoff self::B::bar
-  #C7 = instantiation self::B::bar <core::String*>
-  #C8 = instantiation self::B::• <core::num*>
-  #C9 = instantiation self::B::foo <core::num*>
-  #C10 = instantiation self::B::bar <core::num*>
+  #C2 = typedef-tearoff <unrelated X extends core::num>.(#C1)
+  #C3 = instantiation #C2 <core::num*>
+  #C4 = constructor-tearoff self::B::•
+  #C5 = instantiation self::B::• <core::String*>
+  #C6 = constructor-tearoff self::B::foo
+  #C7 = instantiation self::B::foo <core::String*>
+  #C8 = static-tearoff self::B::bar
+  #C9 = instantiation self::B::bar <core::String*>
+  #C10 = instantiation self::B::• <core::num*>
+  #C11 = instantiation self::B::foo <core::num*>
+  #C12 = instantiation self::B::bar <core::num*>
+  #C13 = typedef-tearoff <X extends core::num>.(#C4<X>)
+  #C14 = instantiation #C13 <core::num*>
+  #C15 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C4<X>)
+  #C16 = instantiation #C15 <core::num*, core::String*>
+  #C17 = instantiation #C13 <Never*>
 }
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect
index 5146a3b..b9c3245 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect
@@ -63,36 +63,36 @@
 static method test2() → () → self::A
   return #C1;
 static method test3() → () → self::A
-  return <unrelated X extends core::num>.(#C1)<core::num>;
+  return #C3;
 static method test4() → () → self::A
-  return <unrelated X extends core::num>.(#C1)<core::num>;
+  return #C3;
 static method test5() → () → self::A
   return #C1;
 static method test6() → () → self::A
   return #C1;
 static method test7() → () → self::B<core::String>
-  return #C3;
+  return #C5;
 static method test8() → () → self::B<core::String>
-  return #C3;
+  return #C5;
 static method test9() → () → self::B<core::num>
   return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<num> Function() test9() => DB1.new; // Error.
-                             ^" in (#C3) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+                             ^" in (#C5) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
 static method test10() → () → self::B<core::String>
-  return #C5;
-static method test11() → () → self::B<core::String>
   return #C7;
-static method test12() → () → self::B<core::num>
-  return #C8;
-static method test13() → () → self::B<core::num>
+static method test11() → () → self::B<core::String>
   return #C9;
-static method test14() → () → self::B<core::num>
+static method test12() → () → self::B<core::num>
   return #C10;
+static method test13() → () → self::B<core::num>
+  return #C11;
+static method test14() → () → self::B<core::num>
+  return #C12;
 static method test15() → () → self::B<core::num>
-  return <X extends core::num>.(#C2<X>)<core::num>;
+  return #C14;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return <X extends core::num>.(#C2<X>);
+  return #C13;
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
   return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
@@ -100,17 +100,17 @@
                                ^" in let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (<X extends core::num>.(#C2<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
 static method test18() → () → self::B<core::num>
-  return #C8;
-static method test19() → () → self::B<core::num>
-  return #C9;
-static method test20() → () → self::B<core::num>
   return #C10;
+static method test19() → () → self::B<core::num>
+  return #C11;
+static method test20() → () → self::B<core::num>
+  return #C12;
 static method test21() → () → self::B<core::num>
-  return <X extends core::num, unrelated Y extends core::String>.(#C2<X>)<core::num, core::String>;
+  return #C16;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return <X extends core::num, unrelated Y extends core::String>.(#C2<X>);
+  return #C15;
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
   return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
@@ -118,20 +118,27 @@
                                   ^" in let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
 B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
-                                  ^" in (<X extends core::num, unrelated Y extends core::String>.(#C2<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+                                  ^" in (#C15) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
 static method test24() → () → self::B<core::String>
-  return <X extends core::num>.(#C2<X>)<Never>;
+  return #C17;
 static method main() → dynamic {}
 
 constants  {
   #C1 = constructor-tearoff self::A::•
-  #C2 = constructor-tearoff self::B::•
-  #C3 = instantiation self::B::• <core::String*>
-  #C4 = constructor-tearoff self::B::foo
-  #C5 = instantiation self::B::foo <core::String*>
-  #C6 = static-tearoff self::B::bar
-  #C7 = instantiation self::B::bar <core::String*>
-  #C8 = instantiation self::B::• <core::num*>
-  #C9 = instantiation self::B::foo <core::num*>
-  #C10 = instantiation self::B::bar <core::num*>
+  #C2 = typedef-tearoff <unrelated X extends core::num>.(#C1)
+  #C3 = instantiation #C2 <core::num*>
+  #C4 = constructor-tearoff self::B::•
+  #C5 = instantiation self::B::• <core::String*>
+  #C6 = constructor-tearoff self::B::foo
+  #C7 = instantiation self::B::foo <core::String*>
+  #C8 = static-tearoff self::B::bar
+  #C9 = instantiation self::B::bar <core::String*>
+  #C10 = instantiation self::B::• <core::num*>
+  #C11 = instantiation self::B::foo <core::num*>
+  #C12 = instantiation self::B::bar <core::num*>
+  #C13 = typedef-tearoff <X extends core::num>.(#C4<X>)
+  #C14 = instantiation #C13 <core::num*>
+  #C15 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C4<X>)
+  #C16 = instantiation #C15 <core::num*, core::String*>
+  #C17 = instantiation #C13 <Never*>
 }
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index d6b5325..96b0f76 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -8,6 +8,7 @@
 
 dart2js/late_statics: SemiFuzzFailure # dartbug.com/45854
 
+constructor_tearoffs/const_tear_off: RuntimeError
 constructor_tearoffs/redirecting_constructors: RuntimeError
 constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 2fdf4fb..0aa79ba 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -6,6 +6,7 @@
 # the round trip for Kernel textual serialization where the initial binary
 # Kernel files are produced by compiling Dart code via Fasta.
 
+constructor_tearoffs/const_tear_off: RuntimeError
 constructor_tearoffs/redirecting_constructors: RuntimeError
 constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 690ab74..3f5fe28 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -23,6 +23,7 @@
 const_functions/const_functions_const_ctor: FormatterCrash
 const_functions/const_functions_const_ctor_error: FormatterCrash
 const_functions/const_functions_const_factory: FormatterCrash
+constructor_tearoffs/const_tear_off: FormatterCrash
 constructor_tearoffs/explicit_instantiation_errors: FormatterCrash
 constructor_tearoffs/explicit_new_as_unnamed: FormatterCrash
 constructor_tearoffs/generic_tearoff_with_context: FormatterCrash
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index f69c2ec..b92823f 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -11,6 +11,7 @@
 regress/utf_16_le_content.crash: SemiFuzzCrash
 dart2js/late_statics: SemiFuzzFailure # dartbug.com/45854
 
+constructor_tearoffs/const_tear_off: RuntimeError
 constructor_tearoffs/redirecting_constructors: RuntimeError
 constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 667092c..2dd4cf9 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -8721,10 +8721,9 @@
     FreshTypeParameters freshTypeParameters =
         getFreshTypeParameters(typeParameters);
     FunctionType type = expression.getStaticType(context) as FunctionType;
-    type = Substitution.combine(
-            Substitution.fromPairs(type.typeParameters, typeArguments),
-            freshTypeParameters.substitution)
-        .substituteType(type.withoutTypeParameters) as FunctionType;
+    type = freshTypeParameters.substitute(
+        Substitution.fromPairs(type.typeParameters, typeArguments)
+            .substituteType(type.withoutTypeParameters)) as FunctionType;
     return new FunctionType(
         type.positionalParameters, type.returnType, type.declaredNullability,
         namedParameters: type.namedParameters,
@@ -12903,7 +12902,7 @@
 }
 
 class InstantiationConstant extends Constant {
-  final TearOffConstant tearOffConstant;
+  final Constant tearOffConstant;
   final List<DartType> types;
 
   InstantiationConstant(this.tearOffConstant, this.types);
@@ -13101,6 +13100,8 @@
   final TearOffConstant tearOffConstant;
   final List<DartType> types;
 
+  late final int hashCode = _computeHashCode();
+
   TypedefTearOffConstant(this.parameters, this.tearOffConstant, this.types);
 
   visitChildren(Visitor v) {
@@ -13110,7 +13111,8 @@
   }
 
   R accept<R>(ConstantVisitor<R> v) => v.visitTypedefTearOffConstant(this);
-  R acceptReference<R>(Visitor<R> v) => v.visitTypedefTearOffConstant(this);
+  R acceptReference<R>(Visitor<R> v) =>
+      v.visitTypedefTearOffConstantReference(this);
 
   @override
   void toTextInternal(AstPrinter printer) {
@@ -13147,13 +13149,26 @@
     return true;
   }
 
+  int _computeHashCode() {
+    int hash = 1237;
+    for (int i = 0; i < parameters.length; ++i) {
+      TypeParameter parameter = parameters[i];
+      hash = 0x3fffffff & (hash * 31 + parameter.bound.hashCode);
+    }
+    for (int i = 0; i < types.length; ++i) {
+      hash = 0x3fffffff & (hash * 31 + types[i].hashCode);
+    }
+    hash = 0x3fffffff & (hash * 31 + tearOffConstant.hashCode);
+    return hash;
+  }
+
   DartType getType(StaticTypeContext context) {
     FunctionType type = tearOffConstant.getType(context) as FunctionType;
     FreshTypeParameters freshTypeParameters =
         getFreshTypeParameters(parameters);
     type = freshTypeParameters.substitute(
-            Substitution.fromPairs(parameters, types).substituteType(type))
-        as FunctionType;
+        Substitution.fromPairs(type.typeParameters, types)
+            .substituteType(type.withoutTypeParameters)) as FunctionType;
     return new FunctionType(
         type.positionalParameters, type.returnType, type.declaredNullability,
         namedParameters: type.namedParameters,
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 06cd777..42c9b87 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -448,17 +448,17 @@
   }
 
   Constant _readInstantiationConstant() {
-    final TearOffConstant tearOffConstant =
-        readConstantReference() as TearOffConstant;
+    final Constant tearOffConstant = readConstantReference();
     final List<DartType> types = readDartTypeList();
     return new InstantiationConstant(tearOffConstant, types);
   }
 
   Constant _readTypedefTearOffConstant() {
     final List<TypeParameter> parameters = readAndPushTypeParameterList();
-    final StaticTearOffConstant tearOffConstant =
-        readConstantReference() as StaticTearOffConstant;
+    final TearOffConstant tearOffConstant =
+        readConstantReference() as TearOffConstant;
     final List<DartType> types = readDartTypeList();
+    typeParameterStack.length -= parameters.length;
     return new TypedefTearOffConstant(parameters, tearOffConstant, types);
   }
 
@@ -1988,6 +1988,8 @@
         return _readConstructorTearOff();
       case Tag.TypedefTearOff:
         return _readTypedefTearOff();
+      case Tag.RedirectingFactoryTearOff:
+        return _readRedirectingFactoryTearOff();
       case Tag.MethodInvocation:
         return _readMethodInvocation();
       case Tag.InstanceInvocation:
@@ -2232,6 +2234,13 @@
     return new TypedefTearOff(typeParameters, expression, typeArguments);
   }
 
+  Expression _readRedirectingFactoryTearOff() {
+    int offset = readOffset();
+    Reference constructorReference = readNonNullMemberReference();
+    return new RedirectingFactoryTearOff.byReference(constructorReference)
+      ..fileOffset = offset;
+  }
+
   Expression _readStaticTearOff() {
     int offset = readOffset();
     return new StaticTearOff.byReference(readNonNullMemberReference())
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index d0d0343..babe0c6 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -2760,6 +2760,11 @@
   }
 
   @override
+  void visitTypedefTearOffConstantReference(TypedefTearOffConstant node) {
+    throw new UnsupportedError('serialization of TypedefTearOffConstants ');
+  }
+
+  @override
   void visitTypeLiteralConstant(TypeLiteralConstant node) {
     throw new UnsupportedError('serialization of TypeLiteralConstants');
   }
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 7c4b76b..bb2aace 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -74,7 +74,7 @@
 }
 
 abstract class DiagnosticReporter<M, C> {
-  void report(M message, int charOffset, int length, Uri fileUri,
+  void report(M message, int charOffset, int length, Uri? fileUri,
       {List<C> context});
 }
 
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index b2666d8..8a2af9b 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -2680,7 +2680,12 @@
     writeSpaced('=');
     writeWord('instantiation');
     writeSpace();
-    writeMemberReferenceFromReference(node.tearOffConstant.targetReference);
+    Constant tearOffConstant = node.tearOffConstant;
+    if (tearOffConstant is TearOffConstant) {
+      writeMemberReferenceFromReference(tearOffConstant.targetReference);
+    } else {
+      writeConstantReference(tearOffConstant);
+    }
     writeSpace();
     writeSymbol('<');
     writeList(node.types, writeType);
@@ -2705,6 +2710,26 @@
     endLine();
   }
 
+  visitTypedefTearOffConstant(TypedefTearOffConstant node) {
+    writeIndentation();
+    writeConstantReference(node);
+    writeSpaced('=');
+    writeWord('typedef-tearoff');
+    writeSpace();
+    writeTypeParameterList(node.parameters);
+    state = SYMBOL;
+    writeSymbol('.(');
+    writeConstantReference(node.tearOffConstant);
+    if (node.types.isNotEmpty) {
+      writeSymbol('<');
+      writeList(node.types, writeType);
+      writeSymbol('>');
+    }
+    writeSymbol(')');
+    state = WORD;
+    endLine();
+  }
+
   visitUnevaluatedConstant(UnevaluatedConstant node) {
     writeIndentation();
     writeConstantReference(node);
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index 0232a67..374cfc4 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -2283,7 +2283,7 @@
 TextSerializer<InstantiationConstant> instantiationConstantSerializer =
     Wrapped<Tuple2<Constant, List<DartType>>, InstantiationConstant>(
         (w) => Tuple2(w.tearOffConstant, w.types),
-        (u) => InstantiationConstant(u.first as TearOffConstant, u.second),
+        (u) => InstantiationConstant(u.first, u.second),
         Tuple2Serializer(
             constantSerializer, ListSerializer(dartTypeSerializer)));
 
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index 16d4c30..f589e8a 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -72,6 +72,8 @@
 
   bool inUnevaluatedConstant = false;
 
+  bool inConstant = false;
+
   Library? currentLibrary;
 
   Member? currentMember;
@@ -886,6 +888,31 @@
           " ${node.typedefNode.typeParameters.length} parameters.");
     }
   }
+
+  @override
+  void visitConstantExpression(ConstantExpression node) {
+    bool oldInConstant = inConstant;
+    inConstant = true;
+    visitChildren(node);
+    inConstant = oldInConstant;
+  }
+
+  @override
+  void visitTypeParameter(TypeParameter node) {
+    if (inConstant) {
+      // Don't expect the type parameters to have the current parent as parent.
+      node.visitChildren(this);
+    } else {
+      visitChildren(node);
+    }
+  }
+
+  @override
+  void visitTypedefTearOffConstant(TypedefTearOffConstant node) {
+    declareTypeParameters(node.parameters);
+    super.visitTypedefTearOffConstant(node);
+    undeclareTypeParameters(node.parameters);
+  }
 }
 
 void verifyGetStaticType(TypeEnvironment env, Component component) {
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index ebbb991..4a3134f 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -903,6 +903,8 @@
   R visitRedirectingFactoryTearOffConstantReference(
           RedirectingFactoryTearOffConstant node) =>
       defaultConstantReference(node);
+  R visitTypedefTearOffConstantReference(TypedefTearOffConstant node) =>
+      defaultConstantReference(node);
   R visitTypeLiteralConstantReference(TypeLiteralConstant node) =>
       defaultConstantReference(node);
   R visitUnevaluatedConstantReference(UnevaluatedConstant node) =>
diff --git a/pkg/kernel/test/constant_equals_test.dart b/pkg/kernel/test/constant_equals_test.dart
index 8674576..80611c6 100644
--- a/pkg/kernel/test/constant_equals_test.dart
+++ b/pkg/kernel/test/constant_equals_test.dart
@@ -8,6 +8,9 @@
   if (a != b) {
     throw 'Expected $a and $b to be equal.';
   }
+  if (a.hashCode != b.hashCode) {
+    throw 'Expected $a and $b hash codes to be equal.';
+  }
 }
 
 testNotEquals(Constant a, Constant b) {
diff --git a/pkg/vm/lib/dominators.dart b/pkg/vm/lib/dominators.dart
index f3b71ed..81309d3 100644
--- a/pkg/vm/lib/dominators.dart
+++ b/pkg/vm/lib/dominators.dart
@@ -2,18 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart=2.9
-
 class Vertex<T extends Vertex<T>> {
   // Input: vertices directly reachable from this vertex.
   final List<T> successors = <T>[];
 
   // Output: the nearest vertex that all paths from the root must go through to
   // reach this vertex.
-  T dominator;
+  T? dominator;
 
   bool isDominatedBy(T other) {
-    var d = this;
+    Vertex<T>? d = this;
     while (d != null) {
       if (d == other) {
         return true;
@@ -26,17 +24,17 @@
   // Temporaries. See Lengauer and Tarjan.
   final List<T> _predecessors = <T>[];
   int _semi = 0;
-  T _label;
-  T _ancestor;
-  T _parent;
-  List<T> _bucket;
+  T? _label;
+  T? _ancestor;
+  T? _parent;
+  List<T>? _bucket;
 }
 
 // T. Lengauer and R. E. Tarjan. "A Fast Algorithm for Finding Dominators
 // in a Flowgraph."
 computeDominators<T extends Vertex<T>>(T root) {
   // Lengauer and Tarjan Step 1.
-  final vertex = <T>[];
+  final vertex = <T?>[];
   vertex.add(null);
 
   var n = 0;
@@ -60,33 +58,35 @@
   dfs(root);
 
   forestCompress(T v) {
-    if (v._ancestor._ancestor != null) {
-      forestCompress(v._ancestor);
-      if (v._ancestor._label._semi < v._label._semi) {
-        v._label = v._ancestor._label;
+    T ancestor = v._ancestor!;
+    if (ancestor._ancestor != null) {
+      forestCompress(ancestor);
+      ancestor = v._ancestor!;
+      if (ancestor._label!._semi < v._label!._semi) {
+        v._label = ancestor._label;
       }
-      v._ancestor = v._ancestor._ancestor;
+      v._ancestor = ancestor._ancestor;
     }
   }
 
-  forestEval(T v) {
+  T forestEval(T v) {
     if (v._ancestor == null) {
       return v;
     } else {
       forestCompress(v);
-      return v._label;
+      return v._label!;
     }
   }
 
-  forestLink(T v, T w) {
+  forestLink(T? v, T w) {
     w._ancestor = v;
   }
 
   for (var i = vertex.length - 1; i > 1; i--) {
-    Vertex<T> w = vertex[i];
+    final T w = vertex[i]!;
 
     // Lengauer and Tarjan Step 2.
-    for (Vertex<T> v in w._predecessors) {
+    for (T v in w._predecessors) {
       if (v._semi == 0) continue; // Unreachable
 
       final u = forestEval(v);
@@ -95,7 +95,7 @@
       }
     }
 
-    Vertex<T> z = vertex[w._semi];
+    Vertex<T> z = vertex[w._semi]!;
     var b = z._bucket;
     if (b == null) {
       z._bucket = b = <T>[];
@@ -104,8 +104,7 @@
     forestLink(w._parent, w);
 
     // Lengauer and Tarjan Step 3.
-    z = w._parent;
-    assert(z != null);
+    z = w._parent!;
     b = z._bucket;
     z._bucket = null;
     if (b != null) {
@@ -118,9 +117,9 @@
 
   // Lengauer and Tarjan Step 4.
   for (var i = 2; i < vertex.length; i++) {
-    final w = vertex[i];
+    final T w = vertex[i]!;
     if (w.dominator != vertex[w._semi]) {
-      w.dominator = w.dominator.dominator;
+      w.dominator = w.dominator!.dominator;
     }
   }
 }
diff --git a/pkg/vm/lib/http_filesystem.dart b/pkg/vm/lib/http_filesystem.dart
index 401d859..18ee3e1 100644
--- a/pkg/vm/lib/http_filesystem.dart
+++ b/pkg/vm/lib/http_filesystem.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' as io;
 
@@ -66,7 +64,7 @@
   }
 
   Future<T> connectAndRun<T>(Future<T> body(io.HttpClient httpClient)) async {
-    io.HttpClient httpClient;
+    io.HttpClient? httpClient;
     try {
       httpClient = new io.HttpClient();
       // Set timeout to be shorter than anticipated OS default
diff --git a/pkg/vm/lib/transformations/deferred_loading.dart b/pkg/vm/lib/transformations/deferred_loading.dart
index ce46af7..b7dd321 100644
--- a/pkg/vm/lib/transformations/deferred_loading.dart
+++ b/pkg/vm/lib/transformations/deferred_loading.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
-
 library vm.transformations.deferred_loading;
 
 import 'package:kernel/ast.dart';
@@ -11,15 +9,15 @@
 import '../metadata/loading_units.dart';
 
 class _LoadingUnitBuilder {
-  int id;
+  late int id;
   final _LibraryVertex root;
   final List<Library> members = <Library>[];
   final List<_LoadingUnitBuilder> children = <_LoadingUnitBuilder>[];
 
   _LoadingUnitBuilder(this.root);
 
-  _LoadingUnitBuilder get parent => root.dominator?.loadingUnit;
-  int get parentId => parent == null ? 0 : parent.id;
+  _LoadingUnitBuilder? get parent => root.dominator?.loadingUnit;
+  int get parentId => parent == null ? 0 : parent!.id;
 
   LoadingUnit asLoadingUnit() {
     return new LoadingUnit(
@@ -33,7 +31,7 @@
 class _LibraryVertex extends Vertex<_LibraryVertex> {
   final Library library;
   bool isLoadingRoot = true;
-  _LoadingUnitBuilder loadingUnit;
+  _LoadingUnitBuilder? loadingUnit;
   _LibraryVertex(this.library);
 
   String toString() => "_LibraryVertex(${library.importUri})";
@@ -47,11 +45,11 @@
   }
   for (final vertex in map.values) {
     for (final dep in vertex.library.dependencies) {
-      final target = map[dep.targetLibrary];
+      final target = map[dep.targetLibrary]!;
       vertex.successors.add(target);
     }
   }
-  final root = map[component.mainMethod.parent as Library];
+  final root = map[component.mainMethod!.enclosingLibrary]!;
 
   // Fake imports from root library to every core library so they end up in
   // the same loading unit attributed to the user's root library.
@@ -73,7 +71,7 @@
       if (dep.isDeferred) {
         continue;
       }
-      var importee = map[dep.targetLibrary];
+      var importee = map[dep.targetLibrary]!;
       if (importer.isDominatedBy(importee)) {
         continue;
       }
@@ -82,7 +80,7 @@
   }
   assert(root.isLoadingRoot);
 
-  var loadingUnits = <_LoadingUnitBuilder>[];
+  final List<_LoadingUnitBuilder> loadingUnits = <_LoadingUnitBuilder>[];
   for (var vertex in map.values) {
     if (vertex.isLoadingRoot) {
       var unit = new _LoadingUnitBuilder(vertex);
@@ -101,11 +99,11 @@
     if (dom == null) {
       continue; // Unreachable library.
     }
-    while (dom.loadingUnit == null) {
+    while (dom!.loadingUnit == null) {
       dom = dom.dominator;
     }
     vertex.loadingUnit = dom.loadingUnit;
-    vertex.loadingUnit.members.add(vertex.library);
+    vertex.loadingUnit!.members.add(vertex.library);
   }
 
   // 4. Sort loading units so parents are before children. Normally this order
@@ -119,7 +117,7 @@
   }
   var index = 0;
   loadingUnits.clear();
-  loadingUnits.add(root.loadingUnit);
+  loadingUnits.add(root.loadingUnit!);
   while (index < loadingUnits.length) {
     var unit = loadingUnits[index];
     unit.id = ++index;
diff --git a/pkg/vm/lib/transformations/devirtualization.dart b/pkg/vm/lib/transformations/devirtualization.dart
index 559dcb2..7d82594 100644
--- a/pkg/vm/lib/transformations/devirtualization.dart
+++ b/pkg/vm/lib/transformations/devirtualization.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
-
 library vm.transformations.cha_devirtualization;
 
 import 'package:kernel/ast.dart';
@@ -18,7 +16,8 @@
 Component transformComponent(CoreTypes coreTypes, Component component) {
   void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
   ClosedWorldClassHierarchy hierarchy = new ClassHierarchy(component, coreTypes,
-      onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
+          onAmbiguousSupertypes: ignoreAmbiguousSupertypes)
+      as ClosedWorldClassHierarchy;
   final hierarchySubtypes = hierarchy.computeSubtypesInformation();
   new CHADevirtualization(coreTypes, component, hierarchy, hierarchySubtypes)
       .visitComponent(component);
@@ -34,14 +33,14 @@
   static const _trace = const bool.fromEnvironment('trace.devirtualization');
 
   final DirectCallMetadataRepository _metadata;
-  Set<Name> _objectMemberNames;
+  final Set<Name> _objectMemberNames;
 
   Devirtualization(
       CoreTypes coreTypes, Component component, ClassHierarchy hierarchy)
-      : _metadata = new DirectCallMetadataRepository() {
-    _objectMemberNames = new Set<Name>.from(hierarchy
-        .getInterfaceMembers(coreTypes.objectClass)
-        .map((Member m) => m.name));
+      : _metadata = new DirectCallMetadataRepository(),
+        _objectMemberNames = new Set<Name>.from(hierarchy
+            .getInterfaceMembers(coreTypes.objectClass)
+            .map((Member m) => m.name)) {
     component.addMetadataRepository(_metadata);
   }
 
@@ -51,7 +50,7 @@
       (member is Field) || ((member is Procedure) && member.isGetter);
 
   bool isLegalTargetForMethodInvocation(Member target, Arguments arguments) {
-    final FunctionNode func = target.function;
+    final FunctionNode func = target.function!;
 
     final positionalArgs = arguments.positional.length;
     if ((positionalArgs < func.requiredParameterCount) ||
@@ -84,10 +83,10 @@
       directCall.checkReceiverForNull &&
       _objectMemberNames.contains(directCall.target.name);
 
-  DirectCallMetadata getDirectCall(TreeNode node, Member interfaceTarget,
+  DirectCallMetadata? getDirectCall(TreeNode node, Member? interfaceTarget,
       {bool setter = false});
 
-  makeDirectCall(TreeNode node, Member target, DirectCallMetadata directCall) {
+  makeDirectCall(TreeNode node, Member? target, DirectCallMetadata directCall) {
     if (_trace) {
       print("[devirt] Resolving ${target} to ${directCall.target}"
           " at ${node.location}");
@@ -104,12 +103,12 @@
   }
 
   void _handleMethodInvocation(
-      TreeNode node, Member target, Arguments arguments) {
+      TreeNode node, Member? target, Arguments arguments) {
     if (target != null && !isMethod(target)) {
       return;
     }
 
-    final DirectCallMetadata directCall = getDirectCall(node, target);
+    final DirectCallMetadata? directCall = getDirectCall(node, target);
 
     // TODO(alexmarkov): Convert _isLegalTargetForMethodInvocation()
     // check into an assertion once front-end implements all override checks.
@@ -138,18 +137,18 @@
     super.visitEqualsCall(node);
 
     final target = node.interfaceTarget;
-    final DirectCallMetadata directCall = getDirectCall(node, target);
+    final DirectCallMetadata? directCall = getDirectCall(node, target);
     if (directCall != null && !directCall.checkReceiverForNull) {
       makeDirectCall(node, target, directCall);
     }
   }
 
-  void _handlePropertyGet(TreeNode node, Member target) {
+  void _handlePropertyGet(TreeNode node, Member? target) {
     if (target != null && !isFieldOrGetter(target)) {
       return;
     }
 
-    final DirectCallMetadata directCall = getDirectCall(node, target);
+    final DirectCallMetadata? directCall = getDirectCall(node, target);
 
     if ((directCall != null) &&
         isFieldOrGetter(directCall.target) &&
@@ -170,8 +169,8 @@
     _handlePropertyGet(node, null);
   }
 
-  void _handlePropertySet(TreeNode node, Member target) {
-    final DirectCallMetadata directCall =
+  void _handlePropertySet(TreeNode node, Member? target) {
+    final DirectCallMetadata? directCall =
         getDirectCall(node, target, setter: true);
     if (directCall != null) {
       makeDirectCall(node, target, directCall);
@@ -200,12 +199,12 @@
       : super(coreTypes, component, hierarchy);
 
   @override
-  DirectCallMetadata getDirectCall(TreeNode node, Member interfaceTarget,
+  DirectCallMetadata? getDirectCall(TreeNode node, Member? interfaceTarget,
       {bool setter = false}) {
     if (interfaceTarget == null) {
       return null;
     }
-    Member singleTarget = _hierarchySubtype
+    Member? singleTarget = _hierarchySubtype
         .getSingleTargetForInterfaceInvocation(interfaceTarget, setter: setter);
     if (singleTarget == null) {
       return null;
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index bc29a1a..93dc309 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -292,7 +292,9 @@
   /// Classes corresponding to [NativeType], indexed by [NativeType].
   final List<Class> nativeTypesClasses;
 
-  Library? currentLibrary;
+  Library? _currentLibrary;
+  Library get currentLibrary => _currentLibrary!;
+
   IndexedLibrary? currentLibraryIndex;
 
   FfiTransformer(this.index, this.coreTypes, this.hierarchy,
@@ -459,11 +461,11 @@
 
   @override
   TreeNode visitLibrary(Library node) {
-    assert(currentLibrary == null);
-    currentLibrary = node;
+    assert(_currentLibrary == null);
+    _currentLibrary = node;
     currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
     final result = super.visitLibrary(node);
-    currentLibrary = null;
+    _currentLibrary = null;
     return result;
   }
 
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index 26cdd5e..2238251 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -2,10 +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
-
-library vm.transformations.ffi_definitions;
-
 import 'dart:math' as math;
 
 import 'package:front_end/src/api_unstable/vm.dart'
@@ -71,8 +67,8 @@
     ClassHierarchy hierarchy,
     List<Library> libraries,
     DiagnosticReporter diagnosticReporter,
-    ReferenceFromIndex referenceFromIndex,
-    ChangedStructureNotifier changedStructureNotifier) {
+    ReferenceFromIndex? referenceFromIndex,
+    ChangedStructureNotifier? changedStructureNotifier) {
   final LibraryIndex index = LibraryIndex(component,
       const ["dart:core", "dart:ffi", "dart:_internal", "dart:typed_data"]);
   if (!index.containsLibrary("dart:ffi")) {
@@ -96,7 +92,7 @@
   CompoundDependencyGraph(this.map);
 
   Iterable<T> get vertices => map.keys;
-  Iterable<T> neighborsOf(T vertex) => map[vertex];
+  Iterable<T> neighborsOf(T vertex) => map[vertex]!;
 }
 
 /// Checks and elaborates the dart:ffi compounds and their fields.
@@ -109,16 +105,14 @@
   Set<Class> transformCompoundsInvalid = {};
   Map<Class, NativeTypeCfe> compoundCache = {};
 
-  ChangedStructureNotifier changedStructureNotifier;
-
-  IndexedLibrary currentLibraryIndex;
+  ChangedStructureNotifier? changedStructureNotifier;
 
   _FfiDefinitionTransformer(
       this.index,
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       DiagnosticReporter diagnosticReporter,
-      ReferenceFromIndex referenceFromIndex,
+      ReferenceFromIndex? referenceFromIndex,
       this.changedStructureNotifier)
       : super(index, coreTypes, hierarchy, diagnosticReporter,
             referenceFromIndex) {}
@@ -185,7 +179,7 @@
         report = true;
       }
       if (component.length == 1) {
-        if (dependencyGraph.map[component.single].contains(component.single)) {
+        if (dependencyGraph.map[component.single]!.contains(component.single)) {
           // Direct cycle.
           report = true;
         }
@@ -193,7 +187,7 @@
       if (report) {
         component.forEach((Class e) {
           diagnosticReporter.report(
-              templateFfiFieldCyclic.withArguments(e.superclass.name, e.name,
+              templateFfiFieldCyclic.withArguments(e.superclass!.name, e.name,
                   component.map((e) => e.name).toList()),
               e.fileOffset,
               e.name.length,
@@ -233,12 +227,6 @@
   }
 
   @override
-  visitLibrary(Library node) {
-    currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
-    return super.visitLibrary(node);
-  }
-
-  @override
   visitExtension(Extension node) {
     // The extension and it's members are only metadata.
     return node;
@@ -262,9 +250,12 @@
 
     final packing = _checkCompoundClass(node);
 
-    final indexedClass = currentLibraryIndex?.lookupIndexedClass(node.name);
+    final IndexedClass? indexedClass =
+        currentLibraryIndex?.lookupIndexedClass(node.name);
     _checkConstructors(node, indexedClass);
-    indexedCompoundClasses[node] = indexedClass;
+    if (indexedClass != null) {
+      indexedCompoundClasses[node] = indexedClass;
+    }
 
     final fieldsValid = _checkFieldAnnotations(node, packing);
     if (fieldsValid) {
@@ -278,14 +269,14 @@
   }
 
   /// Returns packing if any.
-  int _checkCompoundClass(Class node) {
+  int? _checkCompoundClass(Class node) {
     if (node.typeParameters.length > 0) {
       diagnosticReporter.report(
           templateFfiStructGeneric.withArguments(
-              node.superclass.name, node.name),
+              node.superclass!.name, node.name),
           node.fileOffset,
           1,
-          node.location.file);
+          node.location!.file);
     }
 
     if (node.superclass != structClass && node.superclass != unionClass) {
@@ -301,7 +292,7 @@
             templateFfiPackedAnnotation.withArguments(node.name),
             node.fileOffset,
             node.name.length,
-            node.location.file);
+            node.location!.file);
       }
       if (packingAnnotations.isNotEmpty) {
         final packing = packingAnnotations.first;
@@ -311,7 +302,7 @@
             packing == 8 ||
             packing == 16)) {
           diagnosticReporter.report(messageFfiPackedAnnotationAlignment,
-              node.fileOffset, node.name.length, node.location.file);
+              node.fileOffset, node.name.length, node.location!.file);
         }
         return packing;
       }
@@ -354,14 +345,14 @@
     if (member is Field) {
       return member.type;
     }
-    final Procedure p = member;
+    final p = member as Procedure;
     if (p.isGetter) {
       return p.function.returnType;
     }
     return p.function.positionalParameters.single.type;
   }
 
-  bool _checkFieldAnnotations(Class node, int packing) {
+  bool _checkFieldAnnotations(Class node, int? packing) {
     bool success = true;
     final membersWithAnnotations =
         _compoundFieldMembers(node, includeSetters: false);
@@ -445,9 +436,9 @@
         success = false;
       } else {
         final DartType nativeType = InterfaceType(
-            nativeTypesClasses[_getFieldType(nativeTypeAnnos.first).index],
+            nativeTypesClasses[_getFieldType(nativeTypeAnnos.first)!.index],
             Nullability.legacy);
-        final DartType shouldBeDartType = convertNativeTypeToDartType(
+        final DartType? shouldBeDartType = convertNativeTypeToDartType(
             nativeType,
             allowCompounds: true,
             allowHandle: false);
@@ -455,11 +446,11 @@
             !env.isSubtypeOf(type, shouldBeDartType,
                 SubtypeCheckMode.ignoringNullabilities)) {
           diagnosticReporter.report(
-              templateFfiTypeMismatch.withArguments(type, shouldBeDartType,
+              templateFfiTypeMismatch.withArguments(type, shouldBeDartType!,
                   nativeType, node.enclosingLibrary.isNonNullableByDefault),
               f.fileOffset,
               1,
-              f.location.file);
+              f.location!.file);
           // This class is invalid, but continue reporting other errors on it.
           success = false;
         }
@@ -468,7 +459,7 @@
     return success;
   }
 
-  void _checkPacking(Class outerClass, int outerClassPacking, Class fieldClass,
+  void _checkPacking(Class outerClass, int? outerClassPacking, Class fieldClass,
       Member errorNode) {
     if (outerClassPacking == null) {
       // Outer struct has no packing, nesting anything is fine.
@@ -497,7 +488,7 @@
     }
   }
 
-  void _checkConstructors(Class node, IndexedClass indexedClass) {
+  void _checkConstructors(Class node, IndexedClass? indexedClass) {
     final toRemove = <Initializer>[];
 
     // Constructors cannot have initializers because initializers refer to
@@ -510,13 +501,13 @@
               templateFfiFieldInitializer.withArguments(i.field.name.text),
               i.fileOffset,
               1,
-              i.location.file);
+              i.location!.file);
         }
       }
     }
     // Remove initializers referring to fields to prevent cascading errors.
     for (final Initializer i in toRemove) {
-      final Constructor c = i.parent;
+      final c = i.parent as Constructor;
       c.initializers.remove(i);
     }
 
@@ -565,7 +556,7 @@
       final dartType = _compoundMemberType(m);
 
       // Nullable.
-      NativeTypeCfe type;
+      NativeTypeCfe? type;
       if (isArrayType(dartType)) {
         final sizeAnnotations = _getArraySizeAnnotations(m).toList();
         if (sizeAnnotations.length == 1) {
@@ -584,7 +575,7 @@
         final nativeTypeAnnos = _getNativeTypeAnnotations(m).toList();
         if (nativeTypeAnnos.length == 1) {
           final clazz = nativeTypeAnnos.first;
-          final nativeType = _getFieldType(clazz);
+          final nativeType = _getFieldType(clazz)!;
           type = PrimitiveNativeTypeCfe(nativeType, clazz);
         }
       }
@@ -635,17 +626,18 @@
   ///
   /// Returns the total size of the compound (for all ABIs).
   void _replaceFields(
-      Class node, IndexedClass indexedClass, CompoundData compoundData) {
+      Class node, IndexedClass? indexedClass, CompoundData compoundData) {
     final compoundType = compoundData.compoundType as CompoundNativeTypeCfe;
     final compoundLayout = compoundType.layout;
 
     _annoteCompoundWithFields(node, compoundType.members, compoundData.packing);
     if (compoundType.members.isEmpty) {
       diagnosticReporter.report(
-          templateFfiEmptyStruct.withArguments(node.superclass.name, node.name),
+          templateFfiEmptyStruct.withArguments(
+              node.superclass!.name, node.name),
           node.fileOffset,
           node.name.length,
-          node.location.file);
+          node.location!.file);
     }
 
     final unalignedAccess = compoundData.packing != null;
@@ -653,9 +645,9 @@
     int i = 0;
     for (final compoundField in compoundData.compoundFields) {
       NativeTypeCfe type = compoundField.type;
-      Field field = compoundField.field;
-      Procedure getter = compoundField.getter;
-      Procedure setter = compoundField.setter;
+      Field? field = compoundField.field;
+      Procedure? getter = compoundField.getter;
+      Procedure? setter = compoundField.setter;
 
       final fieldOffsets = compoundLayout
           .map((Abi abi, CompoundLayout v) => MapEntry(abi, v.offsets[i]));
@@ -693,7 +685,7 @@
   static const vmFfiStructFields = "vm:ffi:struct-fields";
 
   // return value is nullable.
-  InstanceConstant _compoundAnnotatedFields(Class node) {
+  InstanceConstant? _compoundAnnotatedFields(Class node) {
     for (final annotation in node.annotations) {
       if (annotation is ConstantExpression) {
         final constant = annotation.constant;
@@ -701,7 +693,8 @@
             constant.classNode == pragmaClass &&
             constant.fieldValues[pragmaName.getterReference] ==
                 StringConstant(vmFfiStructFields)) {
-          return constant.fieldValues[pragmaOptions.getterReference];
+          return constant.fieldValues[pragmaOptions.getterReference]
+              as InstanceConstant?;
         }
       }
     }
@@ -726,7 +719,7 @@
 
   /// Must only be called if all the depencies are already in the cache.
   CompoundNativeTypeCfe _compoundAnnotatedNativeTypeCfe(Class compoundClass) {
-    final layoutConstant = _compoundAnnotatedFields(compoundClass);
+    final layoutConstant = _compoundAnnotatedFields(compoundClass)!;
     final fieldTypes = layoutConstant
         .fieldValues[ffiStructLayoutTypesField.getterReference] as ListConstant;
     final members = <NativeTypeCfe>[];
@@ -763,7 +756,7 @@
 
   // packing is `int?`.
   void _annoteCompoundWithFields(
-      Class node, List<NativeTypeCfe> types, int packing) {
+      Class node, List<NativeTypeCfe> types, int? packing) {
     List<Constant> constants =
         types.map((t) => t.generateConstant(this)).toList();
 
@@ -782,7 +775,7 @@
   }
 
   void _generateMethodsForField(Class node, Field field, NativeTypeCfe type,
-      Map<Abi, int> offsets, bool unalignedAccess, IndexedClass indexedClass) {
+      Map<Abi, int> offsets, bool unalignedAccess, IndexedClass? indexedClass) {
     // TODO(johnniwinther): Avoid passing [indexedClass]. When compiling
     // incrementally, [field] should already carry the references from
     // [indexedClass].
@@ -802,7 +795,7 @@
     node.addProcedure(getter);
 
     if (!field.isFinal) {
-      Reference setterReference =
+      Reference? setterReference =
           indexedClass?.lookupSetterReference(field.name) ??
               field.setterReference;
       assert(setterReference == field.setterReference,
@@ -832,8 +825,8 @@
   ///
   /// If sizes are not supplied still emits a field so that the use site
   /// transformer can still rewrite to it.
-  void _addSizeOfField(Class compound, IndexedClass indexedClass,
-      [Map<Abi, int> sizes = null]) {
+  void _addSizeOfField(Class compound, IndexedClass? indexedClass,
+      [Map<Abi, int>? sizes = null]) {
     if (sizes == null) {
       sizes = Map.fromEntries(Abi.values.map((abi) => MapEntry(abi, 0)));
     }
@@ -859,7 +852,7 @@
     compound.addProcedure(getter);
   }
 
-  NativeType _getFieldType(Class c) {
+  NativeType? _getFieldType(Class c) {
     final fieldType = getType(c);
 
     if (fieldType == NativeType.kVoid) {
@@ -928,10 +921,7 @@
 
 class CompoundData {
   final List<CompoundField> compoundFields;
-
-  // Nullable.
-  final int packing;
-
+  final int? packing;
   final NativeTypeCfe compoundType;
 
   CompoundData(this.compoundFields, this.packing, this.compoundType);
@@ -939,15 +929,9 @@
 
 class CompoundField {
   final NativeTypeCfe type;
-
-  // Nullable.
-  final Field field;
-
-  // Nullable.
-  final Procedure getter;
-
-  // Nullable.
-  final Procedure setter;
+  final Field? field;
+  final Procedure? getter;
+  final Procedure? setter;
 
   CompoundField(this.type, this.field, this.getter, this.setter);
 }
@@ -974,11 +958,11 @@
 /// intimately to AST nodes such as [Class].
 abstract class NativeTypeCfe {
   factory NativeTypeCfe(FfiTransformer transformer, DartType dartType,
-      {List<int> arrayDimensions,
+      {List<int>? arrayDimensions,
       Map<Class, NativeTypeCfe> compoundCache = const {}}) {
     if (transformer.isPrimitiveType(dartType)) {
       final clazz = (dartType as InterfaceType).classNode;
-      final nativeType = transformer.getType(clazz);
+      final nativeType = transformer.getType(clazz)!;
       return PrimitiveNativeTypeCfe(nativeType, clazz);
     }
     if (transformer.isPointerType(dartType)) {
@@ -987,7 +971,7 @@
     if (transformer.isCompoundSubtype(dartType)) {
       final clazz = (dartType as InterfaceType).classNode;
       if (compoundCache.containsKey(clazz)) {
-        return compoundCache[clazz];
+        return compoundCache[clazz]!;
       } else {
         throw "Class '$clazz' not found in compoundCache.";
       }
@@ -1094,8 +1078,8 @@
   }
 
   @override
-  Map<Abi, int> get alignment => Map.fromEntries(Abi.values.map(
-      (abi) => MapEntry(abi, nonSizeAlignment[abi][nativeType] ?? size[abi])));
+  Map<Abi, int> get alignment => Map.fromEntries(Abi.values.map((abi) =>
+      MapEntry(abi, nonSizeAlignment[abi]![nativeType] ?? size[abi]!)));
 
   @override
   Constant generateConstant(FfiTransformer transformer) =>
@@ -1107,8 +1091,8 @@
   bool isUnaligned(Map<Abi, int> offsets) {
     final alignments = alignment;
     for (final abi in offsets.keys) {
-      final offset = offsets[abi];
-      final alignment = alignments[abi];
+      final offset = offsets[abi]!;
+      final alignment = alignments[abi]!;
       if (offset % alignment != 0) {
         return true;
       }
@@ -1131,7 +1115,7 @@
       ReturnStatement(StaticInvocation(
           (unalignedAccess && isFloat
               ? transformer.loadUnalignedMethods
-              : transformer.loadMethods)[nativeType],
+              : transformer.loadMethods)[nativeType]!,
           Arguments([
             transformer.getCompoundTypedDataBaseField(
                 ThisExpression(), fileOffset),
@@ -1155,7 +1139,7 @@
       ReturnStatement(StaticInvocation(
           (unalignedAccess && isFloat
               ? transformer.storeUnalignedMethods
-              : transformer.storeMethods)[nativeType],
+              : transformer.storeMethods)[nativeType]!,
           Arguments([
             transformer.getCompoundTypedDataBaseField(
                 ThisExpression(), fileOffset),
@@ -1176,7 +1160,7 @@
   Constant generateConstant(FfiTransformer transformer) => TypeLiteralConstant(
           InterfaceType(transformer.pointerClass, Nullability.nonNullable, [
         InterfaceType(
-            transformer.pointerClass.superclass, Nullability.nonNullable)
+            transformer.pointerClass.superclass!, Nullability.nonNullable)
       ]));
 
   /// Sample output for `Pointer<Int8> get x =>`:
@@ -1195,7 +1179,7 @@
           transformer.fromAddressInternal,
           Arguments([
             StaticInvocation(
-                transformer.loadMethods[NativeType.kIntptr],
+                transformer.loadMethods[NativeType.kIntptr]!,
                 Arguments([
                   transformer.getCompoundTypedDataBaseField(
                       ThisExpression(), fileOffset),
@@ -1221,7 +1205,7 @@
           VariableDeclaration argument,
           FfiTransformer transformer) =>
       ReturnStatement(StaticInvocation(
-          transformer.storeMethods[NativeType.kIntptr],
+          transformer.storeMethods[NativeType.kIntptr]!,
           Arguments([
             transformer.getCompoundTypedDataBaseField(
                 ThisExpression(), fileOffset),
@@ -1312,10 +1296,10 @@
 
 class StructNativeTypeCfe extends CompoundNativeTypeCfe {
   // Nullable int.
-  final int packing;
+  final int? packing;
 
   factory StructNativeTypeCfe(Class clazz, List<NativeTypeCfe> members,
-      {int packing}) {
+      {int? packing}) {
     final layout = Map.fromEntries(Abi.values
         .map((abi) => MapEntry(abi, _calculateLayout(members, packing, abi))));
     return StructNativeTypeCfe._(clazz, members, packing, layout);
@@ -1328,13 +1312,13 @@
   // Keep consistent with runtime/vm/compiler/ffi/native_type.cc
   // NativeStructType::FromNativeTypes.
   static CompoundLayout _calculateLayout(
-      List<NativeTypeCfe> types, int packing, Abi abi) {
+      List<NativeTypeCfe> types, int? packing, Abi abi) {
     int offset = 0;
     final offsets = <int>[];
     int structAlignment = 1;
     for (int i = 0; i < types.length; i++) {
-      final int size = types[i].size[abi];
-      int alignment = types[i].alignment[abi];
+      final int size = types[i].size[abi]!;
+      int alignment = types[i].alignment[abi]!;
       if (packing != null && packing < alignment) {
         alignment = packing;
       }
@@ -1367,8 +1351,8 @@
     int unionSize = 1;
     int unionAlignment = 1;
     for (int i = 0; i < types.length; i++) {
-      final int size = types[i].size[abi];
-      int alignment = types[i].alignment[abi];
+      final int size = types[i].size[abi]!;
+      int alignment = types[i].alignment[abi]!;
       unionSize = math.max(unionSize, size);
       unionAlignment = math.max(unionAlignment, alignment);
     }
diff --git a/pkg/vm/lib/transformations/ffi_native.dart b/pkg/vm/lib/transformations/ffi_native.dart
index 76c25d0..54bdcb6 100644
--- a/pkg/vm/lib/transformations/ffi_native.dart
+++ b/pkg/vm/lib/transformations/ffi_native.dart
@@ -14,7 +14,9 @@
 
 /// Transform @FfiNative annotated functions into FFI native function pointer
 /// functions.
-void transformLibraries(Component component, List<Library> libraries,
+void transformLibraries(
+    Component component,
+    List<Library> libraries,
     DiagnosticReporter diagnosticReporter,
     ReferenceFromIndex? referenceFromIndex) {
   final index = LibraryIndex(component, ['dart:ffi']);
@@ -22,8 +24,8 @@
   if (index.tryGetClass('dart:ffi', 'FfiNative') == null) {
     return;
   }
-  final transformer = FfiNativeTransformer(index, diagnosticReporter,
-      referenceFromIndex);
+  final transformer =
+      FfiNativeTransformer(index, diagnosticReporter, referenceFromIndex);
   libraries.forEach(transformer.visitLibrary);
 }
 
@@ -41,8 +43,8 @@
   final Procedure asFunctionProcedure;
   final Procedure fromAddressInternal;
 
-  FfiNativeTransformer(LibraryIndex index, this.diagnosticReporter,
-      this.referenceFromIndex)
+  FfiNativeTransformer(
+      LibraryIndex index, this.diagnosticReporter, this.referenceFromIndex)
       : ffiNativeClass = index.getClass('dart:ffi', 'FfiNative'),
         nativeFunctionClass = index.getClass('dart:ffi', 'NativeFunction'),
         ffiNativeNameField =
@@ -169,11 +171,8 @@
     }
 
     if (!node.isStatic) {
-      diagnosticReporter.report(
-          messageFfiNativeAnnotationMustAnnotateStatic,
-          node.fileOffset,
-          1,
-          node.location!.file);
+      diagnosticReporter.report(messageFfiNativeAnnotationMustAnnotateStatic,
+          node.fileOffset, 1, node.location!.file);
     }
 
     node.isExternal = false;
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 7ee4ecc..49281ed 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -2,10 +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
-
-library vm.transformations.ffi_use_sites;
-
 import 'package:front_end/src/api_unstable/vm.dart'
     show
         messageFfiExceptionalReturnNull,
@@ -46,7 +42,7 @@
     ClassHierarchy hierarchy,
     List<Library> libraries,
     DiagnosticReporter diagnosticReporter,
-    ReferenceFromIndex referenceFromIndex) {
+    ReferenceFromIndex? referenceFromIndex) {
   final index = new LibraryIndex(
       component, ["dart:ffi", "dart:_internal", "dart:typed_data"]);
   if (!index.containsLibrary("dart:ffi")) {
@@ -66,7 +62,7 @@
 
 /// Checks and replaces calls to dart:ffi compound fields and methods.
 class _FfiUseSiteTransformer extends FfiTransformer {
-  StaticTypeContext _staticTypeContext;
+  StaticTypeContext? _staticTypeContext;
 
   bool get isFfiLibrary => currentLibrary == ffiLibrary;
 
@@ -79,7 +75,7 @@
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       DiagnosticReporter diagnosticReporter,
-      ReferenceFromIndex referenceFromIndex)
+      ReferenceFromIndex? referenceFromIndex)
       : super(index, coreTypes, hierarchy, diagnosticReporter,
             referenceFromIndex) {}
 
@@ -176,7 +172,7 @@
         _ensureNativeTypeValid(nativeType, node, allowCompounds: true);
 
         if (nativeType is InterfaceType) {
-          Expression inlineSizeOf = _inlineSizeOf(nativeType);
+          Expression? inlineSizeOf = _inlineSizeOf(nativeType);
           if (inlineSizeOf != null) {
             return inlineSizeOf;
           }
@@ -206,7 +202,7 @@
         return replacement;
       } else if (target == asFunctionMethod) {
         final dartType = node.arguments.types[1];
-        final DartType nativeType = InterfaceType(
+        final InterfaceType nativeType = InterfaceType(
             nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
 
         _ensureNativeTypeValid(nativeType, node);
@@ -214,10 +210,9 @@
         _ensureIsLeafIsConst(node);
         _ensureLeafCallDoesNotUseHandles(nativeType, node);
 
-        final DartType nativeSignature =
-            (nativeType as InterfaceType).typeArguments[0];
+        final DartType nativeSignature = nativeType.typeArguments[0];
 
-        bool isLeaf = _getIsLeafBoolean(node);
+        bool? isLeaf = _getIsLeafBoolean(node);
         if (isLeaf == null) {
           isLeaf = false;
         }
@@ -243,7 +238,7 @@
         final DartType nativeType = InterfaceType(
             nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
         final Expression func = node.arguments.positional[0];
-        final DartType dartType = func.getStaticType(_staticTypeContext);
+        final DartType dartType = func.getStaticType(_staticTypeContext!);
 
         _ensureIsStaticFunction(func);
 
@@ -257,7 +252,7 @@
             ((node.arguments.types[0] as FunctionType).returnType
                     as InterfaceType)
                 .classNode;
-        final NativeType expectedReturn = getType(expectedReturnClass);
+        final NativeType? expectedReturn = getType(expectedReturnClass);
 
         if (expectedReturn == NativeType.kVoid ||
             expectedReturn == NativeType.kPointer ||
@@ -309,7 +304,7 @@
           }
 
           final DartType returnType =
-              exceptionalReturn.getStaticType(_staticTypeContext);
+              exceptionalReturn.getStaticType(_staticTypeContext!);
 
           if (!env.isSubtypeOf(returnType, funcType.returnType,
               SubtypeCheckMode.ignoringNullabilities)) {
@@ -339,7 +334,7 @@
 
         // Inline the body to get rid of a generic invocation of sizeOf.
         // TODO(http://dartbug.com/39964): Add `allignmentOf<T>()` call.
-        Expression sizeInBytes = _inlineSizeOf(nativeType);
+        Expression? sizeInBytes = _inlineSizeOf(nativeType as InterfaceType);
         if (sizeInBytes != null) {
           if (node.arguments.positional.length == 2) {
             sizeInBytes = multiply(node.arguments.positional[1], sizeInBytes);
@@ -401,9 +396,9 @@
           .distinct()
           .fold(nestedExpression, _invokeCompoundConstructor);
 
-  Expression _inlineSizeOf(InterfaceType nativeType) {
+  Expression? _inlineSizeOf(InterfaceType nativeType) {
     final Class nativeClass = nativeType.classNode;
-    final NativeType nt = getType(nativeClass);
+    final NativeType? nt = getType(nativeClass);
     if (nt == null) {
       // User-defined compounds.
       final Procedure sizeOfGetter = nativeClass.procedures
@@ -457,7 +452,7 @@
                 .substituteType(lookupFunctionType.withoutTypeParameters)
             as FunctionType);
 
-    bool isLeaf = _getIsLeafBoolean(node);
+    bool? isLeaf = _getIsLeafBoolean(node);
     if (isLeaf == null) {
       isLeaf = false;
     }
@@ -518,7 +513,7 @@
           pointer,
           offsetByMethod.name,
           Arguments([
-            multiply(node.arguments.positional[1], _inlineSizeOf(dartType))
+            multiply(node.arguments.positional[1], _inlineSizeOf(dartType)!)
           ]),
           interfaceTarget: offsetByMethod,
           functionType:
@@ -536,8 +531,8 @@
 
     final typedDataBasePrime = typedDataBaseOffset(
         getArrayTypedDataBaseField(NullCheck(node.arguments.positional[0])),
-        multiply(node.arguments.positional[1], _inlineSizeOf(dartType)),
-        _inlineSizeOf(dartType),
+        multiply(node.arguments.positional[1], _inlineSizeOf(dartType)!),
+        _inlineSizeOf(dartType)!,
         dartType,
         node.fileOffset);
 
@@ -600,7 +595,7 @@
         type: coreTypes.intNonNullableRawType)
       ..fileOffset = node.fileOffset;
     final singleElementSizeVar = VariableDeclaration("#singleElementSize",
-        initializer: _inlineSizeOf(elementType),
+        initializer: _inlineSizeOf(elementType as InterfaceType),
         type: coreTypes.intNonNullableRawType)
       ..fileOffset = node.fileOffset;
     final elementSizeVar = VariableDeclaration("#elementSize",
@@ -684,12 +679,12 @@
     try {
       if (target == elementAtMethod) {
         final DartType pointerType =
-            node.receiver.getStaticType(_staticTypeContext);
-        final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
+            node.receiver.getStaticType(_staticTypeContext!);
+        final DartType nativeType = _pointerTypeGetTypeArg(pointerType)!;
 
         _ensureNativeTypeValid(nativeType, node, allowCompounds: true);
 
-        Expression inlineSizeOf = _inlineSizeOf(nativeType);
+        Expression? inlineSizeOf = _inlineSizeOf(nativeType as InterfaceType);
         if (inlineSizeOf != null) {
           // Generates `receiver.offsetBy(inlineSizeOfExpression)`.
           return InstanceInvocation(
@@ -714,7 +709,7 @@
     return node;
   }
 
-  DartType _pointerTypeGetTypeArg(DartType pointerType) {
+  DartType? _pointerTypeGetTypeArg(DartType pointerType) {
     return pointerType is InterfaceType ? pointerType.typeArguments[0] : null;
   }
 
@@ -724,7 +719,7 @@
     final DartType correspondingDartType = convertNativeTypeToDartType(
         nativeType,
         allowCompounds: true,
-        allowHandle: allowHandle);
+        allowHandle: allowHandle)!;
     if (dartType == correspondingDartType) return;
     if (env.isSubtypeOf(correspondingDartType, dartType,
         SubtypeCheckMode.ignoringNullabilities)) {
@@ -787,7 +782,7 @@
   /// Returns the class that should not be implemented or extended.
   ///
   /// If the superclass is not sealed, returns `null`.
-  Class _extendsOrImplementsSealedClass(Class klass) {
+  Class? _extendsOrImplementsSealedClass(Class klass) {
     // Classes in dart:ffi themselves can extend FFI classes.
     if (klass == arrayClass ||
         klass == arraySizeClass ||
@@ -824,7 +819,7 @@
   }
 
   void _ensureNotExtendsOrImplementsSealedClass(Class klass) {
-    final Class extended = _extendsOrImplementsSealedClass(klass);
+    final Class? extended = _extendsOrImplementsSealedClass(klass);
     if (extended != null) {
       diagnosticReporter.report(
           templateFfiExtendsOrImplementsSealedClass
@@ -840,7 +835,7 @@
   // - `true` if leaf
   // - `false` if not leaf
   // - `null` if the expression is not valid (e.g. non-const bool, null)
-  bool _getIsLeafBoolean(StaticInvocation node) {
+  bool? _getIsLeafBoolean(StaticInvocation node) {
     for (final named in node.arguments.named) {
       if (named.name == 'isLeaf') {
         final expr = named.value;
@@ -893,8 +888,8 @@
         }
       }
       // Check if any of the argument types are Handle.
-      for (InterfaceType param in functionType.positionalParameters) {
-        if (param.classNode == handleClass) {
+      for (DartType param in functionType.positionalParameters) {
+        if ((param as InterfaceType).classNode == handleClass) {
           diagnosticReporter.report(messageFfiLeafCallMustNotTakeHandle,
               node.fileOffset, 1, node.location?.file);
         }
diff --git a/pkg/vm/lib/transformations/list_literals_lowering.dart b/pkg/vm/lib/transformations/list_literals_lowering.dart
index c7f6739..1acb42f 100644
--- a/pkg/vm/lib/transformations/list_literals_lowering.dart
+++ b/pkg/vm/lib/transformations/list_literals_lowering.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:front_end/src/api_unstable/vm.dart'
     show isRedirectingFactoryField;
 import 'package:kernel/ast.dart';
@@ -24,23 +22,24 @@
   final Procedure _defaultFactory;
 
   // Specialized _GrowableList._literalN(e1, ..., eN) factories.
-  final List<Procedure> _specializedFactories =
-      List<Procedure>.filled(numSpecializedFactories, null);
+  final List<Procedure?> _specializedFactories =
+      List<Procedure?>.filled(numSpecializedFactories, null);
 
   ListLiteralsLowering(this.coreTypes)
       : _defaultFactory =
-            coreTypes.index.getMember('dart:core', '_GrowableList', '');
+            coreTypes.index.getProcedure('dart:core', '_GrowableList', '');
 
   Procedure getSpecializedFactory(int length) =>
       (_specializedFactories[length - 1] ??= coreTypes.index
-          .getMember('dart:core', '_GrowableList', '_literal$length'));
+          .getProcedure('dart:core', '_GrowableList', '_literal$length'));
 
   Expression transformListLiteral(ListLiteral node) {
     if (node.isConst) {
       throw 'Unexpected constant ListLiteral node'
           ' (such nodes should be converted to ConstantExpression): $node';
     }
-    if (node.parent is Field && isRedirectingFactoryField(node.parent)) {
+    final parent = node.parent;
+    if (parent is Field && isRedirectingFactoryField(parent)) {
       // Do not transform list literals which are used to represent
       // redirecting factories.
       return node;
diff --git a/pkg/vm/lib/transformations/lowering.dart b/pkg/vm/lib/transformations/lowering.dart
index 72932d9..d776f33 100644
--- a/pkg/vm/lib/transformations/lowering.dart
+++ b/pkg/vm/lib/transformations/lowering.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/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/core_types.dart' show CoreTypes;
@@ -39,8 +37,8 @@
   final FactorySpecializer factorySpecializer;
   final ListLiteralsLowering listLiteralsLowering;
 
-  Member _currentMember;
-  StaticTypeContext _cachedStaticTypeContext;
+  Member? _currentMember;
+  StaticTypeContext? _cachedStaticTypeContext;
 
   _Lowering(CoreTypes coreTypes, ClassHierarchy hierarchy, this.nullSafety)
       : env = TypeEnvironment(coreTypes, hierarchy),
@@ -49,7 +47,7 @@
         listLiteralsLowering = ListLiteralsLowering(coreTypes);
 
   StaticTypeContext get _staticTypeContext =>
-      _cachedStaticTypeContext ??= StaticTypeContext(_currentMember, env);
+      _cachedStaticTypeContext ??= StaticTypeContext(_currentMember!, env);
 
   @override
   defaultMember(Member node) {
diff --git a/pkg/vm/test/dominators_test.dart b/pkg/vm/test/dominators_test.dart
index 15163b2..f9e6ee6 100644
--- a/pkg/vm/test/dominators_test.dart
+++ b/pkg/vm/test/dominators_test.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:expect/expect.dart';
 import 'package:vm/dominators.dart';
 
diff --git a/pkg/vm_service/test/mark_main_isolate_as_system_isolate_test.dart b/pkg/vm_service/test/mark_main_isolate_as_system_isolate_test.dart
new file mode 100644
index 0000000..c69323d
--- /dev/null
+++ b/pkg/vm_service/test/mark_main_isolate_as_system_isolate_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart' as service;
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+foo(void _) async {
+  print('non system isolate started');
+  while (true) {}
+}
+
+testMain() async {
+  await Isolate.spawn<void>(foo, null);
+  print('started system isolate main');
+  while (true) {}
+}
+
+var tests = <VMTest>[
+  (service.VmService service) async {
+    final vm = await service.getVM();
+    expect(vm.isolates!.length, 1);
+    expect(vm.isolates!.first.name, 'foo');
+    expect(vm.systemIsolates!.length, greaterThanOrEqualTo(1));
+    expect(vm.systemIsolates!.where((e) => e.name == 'main').isNotEmpty, true);
+  }
+];
+
+main([args = const <String>[]]) => runVMTests(
+      args,
+      tests,
+      'mark_main_isolate_as_system_isolate_test.dart',
+      testeeConcurrent: testMain,
+      extraArgs: ['--mark-main-isolate-as-system-isolate'],
+    );
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index ba743e7..a288a79 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -934,6 +934,7 @@
   int exit_code = 0;
   Dart_IsolateFlags flags;
   Dart_IsolateFlagsInitialize(&flags);
+  flags.is_system_isolate = Options::mark_main_isolate_as_system_isolate();
 
   Dart_Isolate isolate = CreateIsolateGroupAndSetupHelper(
       /* is_main_isolate */ true, script_name, "main",
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 8f9736d..66e6fde 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -46,7 +46,8 @@
   V(disable_dart_dev, disable_dart_dev)                                        \
   V(long_ssl_cert_evaluation, long_ssl_cert_evaluation)                        \
   V(bypass_trusting_system_roots, bypass_trusting_system_roots)                \
-  V(delayed_filewatch_callback, delayed_filewatch_callback)
+  V(delayed_filewatch_callback, delayed_filewatch_callback)                    \
+  V(mark_main_isolate_as_system_isolate, mark_main_isolate_as_system_isolate)
 
 // Boolean flags that have a short form.
 #define SHORT_BOOL_OPTIONS_LIST(V)                                             \
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 18789db..0ca25ee 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -634,6 +634,7 @@
 
     // Make a copy of the state's isolate flags and hand it to the callback.
     Dart_IsolateFlags api_flags = *(state_->isolate_flags());
+    api_flags.is_system_isolate = false;
     Dart_Isolate isolate = (create_group_callback)(
         state_->script_url(), name, nullptr, state_->package_config(),
         &api_flags, parent_isolate_->init_callback_data(), &error);
diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc
index 035bf63..635b3d9 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.cc
+++ b/runtime/vm/compiler/frontend/prologue_builder.cc
@@ -68,6 +68,11 @@
   if (expect_type_args) {
     Fragment f = BuildTypeArgumentsHandling();
     if (link) prologue += f;
+
+    if (function_.IsClosureFunction()) {
+      Fragment f = BuildClosureDelayedTypeArgumentsHandling();
+      if (!compiling_for_osr_) prologue += f;
+    }
   }
 
   const bool is_empty_prologue = prologue.entry == prologue.current;
@@ -372,29 +377,33 @@
 
   handling += TestTypeArgsLen(store_null, store_type_args, 0);
 
-  const auto& function = parsed_function_->function();
-  if (function.IsClosureFunction()) {
-    LocalVariable* closure = parsed_function_->ParameterVariable(0);
-
-    // Currently, delayed type arguments can only be introduced through type
-    // inference in the FE. So if they are present, we can assume they are
-    // correct in number and bound.
-    Fragment use_delayed_type_args;
-    use_delayed_type_args += LoadLocal(closure);
-    use_delayed_type_args +=
-        LoadNativeField(Slot::Closure_delayed_type_arguments());
-    use_delayed_type_args +=
-        StoreLocal(TokenPosition::kNoSource, type_args_var);
-    use_delayed_type_args += Drop();
-
-    handling += TestDelayedTypeArgs(closure,
-                                    /*present=*/use_delayed_type_args,
-                                    /*absent=*/Fragment());
-  }
-
   return handling;
 }
 
+Fragment PrologueBuilder::BuildClosureDelayedTypeArgumentsHandling() {
+  const auto& function = parsed_function_->function();
+  ASSERT(function.IsClosureFunction());
+  LocalVariable* const type_args_var =
+      parsed_function_->RawTypeArgumentsVariable();
+  ASSERT(type_args_var != nullptr);
+
+  LocalVariable* const closure = parsed_function_->ParameterVariable(0);
+
+  // Currently, delayed type arguments can only be introduced through type
+  // inference in the FE. So if they are present, we can assume they are
+  // correct in number and bound.
+  Fragment use_delayed_type_args;
+  use_delayed_type_args += LoadLocal(closure);
+  use_delayed_type_args +=
+      LoadNativeField(Slot::Closure_delayed_type_arguments());
+  use_delayed_type_args += StoreLocal(TokenPosition::kNoSource, type_args_var);
+  use_delayed_type_args += Drop();
+
+  return TestDelayedTypeArgs(closure,
+                             /*present=*/use_delayed_type_args,
+                             /*absent=*/Fragment());
+}
+
 void PrologueBuilder::SortOptionalNamedParametersInto(int* opt_param_position,
                                                       int num_fixed_params,
                                                       int num_params) {
diff --git a/runtime/vm/compiler/frontend/prologue_builder.h b/runtime/vm/compiler/frontend/prologue_builder.h
index c8d629d..d474d72 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.h
+++ b/runtime/vm/compiler/frontend/prologue_builder.h
@@ -61,6 +61,8 @@
 
   Fragment BuildTypeArgumentsHandling();
 
+  Fragment BuildClosureDelayedTypeArgumentsHandling();
+
   LocalVariable* ParameterVariable(intptr_t index) {
     return parsed_function_->RawParameterVariable(index);
   }
diff --git a/tests/language/regress/regress46550_test.dart b/tests/language/regress/regress46550_test.dart
new file mode 100644
index 0000000..9b609da
--- /dev/null
+++ b/tests/language/regress/regress46550_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--optimization_counter_threshold=100 --deterministic
+
+import "package:expect/expect.dart";
+
+typedef void test1<T extends num>();
+
+void t1<T extends int>() {
+  Expect.equals(int, T);
+}
+
+const test1 res1 = t1;
+
+main() {
+  for (int i = 0; i < 120; ++i) {
+    res1();
+  }
+}
diff --git a/tests/language_2/regress/regress46550_test.dart b/tests/language_2/regress/regress46550_test.dart
new file mode 100644
index 0000000..9b609da
--- /dev/null
+++ b/tests/language_2/regress/regress46550_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--optimization_counter_threshold=100 --deterministic
+
+import "package:expect/expect.dart";
+
+typedef void test1<T extends num>();
+
+void t1<T extends int>() {
+  Expect.equals(int, T);
+}
+
+const test1 res1 = t1;
+
+main() {
+  for (int i = 0; i < 120; ++i) {
+    res1();
+  }
+}
diff --git a/tools/VERSION b/tools/VERSION
index 627df9f..1d8f46a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 344
+PRERELEASE 345
 PRERELEASE_PATCH 0
\ No newline at end of file