Version 3.6.0-110.0.dev

Merge a96a8a78d48bbbb4c5ccb325f9798b7b823e47f9 into dev
diff --git a/pkg/front_end/lib/src/base/name_space.dart b/pkg/front_end/lib/src/base/name_space.dart
index 882bbff..03d0f9b 100644
--- a/pkg/front_end/lib/src/base/name_space.dart
+++ b/pkg/front_end/lib/src/base/name_space.dart
@@ -69,6 +69,54 @@
       required bool includeAugmentations});
 }
 
+abstract class DeclarationNameSpace implements NameSpace {
+  MemberBuilder? lookupConstructor(String name);
+
+  void addConstructor(String name, MemberBuilder builder);
+
+  void forEachConstructor(void Function(String, MemberBuilder) f);
+
+  /// Returns an iterator of all constructors mapped in this scope,
+  /// including duplicate constructors mapped to the same name.
+  Iterator<MemberBuilder> get unfilteredConstructorIterator;
+
+  /// Returns an iterator of all constructors mapped in this scope,
+  /// including duplicate constructors mapped to the same name.
+  ///
+  /// Compared to [unfilteredConstructorIterator] this iterator also gives
+  /// access to the name that the builders are mapped to.
+  NameIterator<MemberBuilder> get unfilteredConstructorNameIterator;
+
+  /// Returns a filtered iterator of constructors mapped in this scope.
+  ///
+  /// Only members of type [T] are included. If [parent] is provided, on members
+  /// declared in [parent] are included. If [includeDuplicates] is `true`, all
+  /// duplicates of the same name are included, otherwise, only the first
+  /// declared member is included. If [includeAugmentations] is `true`, both
+  /// original and augmenting/patching members are included, otherwise, only
+  /// original members are included.
+  Iterator<T> filteredConstructorIterator<T extends MemberBuilder>(
+      {Builder? parent,
+      required bool includeDuplicates,
+      required bool includeAugmentations});
+
+  /// Returns a filtered iterator of constructors mapped in this scope.
+  ///
+  /// Only members of type [T] are included. If [parent] is provided, on members
+  /// declared in [parent] are included. If [includeDuplicates] is `true`, all
+  /// duplicates of the same name are included, otherwise, only the first
+  /// declared member is included. If [includeAugmentations] is `true`, both
+  /// original and augmenting/patching members are included, otherwise, only
+  /// original members are included.
+  ///
+  /// Compared to [filteredConstructorIterator] this iterator also gives access
+  /// to the name that the builders are mapped to.
+  NameIterator<T> filteredConstructorNameIterator<T extends MemberBuilder>(
+      {Builder? parent,
+      required bool includeDuplicates,
+      required bool includeAugmentations});
+}
+
 class NameSpaceImpl implements NameSpace {
   Map<String, Builder>? _getables;
   Map<String, MemberBuilder>? _setables;
@@ -161,6 +209,64 @@
       new ScopeNameIterator(_getables, _setables, _extensions?.iterator);
 }
 
+class DeclarationNameSpaceImpl extends NameSpaceImpl
+    implements DeclarationNameSpace {
+  Map<String, MemberBuilder>? _constructors;
+
+  DeclarationNameSpaceImpl(
+      {super.getables,
+      super.setables,
+      super.extensions,
+      Map<String, MemberBuilder>? constructors})
+      : _constructors = constructors;
+
+  @override
+  void addConstructor(String name, MemberBuilder builder) {
+    (_constructors ??= {})[name] = builder;
+  }
+
+  @override
+  MemberBuilder? lookupConstructor(String name) => _constructors?[name];
+
+  /// Returns an iterator of all constructors mapped in this scope,
+  /// including duplicate constructors mapped to the same name.
+  @override
+  Iterator<MemberBuilder> get unfilteredConstructorIterator =>
+      new ConstructorNameSpaceIterator(_constructors?.values.iterator);
+
+  @override
+  NameIterator<MemberBuilder> get unfilteredConstructorNameIterator =>
+      new ConstructorNameSpaceNameIterator(
+          _constructors?.keys.iterator, _constructors?.values.iterator);
+
+  @override
+  Iterator<T> filteredConstructorIterator<T extends MemberBuilder>(
+      {Builder? parent,
+      required bool includeDuplicates,
+      required bool includeAugmentations}) {
+    return new FilteredIterator<T>(unfilteredConstructorIterator,
+        parent: parent,
+        includeDuplicates: includeDuplicates,
+        includeAugmentations: includeAugmentations);
+  }
+
+  @override
+  NameIterator<T> filteredConstructorNameIterator<T extends MemberBuilder>(
+      {Builder? parent,
+      required bool includeDuplicates,
+      required bool includeAugmentations}) {
+    return new FilteredNameIterator<T>(unfilteredConstructorNameIterator,
+        parent: parent,
+        includeDuplicates: includeDuplicates,
+        includeAugmentations: includeAugmentations);
+  }
+
+  @override
+  void forEachConstructor(void Function(String, MemberBuilder) f) {
+    _constructors?.forEach(f);
+  }
+}
+
 abstract class LazyNameSpace extends NameSpaceImpl {
   /// Override this method to lazily populate the scope before access.
   void ensureNameSpace();
diff --git a/pkg/front_end/lib/src/base/scope.dart b/pkg/front_end/lib/src/base/scope.dart
index fa77578..ddf303e 100644
--- a/pkg/front_end/lib/src/base/scope.dart
+++ b/pkg/front_end/lib/src/base/scope.dart
@@ -420,92 +420,28 @@
   LookupScope? get _parent => _libraryBuilder.importScope;
 }
 
-class ConstructorScope {
-  /// Constructors declared in this scope.
-  final Map<String, MemberBuilder> _local;
+abstract class ConstructorScope {
+  MemberBuilder? lookup(String name, int charOffset, Uri fileUri);
+}
 
-  final String className;
+class DeclarationNameSpaceConstructorScope implements ConstructorScope {
+  final String _className;
 
-  ConstructorScope(this.className, this._local);
+  final DeclarationNameSpace _nameSpace;
 
+  DeclarationNameSpaceConstructorScope(this._className, this._nameSpace);
+
+  @override
   MemberBuilder? lookup(String name, int charOffset, Uri fileUri) {
-    MemberBuilder? builder = _local[name];
+    MemberBuilder? builder = _nameSpace.lookupConstructor(name);
     if (builder == null) return null;
     if (builder.next != null) {
       return new AmbiguousMemberBuilder(
-          name.isEmpty ? className : name, builder, charOffset, fileUri);
+          name.isEmpty ? _className : name, builder, charOffset, fileUri);
     } else {
       return builder;
     }
   }
-
-  MemberBuilder? lookupLocalMember(String name) {
-    return _local[name];
-  }
-
-  void addLocalMember(String name, MemberBuilder builder) {
-    _local[name] = builder;
-  }
-
-  // Coverage-ignore(suite): Not run.
-  void addLocalMembers(Map<String, MemberBuilder> map) {
-    _local.addAll(map);
-  }
-
-  /// Returns an iterator of all constructors mapped in this scope,
-  /// including duplicate constructors mapped to the same name.
-  Iterator<MemberBuilder> get unfilteredIterator =>
-      new ConstructorScopeIterator(this);
-
-  /// Returns an iterator of all constructors mapped in this scope,
-  /// including duplicate constructors mapped to the same name.
-  ///
-  /// Compared to [unfilteredIterator] this iterator also gives access to the
-  /// name that the builders are mapped to.
-  NameIterator<MemberBuilder> get unfilteredNameIterator =>
-      new ConstructorScopeNameIterator(this);
-
-  /// Returns a filtered iterator of constructors mapped in this scope.
-  ///
-  /// Only members of type [T] are included. If [parent] is provided, on members
-  /// declared in [parent] are included. If [includeDuplicates] is `true`, all
-  /// duplicates of the same name are included, otherwise, only the first
-  /// declared member is included. If [includeAugmentations] is `true`, both
-  /// original and augmenting/patching members are included, otherwise, only
-  /// original members are included.
-  Iterator<T> filteredIterator<T extends MemberBuilder>(
-      {Builder? parent,
-      required bool includeDuplicates,
-      required bool includeAugmentations}) {
-    return new FilteredIterator<T>(unfilteredIterator,
-        parent: parent,
-        includeDuplicates: includeDuplicates,
-        includeAugmentations: includeAugmentations);
-  }
-
-  /// Returns a filtered iterator of constructors mapped in this scope.
-  ///
-  /// Only members of type [T] are included. If [parent] is provided, on members
-  /// declared in [parent] are included. If [includeDuplicates] is `true`, all
-  /// duplicates of the same name are included, otherwise, only the first
-  /// declared member is included. If [includeAugmentations] is `true`, both
-  /// original and augmenting/patching members are included, otherwise, only
-  /// original members are included.
-  ///
-  /// Compared to [filteredIterator] this iterator also gives access to the
-  /// name that the builders are mapped to.
-  NameIterator<T> filteredNameIterator<T extends MemberBuilder>(
-      {Builder? parent,
-      required bool includeDuplicates,
-      required bool includeAugmentations}) {
-    return new FilteredNameIterator<T>(unfilteredNameIterator,
-        parent: parent,
-        includeDuplicates: includeDuplicates,
-        includeAugmentations: includeAugmentations);
-  }
-
-  @override
-  String toString() => "ConstructorScope($className, ${_local.keys})";
 }
 
 /// Computes a builder for the import/export collision between [declaration] and
@@ -971,15 +907,14 @@
   }
 }
 
-/// Iterator over builders mapped in a [ConstructorScope], including duplicates
-/// for each directly mapped builder.
-class ConstructorScopeIterator implements Iterator<MemberBuilder> {
-  Iterator<MemberBuilder> local;
+/// Iterator over builders mapped in a [ConstructorNameSpace], including
+/// duplicates for each directly mapped builder.
+class ConstructorNameSpaceIterator implements Iterator<MemberBuilder> {
+  Iterator<MemberBuilder>? _local;
 
   MemberBuilder? _current;
 
-  ConstructorScopeIterator(ConstructorScope scope)
-      : local = scope._local.values.iterator;
+  ConstructorNameSpaceIterator(this._local);
 
   @override
   bool moveNext() {
@@ -988,9 +923,12 @@
       _current = next;
       return true;
     }
-    if (local.moveNext()) {
-      _current = local.current;
-      return true;
+    if (_local != null) {
+      if (_local!.moveNext()) {
+        _current = _local!.current;
+        return true;
+      }
+      _local = null;
     }
     return false;
   }
@@ -1002,20 +940,18 @@
   }
 }
 
-/// Iterator over builders mapped in a [ConstructorScope], including duplicates
-/// for each directly mapped builder.
+/// Iterator over builders mapped in a [ConstructorNameSpace], including
+/// duplicates for each directly mapped builder.
 ///
-/// Compared to [ConstructorScopeIterator] this iterator also gives
+/// Compared to [ConstructorNameSpaceIterator] this iterator also gives
 /// access to the name that the builders are mapped to.
-class ConstructorScopeNameIterator extends ConstructorScopeIterator
+class ConstructorNameSpaceNameIterator extends ConstructorNameSpaceIterator
     implements NameIterator<MemberBuilder> {
-  final Iterator<String> localNames;
+  Iterator<String>? _localNames;
 
   String? _name;
 
-  ConstructorScopeNameIterator(ConstructorScope scope)
-      : localNames = scope._local.keys.iterator,
-        super(scope);
+  ConstructorNameSpaceNameIterator(this._localNames, super.local);
 
   @override
   bool moveNext() {
@@ -1024,11 +960,15 @@
       _current = next;
       return true;
     }
-    if (local.moveNext()) {
-      localNames.moveNext();
-      _current = local.current;
-      _name = localNames.current;
-      return true;
+    if (_local != null) {
+      if (_local!.moveNext()) {
+        _localNames!.moveNext();
+        _current = _local!.current;
+        _name = _localNames!.current;
+        return true;
+      }
+      _local = null;
+      _localNames = null;
     }
     _current = null;
     _name = null;
@@ -1378,22 +1318,22 @@
 }
 
 class MergedClassMemberScope extends MergedScope<SourceClassBuilder> {
-  final ConstructorScope _originConstructorScope;
-  Map<SourceClassBuilder, ConstructorScope> _augmentationConstructorScopes = {};
+  final DeclarationNameSpace _originConstructorNameSpace;
+  Map<SourceClassBuilder, DeclarationNameSpace>
+      _augmentationConstructorNameSpaces = {};
 
   MergedClassMemberScope(SourceClassBuilder origin)
-      : _originConstructorScope = origin.constructorScope,
+      : _originConstructorNameSpace = origin.nameSpace,
         super(origin, origin.nameSpace);
 
   @override
   SourceLibraryBuilder get originLibrary => _origin.libraryBuilder;
 
-  void _addAugmentationConstructorScope(ConstructorScope constructorScope,
+  void _addAugmentationConstructorScope(DeclarationNameSpace nameSpace,
       {required bool inPatchLibrary}) {
-    constructorScope._local
-        .forEach((String name, MemberBuilder newConstructor) {
+    nameSpace.forEachConstructor((String name, MemberBuilder newConstructor) {
       MemberBuilder? existingConstructor =
-          _originConstructorScope.lookupLocalMember(name);
+          _originConstructorNameSpace.lookupConstructor(name);
       bool isAugmentationBuilder = inPatchLibrary
           ? newConstructor.hasPatchAnnotation
           : newConstructor.isAugmentation;
@@ -1434,12 +1374,12 @@
               noLength,
               newConstructor.fileUri);
         } else {
-          _originConstructorScope.addLocalMember(name, newConstructor);
-          for (ConstructorScope augmentationConstructorScope
-              in _augmentationConstructorScopes.values) {
+          _originConstructorNameSpace.addConstructor(name, newConstructor);
+          for (DeclarationNameSpace augmentationConstructorNameSpace
+              in _augmentationConstructorNameSpaces.values) {
             // Coverage-ignore-block(suite): Not run.
             _addConstructorToAugmentationScope(
-                augmentationConstructorScope, name, newConstructor);
+                augmentationConstructorNameSpace, name, newConstructor);
           }
         }
         if (inPatchLibrary &&
@@ -1455,21 +1395,20 @@
         }
       }
     });
-    _originConstructorScope._local
-        .forEach((String name, MemberBuilder originConstructor) {
-      _addConstructorToAugmentationScope(
-          constructorScope, name, originConstructor);
+    _originConstructorNameSpace
+        .forEachConstructor((String name, MemberBuilder originConstructor) {
+      _addConstructorToAugmentationScope(nameSpace, name, originConstructor);
     });
   }
 
   void _addConstructorToAugmentationScope(
-      ConstructorScope augmentationConstructorScope,
+      DeclarationNameSpace augmentationConstructorNameSpace,
       String name,
       MemberBuilder constructor) {
     Builder? augmentationConstructor =
-        augmentationConstructorScope.lookupLocalMember(name);
+        augmentationConstructorNameSpace.lookupConstructor(name);
     if (augmentationConstructor == null) {
-      augmentationConstructorScope.addLocalMember(name, constructor);
+      augmentationConstructorNameSpace.addConstructor(name, constructor);
     }
   }
 
@@ -1480,7 +1419,7 @@
         augmentations: null,
         setterAugmentations: null,
         inPatchLibrary: builder.libraryBuilder.isPatchLibrary);
-    _addAugmentationConstructorScope(builder.constructorScope,
+    _addAugmentationConstructorScope(builder.nameSpace,
         inPatchLibrary: builder.libraryBuilder.isPatchLibrary);
   }
 
diff --git a/pkg/front_end/lib/src/builder/declaration_builder.dart b/pkg/front_end/lib/src/builder/declaration_builder.dart
index df82de2..a64c210 100644
--- a/pkg/front_end/lib/src/builder/declaration_builder.dart
+++ b/pkg/front_end/lib/src/builder/declaration_builder.dart
@@ -7,7 +7,9 @@
 abstract class IDeclarationBuilder implements ITypeDeclarationBuilder {
   LookupScope get scope;
 
-  NameSpace get nameSpace;
+  DeclarationNameSpace get nameSpace;
+
+  ConstructorScope get constructorScope;
 
   LibraryBuilder get libraryBuilder;
 
@@ -42,8 +44,6 @@
   Builder? lookupLocalMember(String name,
       {bool setter = false, bool required = false});
 
-  ConstructorScope get constructorScope;
-
   List<DartType> buildAliasedTypeArguments(LibraryBuilder library,
       List<TypeBuilder>? arguments, ClassHierarchyBase? hierarchy);
 }
diff --git a/pkg/front_end/lib/src/dill/dill_class_builder.dart b/pkg/front_end/lib/src/dill/dill_class_builder.dart
index bbf02a2..0bfa0da 100644
--- a/pkg/front_end/lib/src/dill/dill_class_builder.dart
+++ b/pkg/front_end/lib/src/dill/dill_class_builder.dart
@@ -22,18 +22,17 @@
 import 'dill_member_builder.dart';
 
 mixin DillClassMemberAccessMixin implements ClassMemberAccess {
-  NameSpace get nameSpace;
-  ConstructorScope get constructorScope;
+  DeclarationNameSpace get nameSpace;
 
   @override
   // Coverage-ignore(suite): Not run.
   Iterator<T> fullConstructorIterator<T extends MemberBuilder>() =>
-      constructorScope.filteredIterator<T>(
+      nameSpace.filteredConstructorIterator<T>(
           includeAugmentations: true, includeDuplicates: false);
 
   @override
   NameIterator<T> fullConstructorNameIterator<T extends MemberBuilder>() =>
-      constructorScope.filteredNameIterator<T>(
+      nameSpace.filteredConstructorNameIterator<T>(
           includeAugmentations: true, includeDuplicates: false);
 
   @override
@@ -55,10 +54,9 @@
 
   late final LookupScope _scope;
 
-  final NameSpace _nameSpace;
+  final DeclarationNameSpace _nameSpace;
 
-  @override
-  final ConstructorScope constructorScope;
+  late final ConstructorScope _constructorScope;
 
   List<NominalVariableBuilder>? _typeVariables;
 
@@ -67,14 +65,14 @@
   List<TypeBuilder>? _interfaceBuilders;
 
   DillClassBuilder(this.cls, DillLibraryBuilder parent)
-      : _nameSpace = new NameSpaceImpl(),
-        constructorScope =
-            new ConstructorScope(cls.name, <String, MemberBuilder>{}),
+      : _nameSpace = new DeclarationNameSpaceImpl(),
         super(/*metadata builders*/ null, computeModifiers(cls), cls.name,
             parent, cls.fileOffset) {
     _scope = new NameSpaceLookupScope(
         _nameSpace, ScopeKind.declaration, "class ${cls.name}",
         parent: parent.scope);
+    _constructorScope =
+        new DeclarationNameSpaceConstructorScope(cls.name, _nameSpace);
   }
 
   @override
@@ -82,7 +80,10 @@
   LookupScope get scope => _scope;
 
   @override
-  NameSpace get nameSpace => _nameSpace;
+  DeclarationNameSpace get nameSpace => _nameSpace;
+
+  @override
+  ConstructorScope get constructorScope => _constructorScope;
 
   @override
   bool get isEnum => cls.isEnum;
@@ -154,12 +155,12 @@
     DillConstructorBuilder builder =
         new DillConstructorBuilder(constructor, constructorTearOff, this);
     String name = constructor.name.text;
-    constructorScope.addLocalMember(name, builder);
+    nameSpace.addConstructor(name, builder);
   }
 
   void addFactory(Procedure factory, Procedure? factoryTearOff) {
     String name = factory.name.text;
-    constructorScope.addLocalMember(
+    nameSpace.addConstructor(
         name, new DillFactoryBuilder(factory, factoryTearOff, this));
   }
 
diff --git a/pkg/front_end/lib/src/dill/dill_extension_builder.dart b/pkg/front_end/lib/src/dill/dill_extension_builder.dart
index 47577d9..4876282 100644
--- a/pkg/front_end/lib/src/dill/dill_extension_builder.dart
+++ b/pkg/front_end/lib/src/dill/dill_extension_builder.dart
@@ -20,22 +20,22 @@
 
   late final LookupScope _scope;
 
-  final NameSpace _nameSpace;
+  final DeclarationNameSpace _nameSpace;
 
-  @override
-  final ConstructorScope constructorScope;
+  late final ConstructorScope _constructorScope;
 
   List<NominalVariableBuilder>? _typeParameters;
   TypeBuilder? _onType;
 
   DillExtensionBuilder(this.extension, LibraryBuilder parent)
-      : _nameSpace = new NameSpaceImpl(),
-        constructorScope = new ConstructorScope(extension.name, const {}),
+      : _nameSpace = new DeclarationNameSpaceImpl(),
         super(/* metadata = */ null, 0, extension.name, parent,
             extension.fileOffset) {
     _scope = new NameSpaceLookupScope(
         _nameSpace, ScopeKind.declaration, "extension ${extension.name}",
         parent: parent.scope);
+    _constructorScope =
+        new DeclarationNameSpaceConstructorScope(extension.name, _nameSpace);
     for (ExtensionMemberDescriptor descriptor in extension.memberDescriptors) {
       Name name = descriptor.name;
       switch (descriptor.kind) {
@@ -93,7 +93,11 @@
   LookupScope get scope => _scope;
 
   @override
-  NameSpace get nameSpace => _nameSpace;
+  DeclarationNameSpace get nameSpace => _nameSpace;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  ConstructorScope get constructorScope => _constructorScope;
 
   @override
   List<NominalVariableBuilder>? get typeParameters {
diff --git a/pkg/front_end/lib/src/dill/dill_extension_type_declaration_builder.dart b/pkg/front_end/lib/src/dill/dill_extension_type_declaration_builder.dart
index 6fe9fea..f8dad24 100644
--- a/pkg/front_end/lib/src/dill/dill_extension_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/dill/dill_extension_type_declaration_builder.dart
@@ -7,7 +7,6 @@
 import '../base/name_space.dart';
 import '../base/scope.dart';
 import '../builder/declaration_builders.dart';
-import '../builder/member_builder.dart';
 import '../builder/type_builder.dart';
 import 'dill_builder_mixins.dart';
 import 'dill_class_builder.dart';
@@ -22,10 +21,9 @@
 
   late final LookupScope _scope;
 
-  final NameSpace _nameSpace;
+  final DeclarationNameSpace _nameSpace;
 
-  @override
-  final ConstructorScope constructorScope;
+  late final ConstructorScope _constructorScope;
 
   List<NominalVariableBuilder>? _typeParameters;
 
@@ -35,9 +33,7 @@
 
   DillExtensionTypeDeclarationBuilder(
       this._extensionTypeDeclaration, DillLibraryBuilder parent)
-      : _nameSpace = new NameSpaceImpl(),
-        constructorScope = new ConstructorScope(
-            _extensionTypeDeclaration.name, <String, MemberBuilder>{}),
+      : _nameSpace = new DeclarationNameSpaceImpl(),
         super(
             /*metadata builders*/ null,
             /* modifiers*/ 0,
@@ -47,6 +43,8 @@
     _scope = new NameSpaceLookupScope(_nameSpace, ScopeKind.declaration,
         "extension type ${_extensionTypeDeclaration.name}",
         parent: parent.scope);
+    _constructorScope = new DeclarationNameSpaceConstructorScope(
+        _extensionTypeDeclaration.name, _nameSpace);
     for (Procedure procedure in _extensionTypeDeclaration.procedures) {
       String name = procedure.name.text;
       switch (procedure.kind) {
@@ -127,7 +125,7 @@
         case ExtensionTypeMemberKind.Constructor:
           Procedure procedure = descriptor.memberReference.asProcedure;
           Procedure? tearOff = descriptor.tearOffReference?.asProcedure;
-          constructorScope.addLocalMember(
+          nameSpace.addConstructor(
               name.text,
               new DillExtensionTypeConstructorBuilder(
                   procedure, tearOff, descriptor, this));
@@ -136,7 +134,7 @@
         case ExtensionTypeMemberKind.RedirectingFactory:
           Procedure procedure = descriptor.memberReference.asProcedure;
           Procedure? tearOff = descriptor.tearOffReference?.asProcedure;
-          constructorScope.addLocalMember(
+          nameSpace.addConstructor(
               name.text,
               new DillExtensionTypeFactoryBuilder(
                   procedure, tearOff, descriptor, this));
@@ -153,7 +151,10 @@
   LookupScope get scope => _scope;
 
   @override
-  NameSpace get nameSpace => _nameSpace;
+  DeclarationNameSpace get nameSpace => _nameSpace;
+
+  @override
+  ConstructorScope get constructorScope => _constructorScope;
 
   @override
   DartType get declaredRepresentationType =>
diff --git a/pkg/front_end/lib/src/kernel/collections.dart b/pkg/front_end/lib/src/kernel/collections.dart
index bcbf67c..660ee0a 100644
--- a/pkg/front_end/lib/src/kernel/collections.dart
+++ b/pkg/front_end/lib/src/kernel/collections.dart
@@ -264,10 +264,19 @@
 }
 
 /// A 'for' element in a list or set literal.
-class ForElement extends ControlFlowElement with ControlFlowElementMixin {
+class ForElement extends ControlFlowElement
+    with ControlFlowElementMixin
+    implements ForElementBase {
+  @override
   final List<VariableDeclaration> variables; // May be empty, but not null.
+
+  @override
   Expression? condition; // May be null.
+
+  @override
   final List<Expression> updates; // May be empty, but not null.
+
+  @override
   Expression body;
 
   ForElement(this.variables, this.condition, this.updates, this.body) {
@@ -555,9 +564,19 @@
   }
 }
 
+abstract interface class ForElementBase implements AuxiliaryExpression {
+  List<VariableDeclaration> get variables;
+
+  abstract Expression? condition;
+
+  List<Expression> get updates;
+
+  abstract Expression body;
+}
+
 class PatternForElement extends ControlFlowElementImpl
     with ControlFlowElementMixin
-    implements ForElement {
+    implements ForElementBase {
   PatternVariableDeclaration patternVariableDeclaration;
   List<VariableDeclaration> intermediateVariables;
 
@@ -1258,6 +1277,8 @@
                 isConvertibleToMapEntry(element.otherwise!));
       case ForElement():
         return isConvertibleToMapEntry(element.body);
+      case PatternForElement():
+        return isConvertibleToMapEntry(element.body);
       case ForInElement():
         return isConvertibleToMapEntry(element.body);
     }
diff --git a/pkg/front_end/lib/src/source/class_declaration.dart b/pkg/front_end/lib/src/source/class_declaration.dart
index 0489aef..9e565f4 100644
--- a/pkg/front_end/lib/src/source/class_declaration.dart
+++ b/pkg/front_end/lib/src/source/class_declaration.dart
@@ -98,7 +98,7 @@
     }
     int count = constructorReferences!.length;
     if (count != 0) {
-      Iterator<MemberBuilder> iterator = constructorScope.filteredIterator(
+      Iterator<MemberBuilder> iterator = nameSpace.filteredConstructorIterator(
           parent: this, includeDuplicates: true, includeAugmentations: true);
       while (iterator.moveNext()) {
         MemberBuilder declaration = iterator.current;
@@ -359,7 +359,7 @@
   ClassDeclarationConstructorIterator._(
       D classDeclaration, this.augmentationBuilders,
       {required this.includeDuplicates})
-      : _iterator = classDeclaration.constructorScope.filteredIterator<T>(
+      : _iterator = classDeclaration.nameSpace.filteredConstructorIterator<T>(
             parent: classDeclaration,
             includeDuplicates: includeDuplicates,
             includeAugmentations: false);
@@ -373,8 +373,8 @@
     }
     if (augmentationBuilders != null && augmentationBuilders!.moveNext()) {
       D augmentationClassDeclaration = augmentationBuilders!.current;
-      _iterator = augmentationClassDeclaration.constructorScope
-          .filteredIterator<T>(
+      _iterator = augmentationClassDeclaration.nameSpace
+          .filteredConstructorIterator<T>(
               parent: augmentationClassDeclaration,
               includeDuplicates: includeDuplicates,
               includeAugmentations: false);
@@ -411,7 +411,7 @@
   ClassDeclarationConstructorNameIterator._(
       D classBuilder, this.augmentationBuilders,
       {required this.includeDuplicates})
-      : _iterator = classBuilder.constructorScope.filteredNameIterator<T>(
+      : _iterator = classBuilder.nameSpace.filteredConstructorNameIterator<T>(
             parent: classBuilder,
             includeDuplicates: includeDuplicates,
             includeAugmentations: false);
@@ -425,8 +425,8 @@
     }
     if (augmentationBuilders != null && augmentationBuilders!.moveNext()) {
       D augmentationClassDeclaration = augmentationBuilders!.current;
-      _iterator = augmentationClassDeclaration.constructorScope
-          .filteredNameIterator<T>(
+      _iterator = augmentationClassDeclaration.nameSpace
+          .filteredConstructorNameIterator<T>(
               parent: augmentationClassDeclaration,
               includeDuplicates: includeDuplicates,
               includeAugmentations: false);
diff --git a/pkg/front_end/lib/src/source/source_builder_factory.dart b/pkg/front_end/lib/src/source/source_builder_factory.dart
index 0ca16da..ef804b7 100644
--- a/pkg/front_end/lib/src/source/source_builder_factory.dart
+++ b/pkg/front_end/lib/src/source/source_builder_factory.dart
@@ -512,8 +512,6 @@
     TypeParameterScopeBuilder declaration =
         endNestedDeclaration(TypeParameterScopeKind.enumDeclaration, name)
           ..resolveNamedTypes(typeVariables, _problemReporting);
-    Map<String, MemberBuilder> constructors = declaration.constructors!;
-
     Map<String, NominalVariableBuilder>? typeVariablesByName =
         _checkTypeVariables(typeVariables,
             ownerName: name, allowNameConflict: false);
@@ -521,8 +519,8 @@
     LookupScope typeParameterScope = typeVariablesByName != null
         ? new TypeParameterScope(_scope, typeVariablesByName)
         : _scope;
-    NameSpaceBuilder nameSpaceBuilder =
-        declaration.toNameSpaceBuilder(typeVariablesByName);
+    DeclarationNameSpaceBuilder nameSpaceBuilder =
+        declaration.toDeclarationNameSpaceBuilder(typeVariablesByName);
     SourceEnumBuilder enumBuilder = new SourceEnumBuilder(
         metadata,
         name,
@@ -553,8 +551,7 @@
         charEndOffset,
         referencesFromIndexedClass,
         typeParameterScope,
-        nameSpaceBuilder,
-        new ConstructorScope(name, constructors));
+        nameSpaceBuilder);
     _constructorReferences.clear();
 
     addBuilder(name, enumBuilder, charOffset,
@@ -639,7 +636,6 @@
         endNestedDeclaration(kind, className)
           ..resolveNamedTypes(typeVariables, _problemReporting);
     assert(declaration.parent == _libraryTypeParameterScopeBuilder);
-    Map<String, MemberBuilder> constructors = declaration.constructors!;
 
     Map<String, NominalVariableBuilder>? typeVariablesByName =
         _checkTypeVariables(typeVariables,
@@ -648,13 +644,9 @@
     LookupScope typeParameterScope = typeVariablesByName != null
         ? new TypeParameterScope(_scope, typeVariablesByName)
         : _scope;
-    NameSpaceBuilder nameSpace =
-        declaration.toNameSpaceBuilder(typeVariablesByName);
+    DeclarationNameSpaceBuilder nameSpaceBuilder =
+        declaration.toDeclarationNameSpaceBuilder(typeVariablesByName);
 
-    // When looking up a constructor, we don't consider type variables or the
-    // library scope.
-    ConstructorScope constructorScope =
-        new ConstructorScope(className, constructors);
     bool isMixinDeclaration = false;
     if (modifiers & mixinDeclarationMask != 0) {
       isMixinDeclaration = true;
@@ -684,8 +676,7 @@
         // here.
         null,
         typeParameterScope,
-        nameSpace,
-        constructorScope,
+        nameSpaceBuilder,
         _parent,
         new List<ConstructorReferenceBuilder>.of(_constructorReferences),
         startOffset,
@@ -1017,7 +1008,8 @@
 
         LookupScope typeParameterScope =
             TypeParameterScope.fromList(_scope, typeVariables);
-        NameSpaceBuilder nameSpaceBuilder = new NameSpaceBuilder.empty();
+        DeclarationNameSpaceBuilder nameSpaceBuilder =
+            new DeclarationNameSpaceBuilder.empty();
         SourceClassBuilder application = new SourceClassBuilder(
             isNamedMixinApplication ? metadata : null,
             isNamedMixinApplication
@@ -1034,7 +1026,6 @@
             null, // No `on` clause types.
             typeParameterScope,
             nameSpaceBuilder,
-            new ConstructorScope(fullname, <String, MemberBuilder>{}),
             _parent,
             <ConstructorReferenceBuilder>[],
             computedStartCharOffset,
@@ -1108,8 +1099,8 @@
     LookupScope typeParameterScope = typeVariablesByName != null
         ? new TypeParameterScope(_scope, typeVariablesByName)
         : _scope;
-    NameSpaceBuilder extensionNameSpace =
-        declaration.toNameSpaceBuilder(typeVariablesByName);
+    DeclarationNameSpaceBuilder extensionNameSpace =
+        declaration.toDeclarationNameSpaceBuilder(typeVariablesByName);
 
     Extension? referenceFrom;
     ExtensionName extensionName = declaration.extensionName!;
@@ -1157,7 +1148,6 @@
         TypeParameterScopeKind.extensionTypeDeclaration, name)
       ..resolveNamedTypes(typeVariables, _problemReporting);
     assert(declaration.parent == _libraryTypeParameterScopeBuilder);
-    Map<String, MemberBuilder> constructors = declaration.constructors!;
     Map<String, NominalVariableBuilder>? typeVariablesByName =
         _checkTypeVariables(typeVariables,
             ownerName: name, allowNameConflict: false);
@@ -1165,10 +1155,8 @@
     LookupScope typeParameterScope = typeVariablesByName != null
         ? new TypeParameterScope(_scope, typeVariablesByName)
         : _scope;
-    NameSpaceBuilder nameSpaceBuilder =
-        declaration.toNameSpaceBuilder(typeVariablesByName);
-    ConstructorScope constructorScope =
-        new ConstructorScope(name, constructors);
+    DeclarationNameSpaceBuilder nameSpaceBuilder =
+        declaration.toDeclarationNameSpaceBuilder(typeVariablesByName);
 
     IndexedContainer? indexedContainer =
         indexedLibrary?.lookupIndexedExtensionTypeDeclaration(name);
@@ -1190,7 +1178,6 @@
             interfaces,
             typeParameterScope,
             nameSpaceBuilder,
-            constructorScope,
             _parent,
             new List<ConstructorReferenceBuilder>.of(_constructorReferences),
             startOffset,
diff --git a/pkg/front_end/lib/src/source/source_builder_mixins.dart b/pkg/front_end/lib/src/source/source_builder_mixins.dart
index 3ed7c07..61ca4ad 100644
--- a/pkg/front_end/lib/src/source/source_builder_mixins.dart
+++ b/pkg/front_end/lib/src/source/source_builder_mixins.dart
@@ -100,7 +100,7 @@
     }
 
     nameSpace.unfilteredNameIterator.forEach(buildBuilders);
-    constructorScope.unfilteredNameIterator.forEach(buildBuilders);
+    nameSpace.unfilteredConstructorNameIterator.forEach(buildBuilders);
   }
 
   int buildBodyNodes({required bool addMembersToLibrary}) {
@@ -108,7 +108,7 @@
     Iterator<SourceMemberBuilder> iterator = nameSpace
         .filteredIterator<SourceMemberBuilder>(
             parent: this, includeDuplicates: false, includeAugmentations: true)
-        .join(constructorScope.filteredIterator<SourceMemberBuilder>(
+        .join(nameSpace.filteredConstructorIterator<SourceMemberBuilder>(
             parent: this,
             includeDuplicates: false,
             includeAugmentations: true));
@@ -297,7 +297,7 @@
   /// in this type declaration.
   void checkConstructorStaticConflict() {
     NameIterator<MemberBuilder> iterator =
-        constructorScope.filteredNameIterator(
+        nameSpace.filteredConstructorNameIterator(
             includeDuplicates: false, includeAugmentations: true);
     while (iterator.moveNext()) {
       String name = iterator.name;
@@ -324,7 +324,7 @@
     }
 
     nameSpace.forEachLocalSetter((String name, Builder setter) {
-      Builder? constructor = constructorScope.lookupLocalMember(name);
+      Builder? constructor = nameSpace.lookupConstructor(name);
       if (constructor == null || !setter.isStatic) return;
       // Coverage-ignore-block(suite): Not run.
       addProblem(templateConflictsWithConstructor.withArguments(name),
diff --git a/pkg/front_end/lib/src/source/source_class_builder.dart b/pkg/front_end/lib/src/source/source_class_builder.dart
index c073e9d..51fc19f 100644
--- a/pkg/front_end/lib/src/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/source/source_class_builder.dart
@@ -94,14 +94,13 @@
         SourceDeclarationBuilder {
   final Class actualCls;
 
-  final NameSpaceBuilder nameSpaceBuilder;
+  final DeclarationNameSpaceBuilder nameSpaceBuilder;
 
   late final LookupScope _scope;
 
-  late final NameSpace _nameSpace;
+  late final DeclarationNameSpace _nameSpace;
 
-  @override
-  final ConstructorScope constructorScope;
+  late final ConstructorScope _constructorScope;
 
   @override
   List<NominalVariableBuilder>? typeVariables;
@@ -180,7 +179,6 @@
       this.onTypes,
       this.typeParameterScope,
       this.nameSpaceBuilder,
-      this.constructorScope,
       SourceLibraryBuilder parent,
       this.constructorReferences,
       int startCharOffset,
@@ -208,14 +206,19 @@
   LookupScope get scope => _scope;
 
   @override
-  NameSpace get nameSpace => _nameSpace;
+  DeclarationNameSpace get nameSpace => _nameSpace;
+
+  @override
+  ConstructorScope get constructorScope => _constructorScope;
 
   @override
   void buildScopes(LibraryBuilder coreLibrary) {
     _nameSpace = nameSpaceBuilder.buildNameSpace(this);
     _scope = new NameSpaceLookupScope(
-        nameSpace, ScopeKind.declaration, "class $name",
+        _nameSpace, ScopeKind.declaration, "class $name",
         parent: typeParameterScope);
+    _constructorScope =
+        new DeclarationNameSpaceConstructorScope(name, _nameSpace);
   }
 
   MergedClassMemberScope get mergedScope => _mergedScope ??= isAugmenting
@@ -279,7 +282,7 @@
     }
 
     nameSpace.unfilteredIterator.forEach(buildBuilders);
-    constructorScope.unfilteredIterator.forEach(buildBuilders);
+    nameSpace.unfilteredConstructorIterator.forEach(buildBuilders);
     if (supertypeBuilder != null) {
       supertypeBuilder = _checkSupertype(supertypeBuilder!);
     }
@@ -414,8 +417,8 @@
       }
     }
 
-    constructorScope
-        .filteredIterator(
+    nameSpace
+        .filteredConstructorIterator(
             parent: this, includeDuplicates: false, includeAugmentations: true)
         .forEach(build);
     nameSpace
@@ -468,7 +471,7 @@
       name = new Name("", name.library);
     }
 
-    Builder? builder = constructorScope.lookupLocalMember(name.text);
+    Builder? builder = nameSpace.lookupConstructor(name.text);
     if (builder is SourceConstructorBuilder) {
       return builder;
     }
@@ -980,8 +983,9 @@
   }
 
   void checkRedirectingFactories(TypeEnvironment typeEnvironment) {
-    Iterator<SourceFactoryBuilder> iterator = constructorScope.filteredIterator(
-        parent: this, includeDuplicates: true, includeAugmentations: true);
+    Iterator<SourceFactoryBuilder> iterator =
+        nameSpace.filteredConstructorIterator(
+            parent: this, includeDuplicates: true, includeAugmentations: true);
     while (iterator.moveNext()) {
       iterator.current.checkRedirectingFactories(typeEnvironment);
     }
@@ -1156,8 +1160,8 @@
   void addSyntheticConstructor(
       SyntheticSourceConstructorBuilder constructorBuilder) {
     String name = constructorBuilder.name;
-    constructorBuilder.next = constructorScope.lookupLocalMember(name);
-    constructorScope.addLocalMember(name, constructorBuilder);
+    constructorBuilder.next = nameSpace.lookupConstructor(name);
+    nameSpace.addConstructor(name, constructorBuilder);
     // Synthetic constructors are created after the component has been built
     // so we need to add the constructor to the class.
     cls.addConstructor(constructorBuilder.invokeTarget);
@@ -1196,8 +1200,8 @@
         .filteredIterator(
             parent: this, includeDuplicates: true, includeAugmentations: true)
         .forEach(buildMembers);
-    constructorScope
-        .filteredIterator(
+    nameSpace
+        .filteredConstructorIterator(
             parent: this, includeDuplicates: true, includeAugmentations: true)
         .forEach(buildMembers);
     return count;
diff --git a/pkg/front_end/lib/src/source/source_compilation_unit.dart b/pkg/front_end/lib/src/source/source_compilation_unit.dart
index b3af465..9138c83 100644
--- a/pkg/front_end/lib/src/source/source_compilation_unit.dart
+++ b/pkg/front_end/lib/src/source/source_compilation_unit.dart
@@ -967,8 +967,8 @@
         count += computeDefaultTypesForVariables(declaration.typeVariables,
             inErrorRecovery: issues.isNotEmpty);
 
-        Iterator<SourceMemberBuilder> iterator = declaration.constructorScope
-            .filteredIterator<SourceMemberBuilder>(
+        Iterator<SourceMemberBuilder> iterator = declaration.nameSpace
+            .filteredConstructorIterator<SourceMemberBuilder>(
                 includeDuplicates: false, includeAugmentations: true);
         while (iterator.moveNext()) {
           processSourceMemberBuilder(iterator.current,
@@ -1019,8 +1019,8 @@
         count += computeDefaultTypesForVariables(declaration.typeParameters,
             inErrorRecovery: issues.isNotEmpty);
 
-        Iterator<SourceMemberBuilder> iterator = declaration.constructorScope
-            .filteredIterator<SourceMemberBuilder>(
+        Iterator<SourceMemberBuilder> iterator = declaration.nameSpace
+            .filteredConstructorIterator<SourceMemberBuilder>(
                 includeDuplicates: false, includeAugmentations: true);
         while (iterator.moveNext()) {
           processSourceMemberBuilder(iterator.current,
diff --git a/pkg/front_end/lib/src/source/source_enum_builder.dart b/pkg/front_end/lib/src/source/source_enum_builder.dart
index c2cf43a..1d08ca1 100644
--- a/pkg/front_end/lib/src/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/source/source_enum_builder.dart
@@ -89,8 +89,7 @@
       TypeBuilder supertypeBuilder,
       List<TypeBuilder>? interfaceBuilders,
       LookupScope typeParameterScope,
-      NameSpaceBuilder nameSpaceBuilder,
-      ConstructorScope constructors,
+      DeclarationNameSpaceBuilder nameSpaceBuilder,
       this.enumConstantInfos,
       SourceLibraryBuilder parent,
       List<ConstructorReferenceBuilder> constructorReferences,
@@ -108,7 +107,6 @@
             /* onTypes = */ null,
             typeParameterScope,
             nameSpaceBuilder,
-            constructors,
             parent,
             constructorReferences,
             startCharOffset,
@@ -130,8 +128,7 @@
       int charEndOffset,
       IndexedClass? referencesFromIndexed,
       LookupScope typeParameterScope,
-      NameSpaceBuilder nameSpaceBuilder,
-      ConstructorScope constructorScope) {
+      DeclarationNameSpaceBuilder nameSpaceBuilder) {
     final int startCharOffsetComputed =
         metadata == null ? startCharOffset : metadata.first.charOffset;
     // Coverage-ignore(suite): Not run.
@@ -146,7 +143,6 @@
         interfaceBuilders,
         typeParameterScope,
         nameSpaceBuilder,
-        constructorScope,
         enumConstantInfos,
         libraryBuilder,
         constructorReferences,
@@ -161,6 +157,49 @@
   void buildScopes(LibraryBuilder coreLibrary) {
     _createSynthesizedMembers(coreLibrary);
     super.buildScopes(coreLibrary);
+
+    Iterator<MemberBuilder> iterator =
+        nameSpace.filteredConstructorNameIterator(
+            includeDuplicates: false, includeAugmentations: true);
+    while (iterator.moveNext()) {
+      MemberBuilder member = iterator.current;
+      if (member is DeclaredSourceConstructorBuilder) {
+        member.ensureGrowableFormals();
+        member.formals!.insert(
+            0,
+            new FormalParameterBuilder(
+                FormalParameterKind.requiredPositional,
+                /* modifiers = */ 0,
+                stringType,
+                "#name",
+                libraryBuilder,
+                charOffset,
+                fileUri: fileUri,
+                hasImmediatelyDeclaredInitializer: false));
+        member.formals!.insert(
+            0,
+            new FormalParameterBuilder(
+                FormalParameterKind.requiredPositional,
+                /* modifiers = */ 0,
+                intType,
+                "#index",
+                libraryBuilder,
+                charOffset,
+                fileUri: fileUri,
+                hasImmediatelyDeclaredInitializer: false));
+      }
+    }
+
+    Iterator<MemberBuilder> constructorIterator =
+        nameSpace.filteredConstructorIterator(
+            includeDuplicates: false, includeAugmentations: true);
+    while (constructorIterator.moveNext()) {
+      MemberBuilder constructorBuilder = constructorIterator.current;
+      if (!constructorBuilder.isFactory && !constructorBuilder.isConst) {
+        libraryBuilder.addProblem(messageEnumNonConstConstructor,
+            constructorBuilder.charOffset, noLength, fileUri);
+      }
+    }
   }
 
   void _createSynthesizedMembers(LibraryBuilder coreLibrary) {
@@ -298,16 +337,12 @@
     // The default constructor is added if no generative or unnamed factory
     // constructors are declared.
     bool needsSynthesizedDefaultConstructor = true;
-    Iterator<MemberBuilder> iterator = constructorScope.filteredIterator(
-        includeDuplicates: false, includeAugmentations: true);
-    while (iterator.moveNext()) {
-      MemberBuilder constructorBuilder = iterator.current;
+    for (MemberBuilder constructorBuilder in nameSpaceBuilder.constructors) {
       if (!constructorBuilder.isFactory || constructorBuilder.name == "") {
         needsSynthesizedDefaultConstructor = false;
         break;
       }
     }
-
     if (needsSynthesizedDefaultConstructor) {
       synthesizedDefaultConstructorBuilder =
           new DeclaredSourceConstructorBuilder(
@@ -315,28 +350,9 @@
               constMask,
               /* returnType = */ libraryBuilder.loader.inferableTypes
                   .addInferableType(),
-              "",
+              /* name = */ "",
               /* typeParameters = */ null,
-              <FormalParameterBuilder>[
-                new FormalParameterBuilder(
-                    FormalParameterKind.requiredPositional,
-                    0,
-                    intType,
-                    "#index",
-                    libraryBuilder,
-                    charOffset,
-                    fileUri: fileUri,
-                    hasImmediatelyDeclaredInitializer: false),
-                new FormalParameterBuilder(
-                    FormalParameterKind.requiredPositional,
-                    0,
-                    stringType,
-                    "#name",
-                    libraryBuilder,
-                    charOffset,
-                    fileUri: fileUri,
-                    hasImmediatelyDeclaredInitializer: false)
-              ],
+              /* formals = */ [],
               libraryBuilder,
               fileUri,
               charOffset,
@@ -354,39 +370,8 @@
               isSynthetic: true);
       synthesizedDefaultConstructorBuilder!
           .registerInitializedField(valuesBuilder);
-      constructorScope.addLocalMember(
+      nameSpaceBuilder.addConstructor(
           "", synthesizedDefaultConstructorBuilder!);
-    } else {
-      Iterator<MemberBuilder> iterator = constructorScope.filteredNameIterator(
-          includeDuplicates: false, includeAugmentations: true);
-      while (iterator.moveNext()) {
-        MemberBuilder member = iterator.current;
-        if (member is DeclaredSourceConstructorBuilder) {
-          member.ensureGrowableFormals();
-          member.formals!.insert(
-              0,
-              new FormalParameterBuilder(
-                  FormalParameterKind.requiredPositional,
-                  /* modifiers = */ 0,
-                  stringType,
-                  "#name",
-                  libraryBuilder,
-                  charOffset,
-                  fileUri: fileUri,
-                  hasImmediatelyDeclaredInitializer: false));
-          member.formals!.insert(
-              0,
-              new FormalParameterBuilder(
-                  FormalParameterKind.requiredPositional,
-                  /* modifiers = */ 0,
-                  intType,
-                  "#index",
-                  libraryBuilder,
-                  charOffset,
-                  fileUri: fileUri,
-                  hasImmediatelyDeclaredInitializer: false));
-        }
-      }
     }
 
     ProcedureBuilder toStringBuilder = new SourceProcedureBuilder(
@@ -497,36 +482,8 @@
       }
     }
 
-    void setParent(MemberBuilder? builder) {
-      while (builder != null) {
-        builder.parent = this;
-        builder = builder.next as MemberBuilder?;
-      }
-    }
-
-    Map<String, NominalVariableBuilder>? typeVariablesByName;
-    if (typeVariables != null) {
-      typeVariablesByName = {};
-      for (NominalVariableBuilder typeVariable in typeVariables!) {
-        typeVariablesByName[typeVariable.name] = typeVariable;
-      }
-    }
-
-    constructorScope
-        .filteredIterator(includeDuplicates: false, includeAugmentations: true)
-        .forEach(setParent);
     selfType.bind(libraryBuilder, this);
 
-    Iterator<MemberBuilder> constructorIterator = constructorScope
-        .filteredIterator(includeDuplicates: false, includeAugmentations: true);
-    while (constructorIterator.moveNext()) {
-      MemberBuilder constructorBuilder = constructorIterator.current;
-      if (!constructorBuilder.isFactory && !constructorBuilder.isConst) {
-        libraryBuilder.addProblem(messageEnumNonConstConstructor,
-            constructorBuilder.charOffset, noLength, fileUri);
-      }
-    }
-
     if (name == "values") {
       libraryBuilder.addProblem(
           messageEnumWithNameValues, this.charOffset, name.length, fileUri);
@@ -656,7 +613,7 @@
         enumConstantInfo.charOffset;
     constructorName = constructorName == "new" ? "" : constructorName;
     MemberBuilder? constructorBuilder =
-        constructorScope.lookupLocalMember(constructorName);
+        nameSpace.lookupConstructor(constructorName);
 
     ArgumentsImpl arguments;
     List<Expression> enumSyntheticArguments = <Expression>[
diff --git a/pkg/front_end/lib/src/source/source_extension_builder.dart b/pkg/front_end/lib/src/source/source_extension_builder.dart
index 8f35089..7431451 100644
--- a/pkg/front_end/lib/src/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/source/source_extension_builder.dart
@@ -34,14 +34,13 @@
 
   MergedClassMemberScope? _mergedScope;
 
-  final NameSpaceBuilder _nameSpaceBuilder;
+  final DeclarationNameSpaceBuilder _nameSpaceBuilder;
 
   late final LookupScope _scope;
 
-  late final NameSpace _nameSpace;
+  late final DeclarationNameSpace _nameSpace;
 
-  @override
-  final ConstructorScope constructorScope;
+  late final ConstructorScope _constructorScope;
 
   @override
   final List<NominalVariableBuilder>? typeParameters;
@@ -75,7 +74,6 @@
             reference: referenceFrom?.reference)
           ..isUnnamedExtension = extensionName.isUnnamedExtension
           ..fileOffset = nameOffset,
-        constructorScope = new ConstructorScope(extensionName.name, const {}),
         super(metadata, modifiers, extensionName.name, parent, nameOffset) {
     extensionName.attachExtension(_extension);
   }
@@ -84,14 +82,21 @@
   LookupScope get scope => _scope;
 
   @override
-  NameSpace get nameSpace => _nameSpace;
+  DeclarationNameSpace get nameSpace => _nameSpace;
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  ConstructorScope get constructorScope => _constructorScope;
 
   @override
   void buildScopes(LibraryBuilder coreLibrary) {
-    _nameSpace = _nameSpaceBuilder.buildNameSpace(this);
+    _nameSpace =
+        _nameSpaceBuilder.buildNameSpace(this, includeConstructors: false);
     _scope = new NameSpaceLookupScope(
-        nameSpace, ScopeKind.declaration, "extension ${extensionName.name}",
+        _nameSpace, ScopeKind.declaration, "extension ${extensionName.name}",
         parent: typeParameterScope);
+    _constructorScope =
+        new DeclarationNameSpaceConstructorScope(name, _nameSpace);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
index d892e59..6128ff7 100644
--- a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
@@ -56,14 +56,13 @@
 
   MergedClassMemberScope? _mergedScope;
 
-  final NameSpaceBuilder _nameSpaceBuilder;
+  final DeclarationNameSpaceBuilder _nameSpaceBuilder;
 
   late final LookupScope _scope;
 
-  late final NameSpace _nameSpace;
+  late final DeclarationNameSpace _nameSpace;
 
-  @override
-  final ConstructorScope constructorScope;
+  late final ConstructorScope _constructorScope;
 
   @override
   final List<NominalVariableBuilder>? typeParameters;
@@ -86,7 +85,6 @@
       this.interfaceBuilders,
       this.typeParameterScope,
       this._nameSpaceBuilder,
-      this.constructorScope,
       SourceLibraryBuilder parent,
       this.constructorReferences,
       int startOffset,
@@ -107,14 +105,19 @@
   LookupScope get scope => _scope;
 
   @override
-  NameSpace get nameSpace => _nameSpace;
+  DeclarationNameSpace get nameSpace => _nameSpace;
+
+  @override
+  ConstructorScope get constructorScope => _constructorScope;
 
   @override
   void buildScopes(LibraryBuilder coreLibrary) {
     _nameSpace = _nameSpaceBuilder.buildNameSpace(this);
     _scope = new NameSpaceLookupScope(
-        nameSpace, ScopeKind.declaration, "extension type $name",
+        _nameSpace, ScopeKind.declaration, "extension type $name",
         parent: typeParameterScope);
+    _constructorScope =
+        new DeclarationNameSpaceConstructorScope(name, _nameSpace);
   }
 
   @override
@@ -585,7 +588,7 @@
 
   void checkRedirectingFactories(TypeEnvironment typeEnvironment) {
     Iterator<SourceFactoryBuilder> iterator =
-        constructorScope.filteredIterator<SourceFactoryBuilder>(
+        nameSpace.filteredConstructorIterator<SourceFactoryBuilder>(
             parent: this, includeDuplicates: true, includeAugmentations: true);
     while (iterator.moveNext()) {
       iterator.current.checkRedirectingFactories(typeEnvironment);
@@ -597,8 +600,9 @@
       List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
     super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
 
-    Iterator<SourceMemberBuilder> iterator = constructorScope.filteredIterator(
-        parent: this, includeDuplicates: false, includeAugmentations: true);
+    Iterator<SourceMemberBuilder> iterator =
+        nameSpace.filteredConstructorIterator(
+            parent: this, includeDuplicates: false, includeAugmentations: true);
     while (iterator.moveNext()) {
       iterator.current
           .buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners);
@@ -741,7 +745,7 @@
       name = new Name("", name.library);
     }
 
-    Builder? builder = constructorScope.lookupLocalMember(name.text);
+    Builder? builder = nameSpace.lookupConstructor(name.text);
     if (builder is SourceExtensionTypeConstructorBuilder) {
       return builder;
     }
diff --git a/pkg/front_end/lib/src/source/source_loader.dart b/pkg/front_end/lib/src/source/source_loader.dart
index cdaee95..89d9f3d 100644
--- a/pkg/front_end/lib/src/source/source_loader.dart
+++ b/pkg/front_end/lib/src/source/source_loader.dart
@@ -1736,8 +1736,8 @@
             Map<String, List<String>>? constructorMap;
             for (ClassBuilder macroClass in macroClasses) {
               List<String> constructors = [];
-              NameIterator<MemberBuilder> iterator = macroClass.constructorScope
-                  .filteredNameIterator(
+              NameIterator<MemberBuilder> iterator = macroClass.nameSpace
+                  .filteredConstructorNameIterator(
                       includeDuplicates: false, includeAugmentations: true);
               while (iterator.moveNext()) {
                 constructors.add(iterator.name);
@@ -2087,8 +2087,9 @@
 
   void _checkConstructorsForMixin(
       SourceClassBuilder cls, ClassBuilder builder) {
-    Iterator<MemberBuilder> iterator = builder.constructorScope
-        .filteredIterator(includeDuplicates: false, includeAugmentations: true);
+    Iterator<MemberBuilder> iterator = builder.nameSpace
+        .filteredConstructorIterator(
+            includeDuplicates: false, includeAugmentations: true);
     while (iterator.moveNext()) {
       MemberBuilder constructor = iterator.current;
       if (constructor.isConstructor && !constructor.isSynthetic) {
diff --git a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
index 59fe74d..49a2820 100644
--- a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
+++ b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
@@ -400,9 +400,9 @@
         getables: members, setables: setters, extensions: extensions);
   }
 
-  NameSpaceBuilder toNameSpaceBuilder(
+  DeclarationNameSpaceBuilder toDeclarationNameSpaceBuilder(
       Map<String, NominalVariableBuilder>? typeVariables) {
-    return new NameSpaceBuilder._(
+    return new DeclarationNameSpaceBuilder._(
         members, setters, constructors, extensions, typeVariables);
   }
 
@@ -410,22 +410,22 @@
   String toString() => 'DeclarationBuilder(${hashCode}:kind=$kind,name=$name)';
 }
 
-class NameSpaceBuilder {
+class DeclarationNameSpaceBuilder {
   final Map<String, Builder>? _getables;
   final Map<String, MemberBuilder>? _setables;
   final Map<String, MemberBuilder>? _constructors;
   final Set<ExtensionBuilder>? _extensions;
   final Map<String, NominalVariableBuilder>? _typeVariables;
 
-  NameSpaceBuilder.empty()
+  DeclarationNameSpaceBuilder.empty()
       : _getables = null,
         _setables = null,
         _constructors = null,
         _extensions = null,
         _typeVariables = null;
 
-  NameSpaceBuilder._(this._getables, this._setables, this._constructors,
-      this._extensions, this._typeVariables);
+  DeclarationNameSpaceBuilder._(this._getables, this._setables,
+      this._constructors, this._extensions, this._typeVariables);
 
   void addLocalMember(String name, MemberBuilder builder,
       {required bool setter}) {
@@ -444,7 +444,16 @@
         : _getables)![name] as MemberBuilder?;
   }
 
-  NameSpace buildNameSpace(IDeclarationBuilder parent) {
+  void addConstructor(String name, MemberBuilder builder) {
+    _constructors![name] = builder;
+  }
+
+  Iterable<MemberBuilder> get constructors =>
+      _constructors?.values ?? // Coverage-ignore(suite): Not run.
+      [];
+
+  DeclarationNameSpace buildNameSpace(IDeclarationBuilder parent,
+      {bool includeConstructors = true}) {
     void setParent(MemberBuilder? member) {
       while (member != null) {
         member.parent = parent;
@@ -473,7 +482,13 @@
     _setables?.forEach(setParentAndCheckConflicts);
     _constructors?.forEach(setParentAndCheckConflicts);
 
-    return new NameSpaceImpl(
-        getables: _getables, setables: _setables, extensions: _extensions);
+    return new DeclarationNameSpaceImpl(
+        getables: _getables,
+        setables: _setables,
+        extensions: _extensions,
+        // TODO(johnniwinther): Handle constructors in extensions consistently.
+        // Currently they are not part of the name space but still processed
+        // for instance when inferring redirecting factories.
+        constructors: includeConstructors ? _constructors : null);
   }
 }
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index f896aae..24f1072 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -176,8 +176,7 @@
   MemberBuilder? memberBuilder;
   if (classBuilder != null) {
     if (member is Constructor || member is Procedure && member.isFactory) {
-      memberBuilder =
-          classBuilder.constructorScope.lookupLocalMember(memberName);
+      memberBuilder = classBuilder.nameSpace.lookupConstructor(memberName);
     } else {
       memberBuilder = classBuilder.nameSpace.lookupLocalMember(memberName,
           setter: member is Procedure && member.isSetter) as MemberBuilder?;
diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/type_inference/inference_visitor.dart
index ada0c75..7fe8e3ea 100644
--- a/pkg/front_end/lib/src/type_inference/inference_visitor.dart
+++ b/pkg/front_end/lib/src/type_inference/inference_visitor.dart
@@ -38,6 +38,7 @@
         ControlFlowElement,
         ControlFlowMapEntry,
         ForElement,
+        ForElementBase,
         ForInElement,
         ForInMapEntry,
         ForMapEntry,
@@ -2547,54 +2548,71 @@
         element);
   }
 
+  ExpressionInferenceResult _inferPatternForElement(
+      PatternForElement element,
+      DartType inferredTypeArgument,
+      Map<TreeNode, DartType> inferredSpreadTypes,
+      Map<Expression, DartType> inferredConditionTypes) {
+    int? stackBase;
+    assert(checkStackBase(element, stackBase = stackHeight));
+
+    PatternVariableDeclaration patternVariableDeclaration =
+        element.patternVariableDeclaration;
+    PatternVariableDeclarationAnalysisResult<DartType, DartType>
+        analysisResult = analyzePatternVariableDeclaration(
+            patternVariableDeclaration,
+            patternVariableDeclaration.pattern,
+            patternVariableDeclaration.initializer,
+            isFinal: patternVariableDeclaration.isFinal);
+    patternVariableDeclaration.matchedValueType =
+        analysisResult.initializerType;
+
+    assert(checkStack(element, stackBase, [
+      /* pattern = */ ValueKinds.Pattern,
+      /* initializer = */ ValueKinds.Expression,
+    ]));
+
+    Object? rewrite = popRewrite(NullValues.Expression);
+    if (!identical(patternVariableDeclaration.pattern, rewrite)) {
+      // Coverage-ignore-block(suite): Not run.
+      patternVariableDeclaration.pattern = (rewrite as Pattern)
+        ..parent = patternVariableDeclaration;
+    }
+
+    rewrite = popRewrite();
+    if (!identical(patternVariableDeclaration.initializer, rewrite)) {
+      patternVariableDeclaration.initializer = (rewrite as Expression)
+        ..parent = patternVariableDeclaration;
+    }
+
+    List<VariableDeclaration> declaredVariables =
+        patternVariableDeclaration.pattern.declaredVariables;
+    assert(declaredVariables.length == element.intermediateVariables.length);
+    assert(declaredVariables.length == element.variables.length);
+    for (int i = 0; i < declaredVariables.length; i++) {
+      DartType type = declaredVariables[i].type;
+      element.intermediateVariables[i].type = type;
+      element.variables[i].type = type;
+    }
+
+    return _inferForElementBase(element, inferredTypeArgument,
+        inferredSpreadTypes, inferredConditionTypes);
+  }
+
   ExpressionInferenceResult _inferForElement(
       ForElement element,
       DartType inferredTypeArgument,
       Map<TreeNode, DartType> inferredSpreadTypes,
       Map<Expression, DartType> inferredConditionTypes) {
-    if (element is PatternForElement) {
-      int? stackBase;
-      assert(checkStackBase(element, stackBase = stackHeight));
+    return _inferForElementBase(element, inferredTypeArgument,
+        inferredSpreadTypes, inferredConditionTypes);
+  }
 
-      PatternVariableDeclaration patternVariableDeclaration =
-          element.patternVariableDeclaration;
-      PatternVariableDeclarationAnalysisResult<DartType, DartType>
-          analysisResult = analyzePatternVariableDeclaration(
-              patternVariableDeclaration,
-              patternVariableDeclaration.pattern,
-              patternVariableDeclaration.initializer,
-              isFinal: patternVariableDeclaration.isFinal);
-      patternVariableDeclaration.matchedValueType =
-          analysisResult.initializerType;
-
-      assert(checkStack(element, stackBase, [
-        /* pattern = */ ValueKinds.Pattern,
-        /* initializer = */ ValueKinds.Expression,
-      ]));
-
-      Object? rewrite = popRewrite(NullValues.Expression);
-      if (!identical(patternVariableDeclaration.pattern, rewrite)) {
-        // Coverage-ignore-block(suite): Not run.
-        patternVariableDeclaration.pattern = (rewrite as Pattern)
-          ..parent = patternVariableDeclaration;
-      }
-
-      rewrite = popRewrite();
-      if (!identical(patternVariableDeclaration.initializer, rewrite)) {
-        patternVariableDeclaration.initializer = (rewrite as Expression)
-          ..parent = patternVariableDeclaration;
-      }
-
-      List<VariableDeclaration> declaredVariables =
-          patternVariableDeclaration.pattern.declaredVariables;
-      assert(declaredVariables.length == element.intermediateVariables.length);
-      assert(declaredVariables.length == element.variables.length);
-      for (int i = 0; i < declaredVariables.length; i++) {
-        DartType type = declaredVariables[i].type;
-        element.intermediateVariables[i].type = type;
-        element.variables[i].type = type;
-      }
-    }
+  ExpressionInferenceResult _inferForElementBase(
+      ForElementBase element,
+      DartType inferredTypeArgument,
+      Map<TreeNode, DartType> inferredSpreadTypes,
+      Map<Expression, DartType> inferredConditionTypes) {
     // TODO(johnniwinther): Use _visitStatements instead.
     List<VariableDeclaration>? variables;
     for (int index = 0; index < element.variables.length; index++) {
@@ -2727,6 +2745,9 @@
         case ForElement():
           return _inferForElement(element, inferredTypeArgument,
               inferredSpreadTypes, inferredConditionTypes);
+        case PatternForElement():
+          return _inferPatternForElement(element, inferredTypeArgument,
+              inferredSpreadTypes, inferredConditionTypes);
         case ForInElement():
           return _inferForInElement(element, inferredTypeArgument,
               inferredSpreadTypes, inferredConditionTypes);
@@ -2811,6 +2832,19 @@
           checkElement(body, item, typeArgument, inferredSpreadTypes,
               inferredConditionTypes);
         }
+      case PatternForElement(:Expression? condition, :Expression body):
+        if (condition != null) {
+          DartType conditionType = inferredConditionTypes[condition]!;
+          Expression assignableCondition = ensureAssignable(
+              coreTypes.boolRawType(Nullability.nonNullable),
+              conditionType,
+              condition);
+          item.condition = assignableCondition..parent = item;
+        }
+        if (body is ControlFlowElement) {
+          checkElement(body, item, typeArgument, inferredSpreadTypes,
+              inferredConditionTypes);
+        }
       case ForInElement(:Expression body):
         if (body is ControlFlowElement) {
           checkElement(body, item, typeArgument, inferredSpreadTypes,
@@ -3054,15 +3088,12 @@
               element, receiverType, elementType, result, body,
               isSet: isSet);
         case ForElement():
-          if (element is PatternForElement) {
-            _translatePatternForElement(
-                element, receiverType, elementType, result, body,
-                isSet: isSet);
-          } else {
-            _translateForElement(
-                element, receiverType, elementType, result, body,
-                isSet: isSet);
-          }
+          _translateForElement(element, receiverType, elementType, result, body,
+              isSet: isSet);
+        case PatternForElement():
+          _translatePatternForElement(
+              element, receiverType, elementType, result, body,
+              isSet: isSet);
         case ForInElement():
           _translateForInElement(
               element, receiverType, elementType, result, body,
@@ -3934,6 +3965,7 @@
           // Coverage-ignore(suite): Not run.
           case IfCaseElement():
           case ForElement():
+          case PatternForElement():
           case ForInElement():
             // Rejected earlier.
             problems.unhandled("${element.runtimeType}",
diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart
index 667bdc0..05ec0cc 100644
--- a/pkg/front_end/test/coverage_suite_expected.dart
+++ b/pkg/front_end/test/coverage_suite_expected.dart
@@ -185,7 +185,7 @@
   ),
   // 100.0%.
   "package:front_end/src/base/name_space.dart": (
-    hitCount: 138,
+    hitCount: 168,
     missCount: 0,
   ),
   // 100.0%.
@@ -205,7 +205,7 @@
   ),
   // 100.0%.
   "package:front_end/src/base/scope.dart": (
-    hitCount: 666,
+    hitCount: 646,
     missCount: 0,
   ),
   // 100.0%.
@@ -420,12 +420,12 @@
   ),
   // 100.0%.
   "package:front_end/src/dill/dill_class_builder.dart": (
-    hitCount: 173,
+    hitCount: 177,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/dill/dill_extension_builder.dart": (
-    hitCount: 78,
+    hitCount: 81,
     missCount: 0,
   ),
   // 100.0%.
@@ -435,7 +435,7 @@
   ),
   // 100.0%.
   "package:front_end/src/dill/dill_extension_type_declaration_builder.dart": (
-    hitCount: 150,
+    hitCount: 154,
     missCount: 0,
   ),
   // 100.0%.
@@ -790,7 +790,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_builder_factory.dart": (
-    hitCount: 1167,
+    hitCount: 1159,
     missCount: 0,
   ),
   // 100.0%.
@@ -800,7 +800,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_class_builder.dart": (
-    hitCount: 1239,
+    hitCount: 1245,
     missCount: 0,
   ),
   // 100.0%.
@@ -815,18 +815,18 @@
   ),
   // 100.0%.
   "package:front_end/src/source/source_enum_builder.dart": (
-    hitCount: 526,
+    hitCount: 502,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/source/source_extension_builder.dart": (
-    hitCount: 84,
+    hitCount: 86,
     missCount: 0,
   ),
   // 100.0%.
   "package:front_end/src/source/source_extension_type_declaration_builder.dart":
       (
-    hitCount: 440,
+    hitCount: 446,
     missCount: 0,
   ),
   // 100.0%.
@@ -876,7 +876,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/type_parameter_scope_builder.dart": (
-    hitCount: 199,
+    hitCount: 206,
     missCount: 0,
   ),
   // 100.0%.
diff --git a/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart
new file mode 100644
index 0000000..e75c921
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2024, 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.
+
+testList(dynamic x, dynamic list) {
+  return [if (list case [int _]) ...x else ...x];
+}
+
+testSet(dynamic x, dynamic list) {
+  return {0, if (list case [int _]) ...x else ...x};
+}
+
+main() {
+  testList([0], [0]);
+  expectThrows<TypeError>(() {testList(null, [0]);});
+
+  testSet([0], [0]);
+  expectThrows<TypeError>(() {testSet(null, [0]);});
+}
+
+expectThrows<Exception>(void Function() f) {
+  String? message;
+  try {
+    f();
+    message = "Expected the function to throw an exception, but it didn't.";
+  } on Exception catch (_) {
+    // Ok.
+  } on dynamic catch (e) {
+    message = "Expected the function to throw an exception of type '${Exception}', but got '${e.runtimeType}'.";
+  }
+  if (message != null) {
+    throw message;
+  }
+}
diff --git a/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.expect b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.expect
new file mode 100644
index 0000000..c9573aa
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.expect
@@ -0,0 +1,59 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method testList(dynamic x, dynamic list) → dynamic {
+  return block {
+    final core::List<dynamic> #t1 = <dynamic>[];
+    {
+      final synthesized dynamic #0#0 = list;
+      if(#0#0 is core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic} is core::int)
+        #t1.{core::List::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+      else
+        #t1.{core::List::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+    }
+  } =>#t1;
+}
+static method testSet(dynamic x, dynamic list) → dynamic {
+  return block {
+    final core::Set<dynamic> #t2 = col::LinkedHashSet::•<dynamic>();
+    #t2.{core::Set::add}{Invariant}(0){(dynamic) → core::bool};
+    {
+      final synthesized dynamic #0#0 = list;
+      if(#0#0 is core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic} is core::int)
+        #t2.{core::Set::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+      else
+        #t2.{core::Set::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+    }
+  } =>#t2;
+}
+static method main() → dynamic {
+  self::testList(<core::int>[0], <core::int>[0]);
+  self::expectThrows<core::TypeError>(() → void {
+    self::testList(null, <core::int>[0]);
+  });
+  self::testSet(<core::int>[0], <core::int>[0]);
+  self::expectThrows<core::TypeError>(() → void {
+    self::testSet(null, <core::int>[0]);
+  });
+}
+static method expectThrows<Exception extends core::Object? = dynamic>(() → void f) → dynamic {
+  core::String? message;
+  try {
+    f(){() → void};
+    message = "Expected the function to throw an exception, but it didn't.";
+  }
+  on self::expectThrows::Exception% catch(final self::expectThrows::Exception% _) {
+  }
+  on dynamic catch(final dynamic e) {
+    message = "Expected the function to throw an exception of type '${self::expectThrows::Exception%}', but got '${e.{core::Object::runtimeType}{<object>}.{core::Type}}'.";
+  }
+  if(!(message == null)) {
+    throw message{core::String};
+  }
+}
+
+constants  {
+  #C1 = 1
+}
diff --git a/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.modular.expect b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.modular.expect
new file mode 100644
index 0000000..c9573aa
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.modular.expect
@@ -0,0 +1,59 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method testList(dynamic x, dynamic list) → dynamic {
+  return block {
+    final core::List<dynamic> #t1 = <dynamic>[];
+    {
+      final synthesized dynamic #0#0 = list;
+      if(#0#0 is core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic} is core::int)
+        #t1.{core::List::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+      else
+        #t1.{core::List::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+    }
+  } =>#t1;
+}
+static method testSet(dynamic x, dynamic list) → dynamic {
+  return block {
+    final core::Set<dynamic> #t2 = col::LinkedHashSet::•<dynamic>();
+    #t2.{core::Set::add}{Invariant}(0){(dynamic) → core::bool};
+    {
+      final synthesized dynamic #0#0 = list;
+      if(#0#0 is core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic} is core::int)
+        #t2.{core::Set::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+      else
+        #t2.{core::Set::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+    }
+  } =>#t2;
+}
+static method main() → dynamic {
+  self::testList(<core::int>[0], <core::int>[0]);
+  self::expectThrows<core::TypeError>(() → void {
+    self::testList(null, <core::int>[0]);
+  });
+  self::testSet(<core::int>[0], <core::int>[0]);
+  self::expectThrows<core::TypeError>(() → void {
+    self::testSet(null, <core::int>[0]);
+  });
+}
+static method expectThrows<Exception extends core::Object? = dynamic>(() → void f) → dynamic {
+  core::String? message;
+  try {
+    f(){() → void};
+    message = "Expected the function to throw an exception, but it didn't.";
+  }
+  on self::expectThrows::Exception% catch(final self::expectThrows::Exception% _) {
+  }
+  on dynamic catch(final dynamic e) {
+    message = "Expected the function to throw an exception of type '${self::expectThrows::Exception%}', but got '${e.{core::Object::runtimeType}{<object>}.{core::Type}}'.";
+  }
+  if(!(message == null)) {
+    throw message{core::String};
+  }
+}
+
+constants  {
+  #C1 = 1
+}
diff --git a/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.outline.expect b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.outline.expect
new file mode 100644
index 0000000..17a502b
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.outline.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method testList(dynamic x, dynamic list) → dynamic
+  ;
+static method testSet(dynamic x, dynamic list) → dynamic
+  ;
+static method main() → dynamic
+  ;
+static method expectThrows<Exception extends core::Object? = dynamic>(() → void f) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.transformed.expect
new file mode 100644
index 0000000..21e09bf
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.strong.transformed.expect
@@ -0,0 +1,59 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method testList(dynamic x, dynamic list) → dynamic {
+  return block {
+    final core::List<dynamic> #t1 = core::_GrowableList::•<dynamic>(0);
+    {
+      final synthesized dynamic #0#0 = list;
+      if(#0#0 is core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic} is core::int)
+        #t1.{core::List::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+      else
+        #t1.{core::List::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+    }
+  } =>#t1;
+}
+static method testSet(dynamic x, dynamic list) → dynamic {
+  return block {
+    final core::Set<dynamic> #t2 = new col::_Set::•<dynamic>();
+    #t2.{core::Set::add}{Invariant}(0){(dynamic) → core::bool};
+    {
+      final synthesized dynamic #0#0 = list;
+      if(#0#0 is core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic} is core::int)
+        #t2.{core::Set::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+      else
+        #t2.{core::Set::addAll}{Invariant}(x as{TypeError,ForDynamic} core::Iterable<dynamic>){(core::Iterable<dynamic>) → void};
+    }
+  } =>#t2;
+}
+static method main() → dynamic {
+  self::testList(core::_GrowableList::_literal1<core::int>(0), core::_GrowableList::_literal1<core::int>(0));
+  self::expectThrows<core::TypeError>(() → void {
+    self::testList(null, core::_GrowableList::_literal1<core::int>(0));
+  });
+  self::testSet(core::_GrowableList::_literal1<core::int>(0), core::_GrowableList::_literal1<core::int>(0));
+  self::expectThrows<core::TypeError>(() → void {
+    self::testSet(null, core::_GrowableList::_literal1<core::int>(0));
+  });
+}
+static method expectThrows<Exception extends core::Object? = dynamic>(() → void f) → dynamic {
+  core::String? message;
+  try {
+    f(){() → void};
+    message = "Expected the function to throw an exception, but it didn't.";
+  }
+  on self::expectThrows::Exception% catch(final self::expectThrows::Exception% _) {
+  }
+  on dynamic catch(final dynamic e) {
+    message = "Expected the function to throw an exception of type '${self::expectThrows::Exception%}', but got '${e.{core::Object::runtimeType}{<object>}.{core::Type}}'.";
+  }
+  if(!(message == null)) {
+    throw message{core::String};
+  }
+}
+
+constants  {
+  #C1 = 1
+}
diff --git a/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.textual_outline.expect b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.textual_outline.expect
new file mode 100644
index 0000000..d264d11
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.textual_outline.expect
@@ -0,0 +1,7 @@
+testList(dynamic x, dynamic list) {}
+
+testSet(dynamic x, dynamic list) {}
+
+main() {}
+
+expectThrows<Exception>(void Function() f) {}
diff --git a/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..93b3c14
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/coercion_in_if_case_element.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+expectThrows<Exception>(void Function() f) {}
+
+main() {}
+
+testList(dynamic x, dynamic list) {}
+
+testSet(dynamic x, dynamic list) {}
diff --git a/runtime/tests/vm/dart/dynamic_module_pragmas_il_test.dart b/runtime/tests/vm/dart/dynamic_module_pragmas_il_test.dart
index 9fc2e61..3a5a35e 100644
--- a/runtime/tests/vm/dart/dynamic_module_pragmas_il_test.dart
+++ b/runtime/tests/vm/dart/dynamic_module_pragmas_il_test.dart
@@ -116,6 +116,7 @@
       callA2(obj);
     }
   }
+  testCallInTryWithControlFlow(getMyString(), int.parse('1'));
 }
 
 void matchIL$callA1(FlowGraph graph) {
@@ -227,3 +228,113 @@
     ]),
   ]);
 }
+
+@pragma('dyn-module:extendable')
+class MyString {
+  @pragma('dyn-module:can-be-overridden')
+  @pragma('vm:never-inline')
+  int get length => int.parse('2');
+
+  @pragma('dyn-module:can-be-overridden')
+  @pragma('vm:never-inline')
+  String substring(int start) => 42.toString();
+}
+
+MyString getMyString() => [MyString()][int.parse('0')];
+
+@pragma('vm:never-inline')
+int intParse(String str) => int.parse(str);
+
+@pragma('vm:never-inline')
+@pragma('vm:testing:print-flow-graph')
+void testCallInTryWithControlFlow(MyString value, int pos) {
+  if (pos == value.length) {
+  } else {
+    try {
+      intParse(value.substring(pos));
+    } catch (e) {}
+  }
+}
+
+void matchIL$testCallInTryWithControlFlow(FlowGraph graph) {
+  graph.dump();
+  graph.match([
+    match.block('Graph', []),
+    match.block('Function', [
+      'value' << match.Parameter(index: 0),
+      'pos' << match.Parameter(index: 1),
+      match.CheckStackOverflow(),
+      'cid1' << match.LoadClassId('value'),
+      match.Branch(match.TestRange('cid1'), ifTrue: 'B9', ifFalse: 'B10'),
+    ]),
+    'B9' <<
+        match.block('Target', [
+          match.MoveArgument('value'),
+          'value_length1' << match.DispatchTableCall('cid1'),
+          match.Goto('B11'),
+        ]),
+    'B10' <<
+        match.block('Target', [
+          match.MoveArgument('value'),
+          'value_length2' << match.InstanceCall('value'),
+          match.Goto('B11'),
+        ]),
+    'B11' <<
+        match.block('Join', [
+          'value_length' << match.Phi('value_length1', 'value_length2'),
+          'value_length_unboxed' << match.UnboxInt64('value_length'),
+          match.Branch(
+              match.EqualityCompare('pos', 'value_length_unboxed', kind: '=='),
+              ifTrue: 'B3',
+              ifFalse: 'B4'),
+        ]),
+    'B3' <<
+        match.block('Target', [
+          match.Goto('B8'),
+        ]),
+    'B4' <<
+        match.block('Target', [
+          match.Goto('B5'),
+        ]),
+    'B5' <<
+        match.block('Join', [
+          'pos_boxed' << match.BoxInt64('pos'),
+          'cid2' << match.LoadClassId('value'),
+          match.Branch(match.TestRange('cid2'), ifTrue: 'B12', ifFalse: 'B13'),
+        ]),
+    'B12' <<
+        match.block('Target', [
+          match.MoveArgument('value'),
+          match.MoveArgument('pos_boxed'),
+          'value_substring1' << match.DispatchTableCall('cid2'),
+          match.Goto('B14'),
+        ]),
+    'B13' <<
+        match.block('Target', [
+          match.MoveArgument('value'),
+          match.MoveArgument('pos_boxed'),
+          'value_substring2' << match.InstanceCall('value', 'pos_boxed'),
+          match.Goto('B14'),
+        ]),
+    'B14' <<
+        match.block('Join', [
+          'value_substring' <<
+              match.Phi('value_substring1', 'value_substring2'),
+          match.MoveArgument('value_substring'),
+          match.StaticCall('value_substring'),
+          match.Goto('B6'),
+        ]),
+    'B7' <<
+        match.block('CatchBlock', [
+          match.Goto('B6'),
+        ]),
+    'B6' <<
+        match.block('Join', [
+          match.Goto('B8'),
+        ]),
+    'B8' <<
+        match.block('Join', [
+          match.DartReturn(match.any),
+        ]),
+  ]);
+}
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 88a0754..ba64939 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -1243,14 +1243,6 @@
   call->ReplaceWith(dispatch_table_call, current_iterator());
 }
 
-static void InheritDeoptTargetIfNeeded(Zone* zone,
-                                       Instruction* instr,
-                                       Instruction* from) {
-  if (from->env() != nullptr) {
-    instr->InheritDeoptTarget(zone, from);
-  }
-}
-
 void AotCallSpecializer::ReplaceWithConditionalDispatchTableCall(
     InstanceCallBaseInstr* call,
     LoadClassIdInstr* load_cid,
@@ -1258,30 +1250,24 @@
     const compiler::TableSelector* selector) {
   BlockEntryInstr* current_block = call->GetBlock();
   const bool has_uses = call->HasUses();
+  const auto deopt_id = call->deopt_id();
 
   const intptr_t num_cids = isolate_group()->class_table()->NumCids();
   auto* compare = new (Z) TestRangeInstr(
-      call->source(), new (Z) Value(load_cid), 0, num_cids, kUnboxedUword);
+      call->source(), new (Z) Value(load_cid), 0, num_cids - 1, kUnboxedUword);
 
-  BranchInstr* branch = new (Z) BranchInstr(compare, DeoptId::kNone);
-  InheritDeoptTargetIfNeeded(Z, branch, call);
+  BranchInstr* branch = new (Z) BranchInstr(compare, deopt_id);
 
-  TargetEntryInstr* true_target =
-      new (Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
-                               current_block->try_index(), DeoptId::kNone);
-  InheritDeoptTargetIfNeeded(Z, true_target, call);
+  TargetEntryInstr* true_target = new (Z) TargetEntryInstr(
+      flow_graph()->allocate_block_id(), current_block->try_index(), deopt_id);
   *branch->true_successor_address() = true_target;
 
-  TargetEntryInstr* false_target =
-      new (Z) TargetEntryInstr(flow_graph()->allocate_block_id(),
-                               current_block->try_index(), DeoptId::kNone);
-  InheritDeoptTargetIfNeeded(Z, false_target, call);
+  TargetEntryInstr* false_target = new (Z) TargetEntryInstr(
+      flow_graph()->allocate_block_id(), current_block->try_index(), deopt_id);
   *branch->false_successor_address() = false_target;
 
-  JoinEntryInstr* join =
-      new (Z) JoinEntryInstr(flow_graph()->allocate_block_id(),
-                             current_block->try_index(), DeoptId::kNone);
-  InheritDeoptTargetIfNeeded(Z, join, call);
+  JoinEntryInstr* join = new (Z) JoinEntryInstr(
+      flow_graph()->allocate_block_id(), current_block->try_index(), deopt_id);
 
   current_block->ReplaceAsPredecessorWith(join);
 
@@ -1306,13 +1292,11 @@
     call->ReplaceUsesWith(phi);
   }
 
-  GotoInstr* true_goto = new (Z) GotoInstr(join, DeoptId::kNone);
-  InheritDeoptTargetIfNeeded(Z, true_goto, call);
+  GotoInstr* true_goto = new (Z) GotoInstr(join, deopt_id);
   true_target->LinkTo(true_goto);
   true_target->set_last_instruction(true_goto);
 
-  GotoInstr* false_goto = new (Z) GotoInstr(join, DeoptId::kNone);
-  InheritDeoptTargetIfNeeded(Z, false_goto, call);
+  GotoInstr* false_goto = new (Z) GotoInstr(join, deopt_id);
   false_target->LinkTo(false_goto);
   false_target->set_last_instruction(false_goto);
 
@@ -1328,7 +1312,9 @@
   call->set_next(nullptr);
   call->UnuseAllInputs();  // So it can be re-added to the graph.
   call->InsertBefore(false_goto);
-  InheritDeoptTargetIfNeeded(Z, call, call);  // Restore env use list.
+  if (call->env() != nullptr) {
+    call->env()->DeepCopyTo(Z, call);  // Restore env use list.
+  }
 
   if (has_uses) {
     phi->SetInputAt(0, new (Z) Value(dispatch_table_call));
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index 14e61f3..bfd6473 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -2969,6 +2969,8 @@
       return range;
     }
   }
+  TRACE_ALLOC(THR_Print("Range v%" Pd " is not covered at pos %" Pd "\n",
+                        parent->vreg(), pos));
   UNREACHABLE();
   return nullptr;
 }
diff --git a/tools/VERSION b/tools/VERSION
index 5b019ed..54711f1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 3
 MINOR 6
 PATCH 0
-PRERELEASE 109
+PRERELEASE 110
 PRERELEASE_PATCH 0