Version 2.14.0-310.0.dev

Merge commit '21af69a7a56f0e74bc8d5cba873d2ee3bd30579f' into 'dev'
diff --git a/DEPS b/DEPS
index 9ce5a3d..44d5d82 100644
--- a/DEPS
+++ b/DEPS
@@ -103,7 +103,7 @@
   #     and land the review.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-  "dart_style_rev": "0fe592042eda5d9eea6fc240a8ee0fe531bb0794",
+  "dart_style_rev": "9d9dff90d9a2e0793ad2f795f36c2777f720eda0",
 
   "dartdoc_rev" : "c9621b92c738ec21a348cc2de032858276e9c774",
   "devtools_rev" : "64cffbed6366329ad05e44d48fa2298367643bb6",
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 5dc3f5b..e49f3a2e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -11,6 +11,7 @@
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 
 import 'package:kernel/ast.dart';
+import 'package:kernel/type_algebra.dart';
 
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
@@ -24,6 +25,7 @@
 import '../builder/type_alias_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_declaration_builder.dart';
+import '../builder/type_variable_builder.dart';
 import '../builder/unresolved_type.dart';
 
 import '../constant_context.dart' show ConstantContext;
@@ -3099,6 +3101,7 @@
     TypeDeclarationBuilder? declarationBuilder = declaration;
     TypeAliasBuilder? aliasBuilder;
     List<TypeBuilder>? unaliasedTypeArguments;
+    bool isGenericTypedefTearOff = false;
     if (declarationBuilder is TypeAliasBuilder) {
       aliasBuilder = declarationBuilder;
       declarationBuilder = aliasBuilder.unaliasDeclaration(null,
@@ -3129,6 +3132,19 @@
                   ..fileUri = _uri
                   ..offset = fileOffset);
           }
+          if (aliasedTypeArguments == null &&
+              aliasBuilder.typeVariablesCount != 0) {
+            isGenericTypedefTearOff = true;
+            aliasedTypeArguments = <TypeBuilder>[];
+            for (TypeVariableBuilder typeVariable
+                in aliasBuilder.typeVariables!) {
+              aliasedTypeArguments.add(new NamedTypeBuilder(typeVariable.name,
+                  const NullabilityBuilder.omitted(), null, _uri, fileOffset)
+                ..bind(typeVariable));
+            }
+          }
+          unaliasedTypeArguments =
+              aliasBuilder.unaliasTypeArguments(aliasedTypeArguments);
         }
       }
     }
@@ -3177,10 +3193,31 @@
                 builtTypeArguments =
                     _helper.buildDartTypeArguments(typeArguments);
               }
-              return builtTypeArguments != null && builtTypeArguments.isNotEmpty
-                  ? _helper.forest.createInstantiation(
-                      token.charOffset, tearOffExpression, builtTypeArguments)
-                  : tearOffExpression;
+              if (isGenericTypedefTearOff) {
+                FreshTypeParameters freshTypeParameters =
+                    getFreshTypeParameters(
+                        aliasBuilder!.typedef.typeParameters);
+                List<DartType>? substitutedTypeArguments;
+                if (builtTypeArguments != null) {
+                  substitutedTypeArguments = <DartType>[];
+                  for (DartType builtTypeArgument in builtTypeArguments) {
+                    substitutedTypeArguments
+                        .add(freshTypeParameters.substitute(builtTypeArgument));
+                  }
+                }
+                tearOffExpression = _helper.forest.createTypedefTearOff(
+                    token.charOffset,
+                    freshTypeParameters.freshTypeParameters,
+                    tearOffExpression,
+                    substitutedTypeArguments ?? const <DartType>[]);
+              } else {
+                if (builtTypeArguments != null &&
+                    builtTypeArguments.isNotEmpty) {
+                  tearOffExpression = _helper.forest.createInstantiation(
+                      token.charOffset, tearOffExpression, builtTypeArguments);
+                }
+              }
+              return tearOffExpression;
             }
           }
           generator = new UnresolvedNameGenerator(_helper, send.token, name);
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 0a6909a..19e7096 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -846,6 +846,17 @@
     return new Instantiation(expression, typeArguments)
       ..fileOffset = fileOffset;
   }
+
+  TypedefTearOff createTypedefTearOff(
+      int fileOffset,
+      List<TypeParameter> typeParameters,
+      Expression expression,
+      List<DartType> typeArguments) {
+    // ignore: unnecessary_null_comparison
+    assert(fileOffset != null);
+    return new TypedefTearOff(typeParameters, expression, typeArguments)
+      ..fileOffset = fileOffset;
+  }
 }
 
 class _VariablesDeclaration extends Statement {
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index d87c8f9..7fc34a9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -7,7 +7,7 @@
 import 'package:front_end/src/api_prototype/lowering_predicates.dart';
 import 'package:kernel/ast.dart';
 import 'package:kernel/src/legacy_erasure.dart';
-import 'package:kernel/type_algebra.dart' show Substitution;
+import 'package:kernel/type_algebra.dart';
 import 'package:kernel/type_environment.dart';
 
 import '../../base/instrumentation.dart'
@@ -225,7 +225,37 @@
   @override
   ExpressionInferenceResult visitTypedefTearOff(
       TypedefTearOff node, DartType typeContext) {
-    return _unhandledExpression(node, typeContext);
+    ExpressionInferenceResult expressionResult = inferrer.inferExpression(
+        node.expression, const UnknownType(), true,
+        isVoidAllowed: true);
+    node.expression = expressionResult.expression..parent = node;
+
+    assert(
+        expressionResult.inferredType is FunctionType,
+        "Expected a FunctionType from tearing off a constructor from "
+        "a typedef, but got '${expressionResult.inferredType.runtimeType}'.");
+    FunctionType expressionType = expressionResult.inferredType as FunctionType;
+
+    assert(expressionType.typeParameters.length == node.typeArguments.length);
+    Substitution substitution = Substitution.fromPairs(
+        expressionType.typeParameters, node.typeArguments);
+    FunctionType resultType = substitution
+        .substituteType(expressionType.withoutTypeParameters) as FunctionType;
+    FreshTypeParameters freshTypeParameters =
+        getFreshTypeParameters(node.typeParameters);
+    resultType = freshTypeParameters.substitute(resultType) as FunctionType;
+    resultType = new FunctionType(resultType.positionalParameters,
+        resultType.returnType, resultType.declaredNullability,
+        namedParameters: resultType.namedParameters,
+        typeParameters: freshTypeParameters.freshTypeParameters,
+        requiredParameterCount: resultType.requiredParameterCount,
+        typedefType: null);
+    ExpressionInferenceResult inferredResult =
+        inferrer.instantiateTearOff(resultType, typeContext, node);
+    Expression ensuredResultExpression =
+        inferrer.ensureAssignableResult(typeContext, inferredResult);
+    return new ExpressionInferenceResult(
+        inferredResult.inferredType, ensuredResultExpression);
   }
 
   @override
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart
index 0abf8e6..1ee6b80 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart
@@ -45,7 +45,9 @@
 B<num> Function() test19() => DB3<num, String>.foo; // Ok.
 B<num> Function() test20() => DB3<num, String>.bar; // Ok.
 B<num> Function() test21() => DB3.new; // Ok.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
+B<Y> Function<Y extends num, Z extends String>() test22() => DB3.new; // Ok.
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+
+B<String> Function() test24() => DB2.new; // Ok.
 
 main() {}
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 0a4373e..0b438b0 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
@@ -15,24 +15,24 @@
 // B<num> Function() test9() => DB1.new; // Error.
 //                              ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-//                                            ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// 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.
 //                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// 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'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-//                                                              ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+//                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// 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() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+//                                   ^
+//
+// 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'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
 //                                   ^
 //
 import self as self;
@@ -63,9 +63,9 @@
 static method test2() → () → self::A
   return self::A::•;
 static method test3() → () → self::A
-  return self::A::•;
+  return <unrelated X extends core::num>.(self::A::•)<core::num>;
 static method test4() → () → self::A
-  return self::A::•;
+  return <unrelated X extends core::num>.(self::A::•)<core::num>;
 static method test5() → () → self::A
   return self::A::•;
 static method test6() → () → self::A
@@ -90,17 +90,17 @@
 static method test14() → () → self::B<core::num>
   return self::B::bar<core::num>;
 static method test15() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return <X extends core::num>.(self::B::•<X>)<core::num>;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-                                           ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+  return <X extends core::num>.(self::B::•<X>);
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<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'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" 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>.(self::B::•<X>)) 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 self::B::•<core::num>;
 static method test19() → () → self::B<core::num>
@@ -108,15 +108,17 @@
 static method test20() → () → self::B<core::num>
   return self::B::bar<core::num>;
 static method test21() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return <X extends core::num, unrelated Y extends core::String>.(self::B::•<X>)<core::num, core::String>;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-                                                             ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+  return <X extends core::num, unrelated Y extends core::String>.(self::B::•<X>);
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+  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'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
-                                  ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" 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>.(self::B::•<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%>;
+static method test24() → () → self::B<core::String>
+  return <X extends core::num>.(self::B::•<X>)<Never>;
 static method main() → dynamic {}
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 0a4373e..876caac 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
@@ -15,24 +15,24 @@
 // B<num> Function() test9() => DB1.new; // Error.
 //                              ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-//                                            ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// 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.
 //                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// 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'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-//                                                              ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+//                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// 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() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+//                                   ^
+//
+// 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'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
 //                                   ^
 //
 import self as self;
@@ -63,9 +63,9 @@
 static method test2() → () → self::A
   return self::A::•;
 static method test3() → () → self::A
-  return self::A::•;
+  return <unrelated X extends core::num>.(self::A::•)<core::num>;
 static method test4() → () → self::A
-  return self::A::•;
+  return <unrelated X extends core::num>.(self::A::•)<core::num>;
 static method test5() → () → self::A
   return self::A::•;
 static method test6() → () → self::A
@@ -90,17 +90,17 @@
 static method test14() → () → self::B<core::num>
   return self::B::bar<core::num>;
 static method test15() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return <X extends core::num>.(self::B::•<X>)<core::num>;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-                                           ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+  return <X extends core::num>.(self::B::•<X>);
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<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'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" 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>.(self::B::•<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
 static method test18() → () → self::B<core::num>
   return self::B::•<core::num>;
 static method test19() → () → self::B<core::num>
@@ -108,15 +108,17 @@
 static method test20() → () → self::B<core::num>
   return self::B::bar<core::num>;
 static method test21() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return <X extends core::num, unrelated Y extends core::String>.(self::B::•<X>)<core::num, core::String>;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-                                                             ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+  return <X extends core::num, unrelated Y extends core::String>.(self::B::•<X>);
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+  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'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
-                                  ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" 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>.(self::B::•<X>)) 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>.(self::B::•<X>)<Never>;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect
index fe0d7be..c3a7ab9 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect
@@ -30,6 +30,7 @@
 B<num> Function() test19() => DB3<num, String>.foo;
 B<num> Function() test20() => DB3<num, String>.bar;
 B<num> Function() test21() => DB3.new;
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new;
-B<Y> Function<Y, Z>() test23() => DB2.new;
+B<Y> Function<Y extends num, Z extends String>() test22() => DB3.new;
+B<Y> Function<Y, Z>() test23() => DB3.new;
+B<String> Function() test24() => DB2.new;
 main() {}
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 0a4373e..0b438b0 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
@@ -15,24 +15,24 @@
 // B<num> Function() test9() => DB1.new; // Error.
 //                              ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-//                                            ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// 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.
 //                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// 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'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-//                                                              ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+//                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// 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() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+//                                   ^
+//
+// 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'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
 //                                   ^
 //
 import self as self;
@@ -63,9 +63,9 @@
 static method test2() → () → self::A
   return self::A::•;
 static method test3() → () → self::A
-  return self::A::•;
+  return <unrelated X extends core::num>.(self::A::•)<core::num>;
 static method test4() → () → self::A
-  return self::A::•;
+  return <unrelated X extends core::num>.(self::A::•)<core::num>;
 static method test5() → () → self::A
   return self::A::•;
 static method test6() → () → self::A
@@ -90,17 +90,17 @@
 static method test14() → () → self::B<core::num>
   return self::B::bar<core::num>;
 static method test15() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return <X extends core::num>.(self::B::•<X>)<core::num>;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-                                           ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+  return <X extends core::num>.(self::B::•<X>);
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<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'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" 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>.(self::B::•<X>)) 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 self::B::•<core::num>;
 static method test19() → () → self::B<core::num>
@@ -108,15 +108,17 @@
 static method test20() → () → self::B<core::num>
   return self::B::bar<core::num>;
 static method test21() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return <X extends core::num, unrelated Y extends core::String>.(self::B::•<X>)<core::num, core::String>;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-                                                             ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+  return <X extends core::num, unrelated Y extends core::String>.(self::B::•<X>);
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+  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'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
-                                  ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" 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>.(self::B::•<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%>;
+static method test24() → () → self::B<core::String>
+  return <X extends core::num>.(self::B::•<X>)<Never>;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect
index 7110e07..fda6d4f 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect
@@ -65,5 +65,7 @@
   ;
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
   ;
+static method test24() → () → self::B<core::String>
+  ;
 static method main() → dynamic
   ;
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 0a4373e..876caac 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
@@ -15,24 +15,24 @@
 // B<num> Function() test9() => DB1.new; // Error.
 //                              ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-//  - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-//                                            ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// 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.
 //                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// 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'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-//                                                              ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+//                                ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// 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() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+//                                   ^
+//
+// 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'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
 //                                   ^
 //
 import self as self;
@@ -63,9 +63,9 @@
 static method test2() → () → self::A
   return self::A::•;
 static method test3() → () → self::A
-  return self::A::•;
+  return <unrelated X extends core::num>.(self::A::•)<core::num>;
 static method test4() → () → self::A
-  return self::A::•;
+  return <unrelated X extends core::num>.(self::A::•)<core::num>;
 static method test5() → () → self::A
   return self::A::•;
 static method test6() → () → self::A
@@ -90,17 +90,17 @@
 static method test14() → () → self::B<core::num>
   return self::B::bar<core::num>;
 static method test15() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return <X extends core::num>.(self::B::•<X>)<core::num>;
 static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
-  return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-                                           ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+  return <X extends core::num>.(self::B::•<X>);
 static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<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'.
 B<Y> Function<Y>() test17() => DB2.new; // Error.
-                               ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+                               ^" 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>.(self::B::•<X>)) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
 static method test18() → () → self::B<core::num>
   return self::B::•<core::num>;
 static method test19() → () → self::B<core::num>
@@ -108,15 +108,17 @@
 static method test20() → () → self::B<core::num>
   return self::B::bar<core::num>;
 static method test21() → () → self::B<core::num>
-  return self::B::•<core::num>;
+  return <X extends core::num, unrelated Y extends core::String>.(self::B::•<X>)<core::num, core::String>;
 static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
-  return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-                                                             ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+  return <X extends core::num, unrelated Y extends core::String>.(self::B::•<X>);
 static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
-  return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+  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'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
-                                  ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+                                  ^" 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>.(self::B::•<X>)) 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>.(self::B::•<X>)<Never>;
 static method main() → dynamic {}
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 4c7f24f..69b540a 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -8729,9 +8729,11 @@
 
   @override
   void toTextInternal(AstPrinter printer) {
-    printer.writeExpression(expression);
     printer.writeTypeParameters(typeParameters);
+    printer.write(".(");
+    printer.writeExpression(expression);
     printer.writeTypeArguments(typeArguments);
+    printer.write(")");
   }
 }
 
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 5460a6e..9018db9 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -1615,9 +1615,11 @@
   @override
   void visitTypedefTearOff(TypedefTearOff node) {
     writeByte(Tag.TypedefTearOff);
+    enterScope(typeParameters: node.typeParameters);
     writeNodeList(node.typeParameters);
     writeNode(node.expression);
     writeNodeList(node.typeArguments);
+    leaveScope(typeParameters: node.typeParameters);
   }
 
   @override
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 197bdfa..53fbe25 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -2055,6 +2055,20 @@
     writeMemberReferenceFromReference(node.constructorReference);
   }
 
+  visitTypedefTearOff(TypedefTearOff node) {
+    writeTypeParameterList(node.typeParameters);
+    state = SYMBOL;
+    writeSymbol('.(');
+    writeNode(node.expression);
+    if (node.typeArguments.isNotEmpty) {
+      writeSymbol('<');
+      writeList(node.typeArguments, writeType);
+      writeSymbol('>');
+    }
+    writeSymbol(')');
+    state = WORD;
+  }
+
   visitExpressionStatement(ExpressionStatement node) {
     writeIndentation();
     writeExpression(node.expression);
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index aec9d76..15a52eb 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -635,6 +635,13 @@
     }
   }
 
+  @override
+  void visitTypedefTearOff(TypedefTearOff node) {
+    declareTypeParameters(node.typeParameters);
+    super.visitTypedefTearOff(node);
+    undeclareTypeParameters(node.typeParameters);
+  }
+
   void checkTargetedInvocation(Member target, InvocationExpression node) {
     visitChildren(node);
     // ignore: unnecessary_null_comparison
diff --git a/pkg/vm/lib/transformations/ffi_native.dart b/pkg/vm/lib/transformations/ffi_native.dart
index f3fdb03..4c71d56 100644
--- a/pkg/vm/lib/transformations/ffi_native.dart
+++ b/pkg/vm/lib/transformations/ffi_native.dart
@@ -72,14 +72,14 @@
 
   // Transform:
   //   @FfiNative<Double Function(Double)>('Math_sqrt')
-  //   external double _sqrt(double x);
+  //   external double _square_root(double x);
   //
   // Into:
-  //   final _@FfiNative_Math_sqrt =
+  //   final _@FfiNative__square_root =
   //       Pointer<NativeFunction<Double Function(Double)>>
   //           .fromAddress(_ffi_resolver('dart:math', 'Math_sqrt'))
   //           .asFunction<double Function(double)>();
-  //   double _sqrt(double x) => _@FfiNative_Math_sqrt(x);
+  //   double _square_root(double x) => _@FfiNative__square_root(x);
   Statement transformFfiNative(
       Procedure node, InstanceConstant annotationConst) {
     assert(currentLibrary != null);
@@ -119,8 +119,8 @@
     final asFunctionInvocation = StaticInvocation(asFunctionProcedure,
         Arguments([fromAddressInvocation], types: [nativeType, dartType]));
 
-    // final _@FfiNative_Math_sqrt = ...
-    final fieldName = Name('_@FfiNative_${functionName.value}', currentLibrary);
+    // final _@FfiNative__square_root = ...
+    final fieldName = Name('_@FfiNative_${node.name.text}', currentLibrary);
     final funcPtrField = Field.immutable(fieldName,
         type: dartType,
         initializer: asFunctionInvocation,
@@ -130,7 +130,7 @@
         getterReference: currentLibraryIndex?.lookupGetterReference(fieldName));
     currentLibrary!.addField(funcPtrField);
 
-    // _@FfiNative_Math_sqrt(x)
+    // _@FfiNative__square_root(x)
     final callFuncPtrInvocation = FunctionInvocation(
         FunctionAccessKind.FunctionType,
         StaticGet(funcPtrField),
@@ -144,7 +144,7 @@
   visitProcedure(Procedure node) {
     // Only transform functions that are external and have FfiNative annotation:
     //   @FfiNative<Double Function(Double)>('Math_sqrt')
-    //   external double _sqrt(double x);
+    //   external double _square_root(double x);
     if (!node.isExternal) {
       return node;
     }
diff --git a/runtime/platform/atomic.h b/runtime/platform/atomic.h
index ffb5bdc..98bc900 100644
--- a/runtime/platform/atomic.h
+++ b/runtime/platform/atomic.h
@@ -21,16 +21,9 @@
   T load(std::memory_order order = std::memory_order_relaxed) const {
     return value_.load(order);
   }
-  T load(std::memory_order order = std::memory_order_relaxed) const volatile {
-    return value_.load(order);
-  }
   void store(T arg, std::memory_order order = std::memory_order_relaxed) {
     value_.store(arg, order);
   }
-  void store(T arg,
-             std::memory_order order = std::memory_order_relaxed) volatile {
-    value_.store(arg, order);
-  }
 
   T fetch_add(T arg, std::memory_order order = std::memory_order_relaxed) {
     return value_.fetch_add(arg, order);
@@ -51,12 +44,6 @@
       std::memory_order order = std::memory_order_relaxed) {
     return value_.compare_exchange_weak(expected, desired, order, order);
   }
-  bool compare_exchange_weak(
-      T& expected,  // NOLINT
-      T desired,
-      std::memory_order order = std::memory_order_relaxed) volatile {
-    return value_.compare_exchange_weak(expected, desired, order, order);
-  }
   bool compare_exchange_strong(
       T& expected,  // NOLINT
       T desired,
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index 57b9e6d2..4ea2271 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -792,20 +792,16 @@
         }
         intptr_t source_address = reloc.source_offset;
         if (reloc.source_symbol != nullptr) {
-          if (strcmp(reloc.source_symbol, ".") == 0) {
-            source_address += section_start + offset + reloc.section_offset;
-          } else {
-            auto* const source_symbol = symtab.Find(reloc.source_symbol);
-            ASSERT(source_symbol != nullptr);
-            source_address += source_symbol->offset;
-          }
+          auto* const source_symbol = symtab.Find(reloc.source_symbol);
+          ASSERT(source_symbol != nullptr);
+          source_address += source_symbol->offset;
+        } else {
+          source_address += section_start + offset + reloc.section_offset;
         }
         ASSERT(reloc.size_in_bytes <= kWordSize);
         word to_write = reloc.target_offset - source_address;
         if (reloc.target_symbol != nullptr) {
-          if (strcmp(reloc.target_symbol, ".") == 0) {
-            to_write += section_start + offset + reloc.section_offset;
-          } else if (auto* const symbol = symtab.Find(reloc.target_symbol)) {
+          if (auto* const symbol = symtab.Find(reloc.target_symbol)) {
             to_write += symbol->offset;
           } else {
             ASSERT_EQUAL(strcmp(reloc.target_symbol, kSnapshotBuildIdAsmSymbol),
@@ -818,6 +814,8 @@
             // InstructionsSection when there is no build ID.
             to_write = Image::kNoRelocatedAddress;
           }
+        } else {
+          to_write += section_start + offset + reloc.section_offset;
         }
         ASSERT(Utils::IsInt(reloc.size_in_bytes * kBitsPerByte, to_write));
         stream->WriteBytes(reinterpret_cast<const uint8_t*>(&to_write),
@@ -1249,12 +1247,12 @@
 
   void OffsetFromSymbol(const char* symbol, intptr_t offset) {
     relocations_->Add(
-        {kAddressSize, stream_->Position(), nullptr, 0, symbol, offset});
+        {kAddressSize, stream_->Position(), "", 0, symbol, offset});
     addr(0);  // Resolved later.
   }
   template <typename T>
   void RelativeSymbolOffset(const char* symbol) {
-    relocations_->Add({sizeof(T), stream_->Position(), ".", 0, symbol, 0});
+    relocations_->Add({sizeof(T), stream_->Position(), nullptr, 0, symbol, 0});
     stream_->WriteFixed<T>(0);  // Resolved later.
   }
   void InitializeAbstractOrigins(intptr_t size) {
diff --git a/runtime/vm/elf.h b/runtime/vm/elf.h
index 19400f7..579c49f 100644
--- a/runtime/vm/elf.h
+++ b/runtime/vm/elf.h
@@ -51,9 +51,10 @@
 
   // Stores the information needed to appropriately generate a
   // relocation from the target to the source at the given section offset.
-  // If a given symbol is nullptr, then the offset is absolute (from 0).
-  // Both source and target symbols could be "." which is pseudosymbol
-  // corresponding to the location of the relocation itself.
+  // If a given symbol name is nullptr, then the corresponding offset is
+  // relative from the location of the relocation itself.
+  // If a given symbol name is "", then the corresponding offset is relative to
+  // the start of the snapshot.
   struct Relocation {
     size_t size_in_bytes;
     intptr_t section_offset;
diff --git a/runtime/vm/heap/safepoint.cc b/runtime/vm/heap/safepoint.cc
index 52da48b..4a7e5de 100644
--- a/runtime/vm/heap/safepoint.cc
+++ b/runtime/vm/heap/safepoint.cc
@@ -155,7 +155,7 @@
       if (!Thread::IsAtSafepoint(level_, state)) {
         // Send OOB message to get it to safepoint.
         if (current->IsMutatorThread()) {
-          current->ScheduleInterrupts(Thread::kVMInterrupt);
+          current->ScheduleInterruptsLocked(Thread::kVMInterrupt);
         }
         MonitorLocker sl(&parked_lock_);
         num_threads_not_parked_++;
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index e465cb6..587267c 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -692,7 +692,7 @@
     // 2) The BSS offset from this section.
     text_offset += Relocation(text_offset, instructions_symbol, bss_symbol);
     // 3) The relocated address of the instructions.
-    text_offset += Relocation(text_offset, instructions_symbol);
+    text_offset += RelocatedAddress(text_offset, instructions_symbol);
     // 4) The GNU build ID note offset from this section.
     text_offset += Relocation(text_offset, instructions_symbol,
                               SectionSymbol(ProgramSection::BuildId, vm));
@@ -1221,10 +1221,7 @@
                                          intptr_t source_offset,
                                          const char* target_symbol,
                                          intptr_t target_offset) {
-  if (source_symbol == nullptr || target_symbol == nullptr) {
-    // We can't use absolute addresses in assembly relocations.
-    return WriteTargetWord(Image::kNoRelocatedAddress);
-  }
+  ASSERT(source_symbol != nullptr);
   ASSERT(target_symbol != nullptr);
 
   // TODO(dartbug.com/43274): Remove once we generate consistent build IDs
@@ -1237,23 +1234,24 @@
 
   // All relocations are word-sized.
   assembly_stream_->Printf("%s ", kWordDirective);
-  if (strcmp(target_symbol, current_section_symbol_) == 0 &&
-      target_offset == section_offset) {
+  if (strcmp(target_symbol, current_section_symbol_) == 0) {
     assembly_stream_->WriteString("(.)");
+    target_offset -= section_offset;
   } else {
     assembly_stream_->Printf("%s", target_symbol);
-    if (target_offset != 0) {
-      assembly_stream_->Printf(" + %" Pd "", target_offset);
-    }
   }
-  if (strcmp(source_symbol, current_section_symbol_) == 0 &&
-      source_offset == section_offset) {
+  if (target_offset != 0) {
+    assembly_stream_->Printf(" + %" Pd "", target_offset);
+  }
+
+  if (strcmp(source_symbol, current_section_symbol_) == 0) {
     assembly_stream_->WriteString(" - (.)");
+    source_offset -= section_offset;
   } else {
     assembly_stream_->Printf(" - %s", source_symbol);
-    if (source_offset != 0) {
-      assembly_stream_->Printf(" - %" Pd "", source_offset);
-    }
+  }
+  if (source_offset != 0) {
+    assembly_stream_->Printf(" - %" Pd "", source_offset);
   }
   assembly_stream_->WriteString("\n");
   return compiler::target::kWordSize;
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 09a1555..fc2bbdd 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -397,13 +397,15 @@
   // relocated address of the target section and S is the final relocated
   // address of the source, the final value is:
   //   (T + target_offset + target_addend) - (S + source_offset)
-  // If either symbol is nullptr, then the corresponding is treated as an
-  // absolute address.
   virtual intptr_t Relocation(intptr_t section_offset,
                               const char* source_symbol,
                               intptr_t source_offset,
                               const char* target_symbol,
                               intptr_t target_offset) = 0;
+  // Writes a target word-sized value that contains the relocated address
+  // pointed to by the given symbol.
+  virtual intptr_t RelocatedAddress(intptr_t section_offset,
+                                    const char* symbol) = 0;
   // Creates a static symbol for the given Code object when appropriate.
   virtual void AddCodeSymbol(const Code& code,
                              const char* symbol,
@@ -418,11 +420,6 @@
                       const char* target_symbol) {
     return Relocation(section_offset, source_symbol, 0, target_symbol, 0);
   }
-  // An overload of Relocation for outputting the relocated address of the
-  // target symbol at the given section offset.
-  intptr_t Relocation(intptr_t section_offset, const char* target_symbol) {
-    return Relocation(section_offset, nullptr, 0, target_symbol, 0);
-  }
 #endif
   // Writes a fixed-sized value of type T to the section contents.
   template <typename T>
@@ -549,6 +546,11 @@
                               intptr_t source_offset,
                               const char* target_symbol,
                               intptr_t target_offset);
+  virtual intptr_t RelocatedAddress(intptr_t section_offset,
+                                    const char* symbol) {
+    // Cannot calculate snapshot-relative addresses in assembly snapshots.
+    return WriteTargetWord(Image::kNoRelocatedAddress);
+  }
   virtual void FrameUnwindPrologue();
   virtual void FrameUnwindEpilogue();
   virtual void AddCodeSymbol(const Code& code,
@@ -599,6 +601,11 @@
                               intptr_t source_offset,
                               const char* target_symbol,
                               intptr_t target_offset);
+  virtual intptr_t RelocatedAddress(intptr_t section_offset,
+                                    const char* target_symbol) {
+    // ELF symbol tables always have a reserved symbol with name "" and value 0.
+    return ImageWriter::Relocation(section_offset, "", target_symbol);
+  }
   virtual void AddCodeSymbol(const Code& code,
                              const char* symbol,
                              intptr_t offset);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 8993e5f..cb00d29 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -867,6 +867,19 @@
   return Isolate::IsSystemIsolate(isolate);
 }
 
+NoOOBMessageScope::NoOOBMessageScope(Thread* thread)
+    : ThreadStackResource(thread) {
+  if (thread->isolate() != nullptr) {
+    thread->DeferOOBMessageInterrupts();
+  }
+}
+
+NoOOBMessageScope::~NoOOBMessageScope() {
+  if (thread()->isolate() != nullptr) {
+    thread()->RestoreOOBMessageInterrupts();
+  }
+}
+
 Bequest::~Bequest() {
   if (handle_ == nullptr) {
     return;
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 4c2d9f5..c17a81d 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -134,6 +134,16 @@
   DISALLOW_COPY_AND_ASSIGN(LambdaCallable);
 };
 
+// Disallow OOB message handling within this scope.
+class NoOOBMessageScope : public ThreadStackResource {
+ public:
+  explicit NoOOBMessageScope(Thread* thread);
+  ~NoOOBMessageScope();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NoOOBMessageScope);
+};
+
 // Fixed cache for exception handler lookup.
 typedef FixedCache<intptr_t, ExceptionHandlerInfo, 16> HandlerInfoCache;
 // Fixed cache for catch entry state lookup.
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 2003591..9402106 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -145,4 +145,106 @@
   barrier.Exit();
 }
 
+class IsolateTestHelper {
+ public:
+  static uword GetStackLimit(Thread* thread) { return thread->stack_limit_; }
+  static uword GetSavedStackLimit(Thread* thread) {
+    return thread->saved_stack_limit_;
+  }
+  static uword GetDeferredInterruptsMask(Thread* thread) {
+    return thread->deferred_interrupts_mask_;
+  }
+  static uword GetDeferredInterrupts(Thread* thread) {
+    return thread->deferred_interrupts_;
+  }
+};
+
+TEST_CASE(NoOOBMessageScope) {
+  // Finish any GC in progress so that no kVMInterrupt is added for GC reasons.
+  {
+    TransitionNativeToVM transition(thread);
+    GCTestHelper::CollectAllGarbage();
+    const Error& error = Error::Handle(thread->HandleInterrupts());
+    RELEASE_ASSERT(error.IsNull());
+  }
+
+  // EXPECT_EQ is picky about type agreement for its arguments.
+  const uword kZero = 0;
+  const uword kMessageInterrupt = Thread::kMessageInterrupt;
+  const uword kVMInterrupt = Thread::kVMInterrupt;
+  uword stack_limit;
+  uword interrupt_bits;
+
+  // Initially no interrupts are scheduled or deferred.
+  EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+            IsolateTestHelper::GetSavedStackLimit(thread));
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
+
+  {
+    // Defer message interrupts.
+    NoOOBMessageScope no_msg_scope(thread);
+    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+              IsolateTestHelper::GetSavedStackLimit(thread));
+    EXPECT_EQ(kMessageInterrupt,
+              IsolateTestHelper::GetDeferredInterruptsMask(thread));
+    EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
+
+    // Schedule a message, it is deferred.
+    thread->ScheduleInterrupts(Thread::kMessageInterrupt);
+    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+              IsolateTestHelper::GetSavedStackLimit(thread));
+    EXPECT_EQ(kMessageInterrupt,
+              IsolateTestHelper::GetDeferredInterruptsMask(thread));
+    EXPECT_EQ(kMessageInterrupt,
+              IsolateTestHelper::GetDeferredInterrupts(thread));
+
+    // Schedule a vm interrupt, it is not deferred.
+    thread->ScheduleInterrupts(Thread::kVMInterrupt);
+    stack_limit = IsolateTestHelper::GetStackLimit(thread);
+    EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(thread));
+    EXPECT((stack_limit & Thread::kVMInterrupt) != 0);
+    EXPECT_EQ(kMessageInterrupt,
+              IsolateTestHelper::GetDeferredInterruptsMask(thread));
+    EXPECT_EQ(kMessageInterrupt,
+              IsolateTestHelper::GetDeferredInterrupts(thread));
+
+    // Clear the vm interrupt.  Message is still deferred.
+    interrupt_bits = thread->GetAndClearInterrupts();
+    EXPECT_EQ(kVMInterrupt, interrupt_bits);
+    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+              IsolateTestHelper::GetSavedStackLimit(thread));
+    EXPECT_EQ(kMessageInterrupt,
+              IsolateTestHelper::GetDeferredInterruptsMask(thread));
+    EXPECT_EQ(kMessageInterrupt,
+              IsolateTestHelper::GetDeferredInterrupts(thread));
+  }
+
+  // Restore message interrupts.  Message is now pending.
+  stack_limit = IsolateTestHelper::GetStackLimit(thread);
+  EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(thread));
+  EXPECT((stack_limit & Thread::kMessageInterrupt) != 0);
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
+
+  {
+    // Defer message interrupts, again.  The pending interrupt is deferred.
+    NoOOBMessageScope no_msg_scope(thread);
+    EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+              IsolateTestHelper::GetSavedStackLimit(thread));
+    EXPECT_EQ(kMessageInterrupt,
+              IsolateTestHelper::GetDeferredInterruptsMask(thread));
+    EXPECT_EQ(kMessageInterrupt,
+              IsolateTestHelper::GetDeferredInterrupts(thread));
+  }
+
+  // Restore, then clear interrupts.  The world is as it was.
+  interrupt_bits = thread->GetAndClearInterrupts();
+  EXPECT_EQ(kMessageInterrupt, interrupt_bits);
+  EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+            IsolateTestHelper::GetSavedStackLimit(thread));
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
+  EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
+}
+
 }  // namespace dart
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 8c08ad9..7c9214a 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -11162,6 +11162,7 @@
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
+  NoOOBMessageScope no_msg_scope(thread);
   NoReloadScope no_reload_scope(thread);
   const Function& initializer = Function::Handle(EnsureInitializerFunction());
   return DartEntry::InvokeFunction(initializer, Object::empty_array());
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 45d99f9..16a1f8f 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -91,6 +91,9 @@
       no_safepoint_scope_depth_(0),
 #endif
       reusable_handles_(),
+      defer_oob_messages_count_(0),
+      deferred_interrupts_mask_(0),
+      deferred_interrupts_(0),
       stack_overflow_count_(0),
       hierarchy_info_(NULL),
       type_usage_info_(NULL),
@@ -395,7 +398,7 @@
   MonitorLocker ml(&thread_lock_);
   if (!HasScheduledInterrupts()) {
     // No interrupt pending, set stack_limit_ too.
-    stack_limit_.store(limit);
+    stack_limit_ = limit;
   }
   saved_stack_limit_ = limit;
 }
@@ -405,33 +408,95 @@
 }
 
 void Thread::ScheduleInterrupts(uword interrupt_bits) {
+  MonitorLocker ml(&thread_lock_);
+  ScheduleInterruptsLocked(interrupt_bits);
+}
+
+void Thread::ScheduleInterruptsLocked(uword interrupt_bits) {
+  ASSERT(thread_lock_.IsOwnedByCurrentThread());
   ASSERT((interrupt_bits & ~kInterruptsMask) == 0);  // Must fit in mask.
 
-  uword old_limit = stack_limit_.load();
-  uword new_limit;
-  do {
-    if (old_limit == saved_stack_limit_) {
-      new_limit = (kInterruptStackLimit & ~kInterruptsMask) | interrupt_bits;
-    } else {
-      new_limit = old_limit | interrupt_bits;
+  // Check to see if any of the requested interrupts should be deferred.
+  uword defer_bits = interrupt_bits & deferred_interrupts_mask_;
+  if (defer_bits != 0) {
+    deferred_interrupts_ |= defer_bits;
+    interrupt_bits &= ~deferred_interrupts_mask_;
+    if (interrupt_bits == 0) {
+      return;
     }
-  } while (!stack_limit_.compare_exchange_weak(old_limit, new_limit));
+  }
+
+  if (stack_limit_ == saved_stack_limit_) {
+    stack_limit_ = (kInterruptStackLimit & ~kInterruptsMask) | interrupt_bits;
+  } else {
+    stack_limit_ = stack_limit_ | interrupt_bits;
+  }
 }
 
 uword Thread::GetAndClearInterrupts() {
-  uword interrupt_bits = 0;
-  uword old_limit = stack_limit_.load();
-  uword new_limit = saved_stack_limit_;
-  do {
-    if (old_limit == saved_stack_limit_) {
-      return interrupt_bits;
-    }
-    interrupt_bits = interrupt_bits | (old_limit & kInterruptsMask);
-  } while (!stack_limit_.compare_exchange_weak(old_limit, new_limit));
-
+  MonitorLocker ml(&thread_lock_);
+  if (stack_limit_ == saved_stack_limit_) {
+    return 0;  // No interrupt was requested.
+  }
+  uword interrupt_bits = stack_limit_ & kInterruptsMask;
+  stack_limit_ = saved_stack_limit_;
   return interrupt_bits;
 }
 
+void Thread::DeferOOBMessageInterrupts() {
+  MonitorLocker ml(&thread_lock_);
+  defer_oob_messages_count_++;
+  if (defer_oob_messages_count_ > 1) {
+    // OOB message interrupts are already deferred.
+    return;
+  }
+  ASSERT(deferred_interrupts_mask_ == 0);
+  deferred_interrupts_mask_ = kMessageInterrupt;
+
+  if (stack_limit_ != saved_stack_limit_) {
+    // Defer any interrupts which are currently pending.
+    deferred_interrupts_ = stack_limit_ & deferred_interrupts_mask_;
+
+    // Clear deferrable interrupts, if present.
+    stack_limit_ = stack_limit_ & ~deferred_interrupts_mask_;
+
+    if ((stack_limit_ & kInterruptsMask) == 0) {
+      // No other pending interrupts.  Restore normal stack limit.
+      stack_limit_ = saved_stack_limit_;
+    }
+  }
+#if !defined(PRODUCT)
+  if (FLAG_trace_service && FLAG_trace_service_verbose) {
+    OS::PrintErr("[+%" Pd64 "ms] Isolate %s deferring OOB interrupts\n",
+                 Dart::UptimeMillis(), isolate()->name());
+  }
+#endif  // !defined(PRODUCT)
+}
+
+void Thread::RestoreOOBMessageInterrupts() {
+  MonitorLocker ml(&thread_lock_);
+  defer_oob_messages_count_--;
+  if (defer_oob_messages_count_ > 0) {
+    return;
+  }
+  ASSERT(defer_oob_messages_count_ == 0);
+  ASSERT(deferred_interrupts_mask_ == kMessageInterrupt);
+  deferred_interrupts_mask_ = 0;
+  if (deferred_interrupts_ != 0) {
+    if (stack_limit_ == saved_stack_limit_) {
+      stack_limit_ = kInterruptStackLimit & ~kInterruptsMask;
+    }
+    stack_limit_ = stack_limit_ | deferred_interrupts_;
+    deferred_interrupts_ = 0;
+  }
+#if !defined(PRODUCT)
+  if (FLAG_trace_service && FLAG_trace_service_verbose) {
+    OS::PrintErr("[+%" Pd64 "ms] Isolate %s restoring OOB interrupts\n",
+                 Dart::UptimeMillis(), isolate()->name());
+  }
+#endif  // !defined(PRODUCT)
+}
+
 ErrorPtr Thread::HandleInterrupts() {
   uword interrupt_bits = GetAndClearInterrupts();
   if ((interrupt_bits & kVMInterrupt) != 0) {
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 6e3ff67..2d80830 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -417,10 +417,11 @@
   };
 
   void ScheduleInterrupts(uword interrupt_bits);
+  void ScheduleInterruptsLocked(uword interrupt_bits);
   ErrorPtr HandleInterrupts();
   uword GetAndClearInterrupts();
   bool HasScheduledInterrupts() const {
-    return (stack_limit_.load() & kInterruptsMask) != 0;
+    return (stack_limit_ & kInterruptsMask) != 0;
   }
 
   // Monitor corresponding to this thread.
@@ -1030,7 +1031,7 @@
   // in SIMARM(IA32) and ARM, and the same offsets in SIMARM64(X64) and ARM64.
   // We use only word-sized fields to avoid differences in struct packing on the
   // different architectures. See also CheckOffsets in dart.cc.
-  volatile RelaxedAtomic<uword> stack_limit_;
+  RelaxedAtomic<uword> stack_limit_;
   uword write_barrier_mask_;
   uword heap_base_;
   Isolate* isolate_;
@@ -1106,6 +1107,9 @@
   int32_t no_safepoint_scope_depth_;
 #endif
   VMHandles reusable_handles_;
+  intptr_t defer_oob_messages_count_;
+  uint16_t deferred_interrupts_mask_;
+  uint16_t deferred_interrupts_;
   int32_t stack_overflow_count_;
   uint32_t runtime_call_count_ = 0;
 
@@ -1201,6 +1205,9 @@
 
   static void SetCurrent(Thread* current) { OSThread::SetCurrentTLS(current); }
 
+  void DeferOOBMessageInterrupts();
+  void RestoreOOBMessageInterrupts();
+
 #define REUSABLE_FRIEND_DECLARATION(name)                                      \
   friend class Reusable##name##HandleScope;
   REUSABLE_HANDLE_LIST(REUSABLE_FRIEND_DECLARATION)
@@ -1211,7 +1218,9 @@
   friend class InterruptChecker;
   friend class Isolate;
   friend class IsolateGroup;
+  friend class IsolateTestHelper;
   friend class NoActiveIsolateScope;
+  friend class NoOOBMessageScope;
   friend class NoReloadScope;
   friend class Simulator;
   friend class StackZone;
diff --git a/tests/lib/isolate/kill_infinite_loop_in_initializer_test.dart b/tests/lib/isolate/kill_infinite_loop_in_initializer_test.dart
deleted file mode 100644
index 321fbda4..0000000
--- a/tests/lib/isolate/kill_infinite_loop_in_initializer_test.dart
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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=--enable-isolate-groups --experimental-enable-isolate-groups-jit
-// VMOptions=--no-enable-isolate-groups
-
-// Regression test against out-of-band messages being blocked during lazy
-// static field initialization.
-
-import "dart:isolate";
-import "dart:async";
-import "package:expect/expect.dart";
-import "package:async_helper/async_helper.dart";
-
-dynamic staticFieldWithBadInitializer = badInitializer();
-
-badInitializer() {
-  print("badInitializer");
-  for (;;) {}
-  return 42; // Unreachable.
-}
-
-child(message) {
-  print("child");
-  RawReceivePort port = new RawReceivePort();
-  print(staticFieldWithBadInitializer);
-  port.close(); // Unreachable.
-}
-
-void main() {
-  asyncStart();
-  Isolate.spawn(child, null).then((Isolate isolate) {
-    print("spawned");
-    late RawReceivePort exitSignal;
-    exitSignal = new RawReceivePort((_) {
-      print("onExit");
-      exitSignal.close();
-      asyncEnd();
-    });
-    isolate.addOnExitListener(exitSignal.sendPort);
-    isolate.kill(priority: Isolate.immediate);
-  });
-}
diff --git a/tests/lib_2/isolate/kill_infinite_loop_in_initializer_test.dart b/tests/lib_2/isolate/kill_infinite_loop_in_initializer_test.dart
deleted file mode 100644
index af8650e..0000000
--- a/tests/lib_2/isolate/kill_infinite_loop_in_initializer_test.dart
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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=--enable-isolate-groups --experimental-enable-isolate-groups-jit
-// VMOptions=--no-enable-isolate-groups
-
-// Regression test against out-of-band messages being blocked during lazy
-// static field initialization.
-
-import "dart:isolate";
-import "dart:async";
-import "package:expect/expect.dart";
-import "package:async_helper/async_helper.dart";
-
-dynamic staticFieldWithBadInitializer = badInitializer();
-
-badInitializer() {
-  print("badInitializer");
-  for (;;) {}
-  return 42; // Unreachable.
-}
-
-child(message) {
-  print("child");
-  RawReceivePort port = new RawReceivePort();
-  print(staticFieldWithBadInitializer);
-  port.close(); // Unreachable.
-}
-
-void main() {
-  asyncStart();
-  Isolate.spawn(child, null).then((Isolate isolate) {
-    print("spawned");
-    RawReceivePort exitSignal;
-    exitSignal = new RawReceivePort((_) {
-      print("onExit");
-      exitSignal.close();
-      asyncEnd();
-    });
-    isolate.addOnExitListener(exitSignal.sendPort);
-    isolate.kill(priority: Isolate.immediate);
-  });
-}
diff --git a/tools/VERSION b/tools/VERSION
index 67f5806..f7ef7a9 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 309
+PRERELEASE 310
 PRERELEASE_PATCH 0
\ No newline at end of file