Version 2.14.0-334.0.dev

Merge commit '8ea5fc2773a289dc32199f9ab6a4b535103fa5f3' into 'dev'
diff --git a/DEPS b/DEPS
index bbcf4ae..a11c660 100644
--- a/DEPS
+++ b/DEPS
@@ -141,7 +141,7 @@
   "pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
   "process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
   "protobuf_rev": "0d03fd588df69e9863e2a2efc0059dee8f18d5b2",
-  "pub_rev": "d159e5b9f04a7e4826b6afea7b3364d48aa0dad8",
+  "pub_rev": "70b1a4f9229a36bac6340ec7eae2b2068baac96c",
   "pub_semver_rev": "f50d80ef10c4b2fa5f4c8878036a4d9342c0cc82",
   "resource_rev": "6b79867d0becf5395e5819a75720963b8298e9a7",
   "root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 7701321..5c4515c 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -42,8 +42,6 @@
 
 import '../fasta_codes.dart';
 
-import '../kernel/redirecting_factory_body.dart' show getRedirectingFactoryBody;
-
 import '../loader.dart';
 
 import '../modifier.dart';
@@ -74,7 +72,7 @@
 import 'named_type_builder.dart';
 import 'never_type_declaration_builder.dart';
 import 'nullability_builder.dart';
-import 'procedure_builder.dart';
+import 'factory_builder.dart';
 import 'type_alias_builder.dart';
 import 'type_builder.dart';
 import 'type_declaration_builder.dart';
@@ -914,8 +912,7 @@
           charOffset, fileUri);
     }
 
-    List<DartType>? typeArguments =
-        getRedirectingFactoryBody(factory.procedure)!.typeArguments;
+    List<DartType>? typeArguments = factory.getTypeArguments();
     FunctionType targetFunctionType =
         targetNode.computeFunctionType(library.nonNullable);
     if (typeArguments != null &&
@@ -1007,7 +1004,7 @@
     // The factory type cannot contain any type parameters other than those of
     // its enclosing class, because constructors cannot specify type parameters
     // of their own.
-    FunctionType factoryType = factory.procedure.function
+    FunctionType factoryType = factory.function
         .computeThisFunctionType(library.nonNullable)
         .withoutTypeParameters;
     FunctionType? redirecteeType =
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index f2810a8..505f29b 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -51,7 +51,6 @@
 abstract class ConstructorBuilder implements FunctionBuilder {
   abstract Token? beginInitializers;
 
-  @override
   ConstructorBuilder? get actualOrigin;
 
   ConstructorBuilder? get patchForTesting;
@@ -139,7 +138,7 @@
           ..fileEndOffset = charEndOffset
           ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault,
         _constructorTearOff = createConstructorTearOffProcedure(
-            name, compilationUnit, charOffset,
+            name, compilationUnit, compilationUnit.fileUri, charOffset,
             forAbstractClassOrEnum: forAbstractClassOrEnum),
         super(metadata, modifiers, returnType, name, typeVariables, formals,
             compilationUnit, charOffset, nativeMethodName);
diff --git a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
new file mode 100644
index 0000000..ddf666e
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
@@ -0,0 +1,403 @@
+// Copyright (c) 2019, 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:kernel/ast.dart';
+
+import '../dill/dill_member_builder.dart';
+
+import '../kernel/class_hierarchy_builder.dart';
+import '../kernel/forest.dart';
+import '../kernel/internal_ast.dart';
+import '../kernel/kernel_api.dart';
+import '../kernel/redirecting_factory_body.dart'
+    show getRedirectingFactoryBody, RedirectingFactoryBody;
+
+import '../loader.dart' show Loader;
+
+import '../messages.dart'
+    show messageConstFactoryRedirectionToNonConst, noLength;
+
+import '../problems.dart' show unexpected, unhandled;
+
+import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+
+import '../type_inference/type_inferrer.dart';
+import '../type_inference/type_schema.dart';
+
+import '../util/helpers.dart';
+
+import 'builder.dart';
+import 'constructor_reference_builder.dart';
+import 'formal_parameter_builder.dart';
+import 'function_builder.dart';
+import 'member_builder.dart';
+import 'metadata_builder.dart';
+import 'library_builder.dart';
+import 'procedure_builder.dart';
+import 'type_builder.dart';
+import 'type_variable_builder.dart';
+
+class SourceFactoryBuilder extends FunctionBuilderImpl {
+  final int charOpenParenOffset;
+
+  AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
+
+  final bool isExtensionInstanceMember = false;
+
+  late Procedure _procedureInternal;
+
+  SourceFactoryBuilder? actualOrigin;
+
+  SourceFactoryBuilder(
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      TypeBuilder returnType,
+      String name,
+      List<TypeVariableBuilder> typeVariables,
+      List<FormalParameterBuilder>? formals,
+      SourceLibraryBuilder libraryBuilder,
+      int startCharOffset,
+      int charOffset,
+      this.charOpenParenOffset,
+      int charEndOffset,
+      Reference? procedureReference,
+      AsyncMarker asyncModifier,
+      ProcedureNameScheme procedureNameScheme,
+      {String? nativeMethodName})
+      : super(metadata, modifiers, returnType, name, typeVariables, formals,
+            libraryBuilder, charOffset, nativeMethodName) {
+    _procedureInternal = new Procedure(
+        procedureNameScheme.getName(kind, name),
+        isExtensionInstanceMember ? ProcedureKind.Method : kind,
+        new FunctionNode(null),
+        fileUri: libraryBuilder.fileUri,
+        reference: procedureReference)
+      ..startFileOffset = startCharOffset
+      ..fileOffset = charOffset
+      ..fileEndOffset = charEndOffset
+      ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
+
+    this.asyncModifier = asyncModifier;
+  }
+
+  SourceFactoryBuilder? get patchForTesting =>
+      dataForTesting?.patchForTesting as SourceFactoryBuilder?;
+
+  @override
+  AsyncMarker get asyncModifier => actualAsyncModifier;
+
+  @override
+  Statement? get body {
+    if (bodyInternal == null && !isAbstract && !isExternal) {
+      bodyInternal = new EmptyStatement();
+    }
+    return bodyInternal;
+  }
+
+  void set asyncModifier(AsyncMarker newModifier) {
+    actualAsyncModifier = newModifier;
+    function.asyncMarker = actualAsyncModifier;
+    function.dartAsyncMarker = actualAsyncModifier;
+  }
+
+  @override
+  Member get member => _procedure;
+
+  @override
+  SourceFactoryBuilder get origin => actualOrigin ?? this;
+
+  @override
+  ProcedureKind get kind => ProcedureKind.Factory;
+
+  Procedure get _procedure => isPatch ? origin._procedure : _procedureInternal;
+
+  @override
+  FunctionNode get function => _procedureInternal.function;
+
+  @override
+  Member? get readTarget => _procedure;
+
+  @override
+  Member? get writeTarget => null;
+
+  @override
+  Member? get invokeTarget => _procedure;
+
+  @override
+  Iterable<Member> get exportedMembers => [_procedure];
+
+  @override
+  void buildMembers(
+      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    Member member = build(library);
+    f(member, BuiltMemberKind.Method);
+  }
+
+  @override
+  Procedure build(SourceLibraryBuilder libraryBuilder) {
+    buildFunction(libraryBuilder);
+    _procedureInternal.function.fileOffset = charOpenParenOffset;
+    _procedureInternal.function.fileEndOffset =
+        _procedureInternal.fileEndOffset;
+    _procedureInternal.isAbstract = isAbstract;
+    _procedureInternal.isExternal = isExternal;
+    _procedureInternal.isConst = isConst;
+    updatePrivateMemberName(_procedureInternal, libraryBuilder);
+    _procedureInternal.isStatic = isStatic;
+    return _procedureInternal;
+  }
+
+  @override
+  List<ClassMember> get localMembers =>
+      throw new UnsupportedError('${runtimeType}.localMembers');
+
+  @override
+  List<ClassMember> get localSetters =>
+      throw new UnsupportedError('${runtimeType}.localSetters');
+
+  @override
+  void becomeNative(Loader loader) {
+    _procedureInternal.isExternal = true;
+    super.becomeNative(loader);
+  }
+
+  void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
+    if (bodyInternal != null) {
+      unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
+    }
+    bodyInternal = new RedirectingFactoryBody(target, typeArguments);
+    function.body = bodyInternal;
+    bodyInternal?.parent = function;
+    if (isPatch) {
+      actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
+    }
+  }
+
+  @override
+  void applyPatch(Builder patch) {
+    if (patch is SourceFactoryBuilder) {
+      if (checkPatch(patch)) {
+        patch.actualOrigin = this;
+        dataForTesting?.patchForTesting = patch;
+      }
+    } else {
+      reportPatchMismatch(patch);
+    }
+  }
+
+  @override
+  int finishPatch() {
+    if (!isPatch) return 0;
+
+    // TODO(ahe): restore file-offset once we track both origin and patch file
+    // URIs. See https://github.com/dart-lang/sdk/issues/31579
+    origin._procedure.fileUri = fileUri;
+    origin._procedure.startFileOffset = _procedureInternal.startFileOffset;
+    origin._procedure.fileOffset = _procedureInternal.fileOffset;
+    origin._procedure.fileEndOffset = _procedureInternal.fileEndOffset;
+    origin._procedure.annotations
+        .forEach((m) => m.fileOffset = _procedureInternal.fileOffset);
+
+    origin._procedure.isAbstract = _procedureInternal.isAbstract;
+    origin._procedure.isExternal = _procedureInternal.isExternal;
+    origin._procedure.function = _procedureInternal.function;
+    origin._procedure.function.parent = origin._procedure;
+    origin._procedure.isRedirectingFactoryConstructor =
+        _procedureInternal.isRedirectingFactoryConstructor;
+    return 1;
+  }
+}
+
+class RedirectingFactoryBuilder extends SourceFactoryBuilder {
+  final ConstructorReferenceBuilder redirectionTarget;
+  List<DartType>? typeArguments;
+
+  RedirectingFactoryBuilder(
+      List<MetadataBuilder>? metadata,
+      int modifiers,
+      TypeBuilder returnType,
+      String name,
+      List<TypeVariableBuilder> typeVariables,
+      List<FormalParameterBuilder>? formals,
+      SourceLibraryBuilder libraryBuilder,
+      int startCharOffset,
+      int charOffset,
+      int charOpenParenOffset,
+      int charEndOffset,
+      Reference? procedureReference,
+      ProcedureNameScheme procedureNameScheme,
+      String? nativeMethodName,
+      this.redirectionTarget)
+      : super(
+            metadata,
+            modifiers,
+            returnType,
+            name,
+            typeVariables,
+            formals,
+            libraryBuilder,
+            startCharOffset,
+            charOffset,
+            charOpenParenOffset,
+            charEndOffset,
+            procedureReference,
+            AsyncMarker.Sync,
+            procedureNameScheme,
+            nativeMethodName: nativeMethodName);
+
+  @override
+  Statement? get body => bodyInternal;
+
+  @override
+  void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
+    if (bodyInternal != null) {
+      unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
+    }
+
+    // Ensure that constant factories only have constant targets/bodies.
+    if (isConst && !target.isConst) {
+      library.addProblem(messageConstFactoryRedirectionToNonConst, charOffset,
+          noLength, fileUri);
+    }
+
+    bodyInternal = new RedirectingFactoryBody(target, typeArguments);
+    function.body = bodyInternal;
+    bodyInternal?.parent = function;
+    _procedure.isRedirectingFactoryConstructor = true;
+    if (isPatch) {
+      // ignore: unnecessary_null_comparison
+      if (function.typeParameters != null) {
+        Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
+        for (int i = 0; i < function.typeParameters.length; i++) {
+          substitution[function.typeParameters[i]] =
+              new TypeParameterType.withDefaultNullabilityForLibrary(
+                  actualOrigin!.function.typeParameters[i], library.library);
+        }
+        typeArguments = new List<DartType>.generate(typeArguments.length,
+            (int i) => substitute(typeArguments[i], substitution),
+            growable: false);
+      }
+      actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
+    }
+  }
+
+  @override
+  void buildMembers(
+      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+    Member member = build(library);
+    f(member, BuiltMemberKind.RedirectingFactory);
+  }
+
+  @override
+  Procedure build(SourceLibraryBuilder libraryBuilder) {
+    buildFunction(libraryBuilder);
+    _procedureInternal.function.fileOffset = charOpenParenOffset;
+    _procedureInternal.function.fileEndOffset =
+        _procedureInternal.fileEndOffset;
+    _procedureInternal.isAbstract = isAbstract;
+    _procedureInternal.isExternal = isExternal;
+    _procedureInternal.isConst = isConst;
+    _procedureInternal.isStatic = isStatic;
+    _procedureInternal.isRedirectingFactoryConstructor = true;
+    if (redirectionTarget.typeArguments != null) {
+      typeArguments = new List<DartType>.generate(
+          redirectionTarget.typeArguments!.length,
+          (int i) => redirectionTarget.typeArguments![i].build(library),
+          growable: false);
+    }
+    updatePrivateMemberName(_procedureInternal, libraryBuilder);
+    return _procedureInternal;
+  }
+
+  @override
+  void buildOutlineExpressions(
+      SourceLibraryBuilder library,
+      CoreTypes coreTypes,
+      List<DelayedActionPerformer> delayedActionPerformers) {
+    super.buildOutlineExpressions(library, coreTypes, delayedActionPerformers);
+    LibraryBuilder thisLibrary = this.library;
+    if (thisLibrary is SourceLibraryBuilder) {
+      RedirectingFactoryBody redirectingFactoryBody =
+          _procedure.function.body as RedirectingFactoryBody;
+      if (redirectingFactoryBody.typeArguments != null &&
+          redirectingFactoryBody.typeArguments!.any((t) => t is UnknownType)) {
+        TypeInferrerImpl inferrer = thisLibrary.loader.typeInferenceEngine
+                .createLocalTypeInferrer(
+                    fileUri, classBuilder!.thisType, thisLibrary, null)
+            as TypeInferrerImpl;
+        inferrer.helper = thisLibrary.loader
+            .createBodyBuilderForOutlineExpression(
+                thisLibrary, classBuilder, this, classBuilder!.scope, fileUri);
+        Builder? targetBuilder = redirectionTarget.target;
+        Member target;
+        if (targetBuilder is FunctionBuilder) {
+          target = targetBuilder.member;
+        } else if (targetBuilder is DillMemberBuilder) {
+          target = targetBuilder.member;
+        } else {
+          unhandled("${targetBuilder.runtimeType}", "buildOutlineExpressions",
+              charOffset, fileUri);
+        }
+        Arguments targetInvocationArguments;
+        {
+          List<Expression> positionalArguments = <Expression>[];
+          for (VariableDeclaration parameter
+              in _procedure.function.positionalParameters) {
+            inferrer.flowAnalysis.declare(parameter, true);
+            positionalArguments.add(
+                new VariableGetImpl(parameter, forNullGuardedAccess: false));
+          }
+          List<NamedExpression> namedArguments = <NamedExpression>[];
+          for (VariableDeclaration parameter
+              in _procedure.function.namedParameters) {
+            inferrer.flowAnalysis.declare(parameter, true);
+            namedArguments.add(new NamedExpression(parameter.name!,
+                new VariableGetImpl(parameter, forNullGuardedAccess: false)));
+          }
+          // If arguments are created using [Forest.createArguments], and the
+          // type arguments are omitted, they are to be inferred.
+          targetInvocationArguments = const Forest().createArguments(
+              _procedure.fileOffset, positionalArguments,
+              named: namedArguments);
+        }
+        InvocationInferenceResult result = inferrer.inferInvocation(
+            function.returnType,
+            charOffset,
+            target.function!.computeFunctionType(Nullability.nonNullable),
+            targetInvocationArguments,
+            staticTarget: target);
+        List<DartType> typeArguments;
+        if (result.inferredType is InterfaceType) {
+          typeArguments = (result.inferredType as InterfaceType).typeArguments;
+        } else {
+          // Assume that the error is reported elsewhere, use 'dynamic' for
+          // recovery.
+          typeArguments = new List<DartType>.filled(
+              target.enclosingClass!.typeParameters.length, const DynamicType(),
+              growable: true);
+        }
+        member.function!.body =
+            new RedirectingFactoryBody(target, typeArguments);
+      }
+    }
+  }
+
+  @override
+  int finishPatch() {
+    if (!isPatch) return 0;
+
+    super.finishPatch();
+
+    SourceFactoryBuilder redirectingOrigin = origin;
+    if (redirectingOrigin is RedirectingFactoryBuilder) {
+      redirectingOrigin.typeArguments = typeArguments;
+    }
+
+    return 1;
+  }
+
+  List<DartType>? getTypeArguments() {
+    return getRedirectingFactoryBody(_procedure)!.typeArguments;
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
index c1c89d3..b1bd488 100644
--- a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
@@ -14,7 +14,6 @@
     show FormalParameterKind;
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-import 'package:front_end/src/fasta/builder/procedure_builder.dart';
 
 import 'package:kernel/ast.dart'
     show DartType, DynamicType, Expression, VariableDeclaration;
@@ -40,6 +39,7 @@
 import 'builder.dart';
 import 'class_builder.dart';
 import 'constructor_builder.dart';
+import 'factory_builder.dart';
 import 'field_builder.dart';
 import 'library_builder.dart';
 import 'metadata_builder.dart';
@@ -202,7 +202,7 @@
       bool isConstConstructorParameter = false;
       if (parent is ConstructorBuilder) {
         isConstConstructorParameter = parent!.isConst;
-      } else if (parent is ProcedureBuilder) {
+      } else if (parent is SourceFactoryBuilder) {
         isConstConstructorParameter = parent!.isFactory && parent!.isConst;
       }
       if (isConstConstructorParameter || parent!.isClassInstanceMember) {
diff --git a/pkg/front_end/lib/src/fasta/builder/function_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
index dd4d74a..d74aa66 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -13,7 +13,6 @@
 import '../scope.dart';
 
 import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
-import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
 
 import '../loader.dart' show Loader;
 
@@ -28,8 +27,6 @@
 
 import '../modifier.dart';
 
-import '../problems.dart' show unexpected;
-
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
 import '../type_inference/type_inference_engine.dart'
@@ -93,14 +90,10 @@
 
   FunctionNode get function;
 
-  FunctionBuilder? get actualOrigin;
-
   Statement? get body;
 
   void set body(Statement? newBody);
 
-  void setRedirectingFactoryBody(Member target, List<DartType> typeArguments);
-
   bool get isNative;
 
   /// Returns the [index]th parameter of this function.
@@ -317,19 +310,6 @@
   }
 
   @override
-  void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
-    if (bodyInternal != null) {
-      unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
-    }
-    bodyInternal = new RedirectingFactoryBody(target, typeArguments);
-    function.body = bodyInternal;
-    bodyInternal?.parent = function;
-    if (isPatch) {
-      actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
-    }
-  }
-
-  @override
   Statement? get body => bodyInternal ??= new EmptyStatement();
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index 368e69c..1fa324b 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -4,37 +4,20 @@
 
 import 'package:kernel/ast.dart';
 
-import '../dill/dill_member_builder.dart';
-
 import '../kernel/class_hierarchy_builder.dart';
-import '../kernel/forest.dart';
-import '../kernel/internal_ast.dart';
 import '../kernel/kernel_api.dart';
 import '../kernel/member_covariance.dart';
-import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
 
 import '../loader.dart' show Loader;
 
-import '../messages.dart'
-    show messageConstFactoryRedirectionToNonConst, noLength;
-
-import '../problems.dart' show unexpected, unhandled;
-
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
-import '../type_inference/type_inferrer.dart';
-import '../type_inference/type_schema.dart';
-
-import '../util/helpers.dart';
-
 import 'builder.dart';
-import 'constructor_reference_builder.dart';
 import 'extension_builder.dart';
 import 'formal_parameter_builder.dart';
 import 'function_builder.dart';
 import 'member_builder.dart';
 import 'metadata_builder.dart';
-import 'library_builder.dart';
 import 'type_builder.dart';
 import 'type_variable_builder.dart';
 
@@ -62,28 +45,38 @@
   bool get isExtensionMethod;
 }
 
-abstract class ProcedureBuilderImpl extends FunctionBuilderImpl
+class SourceProcedureBuilder extends FunctionBuilderImpl
     implements ProcedureBuilder {
-  late Procedure _procedure;
-
   @override
   final int charOpenParenOffset;
 
   @override
-  final ProcedureKind kind;
-
-  @override
   AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
 
-  @override
-  ProcedureBuilder? actualOrigin;
-
-  @override
-  Procedure get actualProcedure => _procedure;
-
   final bool isExtensionInstanceMember;
 
-  ProcedureBuilderImpl(
+  late Procedure _procedure;
+
+  final Reference? _tearOffReference;
+
+  /// If this is an extension instance method then [_extensionTearOff] holds
+  /// the synthetically created tear off function.
+  Procedure? _extensionTearOff;
+
+  /// If this is an extension instance method then
+  /// [_extensionTearOffParameterMap] holds a map from the parameters of
+  /// the methods to the parameter of the closure returned in the tear-off.
+  ///
+  /// This map is used to set the default values on the closure parameters when
+  /// these have been built.
+  Map<VariableDeclaration, VariableDeclaration>? _extensionTearOffParameterMap;
+
+  @override
+  final ProcedureKind kind;
+
+  SourceProcedureBuilder? actualOrigin;
+
+  SourceProcedureBuilder(
       List<MetadataBuilder>? metadata,
       int modifiers,
       TypeBuilder? returnType,
@@ -97,6 +90,8 @@
       this.charOpenParenOffset,
       int charEndOffset,
       Reference? procedureReference,
+      this._tearOffReference,
+      AsyncMarker asyncModifier,
       ProcedureNameScheme procedureNameScheme,
       {required bool isExtensionMember,
       required bool isInstanceMember,
@@ -105,6 +100,7 @@
       : assert(isExtensionMember != null),
         // ignore: unnecessary_null_comparison
         assert(isInstanceMember != null),
+        assert(kind != ProcedureKind.Factory),
         this.isExtensionInstanceMember = isInstanceMember && isExtensionMember,
         super(metadata, modifiers, returnType, name, typeVariables, formals,
             libraryBuilder, charOffset, nativeMethodName) {
@@ -118,13 +114,20 @@
       ..fileOffset = charOffset
       ..fileEndOffset = charEndOffset
       ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
+    this.asyncModifier = asyncModifier;
+    if (isExtensionMember && isInstanceMember && kind == ProcedureKind.Method) {
+      _extensionTearOff ??= new Procedure(
+          procedureNameScheme.getName(ProcedureKind.Getter, name),
+          ProcedureKind.Method,
+          new FunctionNode(null),
+          isStatic: true,
+          isExtensionMember: true,
+          reference: _tearOffReference,
+          fileUri: fileUri)
+        ..isNonNullableByDefault = library.isNonNullableByDefault;
+    }
   }
 
-  FunctionNode get function => _procedure.function;
-
-  @override
-  ProcedureBuilder get origin => actualOrigin ?? this;
-
   @override
   ProcedureBuilder? get patchForTesting =>
       dataForTesting?.patchForTesting as ProcedureBuilder?;
@@ -166,118 +169,19 @@
   }
 
   @override
-  Procedure get procedure => isPatch ? origin.procedure : _procedure;
-
-  @override
   Member get member => procedure;
 
   @override
-  void becomeNative(Loader loader) {
-    _procedure.isExternal = true;
-    super.becomeNative(loader);
-  }
+  SourceProcedureBuilder get origin => actualOrigin ?? this;
 
   @override
-  void applyPatch(Builder patch) {
-    if (patch is ProcedureBuilderImpl) {
-      if (checkPatch(patch)) {
-        patch.actualOrigin = this;
-        dataForTesting?.patchForTesting = patch;
-      }
-    } else {
-      reportPatchMismatch(patch);
-    }
-  }
+  Procedure get procedure => isPatch ? origin.procedure : _procedure;
 
   @override
-  int finishPatch() {
-    if (!isPatch) return 0;
+  Procedure get actualProcedure => _procedure;
 
-    // TODO(ahe): restore file-offset once we track both origin and patch file
-    // URIs. See https://github.com/dart-lang/sdk/issues/31579
-    origin.procedure.fileUri = fileUri;
-    origin.procedure.startFileOffset = _procedure.startFileOffset;
-    origin.procedure.fileOffset = _procedure.fileOffset;
-    origin.procedure.fileEndOffset = _procedure.fileEndOffset;
-    origin.procedure.annotations
-        .forEach((m) => m.fileOffset = _procedure.fileOffset);
-
-    origin.procedure.isAbstract = _procedure.isAbstract;
-    origin.procedure.isExternal = _procedure.isExternal;
-    origin.procedure.function = _procedure.function;
-    origin.procedure.function.parent = origin.procedure;
-    origin.procedure.isRedirectingFactoryConstructor =
-        _procedure.isRedirectingFactoryConstructor;
-    return 1;
-  }
-}
-
-class SourceProcedureBuilder extends ProcedureBuilderImpl {
-  final Reference? _tearOffReference;
-
-  /// If this is an extension instance method then [_extensionTearOff] holds
-  /// the synthetically created tear off function.
-  Procedure? _extensionTearOff;
-
-  /// If this is an extension instance method then
-  /// [_extensionTearOffParameterMap] holds a map from the parameters of
-  /// the methods to the parameter of the closure returned in the tear-off.
-  ///
-  /// This map is used to set the default values on the closure parameters when
-  /// these have been built.
-  Map<VariableDeclaration, VariableDeclaration>? _extensionTearOffParameterMap;
-
-  SourceProcedureBuilder(
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      TypeBuilder? returnType,
-      String name,
-      List<TypeVariableBuilder>? typeVariables,
-      List<FormalParameterBuilder>? formals,
-      ProcedureKind kind,
-      SourceLibraryBuilder libraryBuilder,
-      int startCharOffset,
-      int charOffset,
-      int charOpenParenOffset,
-      int charEndOffset,
-      Reference? procedureReference,
-      this._tearOffReference,
-      AsyncMarker asyncModifier,
-      ProcedureNameScheme procedureNameScheme,
-      {required bool isExtensionMember,
-      required bool isInstanceMember,
-      String? nativeMethodName})
-      : super(
-            metadata,
-            modifiers,
-            returnType,
-            name,
-            typeVariables,
-            formals,
-            kind,
-            libraryBuilder,
-            startCharOffset,
-            charOffset,
-            charOpenParenOffset,
-            charEndOffset,
-            procedureReference,
-            procedureNameScheme,
-            isExtensionMember: isExtensionMember,
-            isInstanceMember: isInstanceMember,
-            nativeMethodName: nativeMethodName) {
-    this.asyncModifier = asyncModifier;
-    if (isExtensionMember && isInstanceMember && kind == ProcedureKind.Method) {
-      _extensionTearOff ??= new Procedure(
-          procedureNameScheme.getName(ProcedureKind.Getter, name),
-          ProcedureKind.Method,
-          new FunctionNode(null),
-          isStatic: true,
-          isExtensionMember: true,
-          reference: _tearOffReference,
-          fileUri: fileUri)
-        ..isNonNullableByDefault = library.isNonNullableByDefault;
-    }
-  }
+  @override
+  FunctionNode get function => _procedure.function;
 
   bool _typeEnsured = false;
   Set<ClassMember>? _overrideDependencies;
@@ -597,6 +501,46 @@
       _localSetters ??= isSetter && !isConflictingSetter
           ? <ClassMember>[new SourceProcedureMember(this)]
           : const <ClassMember>[];
+
+  @override
+  void becomeNative(Loader loader) {
+    _procedure.isExternal = true;
+    super.becomeNative(loader);
+  }
+
+  @override
+  void applyPatch(Builder patch) {
+    if (patch is SourceProcedureBuilder) {
+      if (checkPatch(patch)) {
+        patch.actualOrigin = this;
+        dataForTesting?.patchForTesting = patch;
+      }
+    } else {
+      reportPatchMismatch(patch);
+    }
+  }
+
+  @override
+  int finishPatch() {
+    if (!isPatch) return 0;
+
+    // TODO(ahe): restore file-offset once we track both origin and patch file
+    // URIs. See https://github.com/dart-lang/sdk/issues/31579
+    origin.procedure.fileUri = fileUri;
+    origin.procedure.startFileOffset = _procedure.startFileOffset;
+    origin.procedure.fileOffset = _procedure.fileOffset;
+    origin.procedure.fileEndOffset = _procedure.fileEndOffset;
+    origin.procedure.annotations
+        .forEach((m) => m.fileOffset = _procedure.fileOffset);
+
+    origin.procedure.isAbstract = _procedure.isAbstract;
+    origin.procedure.isExternal = _procedure.isExternal;
+    origin.procedure.function = _procedure.function;
+    origin.procedure.function.parent = origin.procedure;
+    origin.procedure.isRedirectingFactoryConstructor =
+        _procedure.isRedirectingFactoryConstructor;
+    return 1;
+  }
 }
 
 class SourceProcedureMember extends BuilderClassMember {
@@ -647,216 +591,6 @@
   }
 }
 
-class RedirectingFactoryBuilder extends ProcedureBuilderImpl {
-  final ConstructorReferenceBuilder redirectionTarget;
-  List<DartType>? typeArguments;
-
-  RedirectingFactoryBuilder(
-      List<MetadataBuilder>? metadata,
-      int modifiers,
-      TypeBuilder returnType,
-      String name,
-      List<TypeVariableBuilder> typeVariables,
-      List<FormalParameterBuilder>? formals,
-      SourceLibraryBuilder compilationUnit,
-      int startCharOffset,
-      int charOffset,
-      int charOpenParenOffset,
-      int charEndOffset,
-      Reference? reference,
-      ProcedureNameScheme procedureNameScheme,
-      String? nativeMethodName,
-      this.redirectionTarget)
-      : super(
-            metadata,
-            modifiers,
-            returnType,
-            name,
-            typeVariables,
-            formals,
-            ProcedureKind.Factory,
-            compilationUnit,
-            startCharOffset,
-            charOffset,
-            charOpenParenOffset,
-            charEndOffset,
-            reference,
-            procedureNameScheme,
-            isExtensionMember: false,
-            isInstanceMember: false,
-            nativeMethodName: nativeMethodName);
-
-  @override
-  Member? get readTarget => null;
-
-  @override
-  Member? get writeTarget => null;
-
-  @override
-  Member? get invokeTarget => procedure;
-
-  @override
-  Iterable<Member> get exportedMembers => [procedure];
-
-  @override
-  Statement? get body => bodyInternal;
-
-  @override
-  void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
-    if (bodyInternal != null) {
-      unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
-    }
-
-    // Ensure that constant factories only have constant targets/bodies.
-    if (isConst && !target.isConst) {
-      library.addProblem(messageConstFactoryRedirectionToNonConst, charOffset,
-          noLength, fileUri);
-    }
-
-    bodyInternal = new RedirectingFactoryBody(target, typeArguments);
-    function.body = bodyInternal;
-    bodyInternal?.parent = function;
-    procedure.isRedirectingFactoryConstructor = true;
-    if (isPatch) {
-      // ignore: unnecessary_null_comparison
-      if (function.typeParameters != null) {
-        Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
-        for (int i = 0; i < function.typeParameters.length; i++) {
-          substitution[function.typeParameters[i]] =
-              new TypeParameterType.withDefaultNullabilityForLibrary(
-                  actualOrigin!.function.typeParameters[i], library.library);
-        }
-        typeArguments = new List<DartType>.generate(typeArguments.length,
-            (int i) => substitute(typeArguments[i], substitution),
-            growable: false);
-      }
-      actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
-    }
-  }
-
-  @override
-  void buildMembers(
-      SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
-    Member member = build(library);
-    f(member, BuiltMemberKind.RedirectingFactory);
-  }
-
-  @override
-  Procedure build(SourceLibraryBuilder libraryBuilder) {
-    buildFunction(libraryBuilder);
-    _procedure.function.fileOffset = charOpenParenOffset;
-    _procedure.function.fileEndOffset = _procedure.fileEndOffset;
-    _procedure.isAbstract = isAbstract;
-    _procedure.isExternal = isExternal;
-    _procedure.isConst = isConst;
-    _procedure.isStatic = isStatic;
-    _procedure.isRedirectingFactoryConstructor = true;
-    if (redirectionTarget.typeArguments != null) {
-      typeArguments = new List<DartType>.generate(
-          redirectionTarget.typeArguments!.length,
-          (int i) => redirectionTarget.typeArguments![i].build(library),
-          growable: false);
-    }
-    updatePrivateMemberName(_procedure, libraryBuilder);
-    return _procedure;
-  }
-
-  @override
-  void buildOutlineExpressions(
-      SourceLibraryBuilder library,
-      CoreTypes coreTypes,
-      List<DelayedActionPerformer> delayedActionPerformers) {
-    super.buildOutlineExpressions(library, coreTypes, delayedActionPerformers);
-    LibraryBuilder thisLibrary = this.library;
-    if (thisLibrary is SourceLibraryBuilder) {
-      RedirectingFactoryBody redirectingFactoryBody =
-          procedure.function.body as RedirectingFactoryBody;
-      if (redirectingFactoryBody.typeArguments != null &&
-          redirectingFactoryBody.typeArguments!.any((t) => t is UnknownType)) {
-        TypeInferrerImpl inferrer = thisLibrary.loader.typeInferenceEngine
-                .createLocalTypeInferrer(
-                    fileUri, classBuilder!.thisType, thisLibrary, null)
-            as TypeInferrerImpl;
-        inferrer.helper = thisLibrary.loader
-            .createBodyBuilderForOutlineExpression(
-                thisLibrary, classBuilder, this, classBuilder!.scope, fileUri);
-        Builder? targetBuilder = redirectionTarget.target;
-        Member target;
-        if (targetBuilder is FunctionBuilder) {
-          target = targetBuilder.member;
-        } else if (targetBuilder is DillMemberBuilder) {
-          target = targetBuilder.member;
-        } else {
-          unhandled("${targetBuilder.runtimeType}", "buildOutlineExpressions",
-              charOffset, fileUri);
-        }
-        Arguments targetInvocationArguments;
-        {
-          List<Expression> positionalArguments = <Expression>[];
-          for (VariableDeclaration parameter
-              in procedure.function.positionalParameters) {
-            inferrer.flowAnalysis.declare(parameter, true);
-            positionalArguments.add(
-                new VariableGetImpl(parameter, forNullGuardedAccess: false));
-          }
-          List<NamedExpression> namedArguments = <NamedExpression>[];
-          for (VariableDeclaration parameter
-              in procedure.function.namedParameters) {
-            inferrer.flowAnalysis.declare(parameter, true);
-            namedArguments.add(new NamedExpression(parameter.name!,
-                new VariableGetImpl(parameter, forNullGuardedAccess: false)));
-          }
-          // If arguments are created using [Forest.createArguments], and the
-          // type arguments are omitted, they are to be inferred.
-          targetInvocationArguments = const Forest().createArguments(
-              procedure.fileOffset, positionalArguments,
-              named: namedArguments);
-        }
-        InvocationInferenceResult result = inferrer.inferInvocation(
-            function.returnType,
-            charOffset,
-            target.function!.computeFunctionType(Nullability.nonNullable),
-            targetInvocationArguments,
-            staticTarget: target);
-        List<DartType> typeArguments;
-        if (result.inferredType is InterfaceType) {
-          typeArguments = (result.inferredType as InterfaceType).typeArguments;
-        } else {
-          // Assume that the error is reported elsewhere, use 'dynamic' for
-          // recovery.
-          typeArguments = new List<DartType>.filled(
-              target.enclosingClass!.typeParameters.length, const DynamicType(),
-              growable: true);
-        }
-        member.function!.body =
-            new RedirectingFactoryBody(target, typeArguments);
-      }
-    }
-  }
-
-  @override
-  List<ClassMember> get localMembers =>
-      throw new UnsupportedError('${runtimeType}.localMembers');
-
-  @override
-  List<ClassMember> get localSetters =>
-      throw new UnsupportedError('${runtimeType}.localSetters');
-
-  @override
-  int finishPatch() {
-    if (!isPatch) return 0;
-
-    super.finishPatch();
-
-    ProcedureBuilder redirectingOrigin = origin;
-    if (redirectingOrigin is RedirectingFactoryBuilder) {
-      redirectingOrigin.typeArguments = typeArguments;
-    }
-
-    return 1;
-  }
-}
-
 class ProcedureNameScheme {
   final bool isExtensionMember;
   final bool isStatic;
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 4656d20..ef545f2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -46,6 +46,7 @@
 import '../builder/declaration_builder.dart';
 import '../builder/enum_builder.dart';
 import '../builder/extension_builder.dart';
+import '../builder/factory_builder.dart';
 import '../builder/field_builder.dart';
 import '../builder/fixed_type_builder.dart';
 import '../builder/formal_parameter_builder.dart';
@@ -950,7 +951,9 @@
 
   DartType _computeReturnTypeContext(MemberBuilder member) {
     if (member is ProcedureBuilder) {
-      return member.actualProcedure.function.returnType;
+      return member.function.returnType;
+    } else if (member is SourceFactoryBuilder) {
+      return member.function.returnType;
     } else {
       assert(member is ConstructorBuilder);
       return const DynamicType();
@@ -1018,6 +1021,8 @@
       finishConstructor(builder, asyncModifier, body);
     } else if (builder is ProcedureBuilder) {
       builder.asyncModifier = asyncModifier;
+    } else if (builder is SourceFactoryBuilder) {
+      builder.asyncModifier = asyncModifier;
     } else {
       unhandled("${builder.runtimeType}", "finishFunction", builder.charOffset,
           builder.fileUri);
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index a3f7c13..382ee2b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -3000,12 +3000,7 @@
   Constant _getFromEnvironmentDefaultValue(Procedure target) {
     VariableDeclaration variable = target.function.namedParameters
         .singleWhere((v) => v.name == 'defaultValue');
-    return variable.initializer != null
-        ? _evaluateExpressionInContext(target, variable.initializer!)
-        :
-        // Not reachable unless a defaultValue in fromEnvironment in dart:core
-        // becomes null.
-        nullConstant;
+    return _evaluateExpressionInContext(target, variable.initializer!);
   }
 
   Constant _handleFromEnvironment(
diff --git a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
index 33aa5d1..64c8403 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
@@ -20,15 +20,15 @@
 /// the given [name] in [compilationUnit].
 ///
 /// If constructor tear off lowering is not enabled, `null` is returned.
-Procedure? createConstructorTearOffProcedure(
-    String name, SourceLibraryBuilder compilationUnit, int fileOffset,
+Procedure? createConstructorTearOffProcedure(String name,
+    SourceLibraryBuilder compilationUnit, Uri fileUri, int fileOffset,
     {required bool forAbstractClassOrEnum}) {
   if (!forAbstractClassOrEnum &&
       compilationUnit
           .loader.target.backendTarget.isConstructorTearOffLoweringEnabled) {
     return new Procedure(constructorTearOffName(name, compilationUnit.library),
         ProcedureKind.Method, new FunctionNode(null),
-        fileUri: compilationUnit.fileUri, isStatic: true)
+        fileUri: fileUri, isStatic: true)
       ..startFileOffset = fileOffset
       ..fileOffset = fileOffset
       ..fileEndOffset = fileOffset
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 2531ba7..ef5652b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -810,7 +810,7 @@
       ..isNonNullableByDefault =
           enclosingClass.enclosingLibrary.isNonNullableByDefault;
     Procedure? constructorTearOff = createConstructorTearOffProcedure(
-        '', classBuilder.library, constructor.fileOffset,
+        '', classBuilder.library, classBuilder.fileUri, constructor.fileOffset,
         forAbstractClassOrEnum:
             enclosingClass.isAbstract || enclosingClass.isEnum);
     if (constructorTearOff != null) {
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index 392acae..0a88d80 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -17,6 +17,7 @@
 import '../builder/class_builder.dart';
 import '../builder/constructor_builder.dart';
 import '../builder/constructor_reference_builder.dart';
+import '../builder/factory_builder.dart';
 import '../builder/field_builder.dart';
 import '../builder/function_builder.dart';
 import '../builder/invalid_type_declaration_builder.dart';
@@ -528,7 +529,7 @@
         // Check procedures
         checkVarianceInFunction(
             builder.procedure, typeEnvironment, cls.typeParameters);
-        library.checkTypesInProcedureBuilder(builder, typeEnvironment);
+        library.checkTypesInFunctionBuilder(builder, typeEnvironment);
       } else {
         assert(builder is DillFieldBuilder && builder.name == redirectingName,
             "Unexpected member: $builder.");
@@ -540,9 +541,9 @@
         library.checkTypesInConstructorBuilder(builder, typeEnvironment);
       } else if (builder is RedirectingFactoryBuilder) {
         library.checkTypesInRedirectingFactoryBuilder(builder, typeEnvironment);
-      } else if (builder is ProcedureBuilder) {
+      } else if (builder is SourceFactoryBuilder) {
         assert(builder.isFactory, "Unexpected constructor $builder.");
-        library.checkTypesInProcedureBuilder(builder, typeEnvironment);
+        library.checkTypesInFunctionBuilder(builder, typeEnvironment);
       } else {
         assert(
             // This is a synthesized constructor.
@@ -859,7 +860,7 @@
     procedure.stubTarget = null;
   }
 
-  void _addRedirectingConstructor(ProcedureBuilder constructorBuilder,
+  void _addRedirectingConstructor(SourceFactoryBuilder constructorBuilder,
       SourceLibraryBuilder library, Reference? getterReference) {
     // Add a new synthetic field to this class for representing factory
     // constructors. This is used to support resolving such constructors in
@@ -893,7 +894,7 @@
     Field field = constructorsField.field;
     ListLiteral literal = field.initializer as ListLiteral;
     literal.expressions
-        .add(new StaticGet(constructorBuilder.procedure)..parent = literal);
+        .add(new StaticGet(constructorBuilder.member)..parent = literal);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
index 9adab49..a6774b6 100644
--- a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
@@ -254,7 +254,7 @@
         library.checkTypesInField(builder, typeEnvironment);
       } else if (builder is ProcedureBuilder) {
         // Check procedures
-        library.checkTypesInProcedureBuilder(builder, typeEnvironment);
+        library.checkTypesInFunctionBuilder(builder, typeEnvironment);
         if (builder.isGetter) {
           Builder? setterDeclaration =
               scope.lookupLocalMember(builder.name, setter: true);
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 b9eed88..b3bcc83 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
@@ -47,6 +47,7 @@
 import '../builder/dynamic_type_declaration_builder.dart';
 import '../builder/enum_builder.dart';
 import '../builder/extension_builder.dart';
+import '../builder/factory_builder.dart';
 import '../builder/field_builder.dart';
 import '../builder/formal_parameter_builder.dart';
 import '../builder/function_builder.dart';
@@ -2503,7 +2504,7 @@
             procedureName, _currentClassReferencesFromIndexed!.library))
         ?.reference;
 
-    ProcedureBuilder procedureBuilder;
+    SourceFactoryBuilder procedureBuilder;
     if (redirectionTarget != null) {
       procedureBuilder = new RedirectingFactoryBuilder(
           metadata,
@@ -2525,7 +2526,7 @@
           nativeMethodName,
           redirectionTarget);
     } else {
-      procedureBuilder = new SourceProcedureBuilder(
+      procedureBuilder = new SourceFactoryBuilder(
           metadata,
           staticMask | modifiers,
           returnType,
@@ -2535,18 +2536,14 @@
                   const <TypeVariableBuilder>[],
               factoryDeclaration),
           formals,
-          ProcedureKind.Factory,
           this,
           startCharOffset,
           charOffset,
           charOpenParenOffset,
           charEndOffset,
           reference,
-          /* tearOffReference = */ null,
           asyncModifier,
           procedureNameScheme,
-          isExtensionMember: false,
-          isInstanceMember: false,
           nativeMethodName: nativeMethodName);
     }
 
@@ -3272,7 +3269,7 @@
 
           declaration.constructors.forEach((String name, Builder member) {
             List<FormalParameterBuilder>? formals;
-            if (member is ProcedureBuilder) {
+            if (member is SourceFactoryBuilder) {
               assert(member.isFactory,
                   "Unexpected constructor member (${member.runtimeType}).");
               count += computeDefaultTypesForVariables(member.typeVariables,
@@ -3828,10 +3825,10 @@
     }
   }
 
-  void checkTypesInProcedureBuilder(
-      ProcedureBuilder procedureBuilder, TypeEnvironment typeEnvironment) {
-    checkBoundsInFunctionNode(procedureBuilder.procedure.function,
-        typeEnvironment, procedureBuilder.fileUri!);
+  void checkTypesInFunctionBuilder(
+      FunctionBuilder procedureBuilder, TypeEnvironment typeEnvironment) {
+    checkBoundsInFunctionNode(
+        procedureBuilder.function, typeEnvironment, procedureBuilder.fileUri!);
     if (procedureBuilder.formals != null &&
         !(procedureBuilder.isAbstract || procedureBuilder.isExternal)) {
       checkInitializersInFormals(procedureBuilder.formals!, typeEnvironment);
@@ -3850,7 +3847,7 @@
   void checkTypesInRedirectingFactoryBuilder(
       RedirectingFactoryBuilder redirectingFactoryBuilder,
       TypeEnvironment typeEnvironment) {
-    checkBoundsInFunctionNode(redirectingFactoryBuilder.procedure.function,
+    checkBoundsInFunctionNode(redirectingFactoryBuilder.function,
         typeEnvironment, redirectingFactoryBuilder.fileUri);
     // Default values are not required on redirecting factory constructors so
     // we don't call [checkInitializersInFormals].
@@ -4137,7 +4134,7 @@
       if (declaration is FieldBuilder) {
         checkTypesInField(declaration, typeEnvironment);
       } else if (declaration is ProcedureBuilder) {
-        checkTypesInProcedureBuilder(declaration, typeEnvironment);
+        checkTypesInFunctionBuilder(declaration, typeEnvironment);
         if (declaration.isGetter) {
           Builder? setterDeclaration =
               scope.lookupLocalMember(declaration.name, setter: true);
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 510170a..6f4a1af 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -1017,6 +1017,7 @@
 remedy
 removal
 remover
+renames
 render
 reparse
 repeating
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart
new file mode 100644
index 0000000..d268773
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart
@@ -0,0 +1,7 @@
+// 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.
+
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect
new file mode 100644
index 0000000..7998cc3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect
new file mode 100644
index 0000000..7998cc3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect
new file mode 100644
index 0000000..428e3bc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..428e3bc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect
new file mode 100644
index 0000000..7998cc3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect
new file mode 100644
index 0000000..90a7e36
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic
+  ;
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect
new file mode 100644
index 0000000..7998cc3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+//  - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+//   Class Function(int) f = Class.new;
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::Class
+    return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+  (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+  Class Function(int) f = Class.new;
+                          ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants  {
+  #C1 = tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart
new file mode 100644
index 0000000..042cb62
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart
@@ -0,0 +1,23 @@
+// 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.
+
+part of 'constructor_tear_off_uri.dart';
+
+test() {
+  Class Function(int) f = Class.new;
+}
+
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+
+class Class {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
index 145140e..c7776f1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
@@ -21,18 +21,6 @@
 //   factory A.redirectingFactory() = A.new;
 //                                    ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-//   A Function() f1 = A.redirectingFactory;
-//                       ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-//   A Function() f2 = A.redirectingFactoryChild;
-//                       ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-//   A Function() f3 = A.redirectingTwice;
-//                       ^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
 //   A x3 f3();
 //     ^^
@@ -62,15 +50,9 @@
     ;
 }
 static method test() → dynamic {
-  () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-  A Function() f1 = A.redirectingFactory;
-                      ^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
-  () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-  A Function() f2 = A.redirectingFactoryChild;
-                      ^^^^^^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
-  () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-  A Function() f3 = A.redirectingTwice;
-                      ^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
+  () → self::A f1 = self::A::redirectingFactory;
+  () → self::A f2 = self::A::redirectingFactoryChild;
+  () → self::A f3 = self::A::redirectingTwice;
   self::A x1 = f1(){() → self::A};
   self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
   self::A x3;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
index 943d69c..e232b6bf 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
@@ -21,18 +21,6 @@
 //   factory A.redirectingFactory() = A.new;
 //                                    ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-//   A Function() f1 = A.redirectingFactory;
-//                       ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-//   A Function() f2 = A.redirectingFactoryChild;
-//                       ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-//   A Function() f3 = A.redirectingTwice;
-//                       ^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
 //   A x3 f3();
 //     ^^
@@ -62,15 +50,9 @@
     ;
 }
 static method test() → dynamic {
-  () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-  A Function() f1 = A.redirectingFactory;
-                      ^^^^^^^^^^^^^^^^^^";
-  () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-  A Function() f2 = A.redirectingFactoryChild;
-                      ^^^^^^^^^^^^^^^^^^^^^^^";
-  () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-  A Function() f3 = A.redirectingTwice;
-                      ^^^^^^^^^^^^^^^^";
+  () → self::A f1 = self::A::redirectingFactory;
+  () → self::A f2 = self::A::redirectingFactoryChild;
+  () → self::A f3 = self::A::redirectingTwice;
   self::A x1 = f1(){() → self::A};
   self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
   self::A x3;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
index 145140e..c7776f1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
@@ -21,18 +21,6 @@
 //   factory A.redirectingFactory() = A.new;
 //                                    ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-//   A Function() f1 = A.redirectingFactory;
-//                       ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-//   A Function() f2 = A.redirectingFactoryChild;
-//                       ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-//   A Function() f3 = A.redirectingTwice;
-//                       ^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
 //   A x3 f3();
 //     ^^
@@ -62,15 +50,9 @@
     ;
 }
 static method test() → dynamic {
-  () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-  A Function() f1 = A.redirectingFactory;
-                      ^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
-  () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-  A Function() f2 = A.redirectingFactoryChild;
-                      ^^^^^^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
-  () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-  A Function() f3 = A.redirectingTwice;
-                      ^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
+  () → self::A f1 = self::A::redirectingFactory;
+  () → self::A f2 = self::A::redirectingFactoryChild;
+  () → self::A f3 = self::A::redirectingTwice;
   self::A x1 = f1(){() → self::A};
   self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
   self::A x3;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
index 943d69c..e232b6bf 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
@@ -21,18 +21,6 @@
 //   factory A.redirectingFactory() = A.new;
 //                                    ^
 //
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-//   A Function() f1 = A.redirectingFactory;
-//                       ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-//   A Function() f2 = A.redirectingFactoryChild;
-//                       ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-//   A Function() f3 = A.redirectingTwice;
-//                       ^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
 //   A x3 f3();
 //     ^^
@@ -62,15 +50,9 @@
     ;
 }
 static method test() → dynamic {
-  () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-  A Function() f1 = A.redirectingFactory;
-                      ^^^^^^^^^^^^^^^^^^";
-  () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-  A Function() f2 = A.redirectingFactoryChild;
-                      ^^^^^^^^^^^^^^^^^^^^^^^";
-  () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-  A Function() f3 = A.redirectingTwice;
-                      ^^^^^^^^^^^^^^^^";
+  () → self::A f1 = self::A::redirectingFactory;
+  () → self::A f2 = self::A::redirectingFactoryChild;
+  () → self::A f3 = self::A::redirectingTwice;
   self::A x1 = f1(){() → self::A};
   self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
   self::A x3;
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/libraries.json b/pkg/front_end/testcases/dartdevc/factory_patch/libraries.json
new file mode 100644
index 0000000..154c73c
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/libraries.json
@@ -0,0 +1,12 @@
+{
+  "none": {
+    "libraries": {
+      "test": {
+        "patches": [
+          "patch_lib.dart"
+        ],
+        "uri": "origin_lib.dart"
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart
new file mode 100644
index 0000000..8e6257c
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:test';
+
+main() {
+  new Class.fact();
+  //const Class.redirect();
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+}
+
+constants  {
+  #C1 = _js::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+}
+
+constants  {
+  #C1 = _js::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+}
+
+constants  {
+  #C1 = _js::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect
new file mode 100644
index 0000000..fe1495b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@_js::patch
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = false}) → self2::Class
+    : self2::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @_js::patch
+  external static factory fact({core::bool defaultValue}) → self2::Class;
+  @_js::patch
+  external static factory constFact({core::bool defaultValue = true}) → self2::Class;
+}
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:6:50 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:8:28 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 4, effectively constant: 3
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+}
+
+constants  {
+  #C1 = _js::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/origin_lib.dart b/pkg/front_end/testcases/dartdevc/factory_patch/origin_lib.dart
new file mode 100644
index 0000000..e7895f2
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/origin_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Class {
+  external factory Class.fact({bool defaultValue: true});
+  external const factory Class.constFact({bool defaultValue: true});
+  //external const factory Class.redirect({bool defaultValue: true});
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/patch_lib.dart b/pkg/front_end/testcases/dartdevc/factory_patch/patch_lib.dart
new file mode 100644
index 0000000..394388b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/patch_lib.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2020, 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.
+
+// ignore: import_internal_library
+import 'dart:_js_helper';
+
+@patch
+class Class {
+  final bool defaultValue;
+
+  const Class._internal({this.defaultValue: false});
+
+  @patch
+  factory Class.fact({bool defaultValue: true}) =>
+      new Class._internal(defaultValue: defaultValue);
+
+  @patch
+  factory Class.constFact({bool defaultValue: true}) => throw 'unsupported';
+
+  /*@patch
+  const factory Class.redirect({bool defaultValue: true}) =
+      this._internal(defaultValue: defaultValue);*/
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/libraries.json b/pkg/front_end/testcases/general/factory_patch/libraries.json
new file mode 100644
index 0000000..154c73c
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/libraries.json
@@ -0,0 +1,12 @@
+{
+  "none": {
+    "libraries": {
+      "test": {
+        "patches": [
+          "patch_lib.dart"
+        ],
+        "uri": "origin_lib.dart"
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart b/pkg/front_end/testcases/general/factory_patch/main.dart
new file mode 100644
index 0000000..8e6257c
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:test';
+
+main() {
+  new Class.fact();
+  //const Class.redirect();
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.weak.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.expect
new file mode 100644
index 0000000..f739cd9
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+}
+
+constants  {
+  #C1 = _in::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.outline.expect
new file mode 100644
index 0000000..25c2ffa
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@_in::patch
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = false}) → self2::Class
+    : self2::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @_in::patch
+  external static factory fact({core::bool defaultValue}) → self2::Class;
+  @_in::patch
+  external static factory constFact({core::bool defaultValue = true}) → self2::Class;
+}
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:6:49 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:8:27 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 4, effectively constant: 3
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.weak.transformed.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..f739cd9
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.transformed.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Class extends core::Object {
+  final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+  const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+    : test::Class::defaultValue = defaultValue, super core::Object::•()
+    ;
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+    return new test::Class::_internal(defaultValue: defaultValue);
+  @#C1
+  static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+    return throw "unsupported";
+}
+
+constants  {
+  #C1 = _in::_Patch {}
+  #C2 = false
+  #C3 = true
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/origin_lib.dart b/pkg/front_end/testcases/general/factory_patch/origin_lib.dart
new file mode 100644
index 0000000..e7895f2
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/origin_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Class {
+  external factory Class.fact({bool defaultValue: true});
+  external const factory Class.constFact({bool defaultValue: true});
+  //external const factory Class.redirect({bool defaultValue: true});
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/patch_lib.dart b/pkg/front_end/testcases/general/factory_patch/patch_lib.dart
new file mode 100644
index 0000000..cfc2278
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/patch_lib.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2020, 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.
+
+// ignore: import_internal_library
+import 'dart:_internal';
+
+@patch
+class Class {
+  final bool defaultValue;
+
+  const Class._internal({this.defaultValue: false});
+
+  @patch
+  factory Class.fact({bool defaultValue: true}) =>
+      new Class._internal(defaultValue: defaultValue);
+
+  @patch
+  factory Class.constFact({bool defaultValue: true}) => throw 'unsupported';
+
+  /*@patch
+  const factory Class.redirect({bool defaultValue: true}) =
+      this._internal(defaultValue: defaultValue);*/
+}
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index b1e611f..e60499f 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -12,7 +12,7 @@
 constructor_tearoffs/instantiation: TypeCheckError
 constructor_tearoffs/nongeneric_tearoff_with_context: TextSerializationFailure
 constructor_tearoffs/nongeneric_tearoff_without_context: TextSerializationFailure
-constructor_tearoffs/redirecting_constructors: RuntimeError
+constructor_tearoffs/redirecting_constructors: TextSerializationFailure
 constructor_tearoffs/typedef_tearoffs: TextSerializationFailure
 constructor_tearoffs/unnamed_constructor: TextSerializationFailure
 extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 90615e8..8d01d1f 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -362,6 +362,14 @@
           ConstructorTearOffLowering.constructors) !=
       0;
 
+  /// Returns `true` if lowering of redirecting factory tear offs is enabled.
+  ///
+  /// This is determined by the [enabledConstructorTearOffLowerings] mask.
+  bool get isRedirectingFactoryTearOffLoweringEnabled =>
+      (enabledConstructorTearOffLowerings &
+          ConstructorTearOffLowering.redirectingFactories) !=
+      0;
+
   /// Returns `true` if lowering of typedef tear offs is enabled.
   ///
   /// This is determined by the [enabledConstructorTearOffLowerings] mask.
@@ -635,13 +643,16 @@
 }
 
 class ConstructorTearOffLowering {
-  /// Create top level functions to use as tear offs of constructors.
+  /// Create static functions to use as tear offs of constructors and.
   static const int constructors = 1 << 0;
 
-  /// Create top level functions to use as tear offs of non trivial redirecting
-  /// factory constructors and typedefs.
-  static const int typedefs = 1 << 1;
+  /// Create static functions to use as tear offs of redirecting factories.
+  static const int redirectingFactories = 1 << 1;
+
+  /// Create top level functions to use as tear offs of typedefs that are not
+  /// proper renames.
+  static const int typedefs = 1 << 2;
 
   static const int none = 0;
-  static const int all = (1 << 2) - 1;
+  static const int all = (1 << 3) - 1;
 }
diff --git a/tools/VERSION b/tools/VERSION
index 435c26f..d81caa4 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 333
+PRERELEASE 334
 PRERELEASE_PATCH 0
\ No newline at end of file