Version 2.14.0-241.0.dev

Merge commit '3405b943389fa0d56fd335361ac3fa861057c52e' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 44baa91..efcb595 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -82,7 +82,7 @@
       "name": "analyzer",
       "rootUri": "../pkg/analyzer",
       "packageUri": "lib/",
-      "languageVersion": "2.13"
+      "languageVersion": "2.12"
     },
     {
       "name": "analyzer_cli",
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 9595fbe..52d52dc 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -567,6 +567,7 @@
   HintCode.MUST_CALL_SUPER,
   HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR,
   HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW,
+  HintCode.NULL_ARGUMENT_TO_NON_NULL_TYPE,
   HintCode.NULL_AWARE_BEFORE_OPERATOR,
   HintCode.NULL_AWARE_IN_CONDITION,
   HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR,
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 66cfda4..cedb70b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -869,6 +869,7 @@
     var result = await getResolvedLibrary2(path);
 
     if (result is NotPathOfUriResult) {
+      // ignore: null_argument_to_non_null_type
       return Future.value(); // bug?
     }
 
@@ -1138,7 +1139,7 @@
   Future<String> getUnitElementSignature(String path) {
     _throwIfNotAbsolutePath(path);
     if (!_fsState.hasUri(path)) {
-      return Future.value();
+      return Future.value(); // ignore: null_argument_to_non_null_type
     }
     var completer = Completer<String>();
     _unitElementSignatureFiles
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 14038d6..878e7c7 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -1683,6 +1683,16 @@
   );
 
   /**
+   * Users should not use `Future.value` or `Completer.complete` with a null
+   * argument if the type argument is non-nullable.
+   */
+  static const HintCode NULL_ARGUMENT_TO_NON_NULL_TYPE = HintCode(
+      'NULL_ARGUMENT_TO_NON_NULL_TYPE',
+      "'{0}' should not be called with a null argument for the non-nullable "
+          "type argument '{1}'",
+      correction: 'Try adding a non-null argument.');
+
+  /**
    * When the left operand of a binary expression uses '?.' operator, it can be
    * `null`.
    */
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 0dcc2f6..a1d8739 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -27,6 +27,7 @@
 import 'package:analyzer/src/error/deprecated_member_use_verifier.dart';
 import 'package:analyzer/src/error/error_handler_verifier.dart';
 import 'package:analyzer/src/error/must_call_super_verifier.dart';
+import 'package:analyzer/src/error/null_safe_api_verifier.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -76,6 +77,8 @@
 
   final ErrorHandlerVerifier _errorHandlerVerifier;
 
+  final NullSafeApiVerifier _nullSafeApiVerifier;
+
   /// The [WorkspacePackage] in which [_currentLibrary] is declared.
   final WorkspacePackage? _workspacePackage;
 
@@ -115,6 +118,7 @@
         _mustCallSuperVerifier = MustCallSuperVerifier(_errorReporter),
         _errorHandlerVerifier =
             ErrorHandlerVerifier(_errorReporter, typeProvider, typeSystem),
+        _nullSafeApiVerifier = NullSafeApiVerifier(_errorReporter, typeSystem),
         _workspacePackage = workspacePackage {
     _deprecatedVerifier.pushInDeprecatedValue(_currentLibrary.hasDeprecated);
     _inDoNotStoreMember = _currentLibrary.hasDoNotStore;
@@ -567,6 +571,7 @@
   @override
   void visitInstanceCreationExpression(InstanceCreationExpression node) {
     _deprecatedVerifier.instanceCreationExpression(node);
+    _nullSafeApiVerifier.instanceCreation(node);
     _checkForLiteralConstructorUse(node);
     super.visitInstanceCreationExpression(node);
   }
@@ -644,6 +649,7 @@
     _deprecatedVerifier.methodInvocation(node);
     _checkForNullAwareHints(node, node.operator);
     _errorHandlerVerifier.verifyMethodInvocation(node);
+    _nullSafeApiVerifier.methodInvocation(node);
     super.visitMethodInvocation(node);
   }
 
diff --git a/pkg/analyzer/lib/src/error/null_safe_api_verifier.dart b/pkg/analyzer/lib/src/error/null_safe_api_verifier.dart
new file mode 100644
index 0000000..a0308f1
--- /dev/null
+++ b/pkg/analyzer/lib/src/error/null_safe_api_verifier.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/type_system.dart';
+import 'package:analyzer/src/dart/error/hint_codes.dart';
+
+/// Verifies usages of `Future.value` and `Completer.complete` when null-safety
+/// is enabled.
+///
+/// `Future.value` and `Completer.complete` both accept a `FutureOr<T>?` as an
+/// optional argument but throw an exception when `T` is non-nullable and `null`
+/// is passed as an argument.
+///
+/// This verifier detects and reports those scenarios.
+class NullSafeApiVerifier {
+  final ErrorReporter _errorReporter;
+  final TypeSystemImpl _typeSystem;
+
+  NullSafeApiVerifier(this._errorReporter, this._typeSystem);
+
+  /// Reports an error if the expression creates a `Future<T>.value` with a non-
+  /// nullable value `T` and an argument that is effectively `null`.
+  void instanceCreation(InstanceCreationExpression expression) {
+    if (!_typeSystem.isNonNullableByDefault) return;
+
+    final constructor = expression.constructorName.staticElement;
+    if (constructor == null) return;
+
+    final type = constructor.returnType;
+    final isFutureValue = type.isDartAsyncFuture && constructor.name == 'value';
+
+    if (isFutureValue) {
+      _checkTypes(expression, 'Future.value', type.typeArguments.single,
+          expression.argumentList);
+    }
+  }
+
+  /// Reports an error if `Completer<T>.complete` is invoked with a non-nullable
+  /// `T` and an argument that is effectively `null`.
+  void methodInvocation(MethodInvocation node) {
+    if (!_typeSystem.isNonNullableByDefault) return;
+
+    final targetType = node.realTarget?.staticType;
+    final targetClass = targetType?.element;
+    if (targetClass == null || targetType is! InterfaceType) return;
+
+    if (targetClass.library?.isDartAsync == true &&
+        targetClass.name == 'Completer' &&
+        node.methodName.name == 'complete') {
+      _checkTypes(node, 'Completer.complete', targetType.typeArguments.single,
+          node.argumentList);
+    }
+  }
+
+  void _checkTypes(
+      Expression node, String memberName, DartType type, ArgumentList args) {
+    // If there's more than one argument, something else is wrong (and will
+    // generate another diagnostic). Also, only check the argument type if we
+    // expect a non-nullable type in the first place.
+    if (args.arguments.length > 1 || !_typeSystem.isNonNullable(type)) return;
+
+    final argument = args.arguments.isEmpty ? null : args.arguments.single;
+    final argumentType = argument?.staticType;
+    // Skip if the type is not currently resolved.
+    if (argument != null && argumentType == null) return;
+
+    final argumentIsNull =
+        argument == null || _typeSystem.isNull(argumentType!);
+
+    if (argumentIsNull) {
+      _errorReporter.reportErrorForNode(
+          HintCode.NULL_ARGUMENT_TO_NON_NULL_TYPE,
+          argument ?? node,
+          [memberName, type.getDisplayString(withNullability: true)]);
+    }
+  }
+}
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 529d76a..b3cbff8 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -4,7 +4,7 @@
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
 
 environment:
-  sdk: '>=2.13.0 <3.0.0'
+  sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
   _fe_analyzer_shared: ^22.0.0
diff --git a/pkg/analyzer/test/src/diagnostics/null_argument_to_non_null_type_test.dart b/pkg/analyzer/test/src/diagnostics/null_argument_to_non_null_type_test.dart
new file mode 100644
index 0000000..5e9409d
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/null_argument_to_non_null_type_test.dart
@@ -0,0 +1,134 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/dart/error/hint_codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NullArgumentToNonNullCompleterCompleteTest);
+    defineReflectiveTests(NullArgumentToNonNullFutureValueTest);
+  });
+}
+
+@reflectiveTest
+class NullArgumentToNonNullCompleterCompleteTest
+    extends PubPackageResolutionTest {
+  test_absent() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+void f() => Completer<int>().complete();
+''', [
+      error(HintCode.NULL_ARGUMENT_TO_NON_NULL_TYPE, 33, 27),
+    ]);
+  }
+
+  test_dynamic() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f() {
+  Completer<int>().complete(null as dynamic);
+}
+''');
+  }
+
+  test_legacy() async {
+    await assertNoErrorsInCode('''
+// @dart=2.9
+import 'dart:async';
+
+void f() {
+  final c = Completer<int>();
+  c.complete();
+  c.complete(null);
+}
+''');
+  }
+
+  test_null() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+void f() => Completer<int>().complete(null);
+''', [
+      error(HintCode.NULL_ARGUMENT_TO_NON_NULL_TYPE, 59, 4),
+    ]);
+  }
+
+  test_nullable() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f() {
+  final c = Completer<int?>();
+  c.complete();
+  c.complete(null);
+}
+''');
+  }
+
+  test_nullType() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+void f(Null a) => Completer<int>().complete(a);
+''', [
+      error(HintCode.NULL_ARGUMENT_TO_NON_NULL_TYPE, 65, 1),
+    ]);
+  }
+}
+
+@reflectiveTest
+class NullArgumentToNonNullFutureValueTest extends PubPackageResolutionTest {
+  test_absent() async {
+    await assertErrorsInCode('''
+void foo() => Future<int>.value();
+''', [
+      error(HintCode.NULL_ARGUMENT_TO_NON_NULL_TYPE, 14, 19),
+    ]);
+  }
+
+  test_dynamic() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f() {
+  Future<int>.value(null as dynamic);
+}
+''');
+  }
+
+  test_legacy() async {
+    await assertNoErrorsInCode('''
+// @dart=2.9
+void f() {
+  Future<int>.value();
+  Future<int>.value(null);
+}
+''');
+  }
+
+  test_null() async {
+    await assertErrorsInCode('''
+void foo() => Future<int>.value(null);
+''', [
+      error(HintCode.NULL_ARGUMENT_TO_NON_NULL_TYPE, 32, 4),
+    ]);
+  }
+
+  test_nullable() async {
+    await assertNoErrorsInCode('''
+void f() {
+  Future<int?>.value();
+  Future<int?>.value(null);
+}
+''');
+  }
+
+  test_nullType() async {
+    await assertErrorsInCode('''
+void foo(Null a) => Future<int>.value(a);
+''', [
+      error(HintCode.NULL_ARGUMENT_TO_NON_NULL_TYPE, 38, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 188a40a..8af03ed 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -501,6 +501,8 @@
 import 'not_iterable_spread_test.dart' as not_iterable_spread;
 import 'not_map_spread_test.dart' as not_map_spread;
 import 'not_null_aware_null_spread_test.dart' as not_null_aware_null_spread;
+import 'null_argument_to_non_null_type_test.dart'
+    as null_argument_to_non_null_type;
 import 'null_aware_before_operator_test.dart' as null_aware_before_operator;
 import 'null_aware_in_condition_test.dart' as null_aware_in_condition;
 import 'null_aware_in_logical_operator_test.dart'
@@ -1039,6 +1041,7 @@
     not_iterable_spread.main();
     not_map_spread.main();
     not_null_aware_null_spread.main();
+    null_argument_to_non_null_type.main();
     null_aware_before_operator.main();
     null_aware_in_condition.main();
     null_aware_in_logical_operator.main();
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index a57232b..adbf857 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -335,6 +335,8 @@
   FunctionEntity findHelperFunction(String name);
 
   ClassEntity get closureClass;
+  ClassEntity get closureClass0Args;
+  ClassEntity get closureClass2Args;
 
   ClassEntity get boundClosureClass;
 
@@ -516,8 +518,6 @@
 
   InterfaceType get externalNameType;
 
-  ConstructorEntity get symbolValidatedConstructor;
-
   // From dart:_js_embedded_names
 
   /// Holds the class for the [JsGetName] enum.
@@ -569,8 +569,6 @@
 
   bool isCreateInvocationMirrorHelper(MemberEntity member);
 
-  bool isSymbolValidatedConstructor(ConstructorEntity element);
-
   ClassEntity get metaNoInlineClass;
 
   ClassEntity get metaTryInlineClass;
@@ -1536,6 +1534,16 @@
   @override
   ClassEntity get closureClass => _closureClass ??= _findHelperClass('Closure');
 
+  ClassEntity _closureClass0Args;
+  @override
+  ClassEntity get closureClass0Args =>
+      _closureClass0Args ??= _findHelperClass('Closure0Args');
+
+  ClassEntity _closureClass2Args;
+  @override
+  ClassEntity get closureClass2Args =>
+      _closureClass2Args ??= _findHelperClass('Closure2Args');
+
   ClassEntity _boundClosureClass;
   @override
   ClassEntity get boundClosureClass =>
@@ -2061,11 +2069,6 @@
   @override
   InterfaceType get externalNameType => _getRawType(externalNameClass);
 
-  @override
-  ConstructorEntity get symbolValidatedConstructor =>
-      _symbolValidatedConstructor ??=
-          _findConstructor(symbolImplementationClass, 'validated');
-
   /// Returns the field that holds the internal name in the implementation class
   /// for `Symbol`.
   FieldEntity _symbolImplementationField;
@@ -2073,15 +2076,6 @@
       _env.lookupLocalClassMember(symbolImplementationClass, '_name',
           required: true);
 
-  ConstructorEntity _symbolValidatedConstructor;
-  @override
-  bool isSymbolValidatedConstructor(ConstructorEntity element) {
-    if (_symbolValidatedConstructor != null) {
-      return element == _symbolValidatedConstructor;
-    }
-    return false;
-  }
-
   // From dart:_native_typed_data
 
   ClassEntity _typedArrayOfIntClass;
diff --git a/pkg/compiler/lib/src/elements/entities.dart b/pkg/compiler/lib/src/elements/entities.dart
index f136327..b0f12cf 100644
--- a/pkg/compiler/lib/src/elements/entities.dart
+++ b/pkg/compiler/lib/src/elements/entities.dart
@@ -291,6 +291,12 @@
   static const ParameterStructure zeroArguments =
       ParameterStructure._(0, 0, [], {}, 0);
 
+  static const ParameterStructure oneArgument =
+      ParameterStructure._(1, 1, [], {}, 0);
+
+  static const ParameterStructure twoArguments =
+      ParameterStructure._(2, 2, [], {}, 0);
+
   static const List<ParameterStructure> _simple = [
     ParameterStructure._(0, 0, [], {}, 0),
     ParameterStructure._(1, 1, [], {}, 0),
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index cb72411..d50ddc1b 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -299,13 +299,6 @@
         constantMapLiteral
       ]);
 
-  BackendImpact _symbolConstructor;
-
-  BackendImpact get symbolConstructor {
-    return _symbolConstructor ??= new BackendImpact(
-        staticUses: [_commonElements.symbolValidatedConstructor]);
-  }
-
   BackendImpact _constSymbol;
 
   BackendImpact get constSymbol {
@@ -574,8 +567,11 @@
   BackendImpact _functionClass;
 
   BackendImpact get functionClass {
-    return _functionClass ??=
-        new BackendImpact(globalClasses: [_commonElements.closureClass]);
+    return _functionClass ??= new BackendImpact(globalClasses: [
+      _commonElements.closureClass,
+      _commonElements.closureClass0Args,
+      _commonElements.closureClass2Args,
+    ]);
   }
 
   BackendImpact _mapClass;
diff --git a/pkg/compiler/lib/src/js_backend/backend_usage.dart b/pkg/compiler/lib/src/js_backend/backend_usage.dart
index ad3877c..6b3e73c 100644
--- a/pkg/compiler/lib/src/js_backend/backend_usage.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_usage.dart
@@ -164,8 +164,7 @@
   bool _isValidEntity(Entity element) {
     if (element is ConstructorEntity &&
         (element == _commonElements.streamIteratorConstructor ||
-            _commonElements.isSymbolConstructor(element) ||
-            _commonElements.isSymbolValidatedConstructor(element))) {
+            _commonElements.isSymbolConstructor(element))) {
       // TODO(johnniwinther): These are valid but we could be more precise.
       return true;
     } else if (element == _commonElements.symbolImplementationClass ||
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index 9596fd0..c57ab1c 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -114,9 +114,6 @@
         case Feature.SUPER_NO_SUCH_METHOD:
           registerImpact(_impacts.superNoSuchMethod);
           break;
-        case Feature.SYMBOL_CONSTRUCTOR:
-          registerImpact(_impacts.symbolConstructor);
-          break;
         case Feature.SYNC_FOR_IN:
           registerImpact(_impacts.syncForIn);
           break;
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index fd4296e..156ccb1 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -241,7 +241,14 @@
   final bool onlyForConstructor;
   final bool isDirectlyInstantiated;
   final bool isNative;
-  final bool isClosureBaseClass; // Common base class for closures.
+
+  /// `true` if this is the one class that is the root of all 'Closure' classes.
+  final bool isClosureBaseClass;
+
+  /// If non-null, this class is used as a base class for closures with a fixed
+  /// small number of arguments in order to inherit `Function.apply`
+  /// metadata. The value is the fixed number of arguments.
+  final int sharedClosureApplyMetadata;
 
   final bool isMixinApplicationWithMembers;
 
@@ -279,6 +286,7 @@
       this.isDirectlyInstantiated,
       this.isNative,
       this.isClosureBaseClass,
+      this.sharedClosureApplyMetadata,
       this.isMixinApplicationWithMembers}) {
     assert(onlyForRti != null);
     assert(onlyForConstructor != null);
@@ -492,6 +500,8 @@
   /// functions that can be torn off.
   final bool isClosureCallMethod;
 
+  final bool inheritsApplyMetadata;
+
   /// True if the interceptor calling convention is used for this method.
   final bool isIntercepted;
 
@@ -512,6 +522,7 @@
     int requiredParameterCount,
     /* List | Map */ optionalParameterDefaultValues,
     this.isClosureCallMethod,
+    this.inheritsApplyMetadata,
     this.isIntercepted,
     js.Expression functionType,
     int applyIndex,
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 6c581a5..2a8ae0a 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -557,7 +557,18 @@
     bool onlyForRti = _nativeData.isJsInteropClass(cls);
     bool hasRtiField = _rtiNeed.classNeedsTypeArguments(cls);
     bool onlyForConstructorOrRti = onlyForConstructor || onlyForRti;
+
+    // Recognize the specialized base classes for closures.
     bool isClosureBaseClass = cls == _commonElements.closureClass;
+    int sharedClosureApplyMetadata;
+    if (cls == _commonElements.closureClass) {
+      // The root base class has metadata for single-argument closures.
+      sharedClosureApplyMetadata = 1;
+    } else if (cls == _commonElements.closureClass0Args) {
+      sharedClosureApplyMetadata = 0;
+    } else if (cls == _commonElements.closureClass2Args) {
+      sharedClosureApplyMetadata = 2;
+    }
 
     List<Method> methods = [];
     List<StubMethod> callStubs = [];
@@ -712,6 +723,7 @@
       assert(!_nativeData.isNativeClass(cls));
       assert(methods.isEmpty);
       assert(!isClosureBaseClass);
+      assert(sharedClosureApplyMetadata == null);
 
       result = MixinApplication(cls, typeData, name, instanceFields, callStubs,
           checkedSetters, gettersSetters, isChecks, typeTests.functionTypeIndex,
@@ -738,6 +750,7 @@
           onlyForConstructor: onlyForConstructor,
           isNative: _nativeData.isNativeClass(cls),
           isClosureBaseClass: isClosureBaseClass,
+          sharedClosureApplyMetadata: sharedClosureApplyMetadata,
           isMixinApplicationWithMembers: isMixinApplicationWithMembers);
     }
     _classes[cls] = result;
@@ -814,6 +827,7 @@
     bool tearOffNeedsDirectAccess = false;
     js.Name tearOffName;
     bool isClosureCallMethod = false;
+    bool inheritsApplyMetadata = false;
     bool isNotApplyTarget =
         !element.isFunction || element.isGetter || element.isSetter;
 
@@ -829,6 +843,17 @@
       if (element.enclosingClass.isClosure) {
         canTearOff = false;
         isClosureCallMethod = true;
+        ClassEntity superclass =
+            _elementEnvironment.getSuperClass(element.enclosingClass);
+        if (superclass == _commonElements.closureClass &&
+                element.parameterStructure == ParameterStructure.oneArgument ||
+            superclass == _commonElements.closureClass0Args &&
+                element.parameterStructure ==
+                    ParameterStructure.zeroArguments ||
+            superclass == _commonElements.closureClass2Args &&
+                element.parameterStructure == ParameterStructure.twoArguments) {
+          inheritsApplyMetadata = true;
+        }
       } else {
         // Careful with operators.
         bool needsSuperGetter = _codegenWorld.methodsNeedsSuperGetter(element);
@@ -881,6 +906,7 @@
         tearOffName: tearOffName,
         tearOffNeedsDirectAccess: tearOffNeedsDirectAccess,
         isClosureCallMethod: isClosureCallMethod,
+        inheritsApplyMetadata: inheritsApplyMetadata,
         isIntercepted: isIntercepted,
         aliasName: aliasName,
         canBeApplied: canBeApplied,
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 9f40195..bf57340 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -592,6 +592,9 @@
       _call1Name ??= _namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX1);
   js.Name get call2Name =>
       _call2Name ??= _namer.getNameForJsGetName(null, JsGetName.CALL_PREFIX2);
+  List<js.Name> _callNamesByArity;
+  List<js.Name> get callNamesByArity =>
+      _callNamesByArity ??= [call0Name, call1Name, call2Name];
 
   FragmentEmitter(
       this._options,
@@ -1068,26 +1071,31 @@
     allMethods.forEach((Method method) {
       emitInstanceMethod(method)
           .forEach((js.Expression name, js.Expression code) {
-        var prop = js.Property(name, code);
-        registerEntityAst(method.element, prop);
-        properties.add(prop);
+        final property = js.Property(name, code);
+        registerEntityAst(method.element, property);
+        properties.add(property);
       });
     });
 
-    if (cls.isClosureBaseClass) {
-      // Closures extend a common base class, so we can put properties on the
-      // prototype for common values.
+    // Closures have metadata that is often the same. We avoid repeated metadata
+    // by putting it on a shared superclass. It is overridden in the subclass if
+    // necessary.
 
-      // Closures taking exactly one argument are common.
+    int arity = cls.sharedClosureApplyMetadata;
+    if (arity != null) {
+      // This is a closure base class that has the specialized `Function.apply`
+      // metadata for functions taking exactly [arity] arguments.
       properties.add(js.Property(js.string(_namer.fixedNames.callCatchAllName),
-          js.quoteName(call1Name)));
+          js.quoteName(callNamesByArity[arity])));
       properties.add(js.Property(
-          js.string(_namer.fixedNames.requiredParameterField), js.number(1)));
+          js.string(_namer.fixedNames.requiredParameterField),
+          js.number(arity)));
+    }
 
+    if (cls.isClosureBaseClass) {
       // Most closures have no optional arguments.
       properties.add(js.Property(
-          js.string(_namer.fixedNames.defaultValuesField),
-          new js.LiteralNull()));
+          js.string(_namer.fixedNames.defaultValuesField), js.LiteralNull()));
     }
 
     return new js.ObjectInitializer(properties);
@@ -1112,35 +1120,27 @@
       }
 
       if (method.isClosureCallMethod && method.canBeApplied) {
-        // TODO(sra): We should also add these properties for the user-defined
-        // `call` method on classes. Function.apply is currently broken for
-        // complex cases. [forceAdd] might be true when this is fixed.
-        bool forceAdd = !method.isClosureCallMethod;
+        // The `call` method might flow to `Function.apply`, so the metadata for
+        // `Function.apply` is needed.
 
-        // Common case of "call*": "call$1" is stored on the Closure class.
-        if (method.applyIndex != 0 ||
-            method.parameterStubs.isNotEmpty ||
-            method.requiredParameterCount != 1 ||
-            forceAdd) {
+        // Avoid adding the metadata if a superclass has the same metadata.
+        if (!method.inheritsApplyMetadata) {
           js.Name applyName = method.applyIndex == 0
               ? method.name
               : method.parameterStubs[method.applyIndex - 1].name;
           properties[js.string(_namer.fixedNames.callCatchAllName)] =
               js.quoteName(applyName);
-        }
-        // Common case of '1' is stored on the Closure class.
-        if (method.requiredParameterCount != 1 || forceAdd) {
           properties[js.string(_namer.fixedNames.requiredParameterField)] =
               js.number(method.requiredParameterCount);
-        }
 
-        js.Expression defaultValues =
-            _encodeOptionalParameterDefaultValues(method);
-        // Default values property of `null` is stored on the common JS
-        // superclass.
-        if (defaultValues is! js.LiteralNull || forceAdd) {
-          properties[js.string(_namer.fixedNames.defaultValuesField)] =
-              defaultValues;
+          js.Expression defaultValues =
+              _encodeOptionalParameterDefaultValues(method);
+          // Default values property of `null` is stored on the common JS
+          // superclass.
+          if (defaultValues is! js.LiteralNull) {
+            properties[js.string(_namer.fixedNames.defaultValuesField)] =
+                defaultValues;
+          }
         }
       }
     }
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index c07ccea..8a4928d 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -417,7 +417,8 @@
       Map<ir.VariableDeclaration, JRecordField> boxedVariables,
       KernelScopeInfo info,
       {bool createSignatureMethod}) {
-    ClassEntity superclass = _commonElements.closureClass;
+    ClassEntity superclass =
+        _chooseClosureSuperclass(originalClosureFunctionNode);
 
     JsClosureClassInfo closureClassInfo = _elementMap.constructClosureClass(
         member,
@@ -440,6 +441,21 @@
     return closureClassInfo;
   }
 
+  ClassEntity _chooseClosureSuperclass(ir.FunctionNode node) {
+    // Choose a superclass so that similar closures can share the metadata used
+    // by `Function.apply`.
+    int requiredParameterCount = node.requiredParameterCount;
+    if (node.typeParameters.isEmpty &&
+        node.namedParameters.isEmpty &&
+        requiredParameterCount == node.positionalParameters.length) {
+      if (requiredParameterCount == 0) return _commonElements.closureClass0Args;
+      if (requiredParameterCount == 2) return _commonElements.closureClass2Args;
+    }
+    // Note that the base closure class has specialized metadata for the common
+    // case of single-argument functions.
+    return _commonElements.closureClass;
+  }
+
   OutputUnitData _convertOutputUnitData(JsToFrontendMapImpl map,
       OutputUnitData data, ClosureData closureDataLookup) {
     // Convert front-end maps containing K-class and K-local function keys to a
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index bd6095b..508b578 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -340,10 +340,6 @@
       impactBuilder.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK);
     }
 
-    if (commonElements.isSymbolConstructor(constructor)) {
-      impactBuilder.registerFeature(Feature.SYMBOL_CONSTRUCTOR);
-    }
-
     if (target.isExternal &&
         constructor.isFromEnvironmentConstructor &&
         !isConst) {
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 56c3746..ad8f434 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -5546,9 +5546,6 @@
             node.arguments,
             typeArguments,
             sourceInformation));
-    if (_commonElements.isSymbolConstructor(constructor)) {
-      constructor = _commonElements.symbolValidatedConstructor;
-    }
     // TODO(johnniwinther): Remove this when type arguments are passed to
     // constructors like calling a generic method.
     _addTypeArguments(arguments, _getClassTypeArguments(cls, node.arguments),
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index f907c36..8d8d9ba 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -62,9 +62,6 @@
   /// super method.
   SUPER_NO_SUCH_METHOD,
 
-  /// A redirection to the `Symbol` constructor.
-  SYMBOL_CONSTRUCTOR,
-
   /// An synchronous for in statement, like `for (var e in i) {}`.
   SYNC_FOR_IN,
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 317a63f..2addb57 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -4092,10 +4092,18 @@
   void forEachExtensionInScope(void Function(ExtensionBuilder) f) {
     if (_extensionsInScope == null) {
       _extensionsInScope = <ExtensionBuilder>{};
-      scope.forEachExtension(_extensionsInScope.add);
+      scope.forEachExtension((e) {
+        if (!e.extension.isExtensionTypeDeclaration) {
+          _extensionsInScope.add(e);
+        }
+      });
       if (_prefixBuilders != null) {
         for (PrefixBuilder prefix in _prefixBuilders) {
-          prefix.exportScope.forEachExtension(_extensionsInScope.add);
+          prefix.exportScope.forEachExtension((e) {
+            if (!e.extension.isExtensionTypeDeclaration) {
+              _extensionsInScope.add(e);
+            }
+          });
         }
       }
     }
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index e88b901..2a53afb 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -276,6 +276,7 @@
 erased
 err
 esc
+et
 everytime
 evicting
 exceed
diff --git a/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart b/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart
index 114ac6f..9ecf985 100644
--- a/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart
+++ b/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart
@@ -10,11 +10,22 @@
   double get bar => 3.14;
 }
 
-test(A a, E e) {
+extension type ET on A {
+  String get baz => "baz";
+}
+
+test(A a, E e, ET et) {
   a.foo; // Ok.
   a.bar; // Ok.
+  a.baz; // Error.
+
   e.foo; // Error.
   e.bar; // Ok.
+  e.baz; // Error.
+
+  et.foo; // Error.
+  et.bar; // Error.
+  et.baz; // Ok.
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.strong.expect b/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.strong.expect
index f7bc273..b0091c5 100644
--- a/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.strong.expect
+++ b/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.strong.expect
@@ -2,11 +2,32 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:16:5: Error: The getter 'foo' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:20:5: Error: The getter 'baz' isn't defined for the class 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/extension_types/simple_getter_resolution.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'baz'.
+//   a.baz; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:22:5: Error: The getter 'foo' isn't defined for the extension 'E'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
 //   e.foo; // Error.
 //     ^^^
 //
+// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:24:5: Error: The getter 'baz' isn't defined for the extension 'E'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'baz'.
+//   e.baz; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:26:6: Error: The getter 'foo' isn't defined for the extension 'ET'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+//   et.foo; // Error.
+//      ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:27:6: Error: The getter 'bar' isn't defined for the extension 'ET'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
+//   et.bar; // Error.
+//      ^^^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -20,15 +41,38 @@
 extension E on self::A {
   get bar = self::E|get#bar;
 }
+extension type ET on self::A {
+  get baz = self::ET|get#baz;
+}
 static method E|get#bar(lowered final self::A #this) → core::double
   return 3.14;
-static method test(self::A a, self::E e) → dynamic {
+static method ET|get#baz(lowered final self::A #this) → core::String
+  return "baz";
+static method test(self::A a, self::E e, self::ET et) → dynamic {
   a.{self::A::foo}{core::int};
   self::E|get#bar(a);
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:16:5: Error: The getter 'foo' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:20:5: Error: The getter 'baz' isn't defined for the class 'A'.
+ - 'A' is from 'pkg/front_end/testcases/extension_types/simple_getter_resolution.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'baz'.
+  a.baz; // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:22:5: Error: The getter 'foo' isn't defined for the extension 'E'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
   e.foo; // Error.
     ^^^";
   self::E|get#bar(e);
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:24:5: Error: The getter 'baz' isn't defined for the extension 'E'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'baz'.
+  e.baz; // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:26:6: Error: The getter 'foo' isn't defined for the extension 'ET'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+  et.foo; // Error.
+     ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:27:6: Error: The getter 'bar' isn't defined for the extension 'ET'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
+  et.bar; // Error.
+     ^^^";
+  self::ET|get#baz(et);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.textual_outline.expect
index 587163f..643c52f 100644
--- a/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.textual_outline.expect
@@ -1,10 +1,11 @@
 class A {
   int get foo => 42;
 }
-
 extension E on A {
   double get bar => 3.14;
 }
-
-test(A a, E e) {}
+extension type ET on A {
+  String get baz => "baz";
+}
+test(A a, E e, ET et) {}
 main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.weak.expect b/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.weak.expect
index f7bc273..b0091c5 100644
--- a/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.weak.expect
+++ b/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.weak.expect
@@ -2,11 +2,32 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:16:5: Error: The getter 'foo' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:20:5: Error: The getter 'baz' isn't defined for the class 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/extension_types/simple_getter_resolution.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'baz'.
+//   a.baz; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:22:5: Error: The getter 'foo' isn't defined for the extension 'E'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
 //   e.foo; // Error.
 //     ^^^
 //
+// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:24:5: Error: The getter 'baz' isn't defined for the extension 'E'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'baz'.
+//   e.baz; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:26:6: Error: The getter 'foo' isn't defined for the extension 'ET'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+//   et.foo; // Error.
+//      ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:27:6: Error: The getter 'bar' isn't defined for the extension 'ET'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
+//   et.bar; // Error.
+//      ^^^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -20,15 +41,38 @@
 extension E on self::A {
   get bar = self::E|get#bar;
 }
+extension type ET on self::A {
+  get baz = self::ET|get#baz;
+}
 static method E|get#bar(lowered final self::A #this) → core::double
   return 3.14;
-static method test(self::A a, self::E e) → dynamic {
+static method ET|get#baz(lowered final self::A #this) → core::String
+  return "baz";
+static method test(self::A a, self::E e, self::ET et) → dynamic {
   a.{self::A::foo}{core::int};
   self::E|get#bar(a);
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:16:5: Error: The getter 'foo' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:20:5: Error: The getter 'baz' isn't defined for the class 'A'.
+ - 'A' is from 'pkg/front_end/testcases/extension_types/simple_getter_resolution.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'baz'.
+  a.baz; // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:22:5: Error: The getter 'foo' isn't defined for the extension 'E'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
   e.foo; // Error.
     ^^^";
   self::E|get#bar(e);
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:24:5: Error: The getter 'baz' isn't defined for the extension 'E'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'baz'.
+  e.baz; // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:26:6: Error: The getter 'foo' isn't defined for the extension 'ET'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+  et.foo; // Error.
+     ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_getter_resolution.dart:27:6: Error: The getter 'bar' isn't defined for the extension 'ET'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'bar'.
+  et.bar; // Error.
+     ^^^";
+  self::ET|get#baz(et);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.weak.outline.expect
index 08cef61..23219b8 100644
--- a/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/extension_types/simple_getter_resolution.dart.weak.outline.expect
@@ -11,9 +11,14 @@
 extension E on self::A {
   get bar = self::E|get#bar;
 }
+extension type ET on self::A {
+  get baz = self::ET|get#baz;
+}
 static method E|get#bar(lowered final self::A #this) → core::double
   ;
-static method test(self::A a, self::E e) → dynamic
+static method ET|get#baz(lowered final self::A #this) → core::String
+  ;
+static method test(self::A a, self::E e, self::ET et) → dynamic
   ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/extension_types/simple_method_resolution.dart b/pkg/front_end/testcases/extension_types/simple_method_resolution.dart
index 0406a33..d53964e 100644
--- a/pkg/front_end/testcases/extension_types/simple_method_resolution.dart
+++ b/pkg/front_end/testcases/extension_types/simple_method_resolution.dart
@@ -10,11 +10,22 @@
   void bar() => foo();
 }
 
-test(A a, E e) {
+extension type ET on A {
+  void baz() => foo();
+}
+
+test(A a, E e, ET et) {
   a.foo(); // Ok.
   a.bar(); // Ok.
+  a.baz(); // Error.
+
   e.foo(); // Error.
   e.bar(); // Ok.
+  e.baz(); // Error.
+
+  et.foo(); // Error.
+  et.bar(); // Error.
+  et.baz(); // Ok.
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.strong.expect b/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.strong.expect
index 043030d..d468a09 100644
--- a/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.strong.expect
+++ b/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.strong.expect
@@ -2,11 +2,32 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:16:5: Error: The method 'foo' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:20:5: Error: The method 'baz' isn't defined for the class 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/extension_types/simple_method_resolution.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'baz'.
+//   a.baz(); // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:22:5: Error: The method 'foo' isn't defined for the extension 'E'.
 // Try correcting the name to the name of an existing method, or defining a method name 'foo'.
 //   e.foo(); // Error.
 //     ^^^
 //
+// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:24:5: Error: The method 'baz' isn't defined for the extension 'E'.
+// Try correcting the name to the name of an existing method, or defining a method name 'baz'.
+//   e.baz(); // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:26:6: Error: The method 'foo' isn't defined for the extension 'ET'.
+// Try correcting the name to the name of an existing method, or defining a method name 'foo'.
+//   et.foo(); // Error.
+//      ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:27:6: Error: The method 'bar' isn't defined for the extension 'ET'.
+// Try correcting the name to the name of an existing method, or defining a method name 'bar'.
+//   et.bar(); // Error.
+//      ^^^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -20,17 +41,43 @@
   method bar = self::E|bar;
   tearoff bar = self::E|get#bar;
 }
+extension type ET on self::A {
+  method baz = self::ET|baz;
+  tearoff baz = self::ET|get#baz;
+}
 static method E|bar(lowered final self::A #this) → void
   return #this.{self::A::foo}(){() → void};
 static method E|get#bar(lowered final self::A #this) → () → void
   return () → void => self::E|bar(#this);
-static method test(self::A a, self::E e) → dynamic {
+static method ET|baz(lowered final self::A #this) → void
+  return #this.{self::A::foo}(){() → void};
+static method ET|get#baz(lowered final self::A #this) → () → void
+  return () → void => self::ET|baz(#this);
+static method test(self::A a, self::E e, self::ET et) → dynamic {
   a.{self::A::foo}(){() → void};
   self::E|bar(a);
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:16:5: Error: The method 'foo' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:20:5: Error: The method 'baz' isn't defined for the class 'A'.
+ - 'A' is from 'pkg/front_end/testcases/extension_types/simple_method_resolution.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'baz'.
+  a.baz(); // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:22:5: Error: The method 'foo' isn't defined for the extension 'E'.
 Try correcting the name to the name of an existing method, or defining a method name 'foo'.
   e.foo(); // Error.
     ^^^";
   self::E|bar(e);
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:24:5: Error: The method 'baz' isn't defined for the extension 'E'.
+Try correcting the name to the name of an existing method, or defining a method name 'baz'.
+  e.baz(); // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:26:6: Error: The method 'foo' isn't defined for the extension 'ET'.
+Try correcting the name to the name of an existing method, or defining a method name 'foo'.
+  et.foo(); // Error.
+     ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:27:6: Error: The method 'bar' isn't defined for the extension 'ET'.
+Try correcting the name to the name of an existing method, or defining a method name 'bar'.
+  et.bar(); // Error.
+     ^^^";
+  self::ET|baz(et);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.textual_outline.expect
index d2f4abf..2bc13be 100644
--- a/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.textual_outline.expect
@@ -1,10 +1,11 @@
 class A {
   void foo() {}
 }
-
 extension E on A {
   void bar() => foo();
 }
-
-test(A a, E e) {}
+extension type ET on A {
+  void baz() => foo();
+}
+test(A a, E e, ET et) {}
 main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.weak.expect b/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.weak.expect
index 043030d..d468a09 100644
--- a/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.weak.expect
+++ b/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.weak.expect
@@ -2,11 +2,32 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:16:5: Error: The method 'foo' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:20:5: Error: The method 'baz' isn't defined for the class 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/extension_types/simple_method_resolution.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'baz'.
+//   a.baz(); // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:22:5: Error: The method 'foo' isn't defined for the extension 'E'.
 // Try correcting the name to the name of an existing method, or defining a method name 'foo'.
 //   e.foo(); // Error.
 //     ^^^
 //
+// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:24:5: Error: The method 'baz' isn't defined for the extension 'E'.
+// Try correcting the name to the name of an existing method, or defining a method name 'baz'.
+//   e.baz(); // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:26:6: Error: The method 'foo' isn't defined for the extension 'ET'.
+// Try correcting the name to the name of an existing method, or defining a method name 'foo'.
+//   et.foo(); // Error.
+//      ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_method_resolution.dart:27:6: Error: The method 'bar' isn't defined for the extension 'ET'.
+// Try correcting the name to the name of an existing method, or defining a method name 'bar'.
+//   et.bar(); // Error.
+//      ^^^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -20,17 +41,43 @@
   method bar = self::E|bar;
   tearoff bar = self::E|get#bar;
 }
+extension type ET on self::A {
+  method baz = self::ET|baz;
+  tearoff baz = self::ET|get#baz;
+}
 static method E|bar(lowered final self::A #this) → void
   return #this.{self::A::foo}(){() → void};
 static method E|get#bar(lowered final self::A #this) → () → void
   return () → void => self::E|bar(#this);
-static method test(self::A a, self::E e) → dynamic {
+static method ET|baz(lowered final self::A #this) → void
+  return #this.{self::A::foo}(){() → void};
+static method ET|get#baz(lowered final self::A #this) → () → void
+  return () → void => self::ET|baz(#this);
+static method test(self::A a, self::E e, self::ET et) → dynamic {
   a.{self::A::foo}(){() → void};
   self::E|bar(a);
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:16:5: Error: The method 'foo' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:20:5: Error: The method 'baz' isn't defined for the class 'A'.
+ - 'A' is from 'pkg/front_end/testcases/extension_types/simple_method_resolution.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'baz'.
+  a.baz(); // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:22:5: Error: The method 'foo' isn't defined for the extension 'E'.
 Try correcting the name to the name of an existing method, or defining a method name 'foo'.
   e.foo(); // Error.
     ^^^";
   self::E|bar(e);
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:24:5: Error: The method 'baz' isn't defined for the extension 'E'.
+Try correcting the name to the name of an existing method, or defining a method name 'baz'.
+  e.baz(); // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:26:6: Error: The method 'foo' isn't defined for the extension 'ET'.
+Try correcting the name to the name of an existing method, or defining a method name 'foo'.
+  et.foo(); // Error.
+     ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_method_resolution.dart:27:6: Error: The method 'bar' isn't defined for the extension 'ET'.
+Try correcting the name to the name of an existing method, or defining a method name 'bar'.
+  et.bar(); // Error.
+     ^^^";
+  self::ET|baz(et);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.weak.outline.expect
index e77d076..6072cb8 100644
--- a/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/extension_types/simple_method_resolution.dart.weak.outline.expect
@@ -12,11 +12,19 @@
   method bar = self::E|bar;
   tearoff bar = self::E|get#bar;
 }
+extension type ET on self::A {
+  method baz = self::ET|baz;
+  tearoff baz = self::ET|get#baz;
+}
 static method E|bar(lowered final self::A #this) → void
   ;
 static method E|get#bar(lowered final self::A #this) → () → void
   return () → void => self::E|bar(#this);
-static method test(self::A a, self::E e) → dynamic
+static method ET|baz(lowered final self::A #this) → void
+  ;
+static method ET|get#baz(lowered final self::A #this) → () → void
+  return () → void => self::ET|baz(#this);
+static method test(self::A a, self::E e, self::ET et) → dynamic
   ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart b/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart
index 7f1f10b..ace84f6 100644
--- a/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart
+++ b/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart
@@ -13,18 +13,31 @@
   dynamic operator+(dynamic other) => 42;
 }
 
-test(A a, E e) {
+extension type ET on A {
+  dynamic operator~/(dynamic other) => 42;
+}
+
+test(A a, E e, ET et) {
   a * "foobar"; // Ok.
   a[0]; // Ok.
   a[0] = "foobar"; // Ok.
   -a; // Ok.
   a + "foobar"; // Ok.
+  a ~/ "foobar"; // Error.
 
   e * "foobar"; // Error.
   e[0]; // Error.
   e[0] = "foobar"; // Error.
   -e; // Error.
   e + "foobar"; // Ok.
+  e ~/ "foobar"; // Error.
+
+  et * "foobar"; // Error.
+  et[0]; // Error.
+  et[0] = "foobar"; // Error.
+  -et; // Error.
+  et + "foobar"; // Error.
+  et ~/ "foobar"; // Ok.
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.strong.expect b/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.strong.expect
index 2ff87ce..743deb8 100644
--- a/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.strong.expect
+++ b/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.strong.expect
@@ -2,26 +2,62 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:23:5: Error: The operator '*' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:26:5: Error: The operator '~/' isn't defined for the class 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/extension_types/simple_operator_resolution.dart'.
+// Try correcting the operator to an existing operator, or defining a '~/' operator.
+//   a ~/ "foobar"; // Error.
+//     ^^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:28:5: Error: The operator '*' isn't defined for the extension 'E'.
 // Try correcting the operator to an existing operator, or defining a '*' operator.
 //   e * "foobar"; // Error.
 //     ^
 //
-// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:24:4: Error: The operator '[]' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:29:4: Error: The operator '[]' isn't defined for the extension 'E'.
 // Try correcting the operator to an existing operator, or defining a '[]' operator.
 //   e[0]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:25:4: Error: The operator '[]=' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:30:4: Error: The operator '[]=' isn't defined for the extension 'E'.
 // Try correcting the operator to an existing operator, or defining a '[]=' operator.
 //   e[0] = "foobar"; // Error.
 //    ^
 //
-// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:26:3: Error: The operator 'unary-' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:31:3: Error: The operator 'unary-' isn't defined for the extension 'E'.
 // Try correcting the operator to an existing operator, or defining a 'unary-' operator.
 //   -e; // Error.
 //   ^
 //
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:33:5: Error: The operator '~/' isn't defined for the extension 'E'.
+// Try correcting the operator to an existing operator, or defining a '~/' operator.
+//   e ~/ "foobar"; // Error.
+//     ^^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:35:6: Error: The operator '*' isn't defined for the extension 'ET'.
+// Try correcting the operator to an existing operator, or defining a '*' operator.
+//   et * "foobar"; // Error.
+//      ^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:36:5: Error: The operator '[]' isn't defined for the extension 'ET'.
+// Try correcting the operator to an existing operator, or defining a '[]' operator.
+//   et[0]; // Error.
+//     ^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:37:5: Error: The operator '[]=' isn't defined for the extension 'ET'.
+// Try correcting the operator to an existing operator, or defining a '[]=' operator.
+//   et[0] = "foobar"; // Error.
+//     ^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:38:3: Error: The operator 'unary-' isn't defined for the extension 'ET'.
+// Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+//   -et; // Error.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:39:6: Error: The operator '+' isn't defined for the extension 'ET'.
+// Try correcting the operator to an existing operator, or defining a '+' operator.
+//   et + "foobar"; // Error.
+//      ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -40,30 +76,65 @@
 extension E on self::A {
   operator + = self::E|+;
 }
+extension type ET on self::A {
+  operator ~/ = self::ET|~/;
+}
 static method E|+(lowered final self::A #this, dynamic other) → dynamic
   return 42;
-static method test(self::A a, self::E e) → dynamic {
+static method ET|~/(lowered final self::A #this, dynamic other) → dynamic
+  return 42;
+static method test(self::A a, self::E e, self::ET et) → dynamic {
   a.{self::A::*}("foobar"){(dynamic) → dynamic};
   a.{self::A::[]}(0){(core::int) → dynamic};
   a.{self::A::[]=}(0, "foobar"){(core::int, dynamic) → void};
   a.{self::A::unary-}(){() → dynamic};
   self::E|+(a, "foobar");
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:23:5: Error: The operator '*' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:26:5: Error: The operator '~/' isn't defined for the class 'A'.
+ - 'A' is from 'pkg/front_end/testcases/extension_types/simple_operator_resolution.dart'.
+Try correcting the operator to an existing operator, or defining a '~/' operator.
+  a ~/ \"foobar\"; // Error.
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:28:5: Error: The operator '*' isn't defined for the extension 'E'.
 Try correcting the operator to an existing operator, or defining a '*' operator.
   e * \"foobar\"; // Error.
     ^";
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:24:4: Error: The operator '[]' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:29:4: Error: The operator '[]' isn't defined for the extension 'E'.
 Try correcting the operator to an existing operator, or defining a '[]' operator.
   e[0]; // Error.
    ^";
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:25:4: Error: The operator '[]=' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:30:4: Error: The operator '[]=' isn't defined for the extension 'E'.
 Try correcting the operator to an existing operator, or defining a '[]=' operator.
   e[0] = \"foobar\"; // Error.
    ^";
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:26:3: Error: The operator 'unary-' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:31:3: Error: The operator 'unary-' isn't defined for the extension 'E'.
 Try correcting the operator to an existing operator, or defining a 'unary-' operator.
   -e; // Error.
   ^";
   self::E|+(e, "foobar");
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:33:5: Error: The operator '~/' isn't defined for the extension 'E'.
+Try correcting the operator to an existing operator, or defining a '~/' operator.
+  e ~/ \"foobar\"; // Error.
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:35:6: Error: The operator '*' isn't defined for the extension 'ET'.
+Try correcting the operator to an existing operator, or defining a '*' operator.
+  et * \"foobar\"; // Error.
+     ^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:36:5: Error: The operator '[]' isn't defined for the extension 'ET'.
+Try correcting the operator to an existing operator, or defining a '[]' operator.
+  et[0]; // Error.
+    ^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:37:5: Error: The operator '[]=' isn't defined for the extension 'ET'.
+Try correcting the operator to an existing operator, or defining a '[]=' operator.
+  et[0] = \"foobar\"; // Error.
+    ^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:38:3: Error: The operator 'unary-' isn't defined for the extension 'ET'.
+Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+  -et; // Error.
+  ^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:39:6: Error: The operator '+' isn't defined for the extension 'ET'.
+Try correcting the operator to an existing operator, or defining a '+' operator.
+  et + \"foobar\"; // Error.
+     ^";
+  self::ET|~/(et, "foobar");
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.textual_outline.expect
index b773643..d324d2b 100644
--- a/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.textual_outline.expect
@@ -1,13 +1,14 @@
 class A {
-  dynamic operator *(dynamic other) => 42;
-  dynamic operator [](int index) => 42;
-  void operator []=(int index, dynamic value) {}
-  dynamic operator -() => 42;
+  dynamic operator*(dynamic other) => 42;
+  dynamic operator[](int index) => 42;
+  void operator[]=(int index, dynamic value) {}
+  dynamic operator-() => 42;
 }
-
 extension E on A {
-  dynamic operator +(dynamic other) => 42;
+  dynamic operator+(dynamic other) => 42;
 }
-
-test(A a, E e) {}
+extension type ET on A {
+  dynamic operator~/(dynamic other) => 42;
+}
+test(A a, E e, ET et) {}
 main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.weak.expect b/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.weak.expect
index 2ff87ce..743deb8 100644
--- a/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.weak.expect
+++ b/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.weak.expect
@@ -2,26 +2,62 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:23:5: Error: The operator '*' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:26:5: Error: The operator '~/' isn't defined for the class 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/extension_types/simple_operator_resolution.dart'.
+// Try correcting the operator to an existing operator, or defining a '~/' operator.
+//   a ~/ "foobar"; // Error.
+//     ^^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:28:5: Error: The operator '*' isn't defined for the extension 'E'.
 // Try correcting the operator to an existing operator, or defining a '*' operator.
 //   e * "foobar"; // Error.
 //     ^
 //
-// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:24:4: Error: The operator '[]' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:29:4: Error: The operator '[]' isn't defined for the extension 'E'.
 // Try correcting the operator to an existing operator, or defining a '[]' operator.
 //   e[0]; // Error.
 //    ^
 //
-// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:25:4: Error: The operator '[]=' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:30:4: Error: The operator '[]=' isn't defined for the extension 'E'.
 // Try correcting the operator to an existing operator, or defining a '[]=' operator.
 //   e[0] = "foobar"; // Error.
 //    ^
 //
-// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:26:3: Error: The operator 'unary-' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:31:3: Error: The operator 'unary-' isn't defined for the extension 'E'.
 // Try correcting the operator to an existing operator, or defining a 'unary-' operator.
 //   -e; // Error.
 //   ^
 //
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:33:5: Error: The operator '~/' isn't defined for the extension 'E'.
+// Try correcting the operator to an existing operator, or defining a '~/' operator.
+//   e ~/ "foobar"; // Error.
+//     ^^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:35:6: Error: The operator '*' isn't defined for the extension 'ET'.
+// Try correcting the operator to an existing operator, or defining a '*' operator.
+//   et * "foobar"; // Error.
+//      ^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:36:5: Error: The operator '[]' isn't defined for the extension 'ET'.
+// Try correcting the operator to an existing operator, or defining a '[]' operator.
+//   et[0]; // Error.
+//     ^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:37:5: Error: The operator '[]=' isn't defined for the extension 'ET'.
+// Try correcting the operator to an existing operator, or defining a '[]=' operator.
+//   et[0] = "foobar"; // Error.
+//     ^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:38:3: Error: The operator 'unary-' isn't defined for the extension 'ET'.
+// Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+//   -et; // Error.
+//   ^
+//
+// pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:39:6: Error: The operator '+' isn't defined for the extension 'ET'.
+// Try correcting the operator to an existing operator, or defining a '+' operator.
+//   et + "foobar"; // Error.
+//      ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -40,30 +76,65 @@
 extension E on self::A {
   operator + = self::E|+;
 }
+extension type ET on self::A {
+  operator ~/ = self::ET|~/;
+}
 static method E|+(lowered final self::A #this, dynamic other) → dynamic
   return 42;
-static method test(self::A a, self::E e) → dynamic {
+static method ET|~/(lowered final self::A #this, dynamic other) → dynamic
+  return 42;
+static method test(self::A a, self::E e, self::ET et) → dynamic {
   a.{self::A::*}("foobar"){(dynamic) → dynamic};
   a.{self::A::[]}(0){(core::int) → dynamic};
   a.{self::A::[]=}(0, "foobar"){(core::int, dynamic) → void};
   a.{self::A::unary-}(){() → dynamic};
   self::E|+(a, "foobar");
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:23:5: Error: The operator '*' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:26:5: Error: The operator '~/' isn't defined for the class 'A'.
+ - 'A' is from 'pkg/front_end/testcases/extension_types/simple_operator_resolution.dart'.
+Try correcting the operator to an existing operator, or defining a '~/' operator.
+  a ~/ \"foobar\"; // Error.
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:28:5: Error: The operator '*' isn't defined for the extension 'E'.
 Try correcting the operator to an existing operator, or defining a '*' operator.
   e * \"foobar\"; // Error.
     ^";
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:24:4: Error: The operator '[]' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:29:4: Error: The operator '[]' isn't defined for the extension 'E'.
 Try correcting the operator to an existing operator, or defining a '[]' operator.
   e[0]; // Error.
    ^";
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:25:4: Error: The operator '[]=' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:30:4: Error: The operator '[]=' isn't defined for the extension 'E'.
 Try correcting the operator to an existing operator, or defining a '[]=' operator.
   e[0] = \"foobar\"; // Error.
    ^";
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:26:3: Error: The operator 'unary-' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:31:3: Error: The operator 'unary-' isn't defined for the extension 'E'.
 Try correcting the operator to an existing operator, or defining a 'unary-' operator.
   -e; // Error.
   ^";
   self::E|+(e, "foobar");
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:33:5: Error: The operator '~/' isn't defined for the extension 'E'.
+Try correcting the operator to an existing operator, or defining a '~/' operator.
+  e ~/ \"foobar\"; // Error.
+    ^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:35:6: Error: The operator '*' isn't defined for the extension 'ET'.
+Try correcting the operator to an existing operator, or defining a '*' operator.
+  et * \"foobar\"; // Error.
+     ^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:36:5: Error: The operator '[]' isn't defined for the extension 'ET'.
+Try correcting the operator to an existing operator, or defining a '[]' operator.
+  et[0]; // Error.
+    ^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:37:5: Error: The operator '[]=' isn't defined for the extension 'ET'.
+Try correcting the operator to an existing operator, or defining a '[]=' operator.
+  et[0] = \"foobar\"; // Error.
+    ^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:38:3: Error: The operator 'unary-' isn't defined for the extension 'ET'.
+Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+  -et; // Error.
+  ^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_operator_resolution.dart:39:6: Error: The operator '+' isn't defined for the extension 'ET'.
+Try correcting the operator to an existing operator, or defining a '+' operator.
+  et + \"foobar\"; // Error.
+     ^";
+  self::ET|~/(et, "foobar");
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.weak.outline.expect
index af29517..f6ffff4 100644
--- a/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/extension_types/simple_operator_resolution.dart.weak.outline.expect
@@ -17,9 +17,14 @@
 extension E on self::A {
   operator + = self::E|+;
 }
+extension type ET on self::A {
+  operator ~/ = self::ET|~/;
+}
 static method E|+(lowered final self::A #this, dynamic other) → dynamic
   ;
-static method test(self::A a, self::E e) → dynamic
+static method ET|~/(lowered final self::A #this, dynamic other) → dynamic
+  ;
+static method test(self::A a, self::E e, self::ET et) → dynamic
   ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart b/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart
index 20f43d6..0205c3e 100644
--- a/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart
+++ b/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart
@@ -10,11 +10,22 @@
   void set bar(int value) {}
 }
 
+extension type ET on A {
+  void set baz(int value) {}
+}
+
 test(A a, E e) {
   a.foo = 42; // Ok.
   a.bar = 42; // Ok.
+  a.baz = 42; // Error.
+
   e.foo = 42; // Error.
   e.bar = 42; // Ok.
+  e.baz = 42; // Error.
+
+  et.foo = 42; // Error.
+  et.bar = 42; // Error.
+  et.baz = 42; // Ok.
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.strong.expect b/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.strong.expect
index c7f4354..1ce4b82 100644
--- a/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.strong.expect
+++ b/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.strong.expect
@@ -2,11 +2,34 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:16:5: Error: The setter 'foo' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:26:3: Error: Getter not found: 'et'.
+//   et.foo = 42; // Error.
+//   ^^
+//
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:27:3: Error: Getter not found: 'et'.
+//   et.bar = 42; // Error.
+//   ^^
+//
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:28:3: Error: Getter not found: 'et'.
+//   et.baz = 42; // Ok.
+//   ^^
+//
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:20:5: Error: The setter 'baz' isn't defined for the class 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/extension_types/simple_setter_resolution.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
+//   a.baz = 42; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:22:5: Error: The setter 'foo' isn't defined for the extension 'E'.
 // Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
 //   e.foo = 42; // Error.
 //     ^^^
 //
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:24:5: Error: The setter 'baz' isn't defined for the extension 'E'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
+//   e.baz = 42; // Error.
+//     ^^^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -19,14 +42,36 @@
 extension E on self::A {
   set bar = self::E|set#bar;
 }
+extension type ET on self::A {
+  set baz = self::ET|set#baz;
+}
 static method E|set#bar(lowered final self::A #this, core::int value) → void {}
+static method ET|set#baz(lowered final self::A #this, core::int value) → void {}
 static method test(self::A a, self::E e) → dynamic {
   a.{self::A::foo} = 42;
   self::E|set#bar(a, 42);
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:16:5: Error: The setter 'foo' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:20:5: Error: The setter 'baz' isn't defined for the class 'A'.
+ - 'A' is from 'pkg/front_end/testcases/extension_types/simple_setter_resolution.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
+  a.baz = 42; // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:22:5: Error: The setter 'foo' isn't defined for the extension 'E'.
 Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
   e.foo = 42; // Error.
     ^^^";
   self::E|set#bar(e, 42);
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:24:5: Error: The setter 'baz' isn't defined for the extension 'E'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
+  e.baz = 42; // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:26:3: Error: Getter not found: 'et'.
+  et.foo = 42; // Error.
+  ^^"{dynamic}.foo = 42;
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:27:3: Error: Getter not found: 'et'.
+  et.bar = 42; // Error.
+  ^^"{dynamic}.bar = 42;
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:28:3: Error: Getter not found: 'et'.
+  et.baz = 42; // Ok.
+  ^^"{dynamic}.baz = 42;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.textual_outline.expect
index d7b5425..60eca21 100644
--- a/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.textual_outline.expect
@@ -1,10 +1,11 @@
 class A {
   void set foo(int value) {}
 }
-
 extension E on A {
   void set bar(int value) {}
 }
-
+extension type ET on A {
+  void set baz(int value) {}
+}
 test(A a, E e) {}
 main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.weak.expect b/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.weak.expect
index c7f4354..1ce4b82 100644
--- a/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.weak.expect
+++ b/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.weak.expect
@@ -2,11 +2,34 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:16:5: Error: The setter 'foo' isn't defined for the extension 'E'.
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:26:3: Error: Getter not found: 'et'.
+//   et.foo = 42; // Error.
+//   ^^
+//
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:27:3: Error: Getter not found: 'et'.
+//   et.bar = 42; // Error.
+//   ^^
+//
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:28:3: Error: Getter not found: 'et'.
+//   et.baz = 42; // Ok.
+//   ^^
+//
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:20:5: Error: The setter 'baz' isn't defined for the class 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/extension_types/simple_setter_resolution.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
+//   a.baz = 42; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:22:5: Error: The setter 'foo' isn't defined for the extension 'E'.
 // Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
 //   e.foo = 42; // Error.
 //     ^^^
 //
+// pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:24:5: Error: The setter 'baz' isn't defined for the extension 'E'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
+//   e.baz = 42; // Error.
+//     ^^^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -19,14 +42,36 @@
 extension E on self::A {
   set bar = self::E|set#bar;
 }
+extension type ET on self::A {
+  set baz = self::ET|set#baz;
+}
 static method E|set#bar(lowered final self::A #this, core::int value) → void {}
+static method ET|set#baz(lowered final self::A #this, core::int value) → void {}
 static method test(self::A a, self::E e) → dynamic {
   a.{self::A::foo} = 42;
   self::E|set#bar(a, 42);
-  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:16:5: Error: The setter 'foo' isn't defined for the extension 'E'.
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:20:5: Error: The setter 'baz' isn't defined for the class 'A'.
+ - 'A' is from 'pkg/front_end/testcases/extension_types/simple_setter_resolution.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
+  a.baz = 42; // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:22:5: Error: The setter 'foo' isn't defined for the extension 'E'.
 Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
   e.foo = 42; // Error.
     ^^^";
   self::E|set#bar(e, 42);
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:24:5: Error: The setter 'baz' isn't defined for the extension 'E'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'baz'.
+  e.baz = 42; // Error.
+    ^^^";
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:26:3: Error: Getter not found: 'et'.
+  et.foo = 42; // Error.
+  ^^"{dynamic}.foo = 42;
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:27:3: Error: Getter not found: 'et'.
+  et.bar = 42; // Error.
+  ^^"{dynamic}.bar = 42;
+  invalid-expression "pkg/front_end/testcases/extension_types/simple_setter_resolution.dart:28:3: Error: Getter not found: 'et'.
+  et.baz = 42; // Ok.
+  ^^"{dynamic}.baz = 42;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.weak.outline.expect
index 05a6bb6..191e17f 100644
--- a/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/extension_types/simple_setter_resolution.dart.weak.outline.expect
@@ -11,8 +11,13 @@
 extension E on self::A {
   set bar = self::E|set#bar;
 }
+extension type ET on self::A {
+  set baz = self::ET|set#baz;
+}
 static method E|set#bar(lowered final self::A #this, core::int value) → void
   ;
+static method ET|set#baz(lowered final self::A #this, core::int value) → void
+  ;
 static method test(self::A a, self::E e) → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 7c64966..fd8e874 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -33,6 +33,10 @@
 constructor_tearoffs/unnamed_constructor: FormatterCrash
 dart2js/late_fields: FormatterCrash
 dart2js/late_statics: FormatterCrash
+extension_types/simple_getter_resolution: FormatterCrash
+extension_types/simple_method_resolution: FormatterCrash
+extension_types/simple_operator_resolution: FormatterCrash
+extension_types/simple_setter_resolution: FormatterCrash
 extensions/extension_constructor: FormatterCrash
 extensions/extension_field_with_type_parameter_usage: FormatterCrash
 extensions/issue38600: FormatterCrash
diff --git a/runtime/vm/heap/freelist_test.cc b/runtime/vm/heap/freelist_test.cc
index fe6c1a4..4e7b7f4 100644
--- a/runtime/vm/heap/freelist_test.cc
+++ b/runtime/vm/heap/freelist_test.cc
@@ -146,7 +146,8 @@
 
 TEST_CASE(FreeListProtectedVariableSizeObjects) {
   FreeList* free_list = new FreeList();
-  const intptr_t kBlobSize = 8 * KB;
+  const intptr_t kBlobSize = 16 * KB;
+  ASSERT(kBlobSize >= VirtualMemory::PageSize());
   const intptr_t kMinSize = 2 * kWordSize;
   uword* objects = new uword[kBlobSize / kMinSize];
   for (intptr_t i = 0; i < kBlobSize / kMinSize; ++i) {
@@ -155,28 +156,27 @@
 
   VirtualMemory* blob =
       VirtualMemory::Allocate(kBlobSize, /* is_executable = */ false, "test");
-  ASSERT(Utils::IsAligned(blob->start(), 4096));
   blob->Protect(VirtualMemory::kReadWrite);
 
   // Enqueue the large blob as one free block.
   free_list->Free(blob->start(), blob->size());
 
   // Write protect the whole region.
-  blob->Protect(VirtualMemory::kReadExecute);
+  blob->Protect(VirtualMemory::kReadOnly);
 
   // Allocate and free objects so that free list has > 1 elements.
-  uword e0 = Allocate(free_list, 1 * KB, true);
+  uword e0 = Allocate(free_list, 2 * KB, true);
   ASSERT(e0);
-  uword e1 = Allocate(free_list, 3 * KB, true);
+  uword e1 = Allocate(free_list, 6 * KB, true);
   ASSERT(e1);
-  uword e2 = Allocate(free_list, 2 * KB, true);
+  uword e2 = Allocate(free_list, 4 * KB, true);
   ASSERT(e2);
-  uword e3 = Allocate(free_list, 2 * KB, true);
+  uword e3 = Allocate(free_list, 4 * KB, true);
   ASSERT(e3);
 
-  Free(free_list, e1, 3 * KB, true);
-  Free(free_list, e2, 2 * KB, true);
-  e0 = Allocate(free_list, 3 * KB - 2 * kWordSize, true);
+  Free(free_list, e1, 6 * KB, true);
+  Free(free_list, e2, 4 * KB, true);
+  e0 = Allocate(free_list, 6 * KB - 2 * kWordSize, true);
   ASSERT(e0);
 
   // Delete the memory associated with the test.
diff --git a/sdk/lib/_internal/js_runtime/lib/constant_map.dart b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
index 0f673d8..d5a5174 100644
--- a/sdk/lib/_internal/js_runtime/lib/constant_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
@@ -74,7 +74,10 @@
   void addAll(Map<K, V> other) => _throwUnmodifiable();
 
   Iterable<MapEntry<K, V>> get entries sync* {
-    for (var key in keys) yield new MapEntry<K, V>(key, this[key]!);
+    // `this[key]` has static type `V?` but is always `V`. Rather than `as V`,
+    // we use `as dynamic` so the upcast requires no checking and the implicit
+    // downcast to `V` will be discarded in production.
+    for (var key in keys) yield new MapEntry<K, V>(key, this[key] as dynamic);
   }
 
   void addEntries(Iterable<MapEntry<K, V>> entries) {
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 4ef1735..f06c29a 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -2342,6 +2342,12 @@
   return Closure.fromTearOff(parameters);
 }
 
+/// Base class for closures with no arguments.
+abstract class Closure0Args extends Closure {}
+
+/// Base class for closures with two positional arguments.
+abstract class Closure2Args extends Closure {}
+
 /// Represents an implicit closure of a function.
 abstract class TearOffClosure extends Closure {}
 
diff --git a/sdk/lib/internal/symbol.dart b/sdk/lib/internal/symbol.dart
index c65e5e8..718ac68 100644
--- a/sdk/lib/internal/symbol.dart
+++ b/sdk/lib/internal/symbol.dart
@@ -106,9 +106,6 @@
    */
   const Symbol.unvalidated(this._name);
 
-  // This is called by dart2js.
-  Symbol.validated(String name) : this._name = validatePublicSymbol(name);
-
   bool operator ==(Object other) => other is Symbol && _name == other._name;
 
   external int get hashCode;
diff --git a/tests/web/internal/lax_runtime_type_closure_to_string1_test.dart b/tests/web/internal/lax_runtime_type_closure_to_string1_test.dart
index aed91ee..220d3c6 100644
--- a/tests/web/internal/lax_runtime_type_closure_to_string1_test.dart
+++ b/tests/web/internal/lax_runtime_type_closure_to_string1_test.dart
@@ -18,7 +18,7 @@
   var toString = '${local1.runtimeType}';
   if ('$Object' == 'Object') {
     // `true` if non-minified.
-    Expect.equals("Closure", toString);
+    Expect.equals("Closure0Args", toString);
   }
   print(toString);
   local2(0);
diff --git a/tests/web/regress/46417_test.dart b/tests/web/regress/46417_test.dart
new file mode 100644
index 0000000..3ba7d9b
--- /dev/null
+++ b/tests/web/regress/46417_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+void main() {
+  var v = {
+    ...Map.unmodifiable({'x': null})
+  };
+  Expect.equals(null, v['x']);
+}
diff --git a/tests/web_2/internal/lax_runtime_type_closure_to_string1_test.dart b/tests/web_2/internal/lax_runtime_type_closure_to_string1_test.dart
index 51d90d5..210d320 100644
--- a/tests/web_2/internal/lax_runtime_type_closure_to_string1_test.dart
+++ b/tests/web_2/internal/lax_runtime_type_closure_to_string1_test.dart
@@ -20,7 +20,7 @@
   var toString = '${local1.runtimeType}';
   if ('$Object' == 'Object') {
     // `true` if non-minified.
-    Expect.equals("Closure", toString);
+    Expect.equals("Closure0Args", toString);
   }
   print(toString);
   local2(0);
diff --git a/tests/web_2/regress/46417_test.dart b/tests/web_2/regress/46417_test.dart
new file mode 100644
index 0000000..3ba7d9b
--- /dev/null
+++ b/tests/web_2/regress/46417_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+void main() {
+  var v = {
+    ...Map.unmodifiable({'x': null})
+  };
+  Expect.equals(null, v['x']);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 08c8f41..d064fce 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 240
+PRERELEASE 241
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/README.md b/tools/bots/README.md
index 52dd12f..47acbc4 100644
--- a/tools/bots/README.md
+++ b/tools/bots/README.md
@@ -12,7 +12,7 @@
 
 The test matrix is a JSON document and consists of the `"filesets"` object, the
 `"configurations"` list, and the `"builder_configurations"` list as well as a
-`"global"` values object and a `"branches"` list.
+`"branches"` list.
 
 ### Filesets
 
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 29fe236..e9520a3 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -1,8 +1,4 @@
 {
-  "global": {
-    "chrome": "81",
-    "firefox": "67"
-  },
   "branches": [
     "master"
   ],