Version 2.15.0-79.0.dev

Merge commit '29ba68fcf2ec39cae25ae02e1f56006eb5a40e72' into 'dev'
diff --git a/DEPS b/DEPS
index dc0dbdd..503c2f8 100644
--- a/DEPS
+++ b/DEPS
@@ -44,8 +44,8 @@
   # co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
   # hashes. It requires access to the dart-build-access group, which EngProd
   # has.
-  "co19_rev": "a3af05fb4ee10b065bf0f5bfe4e9546bc077d5e8",
-  "co19_2_rev": "7637bcb24abf21b5e2f8dd24d3fe619f777391f5",
+  "co19_rev": "a4f77a02a3676b1c2e7390c860cb0486c8515d3f",
+  "co19_2_rev": "3e1ea1af9ef293d7f6a8f3332b5c71c7072a30e0",
 
   # The internal benchmarks to use. See go/dart-benchmarks-internal
   "benchmarks_internal_rev": "076df10d9b77af337f2d8029725787155eb1cd52",
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index c4bf424..af1fa6f 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -1043,7 +1043,8 @@
     } else if (operatorType == TokenType.TILDE_SLASH) {
       return _dartObjectComputer.integerDivide(node, leftResult, rightResult);
     } else {
-      // TODO(brianwilkerson) Figure out which error to report.
+      // TODO(https://github.com/dart-lang/sdk/issues/47061): Use a specific
+      // error code.
       _error(node, null);
       return null;
     }
@@ -1108,7 +1109,8 @@
   DartObjectImpl? visitInstanceCreationExpression(
       InstanceCreationExpression node) {
     if (!node.isConst) {
-      // TODO(brianwilkerson) Figure out which error to report.
+      // TODO(https://github.com/dart-lang/sdk/issues/47061): Use a specific
+      // error code.
       _error(node, null);
       return null;
     }
@@ -1209,7 +1211,8 @@
         }
       }
     }
-    // TODO(brianwilkerson) Figure out which error to report.
+    // TODO(https://github.com/dart-lang/sdk/issues/47061): Use a specific
+    // error code.
     _error(node, null);
     return null;
   }
@@ -1220,7 +1223,8 @@
 
   @override
   DartObjectImpl? visitNode(AstNode node) {
-    // TODO(brianwilkerson) Figure out which error to report.
+    // TODO(https://github.com/dart-lang/sdk/issues/47061): Use a specific
+    // error code.
     _error(node, null);
     return null;
   }
@@ -1274,7 +1278,8 @@
     } else if (node.operator.type == TokenType.MINUS) {
       return _dartObjectComputer.negated(node, operand);
     } else {
-      // TODO(brianwilkerson) Figure out which error to report.
+      // TODO(https://github.com/dart-lang/sdk/issues/47061): Use a specific
+      // error code.
       _error(node, null);
       return null;
     }
@@ -1655,7 +1660,8 @@
       // Constants may not refer to type parameters.
     }
 
-    // TODO(brianwilkerson) Figure out which error to report.
+    // TODO(https://github.com/dart-lang/sdk/issues/47061): Use a specific
+    // error code.
     _error(node, null);
     return null;
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
index e2a2b97..75ac605 100644
--- a/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart
@@ -53,7 +53,7 @@
       if (enclosingElement is TypeAliasElement) {
         enclosingElement = enclosingElement.aliasedType.element;
       }
-      // TODO(srawlins): Handle `enclosingElement` being a functio typedef:
+      // TODO(srawlins): Handle `enclosingElement` being a function typedef:
       // typedef F<T> = void Function(); var a = F<int>.extensionOnType;`.
       // This is illegal.
       if (enclosingElement is ClassElement) {
@@ -123,16 +123,7 @@
         constructorName.staticElement = constructorElement.declaration;
         constructorName.name?.staticElement = constructorElement.declaration;
         node.staticType = inferred;
-        // TODO(srawlins): Always set the TypeName's type to `null`, here, and
-        // in the "else" case below, at the very end of [_inferArgumentTypes].
-        // This requires refactoring how type arguments are checked against
-        // bounds, as this is currently always done with the [TypeName], in
-        // type_argument_verifier.dart.
-        if (inferred.typeFormals.isNotEmpty) {
-          constructorName.type.type = null;
-        } else {
-          constructorName.type.type = inferredReturnType;
-        }
+        constructorName.type.type = null;
       }
     } else {
       var constructorElement = constructorName.staticElement;
@@ -141,6 +132,7 @@
       } else {
         node.staticType = constructorElement.type;
       }
+      constructorName.type.type = null;
     }
   }
 }
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index 1bdea4c..71ab7b9 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -32,8 +32,67 @@
   TypeSystemImpl get _typeSystem =>
       _libraryElement.typeSystem as TypeSystemImpl;
 
+  void checkConstructorReference(ConstructorReference node) {
+    var classElement = node.constructorName.type.name.staticElement;
+    List<TypeParameterElement> typeParameters;
+    if (classElement is TypeAliasElement) {
+      typeParameters = classElement.typeParameters;
+    } else if (classElement is ClassElement) {
+      typeParameters = classElement.typeParameters;
+    } else {
+      return;
+    }
+
+    if (typeParameters.isEmpty) {
+      return;
+    }
+    var typeArgumentList = node.constructorName.type.typeArguments;
+    if (typeArgumentList == null) {
+      return;
+    }
+    var constructorType = node.staticType;
+    if (constructorType is DynamicType) {
+      // An erroneous constructor reference.
+      return;
+    }
+    if (constructorType is! FunctionType) {
+      return;
+    }
+    var typeArguments = [
+      for (var type in typeArgumentList.arguments) type.type!,
+    ];
+    if (typeArguments.length != typeParameters.length) {
+      // Wrong number of type arguments to be reported elsewhere.
+      return;
+    }
+    var typeArgumentListLength = typeArgumentList.arguments.length;
+    var substitution = Substitution.fromPairs(typeParameters, typeArguments);
+    for (var i = 0; i < typeArguments.length; i++) {
+      var typeParameter = typeParameters[i];
+      var typeArgument = typeArguments[i];
+
+      var bound = typeParameter.bound;
+      if (bound == null) {
+        continue;
+      }
+
+      bound = _libraryElement.toLegacyTypeIfOptOut(bound);
+      bound = substitution.substituteType(bound);
+
+      if (!_typeSystem.isSubtypeOf(typeArgument, bound)) {
+        var errorNode =
+            i < typeArgumentListLength ? typeArgumentList.arguments[i] : node;
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+          errorNode,
+          [typeArgument, typeParameter.name, bound],
+        );
+      }
+    }
+  }
+
   void checkFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    _checkTypeArguments(
+    _checkInvocationTypeArguments(
       node.typeArguments?.arguments,
       node.function.staticType,
       node.staticInvokeType,
@@ -42,7 +101,7 @@
   }
 
   void checkFunctionReference(FunctionReference node) {
-    _checkTypeArguments(
+    _checkInvocationTypeArguments(
       node.typeArguments?.arguments,
       node.function.staticType,
       node.staticType,
@@ -80,7 +139,7 @@
   }
 
   void checkMethodInvocation(MethodInvocation node) {
-    _checkTypeArguments(
+    _checkInvocationTypeArguments(
       node.typeArguments?.arguments,
       node.function.staticType,
       node.staticInvokeType,
@@ -313,40 +372,9 @@
     }
   }
 
-  /// Checks to ensure that the given list of type [arguments] does not have a
-  /// type parameter as a type argument. The [errorCode] is either
-  /// [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST] or
-  /// [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP].
-  void _checkTypeArgumentConst(
-      NodeList<TypeAnnotation> arguments, ErrorCode errorCode) {
-    for (TypeAnnotation type in arguments) {
-      if (type is TypeName && type.type is TypeParameterType) {
-        _errorReporter.reportErrorForNode(errorCode, type, [type.name]);
-      }
-    }
-  }
-
-  /// Verify that the given list of [typeArguments] contains exactly the
-  /// [expectedCount] of elements, reporting an error with the [errorCode]
-  /// if not.
-  void _checkTypeArgumentCount(
-    TypeArgumentList typeArguments,
-    int expectedCount,
-    ErrorCode errorCode,
-  ) {
-    int actualCount = typeArguments.arguments.length;
-    if (actualCount != expectedCount) {
-      _errorReporter.reportErrorForNode(
-        errorCode,
-        typeArguments,
-        [actualCount],
-      );
-    }
-  }
-
   /// Verify that each type argument in [typeArgumentList] is within its bounds,
   /// as defined by [genericType].
-  void _checkTypeArguments(
+  void _checkInvocationTypeArguments(
     List<TypeAnnotation>? typeArgumentList,
     DartType? genericType,
     DartType? instantiatedType,
@@ -407,6 +435,37 @@
     }
   }
 
+  /// Checks to ensure that the given list of type [arguments] does not have a
+  /// type parameter as a type argument. The [errorCode] is either
+  /// [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST] or
+  /// [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP].
+  void _checkTypeArgumentConst(
+      NodeList<TypeAnnotation> arguments, ErrorCode errorCode) {
+    for (TypeAnnotation type in arguments) {
+      if (type is TypeName && type.type is TypeParameterType) {
+        _errorReporter.reportErrorForNode(errorCode, type, [type.name]);
+      }
+    }
+  }
+
+  /// Verify that the given list of [typeArguments] contains exactly the
+  /// [expectedCount] of elements, reporting an error with the [errorCode]
+  /// if not.
+  void _checkTypeArgumentCount(
+    TypeArgumentList typeArguments,
+    int expectedCount,
+    ErrorCode errorCode,
+  ) {
+    int actualCount = typeArguments.arguments.length;
+    if (actualCount != expectedCount) {
+      _errorReporter.reportErrorForNode(
+        errorCode,
+        typeArguments,
+        [actualCount],
+      );
+    }
+  }
+
   /// Given a [node] without type arguments that refers to [element], issues
   /// an error if [type] is a generic type, and the type arguments were not
   /// supplied from inference or a non-dynamic default instantiation.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index a702c1c..31e2553 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -558,6 +558,11 @@
   }
 
   @override
+  void visitConstructorReference(ConstructorReference node) {
+    _typeArgumentsVerifier.checkConstructorReference(node);
+  }
+
+  @override
   void visitContinueStatement(ContinueStatement node) {
     var labelNode = node.label;
     if (labelNode != null) {
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index f97d66a..4920947 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -126,6 +126,50 @@
     assertType(value.type, 'C');
   }
 
+  test_constructorReference_generic_named() async {
+    var result = await _getExpressionValue("C<int>.foo", context: '''
+class C<T> {
+  C.foo();
+}
+''');
+    expect(result.isValid, isTrue);
+    DartObject value = result.value!;
+    assertType(value.type, 'C<int> Function()');
+  }
+
+  test_constructorReference_generic_unnamed() async {
+    var result = await _getExpressionValue("C<int>.new", context: '''
+class C<T> {
+  C.new();
+}
+''');
+    expect(result.isValid, isTrue);
+    DartObject value = result.value!;
+    assertType(value.type, 'C<int> Function()');
+  }
+
+  test_constructorReference_nonGeneric_named() async {
+    var result = await _getExpressionValue("C.foo", context: '''
+class C {
+  const C.foo();
+}
+''');
+    expect(result.isValid, isTrue);
+    DartObject value = result.value!;
+    assertType(value.type, 'C Function()');
+  }
+
+  test_constructorReference_nonGeneric_unnamed() async {
+    var result = await _getExpressionValue("C.new", context: '''
+class C {
+  const C();
+}
+''');
+    expect(result.isValid, isTrue);
+    DartObject value = result.value!;
+    assertType(value.type, 'C Function()');
+  }
+
   test_divide_double_double() async {
     await _assertValueDouble(3.2 / 2.3, "3.2 / 2.3");
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/constructor_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/constructor_reference_test.dart
index 00b6b27..3262f0b 100644
--- a/pkg/analyzer/test/src/dart/resolution/constructor_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constructor_reference_test.dart
@@ -23,7 +23,7 @@
   test_alias_generic_const() async {
     await assertNoErrorsInCode('''
 class A<T, U> {
-  A.foo();
+  const A.foo();
 }
 typedef TA<T, U> = A<U, T>;
 
@@ -37,7 +37,27 @@
           substitution: {'T': 'String', 'U': 'int'}),
       classElement,
       'A<String, int> Function()',
-      expectedTypeNameType: 'A<String, int>',
+      expectedTypeNameElement: findElement.typeAlias('TA'),
+    );
+  }
+
+  test_alias_generic_const_differingNumberOfTypeParamters() async {
+    await assertNoErrorsInCode('''
+class A<T, U> {
+  A.foo() {}
+}
+typedef TA<T> = A<T, String>;
+
+const x = TA<int>.foo;
+''');
+
+    var classElement = findElement.class_('A');
+    assertConstructorReference(
+      findNode.constructorReference('TA<int>.foo;'),
+      elementMatcher(classElement.getNamedConstructor('foo')!,
+          substitution: {'T': 'int', 'U': 'String'}),
+      classElement,
+      'A<int, String> Function()',
       expectedTypeNameElement: findElement.typeAlias('TA'),
     );
   }
@@ -61,7 +81,6 @@
           substitution: {'T': 'String', 'U': 'int'}),
       classElement,
       'A<String, int> Function()',
-      expectedTypeNameType: 'A<String, int>',
       expectedTypeNameElement: findElement.typeAlias('TA'),
     );
   }
@@ -85,7 +104,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
       expectedTypeNameElement: findElement.typeAlias('TA'),
     );
   }
@@ -109,7 +127,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
       expectedTypeNameElement: findElement.typeAlias('TA'),
     );
   }
@@ -135,7 +152,6 @@
           substitution: {'T': 'String'}),
       classElement,
       'A<String> Function()',
-      expectedTypeNameType: 'A<String>',
       expectedTypeNameElement: findElement.typeAlias('TA'),
     );
   }
@@ -156,7 +172,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
     );
   }
 
@@ -178,7 +193,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
     );
   }
 
@@ -241,7 +255,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
     );
   }
 
@@ -265,7 +278,6 @@
       null,
       classElement,
       'dynamic',
-      expectedTypeNameType: 'A<int>',
     );
   }
 
@@ -287,7 +299,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
     );
   }
 
@@ -309,7 +320,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
     );
   }
 
@@ -331,7 +341,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
     );
   }
 
@@ -355,7 +364,6 @@
           substitution: {'T': 'String'}),
       classElement,
       'A<String> Function()',
-      expectedTypeNameType: 'A<String>',
     );
   }
 
@@ -381,7 +389,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
       expectedPrefix: findElement.import('package:test/a.dart').prefix,
       expectedTypeNameElement:
           findElement.importFind('package:test/a.dart').typeAlias('TA'),
@@ -409,7 +416,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
       expectedPrefix: findElement.import('package:test/a.dart').prefix,
     );
   }
@@ -438,7 +444,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
       expectedPrefix: findElement.import('package:test/a.dart').prefix,
     );
   }
@@ -464,7 +469,6 @@
           substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
       expectedPrefix: findElement.import('package:test/a.dart').prefix,
     );
   }
@@ -491,7 +495,6 @@
       classElement.unnamedConstructor,
       classElement,
       'A Function()',
-      expectedTypeNameType: 'A',
     );
   }
 
@@ -518,7 +521,6 @@
       classElement.unnamedConstructor,
       classElement,
       'A Function()',
-      expectedTypeNameType: 'A',
     );
   }
 
@@ -547,7 +549,6 @@
       classElement.unnamedConstructor,
       classElement,
       'A Function()',
-      expectedTypeNameType: 'A',
     );
   }
 
@@ -571,7 +572,6 @@
       constructorElement,
       classElement,
       'A<Never> Function()',
-      expectedTypeNameType: 'A<Never>',
     );
   }
 
@@ -593,7 +593,6 @@
       constructorElement,
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
     );
   }
 
@@ -615,7 +614,6 @@
       constructorElement,
       classElement,
       'A<T> Function<T>()',
-      expectedTypeNameType: null,
     );
   }
 
@@ -637,7 +635,6 @@
       constructorElement,
       classElement,
       'A<T> Function<T extends num>()',
-      expectedTypeNameType: null,
     );
   }
 
@@ -656,7 +653,6 @@
       classElement.unnamedConstructor,
       classElement,
       'A Function()',
-      expectedTypeNameType: 'A',
     );
   }
 
@@ -677,7 +673,6 @@
       classElement.getNamedConstructor('foo')!,
       classElement,
       'A Function()',
-      expectedTypeNameType: 'A',
     );
   }
 
@@ -698,7 +693,6 @@
       classElement.unnamedConstructor,
       classElement,
       'A Function()',
-      expectedTypeNameType: 'A',
     );
   }
 
@@ -719,7 +713,6 @@
       constructorElement,
       classElement,
       'A<T> Function<T>()',
-      expectedTypeNameType: null,
       expectedTypeNameElement: findElement.typeAlias('TA'),
     );
   }
@@ -743,7 +736,6 @@
       constructorElement,
       findElement.class_('A'),
       'A<String, U> Function<U>()',
-      expectedTypeNameType: null,
       expectedTypeNameElement: findElement.typeAlias('TA'),
     );
   }
@@ -765,7 +757,6 @@
       elementMatcher(constructorElement, substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
       expectedTypeNameElement: findElement.typeAlias('TA'),
     );
   }
@@ -789,7 +780,6 @@
       elementMatcher(constructorElement, substitution: {'T': 'int'}),
       classElement,
       'A<int> Function()',
-      expectedTypeNameType: 'A<int>',
       expectedTypeNameElement: findElement.typeAlias('TA'),
     );
   }
@@ -817,7 +807,6 @@
       null,
       classElement,
       'dynamic',
-      expectedTypeNameType: 'A<int>',
     );
   }
 
@@ -840,7 +829,6 @@
       classElement.getNamedConstructor('foo')!,
       classElement,
       'A Function()',
-      expectedTypeNameType: 'A',
     );
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 9e3ea8b..9a340186 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -166,7 +166,6 @@
     Object? expectedConstructorElement,
     ClassElement expectedClassElement,
     String expectedType, {
-    required String? expectedTypeNameType,
     PrefixElement? expectedPrefix,
     Element? expectedTypeNameElement,
   }) {
@@ -184,7 +183,7 @@
 
     var typeName = node.constructorName.type;
     expectedTypeNameElement ??= expectedClassElement;
-    assertTypeName(typeName, expectedTypeNameElement, expectedTypeNameType,
+    assertTypeName(typeName, expectedTypeNameElement, null,
         expectedPrefix: expectedPrefix);
   }
 
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 9ea82b2..5bd8d77 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -6332,7 +6332,7 @@
                   staticElement: self::@class::A
                   staticType: null
                   token: A @35
-                type: A
+                type: null
             staticType: A Function()
     accessors
       synthetic static get v @-1
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 65efa17..f900fc0 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -662,7 +662,7 @@
     parent_isolate_ = nullptr;
 
     if (isolate == nullptr) {
-      FailedSpawn(error);
+      FailedSpawn(error, false);
       free(error);
       return;
     }
@@ -701,6 +701,7 @@
     }
 
     if (!success) {
+      state_ = nullptr;
       Dart_ShutdownIsolate();
       return;
     }
@@ -811,11 +812,25 @@
     return true;
   }
 
-  void FailedSpawn(const char* error) {
+  void FailedSpawn(const char* error, bool has_current_isolate = true) {
     ReportError(error != nullptr
                     ? error
                     : "Unknown error occured during Isolate spawning.");
-    state_ = nullptr;
+    // Destruction of [IsolateSpawnState] may cause destruction of [Message]
+    // which make need to delete persistent handles (which requires a current
+    // isolate group).
+    if (has_current_isolate) {
+      ASSERT(IsolateGroup::Current() == state_->isolate_group());
+      state_ = nullptr;
+    } else {
+      ASSERT(IsolateGroup::Current() == nullptr);
+      const bool kBypassSafepoint = false;
+      const bool result = Thread::EnterIsolateGroupAsHelper(
+          state_->isolate_group(), Thread::kUnknownTask, kBypassSafepoint);
+      ASSERT(result);
+      state_ = nullptr;
+      Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
+    }
   }
 
   void ReportError(const char* error) {
diff --git a/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart b/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
index 5626076..ac5e9d7 100644
--- a/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
@@ -112,8 +112,11 @@
     expect(arguments, isA<Map>());
     expect(arguments['isolateGroupId'], isA<String>());
     if (!const ['GC', 'Compiler', 'CompilerVerbose'].contains(event['cat']) &&
-        !const ['FinishTopLevelClassLoading', 'FinishClassLoading']
-            .contains(event['name'])) {
+        !const [
+          'FinishTopLevelClassLoading',
+          'FinishClassLoading',
+          'ProcessPendingClasses'
+        ].contains(event['name'])) {
       expect(arguments['isolateId'], isA<String>());
     }
   }
diff --git a/runtime/observatory_2/tests/service_2/get_vm_timeline_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_vm_timeline_rpc_test.dart
index 0f8e1de..38d088e 100644
--- a/runtime/observatory_2/tests/service_2/get_vm_timeline_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_vm_timeline_rpc_test.dart
@@ -112,8 +112,11 @@
     expect(arguments, isA<Map>());
     expect(arguments['isolateGroupId'], isA<String>());
     if (!const ['GC', 'Compiler', 'CompilerVerbose'].contains(event['cat']) &&
-        !const ['FinishTopLevelClassLoading', 'FinishClassLoading']
-            .contains(event['name'])) {
+        !const [
+          'FinishTopLevelClassLoading',
+          'FinishClassLoading',
+          'ProcessPendingClasses'
+        ].contains(event['name'])) {
       expect(arguments['isolateId'], isA<String>());
     }
   }
diff --git a/runtime/tests/vm/dart/isolates/closures_without_captured_variables_test.dart b/runtime/tests/vm/dart/isolates/closures_without_captured_variables_test.dart
new file mode 100644
index 0000000..d7970cc
--- /dev/null
+++ b/runtime/tests/vm/dart/isolates/closures_without_captured_variables_test.dart
@@ -0,0 +1,95 @@
+// 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
+
+// The tests in this file will only succeed when isolate groups are enabled
+// (hence the VMOptions above).
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+
+import 'fast_object_copy_test.dart' show ClassWithNativeFields;
+
+main() async {
+  final rp = ReceivePort();
+
+  testNormalEnclosingFunction(rp);
+  testNormalNestedEnclosingFunction(rp);
+  testNormalNestedEnclosingFunction2(rp);
+
+  final si = StreamIterator(rp);
+  for (int i = 0; i < 3; ++i) {
+    Expect.isTrue(await si.moveNext());
+    Expect.equals(42, (si.current)());
+  }
+  si.cancel(); // closes the port
+}
+
+testNormalEnclosingFunction(ReceivePort rp) {
+  final invalidObject = ClassWithNativeFields();
+  final normalObject = Object();
+
+  captureInvalidObject() => invalidObject;
+  captureNormalObject() => normalObject;
+  captureNothing() => 42;
+
+  Expect.throwsArgumentError(() => rp.sendPort.send(captureInvalidObject));
+
+  // TODO(http://dartbug.com/36983): Avoid capturing more than needed.
+  Expect.throwsArgumentError(() => rp.sendPort.send(captureNormalObject));
+
+  // Should not throw, since the [captureNothing] closure should not have a
+  // parent context and therefore not transitively refer [rp].
+  rp.sendPort.send(captureNothing);
+}
+
+testNormalNestedEnclosingFunction(ReceivePort rp) {
+  final invalidObject = ClassWithNativeFields();
+  final normalObject = Object();
+  nested() {
+    captureInvalidObject() => invalidObject;
+    captureNormalObject() => normalObject;
+    captureNothing() => 42;
+
+    Expect.throwsArgumentError(() => rp.sendPort.send(captureInvalidObject));
+
+    // TODO(http://dartbug.com/36983): Avoid capturing more than needed.
+    Expect.throwsArgumentError(() => rp.sendPort.send(captureNormalObject));
+
+    // Should not throw, since the [captureNothing] closure should not have a
+    // parent context and therefore not transitively refer [rp].
+    rp.sendPort.send(captureNothing);
+  }
+
+  nested();
+}
+
+testNormalNestedEnclosingFunction2(ReceivePort rp) {
+  final invalidObject = ClassWithNativeFields();
+  final normalObject = Object();
+
+  captureInvalidObject() {
+    local() => invalidObject;
+    return local;
+  }
+
+  captureNormalObject() {
+    local() => normalObject;
+    return local;
+  }
+
+  captureNothing() => 42;
+
+  Expect.throwsArgumentError(() => rp.sendPort.send(captureInvalidObject));
+
+  // TODO(http://dartbug.com/36983): Avoid capturing more than needed.
+  Expect.throwsArgumentError(() => rp.sendPort.send(captureNormalObject));
+
+  // Should not throw, since the [captureNothing] closure should not have a
+  // parent context and therefore not transitively refer [rp].
+  rp.sendPort.send(captureNothing);
+}
diff --git a/runtime/tests/vm/dart_2/isolates/closures_without_captured_variables_test.dart b/runtime/tests/vm/dart_2/isolates/closures_without_captured_variables_test.dart
new file mode 100644
index 0000000..3f714b6
--- /dev/null
+++ b/runtime/tests/vm/dart_2/isolates/closures_without_captured_variables_test.dart
@@ -0,0 +1,97 @@
+// 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
+
+// The tests in this file will only succeed when isolate groups are enabled
+// (hence the VMOptions above).
+
+// @dart=2.9
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+
+import 'fast_object_copy_test.dart' show ClassWithNativeFields;
+
+main() async {
+  final rp = ReceivePort();
+
+  testNormalEnclosingFunction(rp);
+  testNormalNestedEnclosingFunction(rp);
+  testNormalNestedEnclosingFunction2(rp);
+
+  final si = StreamIterator(rp);
+  for (int i = 0; i < 3; ++i) {
+    Expect.isTrue(await si.moveNext());
+    Expect.equals(42, (si.current)());
+  }
+  si.cancel(); // closes the port
+}
+
+testNormalEnclosingFunction(ReceivePort rp) {
+  final invalidObject = ClassWithNativeFields();
+  final normalObject = Object();
+
+  captureInvalidObject() => invalidObject;
+  captureNormalObject() => normalObject;
+  captureNothing() => 42;
+
+  Expect.throwsArgumentError(() => rp.sendPort.send(captureInvalidObject));
+
+  // TODO(http://dartbug.com/36983): Avoid capturing more than needed.
+  Expect.throwsArgumentError(() => rp.sendPort.send(captureNormalObject));
+
+  // Should not throw, since the [captureNothing] closure should not have a
+  // parent context and therefore not transitively refer [rp].
+  rp.sendPort.send(captureNothing);
+}
+
+testNormalNestedEnclosingFunction(ReceivePort rp) {
+  final invalidObject = ClassWithNativeFields();
+  final normalObject = Object();
+  nested() {
+    captureInvalidObject() => invalidObject;
+    captureNormalObject() => normalObject;
+    captureNothing() => 42;
+
+    Expect.throwsArgumentError(() => rp.sendPort.send(captureInvalidObject));
+
+    // TODO(http://dartbug.com/36983): Avoid capturing more than needed.
+    Expect.throwsArgumentError(() => rp.sendPort.send(captureNormalObject));
+
+    // Should not throw, since the [captureNothing] closure should not have a
+    // parent context and therefore not transitively refer [rp].
+    rp.sendPort.send(captureNothing);
+  }
+
+  nested();
+}
+
+testNormalNestedEnclosingFunction2(ReceivePort rp) {
+  final invalidObject = ClassWithNativeFields();
+  final normalObject = Object();
+
+  captureInvalidObject() {
+    local() => invalidObject;
+    return local;
+  }
+
+  captureNormalObject() {
+    local() => normalObject;
+    return local;
+  }
+
+  captureNothing() => 42;
+
+  Expect.throwsArgumentError(() => rp.sendPort.send(captureInvalidObject));
+
+  // TODO(http://dartbug.com/36983): Avoid capturing more than needed.
+  Expect.throwsArgumentError(() => rp.sendPort.send(captureNormalObject));
+
+  // Should not throw, since the [captureNothing] closure should not have a
+  // parent context and therefore not transitively refer [rp].
+  rp.sendPort.send(captureNothing);
+}
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 870c86f..7464bef 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -5252,7 +5252,7 @@
     bool has_valid_annotation,
     bool has_pragma,
     intptr_t func_decl_offset) {
-  intptr_t offset = ReaderOffset();
+  const intptr_t offset = ReaderOffset();
 
   FunctionNodeHelper function_node_helper(this);
   function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
@@ -5385,7 +5385,11 @@
 
   Fragment instructions;
   instructions += Constant(function);
-  instructions += LoadLocal(parsed_function()->current_context_var());
+  if (scopes()->IsClosureWithEmptyContext(offset)) {
+    instructions += NullConstant();
+  } else {
+    instructions += LoadLocal(parsed_function()->current_context_var());
+  }
   instructions += flow_graph_builder_->AllocateClosure();
   LocalVariable* closure = MakeTemporary();
 
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 7d7ab7e..f103f14 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -1492,7 +1492,7 @@
 
 void ScopeBuilder::HandleLocalFunction(intptr_t parent_kernel_offset) {
   // "Peek" ahead into the function node
-  intptr_t offset = helper_.ReaderOffset();
+  const intptr_t offset = helper_.ReaderOffset();
 
   FunctionNodeHelper function_node_helper(&helper_);
   function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
@@ -1534,6 +1534,14 @@
 
   VisitFunctionNode();  // read function node.
 
+  // Remember if this closure and all closures nested within it don't
+  // capture any variables from outer scopes.
+  if (scope_->function_level() == 1) {
+    if (scope_->NumCapturedVariables() == 0) {
+      result_->closure_offsets_without_captures.Add(offset);
+    }
+  }
+
   ExitScope(function_node_helper.position_, function_node_helper.end_position_);
   depth_ = saved_depth_state;
   current_function_scope_ = saved_function_scope;
diff --git a/runtime/vm/compiler/frontend/scope_builder.h b/runtime/vm/compiler/frontend/scope_builder.h
index 1531508..9805939 100644
--- a/runtime/vm/compiler/frontend/scope_builder.h
+++ b/runtime/vm/compiler/frontend/scope_builder.h
@@ -189,6 +189,15 @@
         yield_context_variable(NULL),
         raw_variable_counter_(0) {}
 
+  bool IsClosureWithEmptyContext(intptr_t function_node_offset) {
+    for (intptr_t i = 0; i < closure_offsets_without_captures.length(); ++i) {
+      if (closure_offsets_without_captures[i] == function_node_offset) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   IntMap<LocalVariable*> locals;
   IntMap<LocalScope*> scopes;
   GrowableArray<FunctionScope> function_scopes;
@@ -230,6 +239,10 @@
   // For-in iterators, one per for-in nesting level.
   GrowableArray<LocalVariable*> iterator_variables;
 
+  // Remembers closure function kernel offsets that do not capture any
+  // variables.
+  GrowableArray<intptr_t> closure_offsets_without_captures;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ScopeBuildingResult);
 };
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 8dc8f37..d6555b3 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -1774,31 +1774,10 @@
   }
 
  private:
-  friend class DisabledNoActiveIsolateScope;
   Thread* thread_;
   Isolate* saved_isolate_;
 };
 
-// Can be used inside a [NoActiveIsolateScope] to set the current isolate.
-class DisabledNoActiveIsolateScope : public StackResource {
- public:
-  explicit DisabledNoActiveIsolateScope(NoActiveIsolateScope* scope)
-      : StackResource(Thread::Current()),
-        thread_(static_cast<Thread*>(thread())),
-        scope_(scope) {
-    ASSERT(thread_->isolate() == nullptr);
-    thread_->isolate_ = scope_->saved_isolate_;
-  }
-  ~DisabledNoActiveIsolateScope() {
-    ASSERT(thread_->isolate_ == scope_->saved_isolate_);
-    thread_->isolate_ = nullptr;
-  }
-
- private:
-  Thread* thread_;
-  NoActiveIsolateScope* scope_;
-};
-
 }  // namespace dart
 
 #endif  // RUNTIME_VM_ISOLATE_H_
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 2aec2d0..3c538f6 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -189,7 +189,7 @@
     : program_(program),
       thread_(Thread::Current()),
       zone_(thread_->zone()),
-      isolate_(thread_->isolate()),
+      no_active_isolate_scope_(),
       patch_classes_(Array::ZoneHandle(zone_)),
       active_class_(),
       library_kernel_offset_(-1),  // Set to the correct value in LoadLibrary
@@ -462,7 +462,7 @@
     : program_(NULL),
       thread_(Thread::Current()),
       zone_(thread_->zone()),
-      isolate_(thread_->isolate()),
+      no_active_isolate_scope_(),
       patch_classes_(Array::ZoneHandle(zone_)),
       library_kernel_offset_(data_program_offset),
       kernel_binary_version_(kernel_binary_version),
@@ -646,8 +646,6 @@
 }
 
 void KernelLoader::LoadLibrary(const Library& library) {
-  NoActiveIsolateScope no_active_isolate_scope;
-
   // This will be invoked by VM bootstrapping code.
   SafepointWriteRwLocker ml(thread_, thread_->isolate_group()->program_lock());
 
@@ -874,8 +872,6 @@
         "not allowed");
   }
 
-  NoActiveIsolateScope no_active_isolate_scope;
-
   // Read library index.
   library_kernel_offset_ = library_offset(index);
   correction_offset_ = library_kernel_offset_;
@@ -1690,8 +1686,6 @@
 }
 
 void KernelLoader::FinishLoading(const Class& klass) {
-  NoActiveIsolateScope no_active_isolate_scope;
-
   ASSERT(klass.IsTopLevel() || (klass.kernel_offset() > 0));
 
   Zone* zone = Thread::Current()->zone();
diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h
index 4fe570f..573711f 100644
--- a/runtime/vm/kernel_loader.h
+++ b/runtime/vm/kernel_loader.h
@@ -375,7 +375,7 @@
 
   Thread* thread_;
   Zone* zone_;
-  Isolate* isolate_;
+  NoActiveIsolateScope no_active_isolate_scope_;
   Array& patch_classes_;
   ActiveClass active_class_;
   // This is the offset of the current library within
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 3577ccb..8344d4b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -13639,11 +13639,13 @@
         zone, String::New("Kernel isolate returned ill-formed kernel.")));
   }
 
-  kernel::KernelLoader loader(kernel_pgm.get(),
-                              /*uri_to_source_table=*/nullptr);
-  auto& result = Object::Handle(
-      zone, loader.LoadExpressionEvaluationFunction(library_url, klass));
-  kernel_pgm.reset();
+  auto& result = Object::Handle(zone);
+  {
+    kernel::KernelLoader loader(kernel_pgm.get(),
+                                /*uri_to_source_table=*/nullptr);
+    result = loader.LoadExpressionEvaluationFunction(library_url, klass);
+    kernel_pgm.reset();
+  }
 
   if (result.IsError()) return result.ptr();
 
diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc
index c6e6c9d..52c680f 100644
--- a/runtime/vm/object_graph_copy.cc
+++ b/runtime/vm/object_graph_copy.cc
@@ -245,7 +245,9 @@
 DART_FORCE_INLINE
 ObjectPtr AllocateObject(intptr_t cid, intptr_t size) {
 #if defined(DART_COMPRESSED_POINTERS)
-  const bool compressed = true;
+  // TODO(rmacnak): Can be changed unconditionally to `true` once Contexts
+  // are compressed.
+  const bool compressed = cid != kContextCid;
 #else
   const bool compressed = false;
 #endif
@@ -1161,8 +1163,9 @@
 
     UntagContext(to)->num_variables_ = UntagContext(from)->num_variables_;
 
-    Base::ForwardCompressedPointer(from, to,
-                                   OFFSET_OF(UntaggedContext, parent_));
+    // TODO(rmacnak): Should use ForwardCompressedPointer once contexts are
+    // compressed.
+    Base::ForwardPointer(from, to, OFFSET_OF(UntaggedContext, parent_));
     Base::ForwardContextPointers(
         length, from, to, Context::variable_offset(0),
         Context::variable_offset(0) + kWordSize * length);
diff --git a/tests/language/explicit_type_instantiation_parsing_test.dart b/tests/language/explicit_type_instantiation_parsing_test.dart
new file mode 100644
index 0000000..4397a2c
--- /dev/null
+++ b/tests/language/explicit_type_instantiation_parsing_test.dart
@@ -0,0 +1,321 @@
+// 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.
+
+// SharedOptions=--enable-experiment=constructor-tearoffs
+
+// Test parsing around ambiguities in grammar for explicit type instantiation.
+//
+// If an expression is followed by a  `<`
+// which is then followed by potential type arguments and a `>`,
+// it is parsed as type arguments if the next token is one of
+// `)`, `}`, `]`, `:`, `;`, `,`, `(`, `.`, `==` or `!=`.
+// Otherwise it's (attempted) parsed as a `<` infix operator.
+// This decision is made no matter whether what otherwise follows
+// is valid for that choice.
+
+typedef X<_> = Class;
+
+typedef Z<_, __> = Class;
+
+const Object? v = null;
+const dynamic d = null;
+
+class Class {
+  Class([_]);
+  Class.named([_]);
+
+  static Class get instance => Class();
+
+  Class get value => this;
+  Class call([_]) => this;
+}
+
+int f1<X>([_]) => 0;
+int f2<X, Y>([_]) => 0;
+int f3<X, Y, Z>([_]) => 0;
+
+// Type of the instantiation of the functions above.
+typedef F = int Function([Object? _]);
+
+void expect1<T extends Object?>(T? a) {}
+void expect2(Object? a, Object? b) {}
+void expect3(Object? a, Object? b, Object? c) {}
+void expect4(Object? a, Object? b, Object? c, Object? d) {}
+
+// Anything goes!
+// We only care about parsing here, if it parses,
+// all objects support all the operations.
+extension <T extends Object?> on T {
+  T get self => this;
+  dynamic get any => null;
+  Object? operator *(_) => null;
+  Object? operator -(_) => null;
+  Object? operator <(_) => null;
+  Object? operator >(_) => null;
+  Object? operator >>(_) => null;
+  Object? operator >>>(_) => null;
+  Object? operator [](_) => null;
+  Object? call<R, S>([_]) => null;
+  bool get asBool => true;
+  int get prop => 0;
+  set prop(int _) {}
+}
+
+void main() {
+  Object? as = "gotcha!"; // Built-in identifier declared as variable.
+
+  // Validly parsed as type instantiation.
+  // Continuation tokens are: `(`, `.`, `==` and `!=`.
+  expect1<Class>(Z<X, X>(2));
+  expect1<Class>(Z<X, X>.named(2));
+  expect1<Function>(Z<X, X>.named); // constructor tear-off
+  expect1<bool>(Z<X, X> == Class);
+  expect1<bool>(Z<X, X> != Class);
+  // Stop tokens are `)`, `,`, `}`, `]`, `:` and `;`.
+  expect1<Type>(Z<X, X>);
+  expect1<Type>(Z<X, X>,);
+  expect1<Set<Type>>({Z<X, X>});
+  expect1<List<Type>>([Z<X, X>]);
+  expect1<Type>(v.asBool ? Z<X, X> : int);
+  expect1<Map<Type, int>>({Z<X, X>: 1});
+  {
+    Type _ = Z<X, X>;
+  }
+
+  // Validly parsed as generic function instantiation.
+  expect1<int>(f2<X, X>(1));
+  expect1<F>(f2<X, X>.self);
+  expect1<int>(f2<X, X>.self());
+  expect1<bool>(f2<X, X> == null);
+  expect1<bool>(f2<X, X> != null);
+
+  expect1<F>(f2<X, X>);
+  expect1<F>(f2<X, X>,);
+  expect1<Set<F>>({f2<X, X>});
+  expect1<List<F>>([f2<X, X>]);
+  expect1<F>(v.asBool ? f2<X, X> : ([_]) => 2);
+  expect1<Map<F, int>>({f2<X, X> : 2});
+  {
+    F _ = f2<X, X>;
+  }
+
+  // Also works if ending in `>>` or `>>>`
+  expect1<Class>(Z<X, Z<X, X>>(2));
+  expect1<Class>(Z<X, Z<X, X>>.named(2));
+  expect1<Function>(Z<X, Z<X, X>>.named); // constructor tear-off
+  expect1<bool>(Z<X, Z<X, X>> == Class);
+  expect1<bool>(Z<X, Z<X, X>> != Class);
+  // Stop tokens are `)`, `,`, `}`, `]`, `:` and `;`.
+  expect1<Type>(Z<X, Z<X, X>>);
+  expect1<Type>(Z<X, Z<X, X>>,);
+  expect1<Set<Type>>({Z<X, Z<X, X>>});
+  expect1<List<Type>>([Z<X, Z<X, X>>]);
+  expect1<Type>(v.asBool ? Z<X, Z<X, X>> : int);
+  expect1<Map<Type, int>>({Z<X, Z<X, X>> : 1});
+  {
+    Type _ = Z<X, Z<X, X>>;
+  }
+
+  // Validly parsed as generic function instantiation.
+  expect1<int>(f2<X, Z<X, X>>(1));
+  expect1<F>(f2<X, Z<X, X>>.self);
+  expect1<int>(f2<X, Z<X, X>>.self());
+  expect1<bool>(f2<X, Z<X, X>> == null);
+  expect1<bool>(f2<X, Z<X, X>> != null);
+
+  expect1<F>(f2<X, Z<X, X>>);
+  expect1<F>(f2<X, Z<X, X>>,);
+  expect1<Set<F>>({f2<X, Z<X, X>>});
+  expect1<List<F>>([f2<X, Z<X, X>>]);
+  expect1<F>(v.asBool ? f2<X, Z<X, X>> : ([_]) => 2);
+  expect1<Map<F, int>>({f2<X, Z<X, X>> : 2});
+  {
+    F _ = f2<X, Z<X, X>>;
+  }
+
+  expect1<Class>(Z<X, Z<X, Z<X, X>>>(2));
+  expect1<Class>(Z<X, Z<X, Z<X, X>>>.named(2));
+  expect1<Function>(Z<X, Z<X, Z<X, X>>>.named); // constructor tear-off
+  expect1<bool>(Z<X, Z<X, Z<X, X>>> == Class);
+  expect1<bool>(Z<X, Z<X, Z<X, X>>> != Class);
+  // Stop tokens are `)`, `,`, `}`, `]`, `:` and `;`.
+  expect1<Type>(Z<X, Z<X, Z<X, X>>>);
+  expect1<Type>(Z<X, Z<X, Z<X, X>>>,);
+  expect1<Set<Type>>({Z<X, Z<X, Z<X, X>>>});
+  expect1<List<Type>>([Z<X, Z<X, Z<X, X>>>]);
+  expect1<Type>(v.asBool ? Z<X, Z<X, Z<X, X>>> : int);
+  expect1<Map<Type, int>>({Z<X, Z<X, Z<X, X>>>: 1});
+  {
+    Type _ = Z<X, Z<X, Z<X, X>>>;
+  }
+
+  // Validly parsed as generic function instantiation.
+  expect1<int>(f2<X, Z<X, Z<X, X>>>(1));
+  expect1<F>(f2<X, Z<X, Z<X, X>>>.self);
+  expect1<int>(f2<X, Z<X, Z<X, X>>>.self());
+  expect1<bool>(f2<X, Z<X, Z<X, X>>> == null);
+  expect1<bool>(f2<X, Z<X, Z<X, X>>> != null);
+
+  expect1<F>(f2<X, Z<X, Z<X, X>>>);
+  expect1<F>(f2<X, Z<X, Z<X, X>>>,);
+  expect1<Set<F>>({f2<X, Z<X, Z<X, X>>>});
+  expect1<List<F>>([f2<X, Z<X, Z<X, X>>>]);
+  expect1<F>(v.asBool ? f2<X, Z<X, Z<X, X>>> : ([_]) => 2);
+  expect1<Map<F, int>>({f2<X, Z<X, Z<X, X>>> : 2});
+  {
+    F _ = f2<X, Z<X, Z<X, X>>>;
+  }
+
+  // Parsed as instantiation, can't access statics on instantiated type literal.
+  expect1<Class>(Z<X, X>.instance);
+  //                     ^^^^^^^^
+  // [cfe] Cannot access static member on an instantiated generic class.
+  // [analyzer] unspecified
+
+
+  // Not valid <typeList> inside `<..>`, so always parsed as operators.
+  // The expect2 function requires two arguments, so it would be a type
+  // error to parse as type arguments.
+  expect2(Z < X, 2 > (2));
+  expect2(Z < 2, X > (2));
+  expect2(Z < X, 2 > (2));
+  expect2(Z < X, v! > (2));
+  expect3(Z < X, Z < X, 2 >> (2));
+  expect4(Z < X, Z < X, Z < X, 2 >>> (2));
+  // `as` is a built-in identifier, so it cannot be a *type*,
+  // preventing the lookahead from `<` from matching <typeList>,
+  // and therefore it's parsed as an operator.
+  expect2(Z < X, as > (2));
+  expect3(Z < X, Z < X, as >> (2));
+  expect4(Z < X, Z < X, Z < X, as >>> (2));
+
+  // Validly parsed as operators due to disambiguation.
+  expect2(Z < X, X > X);
+  expect2(Z < X, X > 2);
+  expect2(Z < X, X > .2); // That `.` is part of the number literal, not a `.` token.
+  expect2(Z < X, X > -2);
+  expect2(Z < X, X > as);
+  expect2(Z < X, X > [1]);
+  expect2(Z < X, X > ![1].asBool);
+  expect2(Z < X, X > ++[1].prop);
+  expect2(Z < X, X > <int>[1]);
+
+  // Some would be valid as instantiation too, as proven by parenthefication.
+  expect1((Z<X, X>) - 2);
+  expect1((Z<X, X>)[1]);
+  expect1((Z<X, X>)![1].asBool);  // ignore: unnecessary_non_null_assertion
+  //       ^
+  // [cfe] Operand of null-aware operation '!' has type 'Type' which excludes null.
+
+  // Works if the type argument would end in `>>` or `>>>` too.
+  expect3(Z < X, Z < X, X >> X);
+  expect3(Z < X, Z < X, X >> 2);
+  expect3(Z < X, Z < X, X >> .2);
+  expect3(Z < X, Z < X, X >> -2);
+  expect3(Z < X, Z < X, X >> as);
+  expect3(Z < X, Z < X, X >> [1]);
+  expect3(Z < X, Z < X, X >> ![1].asBool);
+  expect3(Z < X, Z < X, X >> ++[1].prop);
+
+  expect4(Z < X, Z < X, Z < X, X >>> X);
+  expect4(Z < X, Z < X, Z < X, X >>> 2);
+  expect4(Z < X, Z < X, Z < X, X >>> .2);
+  expect4(Z < X, Z < X, Z < X, X >>> -2);
+  expect4(Z < X, Z < X, Z < X, X >>> as);
+  expect4(Z < X, Z < X, Z < X, X >>> [1]);
+  expect4(Z < X, Z < X, Z < X, X >>> ![1].asBool);
+  expect4(Z < X, Z < X, Z < X, X >>> ++[1].prop);
+
+  // No valid parsing either way.
+
+  // Content of type arguments not valid types.
+  // Cannot parse as operators since grammar doesn't allow chaining.
+  X<2>(2);
+  // ^
+  // [cfe] A comparison expression can't be an operand of another comparison expression.
+  // [analyzer] SYNTACTIC_ERROR.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
+
+  X<2>;
+  //  ^
+  // [cfe] Expected an identifier, but got ';'.
+  // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+  // ^
+  // [cfe] A comparison expression can't be an operand of another comparison expression.
+  // [analyzer] SYNTACTIC_ERROR.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
+
+  X<2>.instance; // Not type argument.
+  //  ^
+  // [cfe] Expected an identifier, but got '.'.
+  // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+  // ^
+  // [cfe] A comparison expression can't be an operand of another comparison expression.
+  // [analyzer] SYNTACTIC_ERROR.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
+
+  X<2>.any;
+  //  ^
+  // [cfe] Expected an identifier, but got '.'.
+  // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+  // ^
+  // [cfe] A comparison expression can't be an operand of another comparison expression.
+  // [analyzer] SYNTACTIC_ERROR.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
+
+  // This would be invalid even if `X` had an `any` member. See next.
+  X<X>.any; // Invalid, Class does not have any static `any` member.
+  //   ^^^
+  // [cfe] Member not found: 'any'.
+  // [analyzer] unspecified
+
+  X<X>.instance; // Does have static `instance` member, can't access this way.
+  //   ^^^^^^^^
+  // [cfe] Cannot access static member on an instantiated generic class.
+  // [analyzer] unspecified
+
+  // Parse error.
+
+  X<X>2;
+  // ^
+  // [cfe] A comparison expression can't be an operand of another comparison expression.
+  // [analyzer] SYNTACTIC_ERROR.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
+
+  // Doesn't parse as operators, would be valid if type arguments.
+
+  // The following `-` forces operators, but those can't parse like this.
+  X<X>-1;
+  // ^
+  // [cfe] A comparison expression can't be an operand of another comparison expression.
+  // [analyzer] SYNTACTIC_ERROR.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
+
+  // Parsed as operators on function instantiation too (parsing doesn't know.)
+  f1<X> - 1;
+  //  ^
+  // [cfe] A comparison expression can't be an operand of another comparison expression.
+  // [analyzer] SYNTACTIC_ERROR.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
+
+  // Parsed as a generic instantiation, but `v` is not generic function or type.
+  // Would be valid if parsed as operators.
+  expect1(v < X, X > (2));
+  //        ^^^^^^^^
+  // [cfe] unspecified
+  // [analyzer] unspecified
+
+  // Parsed as a generic instantiation, but `d` is not generic function or type.
+  // Being dynamic doesn't help.
+  // Would be valid if parsed as operators.
+  expect1(v < X, X > (2));
+  //        ^^^^^^^^
+  // [cfe] unspecified
+  // [analyzer] unspecified
+
+  // Valid only if parenthesized.
+  expect1((Z < X, X >) * 2);
+
+  // Valid only if parenthesized.
+  expect1((Z < X, X >) < 4);
+
+  // Still can't instantiate something non-generic.
+  /**/ v<int>;
+  //    ^^^^^
+  // [cfe] The static type of the explicit instantiation operand must be a generic function type but is 'Object?'.
+  // [analyzer] unspecified
+}
diff --git a/tests/lib/isolate/illegal_msg_function_test.dart b/tests/lib/isolate/illegal_msg_function_test.dart
index 5b5aa45..62cbe70 100644
--- a/tests/lib/isolate/illegal_msg_function_test.dart
+++ b/tests/lib/isolate/illegal_msg_function_test.dart
@@ -2,7 +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.
 
-// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library illegal_msg_function_test;
diff --git a/tests/lib_2/isolate/illegal_msg_function_test.dart b/tests/lib_2/isolate/illegal_msg_function_test.dart
index 5ea24f0..dbd3699 100644
--- a/tests/lib_2/isolate/illegal_msg_function_test.dart
+++ b/tests/lib_2/isolate/illegal_msg_function_test.dart
@@ -4,7 +4,6 @@
 
 // @dart = 2.9
 
-// VMOptions=--enable-isolate-groups
 // VMOptions=--no-enable-isolate-groups
 
 library illegal_msg_function_test;
diff --git a/tools/VERSION b/tools/VERSION
index 061b57b..b52e166 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 78
+PRERELEASE 79
 PRERELEASE_PATCH 0
\ No newline at end of file