Version 3.6.0-86.0.dev

Merge 7347bdcdba4266ce7265414e9ac6bfcf6ed18984 into dev
diff --git a/pkg/front_end/lib/src/base/import.dart b/pkg/front_end/lib/src/base/import.dart
index 8b0eb3a..26cc39a 100644
--- a/pkg/front_end/lib/src/base/import.dart
+++ b/pkg/front_end/lib/src/base/import.dart
@@ -82,7 +82,7 @@
         prefixBuilder!.addToExportScope(name, member, charOffset);
       };
     }
-    NameIterator<Builder> iterator = importedLibraryBuilder!.exportScope
+    NameIterator<Builder> iterator = importedLibraryBuilder!.exportNameSpace
         .filteredNameIterator(
             includeDuplicates: false, includeAugmentations: false);
     while (iterator.moveNext()) {
diff --git a/pkg/front_end/lib/src/base/incremental_compiler.dart b/pkg/front_end/lib/src/base/incremental_compiler.dart
index fb355a6..a88a327 100644
--- a/pkg/front_end/lib/src/base/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/base/incremental_compiler.dart
@@ -101,7 +101,6 @@
 import 'hybrid_file_system.dart' show HybridFileSystem;
 import 'incremental_serializer.dart' show IncrementalSerializer;
 import 'library_graph.dart' show LibraryGraph;
-import 'scope.dart' show ScopeKind;
 import 'ticker.dart' show Ticker;
 import 'uri_translator.dart' show UriTranslator;
 import 'uris.dart' show dartCore, getPartUri;
@@ -685,10 +684,10 @@
     bool isEquivalent = true;
     StringBuffer sb = new StringBuffer();
     sb.writeln('Mismatch on ${sourceLibraryBuilder.importUri}:');
-    sourceLibraryBuilder.exportScope
+    sourceLibraryBuilder.exportNameSpace
         .forEachLocalMember((String name, Builder sourceBuilder) {
-      Builder? dillBuilder =
-          dillLibraryBuilder.exportScope.lookupLocalMember(name, setter: false);
+      Builder? dillBuilder = dillLibraryBuilder.exportNameSpace
+          .lookupLocalMember(name, setter: false);
       if (dillBuilder == null) {
         if ((name == 'dynamic' || name == 'Never') &&
             sourceLibraryBuilder.importUri == dartCore) {
@@ -701,30 +700,30 @@
         isEquivalent = false;
       }
     });
-    dillLibraryBuilder.exportScope
+    dillLibraryBuilder.exportNameSpace
         .forEachLocalMember((String name, Builder dillBuilder) {
-      Builder? sourceBuilder = sourceLibraryBuilder.exportScope
+      Builder? sourceBuilder = sourceLibraryBuilder.exportNameSpace
           .lookupLocalMember(name, setter: false);
       if (sourceBuilder == null) {
         sb.writeln('No source builder for ${name}: $dillBuilder');
         isEquivalent = false;
       }
     });
-    sourceLibraryBuilder.exportScope
+    sourceLibraryBuilder.exportNameSpace
         .forEachLocalSetter((String name, Builder sourceBuilder) {
-      Builder? dillBuilder =
-          dillLibraryBuilder.exportScope.lookupLocalMember(name, setter: true);
+      Builder? dillBuilder = dillLibraryBuilder.exportNameSpace
+          .lookupLocalMember(name, setter: true);
       if (dillBuilder == null) {
         sb.writeln('No dill builder for ${name}=: $sourceBuilder');
         isEquivalent = false;
       }
     });
-    dillLibraryBuilder.exportScope
+    dillLibraryBuilder.exportNameSpace
         .forEachLocalSetter((String name, Builder dillBuilder) {
-      Builder? sourceBuilder = sourceLibraryBuilder.exportScope
+      Builder? sourceBuilder = sourceLibraryBuilder.exportNameSpace
           .lookupLocalMember(name, setter: true);
       if (sourceBuilder == null) {
-        sourceBuilder = sourceLibraryBuilder.exportScope
+        sourceBuilder = sourceLibraryBuilder.exportNameSpace
             .lookupLocalMember(name, setter: false);
         if (sourceBuilder is FieldBuilder && sourceBuilder.isAssignable) {
           // Assignable fields can be lowered into a getter and setter.
@@ -2026,8 +2025,7 @@
         packageLanguageVersion:
             new ImplicitLanguageVersion(libraryBuilder.languageVersion),
         loader: lastGoodKernelTarget.loader,
-        importScope: debugLibrary.scope.createNestedScope(
-            debugName: "expression", kind: ScopeKind.library),
+        parentScope: debugLibrary.scope,
         nameOrigin: libraryBuilder,
         isUnsupported: libraryBuilder.isUnsupported,
         isAugmentation: false,
diff --git a/pkg/front_end/lib/src/base/local_scope.dart b/pkg/front_end/lib/src/base/local_scope.dart
index 8db0333..e227674 100644
--- a/pkg/front_end/lib/src/base/local_scope.dart
+++ b/pkg/front_end/lib/src/base/local_scope.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import '../builder/builder.dart';
+import '../builder/declaration_builders.dart';
 import '../kernel/body_builder.dart' show JumpTarget;
 import 'scope.dart';
 
@@ -116,6 +117,11 @@
   }
 
   void recordUse(String name, int charOffset) {}
+
+  @override
+  void forEachExtension(void Function(ExtensionBuilder) f) {
+    _parent?.forEachExtension(f);
+  }
 }
 
 final class LocalScopeImpl extends BaseLocalScope
@@ -345,5 +351,10 @@
   }
 
   @override
+  void forEachExtension(void Function(ExtensionBuilder) f) {
+    _scope.forEachExtension(f);
+  }
+
+  @override
   String toString() => "$runtimeType(${kind},$_scope)";
 }
diff --git a/pkg/front_end/lib/src/base/name_space.dart b/pkg/front_end/lib/src/base/name_space.dart
index e4e2bb7..a8e2734 100644
--- a/pkg/front_end/lib/src/base/name_space.dart
+++ b/pkg/front_end/lib/src/base/name_space.dart
@@ -151,15 +151,14 @@
   }
 
   @override
-  Iterator<Builder> get unfilteredIterator => new ScopeIterator.fromIterators(
+  Iterator<Builder> get unfilteredIterator => new ScopeIterator(
       _getables?.values.iterator,
       _setables?.values.iterator,
       _extensions?.iterator);
 
   @override
   NameIterator<Builder> get unfilteredNameIterator =>
-      new ScopeNameIterator.fromIterators(
-          _getables, _setables, _extensions?.iterator);
+      new ScopeNameIterator(_getables, _setables, _extensions?.iterator);
 }
 
 abstract class LazyNameSpace extends NameSpaceImpl {
@@ -185,6 +184,17 @@
   }
 }
 
+class DillLibraryNameSpace extends LazyNameSpace {
+  final DillLibraryBuilder _libraryBuilder;
+
+  DillLibraryNameSpace(this._libraryBuilder);
+
+  @override
+  void ensureNameSpace() {
+    _libraryBuilder.ensureLoaded();
+  }
+}
+
 class DillExportNameSpace extends LazyNameSpace {
   final DillLibraryBuilder _libraryBuilder;
 
diff --git a/pkg/front_end/lib/src/base/scope.dart b/pkg/front_end/lib/src/base/scope.dart
index a189b62..8e6580f 100644
--- a/pkg/front_end/lib/src/base/scope.dart
+++ b/pkg/front_end/lib/src/base/scope.dart
@@ -14,7 +14,7 @@
 import '../builder/metadata_builder.dart';
 import '../builder/name_iterator.dart';
 import '../builder/prefix_builder.dart';
-import '../kernel/body_builder.dart' show JumpTarget;
+//import '../kernel/body_builder.dart' show JumpTarget;
 import '../kernel/body_builder_context.dart';
 import '../kernel/hierarchy/class_member.dart' show ClassMember;
 import '../kernel/kernel_helper.dart';
@@ -112,6 +112,8 @@
   ScopeKind get kind;
   Builder? lookup(String name, int charOffset, Uri fileUri);
   Builder? lookupSetter(String name, int charOffset, Uri fileUri);
+  // TODO(johnniwinther): Should this be moved to an outer scope interface?
+  void forEachExtension(void Function(ExtensionBuilder) f);
 }
 
 /// Returns the correct value of the [getable] and [setable] found as a lookup
@@ -281,6 +283,35 @@
         isSetter: true);
     return builder ?? _parent?.lookupSetter(name, charOffset, fileUri);
   }
+
+  @override
+  void forEachExtension(void Function(ExtensionBuilder) f) {
+    _nameSpace.forEachLocalExtension(f);
+    _parent?.forEachExtension(f);
+  }
+}
+
+// TODO(johnniwinther): Avoid this.
+class MutableNameSpaceLookupScope extends NameSpaceLookupScope {
+  MutableNameSpaceLookupScope(
+      super.nameSpace, super.kind, super.classNameOrDebugName,
+      {required super.parent});
+
+  NameSpace? _replacedNamedSpace;
+  LookupScope? _replacedParent;
+
+  /// This scope becomes equivalent to [scope]. This is used for parts to
+  /// become part of their library's scope.
+  void replaceNameSpaceAndParent(NameSpace nameSpace, LookupScope parent) {
+    _replacedNamedSpace = nameSpace;
+    _replacedParent = parent;
+  }
+
+  @override
+  LookupScope? get _parent => _replacedParent ?? super._parent;
+
+  @override
+  NameSpace get _nameSpace => _replacedNamedSpace ?? super._nameSpace;
 }
 
 class TypeParameterScope with LookupScopeMixin {
@@ -324,6 +355,11 @@
     }
     return new TypeParameterScope(parent, map);
   }
+
+  @override
+  void forEachExtension(void Function(ExtensionBuilder) f) {
+    _parent.forEachExtension(f);
+  }
 }
 
 class FixedLookupScope implements LookupScope {
@@ -367,397 +403,11 @@
         isSetter: true);
     return builder ?? _parent?.lookupSetter(name, charOffset, fileUri);
   }
-}
 
-abstract class ParentScope {
-  ParentScope? get parent;
-  void forEachExtension(void Function(ExtensionBuilder) f);
-  Builder? lookup(String name, int charOffset, Uri fileUri);
-  Builder? lookupSetter(String name, int charOffset, Uri fileUri);
-  int writeOn(StringSink sink);
-}
-
-class MutableScope {
-  /// Names declared in this scope.
-  Map<String, Builder>? _local;
-
-  /// Setters declared in this scope.
-  Map<String, MemberBuilder>? _setters;
-
-  /// The extensions declared in this scope.
-  ///
-  /// This includes all available extensions even if the extensions are not
-  /// accessible by name because of duplicate imports.
-  ///
-  /// For instance:
-  ///
-  ///   lib1.dart:
-  ///     extension Extension on String {
-  ///       method1() {}
-  ///       staticMethod1() {}
-  ///     }
-  ///   lib2.dart:
-  ///     extension Extension on String {
-  ///       method2() {}
-  ///       staticMethod2() {}
-  ///     }
-  ///   main.dart:
-  ///     import 'lib1.dart';
-  ///     import 'lib2.dart';
-  ///
-  ///     main() {
-  ///       'foo'.method1(); // This method is available.
-  ///       'foo'.method2(); // This method is available.
-  ///       // These methods are not available because Extension is ambiguous:
-  ///       Extension.staticMethod1();
-  ///       Extension.staticMethod2();
-  ///     }
-  ///
-  Set<ExtensionBuilder>? _extensions;
-
-  /// The scope that this scope is nested within, or `null` if this is the top
-  /// level scope.
-  ParentScope? _parent;
-
-  final String classNameOrDebugName;
-
-  final ScopeKind kind;
-
-  MutableScope(this.kind, this._local, this._setters, this._extensions,
-      this._parent, this.classNameOrDebugName);
-
-  ParentScope? get parent => _parent;
-
-  @override
-  String toString() => "Scope(${kind}, $classNameOrDebugName, ${_local?.keys})";
-}
-
-class Scope extends MutableScope
-    implements ParentScope, LookupScope, NameSpace {
-  /// Indicates whether an attempt to declare new names in this scope should
-  /// succeed.
-  final bool isModifiable;
-
-  Map<String, JumpTarget>? labels;
-
-  Map<String, JumpTarget>? forwardDeclaredLabels;
-
-  Map<String, List<Builder>>? augmentations;
-
-  Map<String, List<Builder>>? setterAugmentations;
-
-  Scope(
-      {required ScopeKind kind,
-      Map<String, Builder>? local,
-      Map<String, MemberBuilder>? setters,
-      Set<ExtensionBuilder>? extensions,
-      ParentScope? parent,
-      this.augmentations,
-      this.setterAugmentations,
-      required String debugName,
-      this.isModifiable = true})
-      : super(kind, local, setters, extensions, parent, debugName);
-
-  Scope.top({required ScopeKind kind, bool isModifiable = false})
-      : this(
-            kind: kind,
-            local: <String, Builder>{},
-            setters: <String, MemberBuilder>{},
-            debugName: "top",
-            isModifiable: isModifiable);
-
-  Scope.nested(Scope parent, String debugName,
-      {bool isModifiable = true,
-      required ScopeKind kind,
-      Map<String, Builder>? local})
-      : this(
-            kind: kind,
-            parent: parent,
-            debugName: debugName,
-            isModifiable: isModifiable,
-            local: local);
-
-  /// Returns an iterator of all members and setters mapped in this scope,
-  /// including duplicate members mapped to the same name.
-  ///
-  /// The iterator does _not_ include the members and setters mapped in the
-  /// [parent] scope.
-  @override
-  @deprecated
-  Iterator<Builder> get unfilteredIterator {
-    return new ScopeIterator(this);
-  }
-
-  /// Returns an iterator of all members and setters mapped in this scope,
-  /// including duplicate members mapped to the same name.
-  ///
-  /// The iterator does _not_ include the members and setters mapped in the
-  /// [parent] scope.
-  ///
-  /// Compared to [unfilteredIterator] this iterator also gives access to the
-  /// name that the builders are mapped to.
-  @override
-  @deprecated
-  NameIterator get unfilteredNameIterator {
-    return new ScopeNameIterator(this);
-  }
-
-  /// Returns a filtered iterator of members and setters 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.
-  @override
-  @deprecated
-  Iterator<T> filteredIterator<T extends Builder>(
-      {Builder? parent,
-      required bool includeDuplicates,
-      required bool includeAugmentations}) {
-    return new FilteredIterator<T>(unfilteredIterator,
-        parent: parent,
-        includeDuplicates: includeDuplicates,
-        includeAugmentations: includeAugmentations);
-  }
-
-  /// Returns a filtered iterator of members and setters 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.
-  @override
-  @deprecated
-  NameIterator<T> filteredNameIterator<T extends Builder>(
-      {Builder? parent,
-      required bool includeDuplicates,
-      required bool includeAugmentations}) {
-    return new FilteredNameIterator<T>(unfilteredNameIterator,
-        parent: parent,
-        includeDuplicates: includeDuplicates,
-        includeAugmentations: includeAugmentations);
-  }
-
-  void debug() {
-    print("Locals:");
-    _local?.forEach((key, value) {
-      print("  $key: $value (${identityHashCode(value)}) (${value.parent})");
-    });
-    print("Setters:");
-    _setters?.forEach((key, value) {
-      print("  $key: $value (${identityHashCode(value)}) (${value.parent})");
-    });
-    print("Extensions:");
-    _extensions?.forEach((v) {
-      print("  $v");
-    });
-  }
-
-  // Coverage-ignore(suite): Not run.
-  Scope copyWithParent(Scope parent, String debugName) {
-    return new Scope(
-        kind: kind,
-        local: super._local,
-        setters: super._setters,
-        extensions: _extensions,
-        parent: parent,
-        debugName: debugName,
-        isModifiable: isModifiable);
-  }
-
-  /// This scope becomes equivalent to [scope]. This is used for parts to
-  /// become part of their library's scope.
-  void becomePartOf(Scope scope) {
-    assert(_parent!.parent == null);
-    assert(scope._parent!.parent == null);
-    super._local = scope._local;
-    super._setters = scope._setters;
-    super._parent = scope._parent;
-    super._extensions = scope._extensions;
-  }
-
-  Scope createNestedScope(
-      {required String debugName,
-      bool isModifiable = true,
-      required ScopeKind kind,
-      Map<String, Builder>? local}) {
-    return new Scope.nested(this, debugName,
-        isModifiable: isModifiable, kind: kind, local: local);
-  }
-
-  Scope withTypeVariables(List<NominalVariableBuilder>? typeVariables) {
-    if (typeVariables == null) return this;
-    Scope newScope = new Scope.nested(this, "type variables",
-        isModifiable: false, kind: ScopeKind.typeParameters);
-    for (NominalVariableBuilder t in typeVariables) {
-      if (t.isWildcard) continue;
-      (newScope._local ??= {})[t.name] = t;
-    }
-    return newScope;
-  }
-
-  Scope withStructuralVariables(
-      List<StructuralVariableBuilder>? typeVariables) {
-    if (typeVariables == null) return this;
-    Scope newScope = new Scope.nested(this, "type variables",
-        isModifiable: false, kind: ScopeKind.typeParameters);
-    for (StructuralVariableBuilder t in typeVariables) {
-      (newScope._local ??= {})[t.name] = t;
-    }
-    return newScope;
-  }
-
-  Builder? lookupIn(String name, int charOffset, Uri fileUri,
-      Map<String, Builder> map, bool isInstanceScope) {
-    Builder? builder = map[name];
-    if (builder == null) return null;
-    if (builder.next != null) {
-      return new AmbiguousBuilder(
-          name.isEmpty
-              ?
-              // Coverage-ignore(suite): Not run.
-              classNameOrDebugName
-              : name,
-          builder,
-          charOffset,
-          fileUri);
-    } else if (!isInstanceScope && builder.isDeclarationInstanceMember) {
-      return null;
-    } else if (builder is MemberBuilder && builder.isConflictingSetter) {
-      // TODO(johnniwinther): Use a variant of [AmbiguousBuilder] for this case.
-      return null;
-    } else {
-      return builder;
-    }
-  }
-
-  /// Lookup a member with [name] in the scope.
-  @override
-  Builder? lookup(String name, int charOffset, Uri fileUri,
-      {bool isInstanceScope = true}) {
-    Builder? builder;
-    if (_local != null) {
-      builder = lookupIn(name, charOffset, fileUri, _local!, isInstanceScope);
-      if (builder != null) return builder;
-    }
-    if (_setters != null) {
-      builder = lookupIn(name, charOffset, fileUri, _setters!, isInstanceScope);
-      if (builder != null && !builder.hasProblem) {
-        return new AccessErrorBuilder(name, builder, charOffset, fileUri);
-      }
-      if (!isInstanceScope) {
-        // For static lookup, do not search the parent scope.
-        return builder;
-      }
-    }
-    return builder ?? _parent?.lookup(name, charOffset, fileUri);
-  }
-
-  @override
-  Builder? lookupSetter(String name, int charOffset, Uri fileUri,
-      {bool isInstanceScope = true}) {
-    Builder? builder;
-    if (_setters != null) {
-      builder = lookupIn(name, charOffset, fileUri, _setters!, isInstanceScope);
-      if (builder != null) return builder;
-    }
-    if (_local != null) {
-      builder = lookupIn(name, charOffset, fileUri, _local!, isInstanceScope);
-      if (builder != null && !builder.hasProblem) {
-        return new AccessErrorBuilder(name, builder, charOffset, fileUri);
-      }
-      if (!isInstanceScope) {
-        // For static lookup, do not search the parent scope.
-        return builder;
-      }
-    }
-    return builder ?? _parent?.lookupSetter(name, charOffset, fileUri);
-  }
-
-  @override
-  @deprecated
-  Builder? lookupLocalMember(String name, {required bool setter}) {
-    return setter ? (_setters?[name]) : (_local?[name]);
-  }
-
-  @override
-  @deprecated
-  void addLocalMember(String name, Builder member, {required bool setter}) {
-    if (setter) {
-      (_setters ??= // Coverage-ignore(suite): Not run.
-          {})[name] = member as MemberBuilder;
-    } else {
-      (_local ??= {})[name] = member;
-    }
-  }
-
-  @override
-  @deprecated
-  void forEachLocalMember(void Function(String name, Builder member) f) {
-    _local?.forEach(f);
-  }
-
-  @override
-  @deprecated
-  void forEachLocalSetter(void Function(String name, MemberBuilder member) f) {
-    _setters?.forEach(f);
-  }
-
-  @override
-  @deprecated
-  void forEachLocalExtension(void Function(ExtensionBuilder member) f) {
-    _extensions?.forEach(f);
-  }
-
-  @override
-  @deprecated
-  Iterable<Builder> get localMembers => _local?.values ?? const {};
-
-  /// Adds [builder] to the extensions in this scope.
-  @override
-  @deprecated
-  void addExtension(ExtensionBuilder builder) {
-    _extensions ??= <ExtensionBuilder>{};
-    _extensions!.add(builder);
-  }
-
-  /// Calls [f] for each extension in this scope and parent scopes.
   @override
   void forEachExtension(void Function(ExtensionBuilder) f) {
-    _extensions?.forEach(f);
     _parent?.forEachExtension(f);
   }
-
-  String get debugString {
-    StringBuffer buffer = new StringBuffer();
-    int nestingLevel = writeOn(buffer);
-    for (int i = nestingLevel; i >= 0; i--) {
-      buffer.writeln("${'  ' * i}}");
-    }
-    return "$buffer";
-  }
-
-  // Coverage-ignore(suite): Not run.
-  @override
-  int writeOn(StringSink sink) {
-    int nestingLevel = (_parent?.writeOn(sink) ?? -1) + 1;
-    String indent = "  " * nestingLevel;
-    sink.writeln("$indent{");
-    _local?.forEach((String name, Builder member) {
-      sink.writeln("$indent  $name");
-    });
-    _setters?.forEach((String name, Builder member) {
-      sink.writeln("$indent  $name=");
-    });
-    return nestingLevel;
-  }
 }
 
 class ConstructorScope {
@@ -847,40 +497,6 @@
   String toString() => "ConstructorScope($className, ${_local.keys})";
 }
 
-abstract class LazyScope extends Scope {
-  LazyScope(Map<String, Builder> local, Map<String, MemberBuilder> setters,
-      Scope? parent, String debugName,
-      {bool isModifiable = true, required ScopeKind kind})
-      : super(
-            kind: kind,
-            local: local,
-            setters: setters,
-            parent: parent,
-            debugName: debugName,
-            isModifiable: isModifiable);
-
-  /// Override this method to lazily populate the scope before access.
-  void ensureScope();
-
-  @override
-  Map<String, Builder>? get _local {
-    ensureScope();
-    return super._local;
-  }
-
-  @override
-  Map<String, MemberBuilder>? get _setters {
-    ensureScope();
-    return super._setters;
-  }
-
-  @override
-  Set<ExtensionBuilder>? get _extensions {
-    ensureScope();
-    return super._extensions;
-  }
-}
-
 /// Computes a builder for the import/export collision between [declaration] and
 /// [other] and adds it to [nameSpace].
 Builder computeAmbiguousDeclarationForScope(ProblemReporting problemReporting,
@@ -1229,11 +845,7 @@
 
   Builder? _current;
 
-  ScopeIterator.fromIterators(this.local, this.setters, this.extensions);
-
-  ScopeIterator(Scope scope)
-      : this.fromIterators(scope._local?.values.iterator,
-            scope._setters?.values.iterator, scope._extensions?.iterator);
+  ScopeIterator(this.local, this.setters, this.extensions);
 
   @override
   bool moveNext() {
@@ -1291,17 +903,11 @@
 
   String? _name;
 
-  ScopeNameIterator.fromIterators(Map<String, Builder>? getables,
+  ScopeNameIterator(Map<String, Builder>? getables,
       Map<String, Builder>? setables, Iterator<Builder>? extensions)
       : localNames = getables?.keys.iterator,
         setterNames = setables?.keys.iterator,
-        super.fromIterators(
-            getables?.values.iterator, setables?.values.iterator, extensions);
-
-  ScopeNameIterator(Scope scope)
-      : localNames = scope._local?.keys.iterator,
-        setterNames = scope._setters?.keys.iterator,
-        super(scope);
+        super(getables?.values.iterator, setables?.values.iterator, extensions);
 
   @override
   bool moveNext() {
@@ -1742,15 +1348,16 @@
 }
 
 class MergedLibraryScope extends MergedScope<SourceLibraryBuilder> {
-  MergedLibraryScope(SourceLibraryBuilder origin) : super(origin, origin.scope);
+  MergedLibraryScope(SourceLibraryBuilder origin)
+      : super(origin, origin.nameSpace);
 
   @override
   SourceLibraryBuilder get originLibrary => _origin;
 
   void addAugmentationScope(SourceLibraryBuilder builder) {
-    _addAugmentationScope(builder, builder.scope,
-        augmentations: builder.scope.augmentations,
-        setterAugmentations: builder.scope.setterAugmentations,
+    _addAugmentationScope(builder, builder.nameSpace,
+        augmentations: builder.augmentations,
+        setterAugmentations: builder.setterAugmentations,
         inPatchLibrary: builder.isPatchLibrary);
   }
 
@@ -1861,8 +1468,8 @@
   //  members.
   void addAugmentationScope(SourceClassBuilder builder) {
     _addAugmentationScope(builder, builder.nameSpace,
-        augmentations: builder.augmentations,
-        setterAugmentations: builder.setterAugmentations,
+        augmentations: null,
+        setterAugmentations: null,
         inPatchLibrary: builder.libraryBuilder.isPatchLibrary);
     _addAugmentationConstructorScope(builder.constructorScope,
         inPatchLibrary: builder.libraryBuilder.isPatchLibrary);
diff --git a/pkg/front_end/lib/src/builder/library_builder.dart b/pkg/front_end/lib/src/builder/library_builder.dart
index 53f5dff..b0bc251 100644
--- a/pkg/front_end/lib/src/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/builder/library_builder.dart
@@ -259,11 +259,11 @@
 }
 
 abstract class LibraryBuilder implements Builder, ProblemReporting {
-  Scope get scope;
+  LookupScope get scope;
 
   NameSpace get nameSpace;
 
-  NameSpace get exportScope;
+  NameSpace get exportNameSpace;
 
   List<Export> get exporters;
 
@@ -461,7 +461,7 @@
     if (name.startsWith("_")) return false;
     if (member is PrefixBuilder) return false;
     Builder? existing =
-        exportScope.lookupLocalMember(name, setter: member.isSetter);
+        exportNameSpace.lookupLocalMember(name, setter: member.isSetter);
     if (existing == member) {
       return false;
     } else {
@@ -469,10 +469,10 @@
         Builder result = computeAmbiguousDeclarationForScope(
             this, nameSpace, name, existing, member,
             uriOffset: uriOffset, isExport: true);
-        exportScope.addLocalMember(name, result, setter: member.isSetter);
+        exportNameSpace.addLocalMember(name, result, setter: member.isSetter);
         return result != existing;
       } else {
-        exportScope.addLocalMember(name, member, setter: member.isSetter);
+        exportNameSpace.addLocalMember(name, member, setter: member.isSetter);
         return true;
       }
     }
@@ -489,7 +489,7 @@
           -1,
           null);
     }
-    Builder? cls = (bypassLibraryPrivacy ? nameSpace : exportScope)
+    Builder? cls = (bypassLibraryPrivacy ? nameSpace : exportNameSpace)
         .lookupLocalMember(className, setter: false);
     if (cls is TypeAliasBuilder) {
       // Coverage-ignore-block(suite): Not run.
diff --git a/pkg/front_end/lib/src/builder/prefix_builder.dart b/pkg/front_end/lib/src/builder/prefix_builder.dart
index fb8c795..7631370 100644
--- a/pkg/front_end/lib/src/builder/prefix_builder.dart
+++ b/pkg/front_end/lib/src/builder/prefix_builder.dart
@@ -75,7 +75,7 @@
     if (existing != null) {
       // Coverage-ignore-block(suite): Not run.
       result = computeAmbiguousDeclarationForScope(
-          parent, parent.scope, name, existing, member,
+          parent, parent.nameSpace, name, existing, member,
           uriOffset: new UriOffset(fileUri, charOffset), isExport: true);
     } else {
       result = member;
diff --git a/pkg/front_end/lib/src/dill/dill_library_builder.dart b/pkg/front_end/lib/src/dill/dill_library_builder.dart
index b510e9b..687abb0 100644
--- a/pkg/front_end/lib/src/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/dill/dill_library_builder.dart
@@ -33,19 +33,6 @@
 import 'dill_member_builder.dart';
 import 'dill_type_alias_builder.dart' show DillTypeAliasBuilder;
 
-class LazyLibraryScope extends LazyScope {
-  final DillLibraryBuilder libraryBuilder;
-
-  LazyLibraryScope.top(this.libraryBuilder)
-      : super(<String, Builder>{}, <String, MemberBuilder>{}, null, "top",
-            isModifiable: false, kind: ScopeKind.library);
-
-  @override
-  void ensureScope() {
-    libraryBuilder.ensureLoaded();
-  }
-}
-
 class DillCompilationUnitImpl extends DillCompilationUnit {
   final DillLibraryBuilder _dillLibraryBuilder;
 
@@ -116,7 +103,9 @@
 }
 
 class DillLibraryBuilder extends LibraryBuilderImpl {
-  late final LazyLibraryScope _scope;
+  late final LookupScope _scope;
+
+  late final DillLibraryNameSpace _nameSpace;
 
   late final DillExportNameSpace _exportScope;
 
@@ -144,18 +133,19 @@
   bool isBuiltAndMarked = false;
 
   DillLibraryBuilder(this.library, this.loader) : super(library.fileUri) {
-    _scope = new LazyLibraryScope.top(this);
+    _nameSpace = new DillLibraryNameSpace(this);
+    _scope = new NameSpaceLookupScope(_nameSpace, ScopeKind.library, 'top');
     _exportScope = new DillExportNameSpace(this);
   }
 
   @override
-  Scope get scope => _scope;
+  LookupScope get scope => _scope;
 
   @override
-  NameSpace get nameSpace => _scope;
+  NameSpace get nameSpace => _nameSpace;
 
   @override
-  NameSpace get exportScope => _exportScope;
+  NameSpace get exportNameSpace => _exportScope;
 
   @override
   List<Export> get exporters => mainCompilationUnit.exporters;
@@ -360,10 +350,10 @@
     }
     if (!name.startsWith("_") && !name.contains('#')) {
       if (isSetter) {
-        exportScope.addLocalMember(name, declaration as MemberBuilder,
+        exportNameSpace.addLocalMember(name, declaration as MemberBuilder,
             setter: true);
       } else {
-        exportScope.addLocalMember(name, declaration, setter: false);
+        exportNameSpace.addLocalMember(name, declaration, setter: false);
       }
     }
     return declaration;
@@ -396,13 +386,13 @@
         assert(
             name == 'dynamic', // Coverage-ignore(suite): Not run.
             "Unexpected export name for 'dynamic': '$name'");
-        declaration = loader.coreLibrary.exportScope
+        declaration = loader.coreLibrary.exportNameSpace
             .lookupLocalMember(name, setter: false)!;
       } else if (messageText == exportNeverSentinel) {
         assert(
             name == 'Never', // Coverage-ignore(suite): Not run.
             "Unexpected export name for 'Never': '$name'");
-        declaration = loader.coreLibrary.exportScope
+        declaration = loader.coreLibrary.exportNameSpace
             .lookupLocalMember(name, setter: false)!;
       } else {
         Message message = templateUnspecified.withArguments(messageText);
@@ -412,7 +402,7 @@
         declaration =
             new InvalidTypeDeclarationBuilder(name, message.withoutLocation());
       }
-      exportScope.addLocalMember(name, declaration, setter: false);
+      exportNameSpace.addLocalMember(name, declaration, setter: false);
     });
 
     Map<Reference, Builder>? sourceBuildersMap =
@@ -434,10 +424,10 @@
         }
 
         if (declaration.isSetter) {
-          exportScope.addLocalMember(name, declaration as MemberBuilder,
+          exportNameSpace.addLocalMember(name, declaration as MemberBuilder,
               setter: true);
         } else {
-          exportScope.addLocalMember(name, declaration, setter: false);
+          exportNameSpace.addLocalMember(name, declaration, setter: false);
         }
       } else {
         Uri libraryUri;
@@ -474,13 +464,13 @@
         }
         if (isSetter) {
           declaration =
-              library.exportScope.lookupLocalMember(name, setter: true)!;
-          exportScope.addLocalMember(name, declaration as MemberBuilder,
+              library.exportNameSpace.lookupLocalMember(name, setter: true)!;
+          exportNameSpace.addLocalMember(name, declaration as MemberBuilder,
               setter: true);
         } else {
           declaration =
-              library.exportScope.lookupLocalMember(name, setter: false)!;
-          exportScope.addLocalMember(name, declaration, setter: false);
+              library.exportNameSpace.lookupLocalMember(name, setter: false)!;
+          exportNameSpace.addLocalMember(name, declaration, setter: false);
         }
       }
 
diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart
index 6aff9c2..02c3aa7 100644
--- a/pkg/front_end/lib/src/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/kernel/body_builder.dart
@@ -4944,9 +4944,11 @@
       for (int i = 0; i < setOrMapEntries.length; ++i) {
         if (setOrMapEntries[i] is MapLiteralEntry) {
           mapEntries[i] = setOrMapEntries[i];
-        } else {
+        } else if (setOrMapEntries[i] is ControlFlowElement) {
           mapEntries[i] = convertToMapEntry(setOrMapEntries[i], this,
               typeInferrer.assignedVariables.reassignInfo);
+        } else {
+          mapEntries[i] = convertToErroneousMapEntry(setOrMapEntries[i], this);
         }
       }
       buildLiteralMap(typeArguments, constKeyword, leftBrace, mapEntries);
diff --git a/pkg/front_end/lib/src/kernel/collections.dart b/pkg/front_end/lib/src/kernel/collections.dart
index 2364008..be47825 100644
--- a/pkg/front_end/lib/src/kernel/collections.dart
+++ b/pkg/front_end/lib/src/kernel/collections.dart
@@ -12,15 +12,39 @@
     show noLength, templateExpectedAfterButGot, templateExpectedButGot;
 import '../base/problems.dart' show getFileUri, unsupported;
 import '../type_inference/inference_helper.dart' show InferenceHelper;
+import '../type_inference/inference_results.dart';
+import '../type_inference/inference_visitor.dart';
 import 'internal_ast.dart';
 
+/// Base class for all control-flow elements.
+sealed class ControlFlowElement extends AuxiliaryExpression {
+  /// Returns this control flow element as a [MapLiteralEntry], or `null` if
+  /// this control flow element cannot be converted into a [MapLiteralEntry].
+  ///
+  /// [onConvertElement] is called when a [ForElement], [ForInElement], or
+  /// [IfElement] is converted to a [ForMapEntry], [ForInMapEntry], or
+  /// [IfMapEntry], respectively.
+  // TODO(johnniwinther): Merge this with [convertToMapEntry].
+  MapLiteralEntry? toMapLiteralEntry(
+      void onConvertElement(TreeNode from, TreeNode to));
+}
+
+/// Base class for control-flow elements with default internal implementations.
+///
+/// Such elements are, for example, control-flow elements containing patterns.
+sealed class ControlFlowElementImpl extends InternalExpression
+    implements ControlFlowElement {}
+
 /// Mixin for spread and control-flow elements.
 ///
 /// Spread and control-flow elements are not truly expressions and they cannot
 /// appear in arbitrary expression contexts in the Kernel program.  They can
 /// only appear as elements in list or set literals.  They are translated into
 /// a lower-level representation and never serialized to .dill files.
-mixin ControlFlowElement on AuxiliaryExpression {
+///
+/// [ControlFlowElementMixin] doesn't use [ControlFlowElement] as its `on`-type
+/// to avoid being required in switch-statements over [ControlFlowElement]s.
+mixin ControlFlowElementMixin on AuxiliaryExpression {
   /// Spread and control-flow elements are not expressions and do not have a
   /// static type.
   @override
@@ -43,20 +67,10 @@
   // Coverage-ignore(suite): Not run.
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
       v.visitAuxiliaryExpression(this, arg);
-
-  /// Returns this control flow element as a [MapLiteralEntry], or `null` if
-  /// this control flow element cannot be converted into a [MapLiteralEntry].
-  ///
-  /// [onConvertElement] is called when a [ForElement], [ForInElement], or
-  /// [IfElement] is converted to a [ForMapEntry], [ForInMapEntry], or
-  /// [IfMapEntry], respectively.
-  // TODO(johnniwinther): Merge this with [convertToMapEntry].
-  MapLiteralEntry? toMapLiteralEntry(
-      void onConvertElement(TreeNode from, TreeNode to));
 }
 
 /// A spread element in a list or set literal.
-class SpreadElement extends AuxiliaryExpression with ControlFlowElement {
+class SpreadElement extends ControlFlowElement with ControlFlowElementMixin {
   Expression expression;
   bool isNullAware;
 
@@ -113,7 +127,7 @@
   }
 }
 
-class NullAwareElement extends AuxiliaryExpression with ControlFlowElement {
+class NullAwareElement extends ControlFlowElement with ControlFlowElementMixin {
   Expression expression;
 
   NullAwareElement(this.expression);
@@ -154,7 +168,7 @@
 }
 
 /// An 'if' element in a list or set literal.
-class IfElement extends AuxiliaryExpression with ControlFlowElement {
+class IfElement extends ControlFlowElement with ControlFlowElementMixin {
   Expression condition;
   Expression then;
   Expression? otherwise;
@@ -245,7 +259,7 @@
 }
 
 /// A 'for' element in a list or set literal.
-class ForElement extends AuxiliaryExpression with ControlFlowElement {
+class ForElement extends ControlFlowElement with ControlFlowElementMixin {
   final List<VariableDeclaration> variables; // May be empty, but not null.
   Expression? condition; // May be null.
   final List<Expression> updates; // May be empty, but not null.
@@ -338,7 +352,7 @@
 }
 
 /// A 'for-in' element in a list or set literal.
-class ForInElement extends AuxiliaryExpression with ControlFlowElement {
+class ForInElement extends ControlFlowElement with ControlFlowElementMixin {
   VariableDeclaration variable; // Has no initializer.
   Expression iterable;
   Expression? syntheticAssignment; // May be null.
@@ -451,6 +465,157 @@
   }
 }
 
+class IfCaseElement extends ControlFlowElementImpl
+    with ControlFlowElementMixin {
+  Expression expression;
+  PatternGuard patternGuard;
+  Expression then;
+  Expression? otherwise;
+  List<Statement> prelude;
+
+  /// The type of the expression against which this pattern is matched.
+  ///
+  /// This is set during inference.
+  DartType? matchedValueType;
+
+  IfCaseElement(
+      {required this.prelude,
+      required this.expression,
+      required this.patternGuard,
+      required this.then,
+      this.otherwise}) {
+    setParents(prelude, this);
+    expression.parent = this;
+    patternGuard.parent = this;
+    then.parent = this;
+    otherwise?.parent = this;
+  }
+
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitorImpl visitor, DartType typeContext) {
+    throw new UnsupportedError("IfCaseElement.acceptInference");
+  }
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  void toTextInternal(AstPrinter printer) {
+    printer.write('if (');
+    printer.writeExpression(expression);
+    printer.write(' case ');
+    patternGuard.toTextInternal(printer);
+    printer.write(') ');
+    printer.writeExpression(then);
+    if (otherwise != null) {
+      printer.write(' else ');
+      printer.writeExpression(otherwise!);
+    }
+  }
+
+  @override
+  MapLiteralEntry? toMapLiteralEntry(
+      void Function(TreeNode from, TreeNode to) onConvertElement) {
+    MapLiteralEntry? thenEntry;
+    Expression then = this.then;
+    if (then is ControlFlowElement) {
+      ControlFlowElement thenElement = then;
+      thenEntry = thenElement.toMapLiteralEntry(onConvertElement);
+    }
+    if (thenEntry == null) return null;
+    MapLiteralEntry? otherwiseEntry;
+    Expression? otherwise = this.otherwise;
+    if (otherwise != null) {
+      // Coverage-ignore-block(suite): Not run.
+      if (otherwise is ControlFlowElement) {
+        ControlFlowElement otherwiseElement = otherwise;
+        otherwiseEntry = otherwiseElement.toMapLiteralEntry(onConvertElement);
+      }
+      if (otherwiseEntry == null) return null;
+    }
+    IfCaseMapEntry result = new IfCaseMapEntry(
+        prelude: prelude,
+        expression: expression,
+        patternGuard: patternGuard,
+        then: thenEntry,
+        otherwise: otherwiseEntry)
+      ..matchedValueType = matchedValueType
+      ..fileOffset = fileOffset;
+    onConvertElement(this, result);
+    return result;
+  }
+
+  @override
+  String toString() {
+    return "IfCaseElement(${toStringInternal()})";
+  }
+}
+
+class PatternForElement extends ControlFlowElementImpl
+    with ControlFlowElementMixin
+    implements ForElement {
+  PatternVariableDeclaration patternVariableDeclaration;
+  List<VariableDeclaration> intermediateVariables;
+
+  @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;
+
+  PatternForElement(
+      {required this.patternVariableDeclaration,
+      required this.intermediateVariables,
+      required this.variables,
+      required this.condition,
+      required this.updates,
+      required this.body});
+
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitorImpl visitor, DartType typeContext) {
+    throw new UnsupportedError("PatternForElement.acceptInference");
+  }
+
+  @override
+  // Coverage-ignore(suite): Not run.
+  void toTextInternal(AstPrinter printer) {
+    patternVariableDeclaration.toTextInternal(printer);
+    printer.write('for (');
+    for (int index = 0; index < variables.length; index++) {
+      if (index > 0) {
+        printer.write(', ');
+      }
+      printer.writeVariableDeclaration(variables[index],
+          includeModifiersAndType: index == 0);
+    }
+    printer.write('; ');
+    if (condition != null) {
+      printer.writeExpression(condition!);
+    }
+    printer.write('; ');
+    printer.writeExpressions(updates);
+    printer.write(') ');
+    printer.writeExpression(body);
+  }
+
+  @override
+  MapLiteralEntry? toMapLiteralEntry(
+      void Function(TreeNode from, TreeNode to) onConvertElement) {
+    throw new UnimplementedError("toMapLiteralEntry");
+  }
+
+  @override
+  String toString() {
+    return "PatternForElement(${toStringInternal()})";
+  }
+}
+
 mixin ControlFlowMapEntry implements MapLiteralEntry {
   @override
   Expression get key {
@@ -874,30 +1039,29 @@
 }
 
 bool isConvertibleToMapEntry(Expression element) {
-  if (element is SpreadElement) return true;
-  if (element is NullAwareElement) return false;
-  if (element is IfElement) {
-    return isConvertibleToMapEntry(element.then) &&
-        (element.otherwise == null ||
-            isConvertibleToMapEntry(element.otherwise!));
+  if (element is ControlFlowElement) {
+    switch (element) {
+      case SpreadElement():
+        return true;
+      case NullAwareElement():
+        return false;
+      case IfElement():
+        return isConvertibleToMapEntry(element.then) &&
+            (element.otherwise == null ||
+                isConvertibleToMapEntry(element.otherwise!));
+      case IfCaseElement():
+        return isConvertibleToMapEntry(element.then) &&
+            (element.otherwise == null ||
+                // Coverage-ignore(suite): Not run.
+                isConvertibleToMapEntry(element.otherwise!));
+      case ForElement():
+        return isConvertibleToMapEntry(element.body);
+      case ForInElement():
+        return isConvertibleToMapEntry(element.body);
+    }
+  } else {
+    return false;
   }
-  if (element is IfCaseElement) {
-    return isConvertibleToMapEntry(element.then) &&
-        (element.otherwise == null ||
-            // Coverage-ignore(suite): Not run.
-            isConvertibleToMapEntry(element.otherwise!));
-  }
-  if (element is ForElement) {
-    return isConvertibleToMapEntry(element.body);
-  }
-  if (element is PatternForElement) {
-    // Coverage-ignore-block(suite): Not run.
-    return isConvertibleToMapEntry(element.body);
-  }
-  if (element is ForInElement) {
-    return isConvertibleToMapEntry(element.body);
-  }
-  return false;
 }
 
 /// Convert [element] to a [MapLiteralEntry], if possible. If [element] cannot
@@ -907,76 +1071,96 @@
 /// [onConvertElement] is called when a [ForElement], [ForInElement], or
 /// [IfElement] is converted to a [ForMapEntry], [ForInMapEntry], or
 /// [IfMapEntry], respectively.
-MapLiteralEntry convertToMapEntry(Expression element, InferenceHelper helper,
-    void onConvertElement(TreeNode from, TreeNode to)) {
-  if (element is SpreadElement) {
-    return new SpreadMapEntry(element.expression,
-        isNullAware: element.isNullAware)
-      ..fileOffset = element.expression.fileOffset;
-  }
-  if (element is IfElement) {
-    IfMapEntry result = new IfMapEntry(
-        element.condition,
-        convertToMapEntry(element.then, helper, onConvertElement),
-        element.otherwise == null
-            ? null
-            : convertToMapEntry(element.otherwise!, helper, onConvertElement))
-      ..fileOffset = element.fileOffset;
-    onConvertElement(element, result);
-    return result;
-  }
-  if (element is IfCaseElement) {
-    IfCaseMapEntry result = new IfCaseMapEntry(
-        prelude: [],
-        expression: element.expression,
-        patternGuard: element.patternGuard,
-        then: convertToMapEntry(element.then, helper, onConvertElement),
-        otherwise: element.otherwise == null
-            ? null
-            :
-            // Coverage-ignore(suite): Not run.
-            convertToMapEntry(element.otherwise!, helper, onConvertElement))
-      ..matchedValueType = element.matchedValueType
-      ..fileOffset = element.fileOffset;
-    onConvertElement(element, result);
-    return result;
-  }
-  if (element is ForElement) {
-    if (element is PatternForElement) {
+MapLiteralEntry convertToMapEntry(ControlFlowElement element,
+    InferenceHelper helper, void onConvertElement(TreeNode from, TreeNode to)) {
+  switch (element) {
+    case SpreadElement():
+      return new SpreadMapEntry(element.expression,
+          isNullAware: element.isNullAware)
+        ..fileOffset = element.expression.fileOffset;
+
+    case NullAwareElement():
+      return convertToErroneousMapEntry(element, helper);
+
+    case IfElement():
+      IfMapEntry result = new IfMapEntry(
+          element.condition,
+          _convertNestedToMapEntry(element.then, helper, onConvertElement),
+          element.otherwise == null
+              ? null
+              : _convertNestedToMapEntry(
+                  element.otherwise!, helper, onConvertElement))
+        ..fileOffset = element.fileOffset;
+      onConvertElement(element, result);
+      return result;
+
+    case IfCaseElement():
+      IfCaseMapEntry result = new IfCaseMapEntry(
+          prelude: [],
+          expression: element.expression,
+          patternGuard: element.patternGuard,
+          then:
+              _convertNestedToMapEntry(element.then, helper, onConvertElement),
+          otherwise: element.otherwise == null
+              ? null
+              :
+              // Coverage-ignore(suite): Not run.
+              _convertNestedToMapEntry(
+                  element.otherwise!, helper, onConvertElement))
+        ..matchedValueType = element.matchedValueType
+        ..fileOffset = element.fileOffset;
+      onConvertElement(element, result);
+      return result;
+
+    case PatternForElement():
       PatternForMapEntry result = new PatternForMapEntry(
           patternVariableDeclaration: element.patternVariableDeclaration,
           intermediateVariables: element.intermediateVariables,
           variables: element.variables,
           condition: element.condition,
           updates: element.updates,
-          body: convertToMapEntry(element.body, helper, onConvertElement))
+          body:
+              _convertNestedToMapEntry(element.body, helper, onConvertElement))
         ..fileOffset = element.fileOffset;
       onConvertElement(element, result);
       return result;
-    }
-    ForMapEntry result = new ForMapEntry(
-        element.variables,
-        element.condition,
-        element.updates,
-        convertToMapEntry(element.body, helper, onConvertElement))
-      ..fileOffset = element.fileOffset;
-    onConvertElement(element, result);
-    return result;
+
+    case ForElement():
+      ForMapEntry result = new ForMapEntry(
+          element.variables,
+          element.condition,
+          element.updates,
+          _convertNestedToMapEntry(element.body, helper, onConvertElement))
+        ..fileOffset = element.fileOffset;
+      onConvertElement(element, result);
+      return result;
+
+    case ForInElement():
+      ForInMapEntry result = new ForInMapEntry(
+          element.variable,
+          element.iterable,
+          element.syntheticAssignment,
+          element.expressionEffects,
+          _convertNestedToMapEntry(element.body, helper, onConvertElement),
+          element.problem,
+          isAsync: element.isAsync)
+        ..fileOffset = element.fileOffset;
+      onConvertElement(element, result);
+      return result;
   }
-  if (element is ForInElement) {
-    ForInMapEntry result = new ForInMapEntry(
-        element.variable,
-        element.iterable,
-        element.syntheticAssignment,
-        element.expressionEffects,
-        convertToMapEntry(element.body, helper, onConvertElement),
-        element.problem,
-        isAsync: element.isAsync)
-      ..fileOffset = element.fileOffset;
-    onConvertElement(element, result);
-    return result;
+}
+
+MapLiteralEntry _convertNestedToMapEntry(Expression element,
+    InferenceHelper helper, void onConvertElement(TreeNode from, TreeNode to)) {
+  if (element is ControlFlowElement) {
+    return convertToMapEntry(element, helper, onConvertElement);
+  } else {
+    return convertToErroneousMapEntry(element, helper);
   }
-  // Coverage-ignore(suite): Not run.
+}
+
+MapLiteralEntry convertToErroneousMapEntry(
+    Expression element, InferenceHelper helper) {
   return new MapLiteralEntry(
       helper.buildProblem(
         templateExpectedAfterButGot.withArguments(':'),
diff --git a/pkg/front_end/lib/src/kernel/forest.dart b/pkg/front_end/lib/src/kernel/forest.dart
index b57c13d..18a1c26 100644
--- a/pkg/front_end/lib/src/kernel/forest.dart
+++ b/pkg/front_end/lib/src/kernel/forest.dart
@@ -17,9 +17,11 @@
         ForInElement,
         ForInMapEntry,
         ForMapEntry,
+        IfCaseElement,
         IfElement,
         IfMapEntry,
         NullAwareElement,
+        PatternForElement,
         SpreadElement;
 
 import 'internal_ast.dart';
diff --git a/pkg/front_end/lib/src/kernel/internal_ast.dart b/pkg/front_end/lib/src/kernel/internal_ast.dart
index 604ec03..dec3e4f 100644
--- a/pkg/front_end/lib/src/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/kernel/internal_ast.dart
@@ -3124,90 +3124,6 @@
   }
 }
 
-class IfCaseElement extends InternalExpression with ControlFlowElement {
-  Expression expression;
-  PatternGuard patternGuard;
-  Expression then;
-  Expression? otherwise;
-  List<Statement> prelude;
-
-  /// The type of the expression against which this pattern is matched.
-  ///
-  /// This is set during inference.
-  DartType? matchedValueType;
-
-  IfCaseElement(
-      {required this.prelude,
-      required this.expression,
-      required this.patternGuard,
-      required this.then,
-      this.otherwise}) {
-    setParents(prelude, this);
-    expression.parent = this;
-    patternGuard.parent = this;
-    then.parent = this;
-    otherwise?.parent = this;
-  }
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitorImpl visitor, DartType typeContext) {
-    throw new UnsupportedError("IfCaseElement.acceptInference");
-  }
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  void toTextInternal(AstPrinter printer) {
-    printer.write('if (');
-    printer.writeExpression(expression);
-    printer.write(' case ');
-    patternGuard.toTextInternal(printer);
-    printer.write(') ');
-    printer.writeExpression(then);
-    if (otherwise != null) {
-      printer.write(' else ');
-      printer.writeExpression(otherwise!);
-    }
-  }
-
-  @override
-  MapLiteralEntry? toMapLiteralEntry(
-      void Function(TreeNode from, TreeNode to) onConvertElement) {
-    MapLiteralEntry? thenEntry;
-    Expression then = this.then;
-    if (then is ControlFlowElement) {
-      ControlFlowElement thenElement = then;
-      thenEntry = thenElement.toMapLiteralEntry(onConvertElement);
-    }
-    if (thenEntry == null) return null;
-    MapLiteralEntry? otherwiseEntry;
-    Expression? otherwise = this.otherwise;
-    if (otherwise != null) {
-      // Coverage-ignore-block(suite): Not run.
-      if (otherwise is ControlFlowElement) {
-        ControlFlowElement otherwiseElement = otherwise;
-        otherwiseEntry = otherwiseElement.toMapLiteralEntry(onConvertElement);
-      }
-      if (otherwiseEntry == null) return null;
-    }
-    IfCaseMapEntry result = new IfCaseMapEntry(
-        prelude: prelude,
-        expression: expression,
-        patternGuard: patternGuard,
-        then: thenEntry,
-        otherwise: otherwiseEntry)
-      ..matchedValueType = matchedValueType
-      ..fileOffset = fileOffset;
-    onConvertElement(this, result);
-    return result;
-  }
-
-  @override
-  String toString() {
-    return "IfCaseElement(${toStringInternal()})";
-  }
-}
-
 class IfCaseMapEntry extends TreeNode
     with InternalTreeNode, ControlFlowMapEntry {
   Expression expression;
@@ -3254,72 +3170,6 @@
   }
 }
 
-class PatternForElement extends InternalExpression
-    with ControlFlowElement
-    implements ForElement {
-  PatternVariableDeclaration patternVariableDeclaration;
-  List<VariableDeclaration> intermediateVariables;
-
-  @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;
-
-  PatternForElement(
-      {required this.patternVariableDeclaration,
-      required this.intermediateVariables,
-      required this.variables,
-      required this.condition,
-      required this.updates,
-      required this.body});
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitorImpl visitor, DartType typeContext) {
-    throw new UnsupportedError("PatternForElement.acceptInference");
-  }
-
-  @override
-  // Coverage-ignore(suite): Not run.
-  void toTextInternal(AstPrinter printer) {
-    patternVariableDeclaration.toTextInternal(printer);
-    printer.write('for (');
-    for (int index = 0; index < variables.length; index++) {
-      if (index > 0) {
-        printer.write(', ');
-      }
-      printer.writeVariableDeclaration(variables[index],
-          includeModifiersAndType: index == 0);
-    }
-    printer.write('; ');
-    if (condition != null) {
-      printer.writeExpression(condition!);
-    }
-    printer.write('; ');
-    printer.writeExpressions(updates);
-    printer.write(') ');
-    printer.writeExpression(body);
-  }
-
-  @override
-  MapLiteralEntry? toMapLiteralEntry(
-      void Function(TreeNode from, TreeNode to) onConvertElement) {
-    throw new UnimplementedError("toMapLiteralEntry");
-  }
-
-  @override
-  String toString() {
-    return "PatternForElement(${toStringInternal()})";
-  }
-}
-
 class PatternForMapEntry extends TreeNode
     with InternalTreeNode, ControlFlowMapEntry
     implements ForMapEntry {
diff --git a/pkg/front_end/lib/src/kernel/kernel_target.dart b/pkg/front_end/lib/src/kernel/kernel_target.dart
index e9a63d0..80a15a9 100644
--- a/pkg/front_end/lib/src/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/kernel/kernel_target.dart
@@ -862,7 +862,7 @@
     if (firstRoot != null) {
       // TODO(sigmund): do only for full program
       Builder? declaration =
-          firstRoot.exportScope.lookupLocalMember("main", setter: false);
+          firstRoot.exportNameSpace.lookupLocalMember("main", setter: false);
       if (declaration is AmbiguousBuilder) {
         // Coverage-ignore-block(suite): Not run.
         AmbiguousBuilder problem = declaration;
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 ce75071..aebe429 100644
--- a/pkg/front_end/lib/src/source/source_builder_factory.dart
+++ b/pkg/front_end/lib/src/source/source_builder_factory.dart
@@ -136,7 +136,9 @@
 
   final LibraryName libraryName;
 
-  final Scope scope;
+  final LookupScope _scope;
+
+  final NameSpace _nameSpace;
 
   BuilderFactoryImpl(
       {required SourceCompilationUnit compilationUnit,
@@ -144,7 +146,8 @@
       required SourceLibraryBuilder parent,
       required TypeParameterScopeBuilder libraryTypeParameterScopeBuilder,
       required ProblemReporting problemReporting,
-      required Scope scope,
+      required LookupScope scope,
+      required NameSpace nameSpace,
       required LibraryName libraryName,
       required IndexedLibrary? indexedLibrary,
       required Map<String, Builder>? omittedTypeDeclarationBuilders})
@@ -154,7 +157,8 @@
         currentTypeParameterScopeBuilder = libraryTypeParameterScopeBuilder,
         _problemReporting = problemReporting,
         _parent = parent,
-        scope = scope,
+        _scope = scope,
+        _nameSpace = nameSpace,
         libraryName = libraryName,
         indexedLibrary = indexedLibrary,
         _omittedTypeDeclarationBuilders = omittedTypeDeclarationBuilders;
@@ -509,7 +513,7 @@
     Map<String, MemberBuilder> setters = declaration.setters!;
 
     LookupScope typeParameterScope =
-        TypeParameterScope.fromList(scope, typeVariables);
+        TypeParameterScope.fromList(_scope, typeVariables);
     NameSpace enumNameSpace =
         new NameSpaceImpl(getables: members, setables: setters);
     SourceEnumBuilder enumBuilder = new SourceEnumBuilder(
@@ -665,7 +669,7 @@
     Map<String, MemberBuilder> setters = declaration.setters!;
 
     LookupScope typeParameterScope =
-        TypeParameterScope.fromList(scope, typeVariables);
+        TypeParameterScope.fromList(_scope, typeVariables);
     NameSpace classNameSpace =
         new NameSpaceImpl(getables: members, setables: setters);
 
@@ -1061,7 +1065,7 @@
         }
 
         LookupScope typeParameterScope =
-            TypeParameterScope.fromList(scope, typeVariables);
+            TypeParameterScope.fromList(_scope, typeVariables);
         NameSpace nameSpace = new NameSpaceImpl();
         SourceClassBuilder application = new SourceClassBuilder(
             isNamedMixinApplication ? metadata : null,
@@ -1151,7 +1155,7 @@
     Map<String, MemberBuilder> setters = declaration.setters!;
 
     LookupScope typeParameterScope =
-        TypeParameterScope.fromList(scope, typeVariables);
+        TypeParameterScope.fromList(_scope, typeVariables);
     NameSpace extensionNameSpace =
         new NameSpaceImpl(getables: members, setables: setters);
 
@@ -1235,7 +1239,7 @@
     Map<String, MemberBuilder> setters = declaration.setters!;
 
     LookupScope typeParameterScope =
-        TypeParameterScope.fromList(scope, typeVariables);
+        TypeParameterScope.fromList(_scope, typeVariables);
     NameSpace extensionTypeNameSpace =
         new NameSpaceImpl(getables: members, setables: setters);
     ConstructorScope constructorScope =
@@ -2364,7 +2368,7 @@
                       _compilationUnit.fileUri, other!.charOffset, noLength)
             ]);
       }
-      existing.mergeScopes(declaration, _problemReporting, scope,
+      existing.mergeScopes(declaration, _problemReporting, _nameSpace,
           uriOffset: new UriOffset(_compilationUnit.fileUri, charOffset));
       return existing;
     } else if (_isDuplicatedDeclaration(existing, declaration)) {
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 7ea41b3..4845480 100644
--- a/pkg/front_end/lib/src/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/source/source_class_builder.dart
@@ -211,12 +211,6 @@
   @override
   NameSpace get nameSpace => _nameSpace;
 
-  // TODO(johnniwinther): Remove this.
-  Map<String, List<Builder>>? get augmentations => null;
-
-  // TODO(johnniwinther): Remove this.
-  Map<String, List<Builder>>? get setterAugmentations => null;
-
   MergedClassMemberScope get mergedScope => _mergedScope ??= isAugmenting
       ?
       // Coverage-ignore(suite): Not run.
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 8c20449..f4ca1c9 100644
--- a/pkg/front_end/lib/src/source/source_compilation_unit.dart
+++ b/pkg/front_end/lib/src/source/source_compilation_unit.dart
@@ -66,7 +66,7 @@
 
   late final BuilderFactoryResult _builderFactoryResult;
 
-  final NameSpace _importScope;
+  final NameSpace _importNameSpace;
 
   LibraryFeatures? _libraryFeatures;
 
@@ -92,7 +92,7 @@
       required this.indexedLibrary,
       required LibraryName libraryName,
       Map<String, Builder>? omittedTypeDeclarationBuilders,
-      required NameSpace importScope,
+      required NameSpace importNameSpace,
       required this.forAugmentationLibrary,
       required this.forPatchLibrary,
       required this.isAugmenting,
@@ -101,7 +101,7 @@
       : _libraryName = libraryName,
         _languageVersion = packageLanguageVersion,
         _packageUri = packageUri,
-        _importScope = importScope {
+        _importNameSpace = importNameSpace {
     // TODO(johnniwinther): Create these in [createOutlineBuilder].
     _builderFactoryResult = _builderFactory = new BuilderFactoryImpl(
         compilationUnit: this,
@@ -110,6 +110,7 @@
         libraryTypeParameterScopeBuilder: libraryTypeParameterScopeBuilder,
         problemReporting: this,
         scope: _scope,
+        nameSpace: _nameSpace,
         libraryName: _libraryName,
         indexedLibrary: indexedLibrary,
         omittedTypeDeclarationBuilders: omittedTypeDeclarationBuilders);
@@ -405,7 +406,9 @@
   @override
   Uri? get partOfUri => _builderFactoryResult.partOfUri;
 
-  Scope get _scope => _sourceLibraryBuilder.scope;
+  LookupScope get _scope => _sourceLibraryBuilder.scope;
+
+  NameSpace get _nameSpace => _sourceLibraryBuilder.nameSpace;
 
   @override
   void takeMixinApplications(
@@ -620,7 +623,14 @@
     }
     libraryBuilder.unresolvedNamedTypes.addAll(unresolvedNamedTypes);
     _libraryName.reference = libraryBuilder.libraryName.reference;
-    _scope.becomePartOf(libraryBuilder.scope);
+
+    // TODO(johnniwinther): Avoid these. The compilation unit should not have
+    // a name space and its import scope should be nested within its parent's
+    // import scope.
+    _sourceLibraryBuilder._nameSpace = libraryBuilder.nameSpace;
+    _sourceLibraryBuilder._scope.replaceNameSpaceAndParent(
+        libraryBuilder.nameSpace, libraryBuilder._importScope);
+
     // TODO(ahe): Include metadata from part?
 
     // Recovery: Take on all exporters (i.e. if a library has erroneously
@@ -735,7 +745,7 @@
       import.finalizeImports(this);
     }
     if (!hasCoreImport) {
-      NameIterator<Builder> iterator = loader.coreLibrary.exportScope
+      NameIterator<Builder> iterator = loader.coreLibrary.exportNameSpace
           .filteredNameIterator(
               includeDuplicates: false, includeAugmentations: false);
       while (iterator.moveNext()) {
@@ -747,22 +757,22 @@
   @override
   void addToScope(String name, Builder member, int charOffset, bool isImport) {
     Builder? existing =
-        _importScope.lookupLocalMember(name, setter: member.isSetter);
+        _importNameSpace.lookupLocalMember(name, setter: member.isSetter);
     if (existing != null) {
       if (existing != member) {
-        _importScope.addLocalMember(
+        _importNameSpace.addLocalMember(
             name,
             computeAmbiguousDeclarationForScope(
-                this, _scope, name, existing, member,
+                this, _nameSpace, name, existing, member,
                 uriOffset: new UriOffset(fileUri, charOffset),
                 isImport: isImport),
             setter: member.isSetter);
       }
     } else {
-      _importScope.addLocalMember(name, member, setter: member.isSetter);
+      _importNameSpace.addLocalMember(name, member, setter: member.isSetter);
     }
     if (member.isExtension) {
-      _importScope.addExtension(member as ExtensionBuilder);
+      _importNameSpace.addExtension(member as ExtensionBuilder);
     }
   }
 
diff --git a/pkg/front_end/lib/src/source/source_library_builder.dart b/pkg/front_end/lib/src/source/source_library_builder.dart
index 2adb45a..488607b 100644
--- a/pkg/front_end/lib/src/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/source/source_library_builder.dart
@@ -98,11 +98,13 @@
 class SourceLibraryBuilder extends LibraryBuilderImpl {
   late final SourceCompilationUnit compilationUnit;
 
-  final Scope _scope;
+  final LookupScope _importScope;
 
-  final NameSpace _nameSpace;
+  final MutableNameSpaceLookupScope _scope;
 
-  final NameSpace _exportScope;
+  NameSpace _nameSpace;
+
+  final NameSpace _exportNameSpace;
 
   @override
   final SourceLoader loader;
@@ -187,6 +189,12 @@
   /// if [SourceLoader.computeFieldPromotability] hasn't been called.
   FieldNonPromotabilityInfo? fieldNonPromotabilityInfo;
 
+  // TODO(johnniwinther): Remove this.
+  final Map<String, List<Builder>>? augmentations;
+
+  // TODO(johnniwinther): Remove this.
+  final Map<String, List<Builder>>? setterAugmentations;
+
   factory SourceLibraryBuilder(
       {required Uri importUri,
       required Uri fileUri,
@@ -195,7 +203,7 @@
       required LanguageVersion packageLanguageVersion,
       required SourceLoader loader,
       SourceLibraryBuilder? origin,
-      Scope? importScope,
+      LookupScope? parentScope,
       Library? target,
       LibraryBuilder? nameOrigin,
       IndexedLibrary? indexedLibrary,
@@ -212,14 +220,23 @@
                     ? null
                     : indexedLibrary?.library.reference)
           ..setLanguageVersion(packageLanguageVersion.version));
+    LibraryName libraryName = new LibraryName(library.reference);
     TypeParameterScopeBuilder libraryTypeParameterScopeBuilder =
         new TypeParameterScopeBuilder.library();
-    importScope ??= new Scope.top(kind: ScopeKind.library);
-    LibraryName libraryName = new LibraryName(library.reference);
-    Scope scope = libraryTypeParameterScopeBuilder.toScope(importScope,
-        omittedTypeDeclarationBuilders: omittedTypes);
-    NameSpace exportScope =
-        origin?.exportScope ?? new Scope.top(kind: ScopeKind.library);
+    NameSpace? importNameSpace = new NameSpaceImpl();
+    LookupScope importScope = new NameSpaceLookupScope(
+        importNameSpace, ScopeKind.library, 'top',
+        parent: parentScope);
+    importScope = new FixedLookupScope(
+        ScopeKind.typeParameters, 'omitted-types',
+        getables: omittedTypes, parent: importScope);
+    NameSpace libraryNameSpace = libraryTypeParameterScopeBuilder.toNameSpace();
+    MutableNameSpaceLookupScope scope = new MutableNameSpaceLookupScope(
+        libraryNameSpace,
+        ScopeKind.typeParameters,
+        libraryTypeParameterScopeBuilder.name,
+        parent: importScope);
+    NameSpace exportNameSpace = origin?.exportNameSpace ?? new NameSpaceImpl();
     return new SourceLibraryBuilder._(
         loader: loader,
         importUri: importUri,
@@ -228,10 +245,11 @@
         originImportUri: originImportUri,
         packageLanguageVersion: packageLanguageVersion,
         libraryTypeParameterScopeBuilder: libraryTypeParameterScopeBuilder,
+        importNameSpace: importNameSpace,
         importScope: importScope,
         scope: scope,
-        nameSpace: scope,
-        exportScope: exportScope,
+        libraryNameSpace: libraryNameSpace,
+        exportNameSpace: exportNameSpace,
         origin: origin,
         library: library,
         libraryName: libraryName,
@@ -240,7 +258,10 @@
         isUnsupported: isUnsupported,
         isAugmentation: isAugmentation,
         isPatch: isPatch,
-        omittedTypes: omittedTypes);
+        omittedTypes: omittedTypes,
+        augmentations: libraryTypeParameterScopeBuilder.augmentations,
+        setterAugmentations:
+            libraryTypeParameterScopeBuilder.setterAugmentations);
   }
 
   SourceLibraryBuilder._(
@@ -251,10 +272,11 @@
       required Uri originImportUri,
       required LanguageVersion packageLanguageVersion,
       required TypeParameterScopeBuilder libraryTypeParameterScopeBuilder,
-      required NameSpace importScope,
-      required Scope scope,
-      required NameSpace nameSpace,
-      required NameSpace exportScope,
+      required NameSpace importNameSpace,
+      required LookupScope importScope,
+      required MutableNameSpaceLookupScope scope,
+      required NameSpace libraryNameSpace,
+      required NameSpace exportNameSpace,
       required SourceLibraryBuilder? origin,
       required this.library,
       required this.libraryName,
@@ -263,13 +285,16 @@
       required bool isUnsupported,
       required bool isAugmentation,
       required bool isPatch,
-      required Map<String, Builder>? omittedTypes})
+      required Map<String, Builder>? omittedTypes,
+      required this.augmentations,
+      required this.setterAugmentations})
       : _packageUri = packageUri,
         _immediateOrigin = origin,
         _nameOrigin = nameOrigin,
+        _importScope = importScope,
         _scope = scope,
-        _nameSpace = nameSpace,
-        _exportScope = exportScope,
+        _nameSpace = libraryNameSpace,
+        _exportNameSpace = exportNameSpace,
         super(fileUri) {
     assert(
         _packageUri == null ||
@@ -294,7 +319,7 @@
         indexedLibrary: indexedLibrary,
         libraryName: libraryName,
         omittedTypeDeclarationBuilders: omittedTypes,
-        importScope: importScope,
+        importNameSpace: importNameSpace,
         forAugmentationLibrary: isAugmentation,
         forPatchLibrary: isPatch,
         isAugmenting: origin != null,
@@ -370,13 +395,13 @@
   }
 
   @override
-  Scope get scope => _scope;
+  LookupScope get scope => _scope;
 
   @override
   NameSpace get nameSpace => _nameSpace;
 
   @override
-  NameSpace get exportScope => _exportScope;
+  NameSpace get exportNameSpace => _exportNameSpace;
 
   Iterable<SourceCompilationUnit> get parts => _parts;
 
@@ -596,7 +621,7 @@
       part.buildOutlineNode(library);
     }*/
 
-    checkMemberConflicts(this, scope,
+    checkMemberConflicts(this, nameSpace,
         checkForInstanceVsStaticConflict: false,
         checkForMethodVsSetterConflict: true);
 
@@ -660,7 +685,7 @@
       part.addImportsToScope();
     }*/
 
-    NameIterator<Builder> iterator = exportScope.filteredNameIterator(
+    NameIterator<Builder> iterator = exportNameSpace.filteredNameIterator(
         includeDuplicates: false, includeAugmentations: false);
     while (iterator.moveNext()) {
       String name = iterator.name;
diff --git a/pkg/front_end/lib/src/source/source_loader.dart b/pkg/front_end/lib/src/source/source_loader.dart
index 60d5bef..ee7a609 100644
--- a/pkg/front_end/lib/src/source/source_loader.dart
+++ b/pkg/front_end/lib/src/source/source_loader.dart
@@ -1531,7 +1531,7 @@
         both.add(exported as SourceLibraryBuilder);
       }
       for (Export export in exported.exporters) {
-        exported.exportScope
+        exported.exportNameSpace
             .filteredNameIterator(
                 includeDuplicates: false, includeAugmentations: false)
             .forEach(export.addToExportScope);
@@ -1542,7 +1542,7 @@
       wasChanged = false;
       for (SourceLibraryBuilder exported in both) {
         for (Export export in exported.exporters) {
-          NameIterator<Builder> iterator = exported.exportScope
+          NameIterator<Builder> iterator = exported.exportNameSpace
               .filteredNameIterator(
                   includeDuplicates: false, includeAugmentations: false);
           while (iterator.moveNext()) {
@@ -2968,9 +2968,9 @@
     }
 
     Builder? mainBuilder =
-        libraryBuilder.exportScope.lookupLocalMember('main', setter: false);
+        libraryBuilder.exportNameSpace.lookupLocalMember('main', setter: false);
     mainBuilder ??=
-        libraryBuilder.exportScope.lookupLocalMember('main', setter: true);
+        libraryBuilder.exportNameSpace.lookupLocalMember('main', setter: true);
     if (mainBuilder is MemberBuilder) {
       if (mainBuilder is InvalidTypeDeclarationBuilder) {
         // This is an ambiguous export, skip the check.
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 927a88a..f9ed025 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
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import '../base/messages.dart';
+import '../base/name_space.dart';
 import '../base/scope.dart';
 import '../builder/builder.dart';
 import '../builder/declaration_builders.dart';
@@ -440,28 +441,9 @@
     return TypeParameterScope.fromList(lookupScope, typeVariableBuilders);
   }
 
-  Scope toScope(Scope? parent,
-      {Map<String, Builder>? omittedTypeDeclarationBuilders}) {
-    // Coverage-ignore(suite): Not run.
-    if (omittedTypeDeclarationBuilders != null &&
-        omittedTypeDeclarationBuilders.isNotEmpty) {
-      parent = new Scope(
-          kind: ScopeKind.typeParameters,
-          local: omittedTypeDeclarationBuilders,
-          parent: parent,
-          debugName: 'omitted-types',
-          isModifiable: false);
-    }
-    return new Scope(
-        kind: ScopeKind.typeParameters,
-        local: members ?? const {},
-        setters: setters,
-        extensions: extensions,
-        parent: parent,
-        debugName: name,
-        isModifiable: false,
-        augmentations: augmentations,
-        setterAugmentations: setterAugmentations);
+  NameSpace toNameSpace() {
+    return new NameSpaceImpl(
+        getables: members, setables: setters, extensions: extensions);
   }
 
   @override
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 2be67fa..1708ebe 100644
--- a/pkg/front_end/lib/src/type_inference/inference_visitor.dart
+++ b/pkg/front_end/lib/src/type_inference/inference_visitor.dart
@@ -40,9 +40,11 @@
         ForInElement,
         ForInMapEntry,
         ForMapEntry,
+        IfCaseElement,
         IfElement,
         IfMapEntry,
         NullAwareElement,
+        PatternForElement,
         SpreadElement,
         SpreadMapEntry,
         convertToElement;
@@ -2685,24 +2687,27 @@
       DartType inferredTypeArgument,
       Map<TreeNode, DartType> inferredSpreadTypes,
       Map<Expression, DartType> inferredConditionTypes) {
-    if (element is SpreadElement) {
-      return _inferSpreadElement(element, inferredTypeArgument,
-          inferredSpreadTypes, inferredConditionTypes);
-    } else if (element is NullAwareElement) {
-      return _inferNullAwareElement(element, inferredTypeArgument,
-          inferredSpreadTypes, inferredConditionTypes);
-    } else if (element is IfElement) {
-      return _inferIfElement(element, inferredTypeArgument, inferredSpreadTypes,
-          inferredConditionTypes);
-    } else if (element is IfCaseElement) {
-      return _inferIfCaseElement(element, inferredTypeArgument,
-          inferredSpreadTypes, inferredConditionTypes);
-    } else if (element is ForElement) {
-      return _inferForElement(element, inferredTypeArgument,
-          inferredSpreadTypes, inferredConditionTypes);
-    } else if (element is ForInElement) {
-      return _inferForInElement(element, inferredTypeArgument,
-          inferredSpreadTypes, inferredConditionTypes);
+    if (element is ControlFlowElement) {
+      switch (element) {
+        case SpreadElement():
+          return _inferSpreadElement(element, inferredTypeArgument,
+              inferredSpreadTypes, inferredConditionTypes);
+        case NullAwareElement():
+          return _inferNullAwareElement(element, inferredTypeArgument,
+              inferredSpreadTypes, inferredConditionTypes);
+        case IfElement():
+          return _inferIfElement(element, inferredTypeArgument,
+              inferredSpreadTypes, inferredConditionTypes);
+        case IfCaseElement():
+          return _inferIfCaseElement(element, inferredTypeArgument,
+              inferredSpreadTypes, inferredConditionTypes);
+        case ForElement():
+          return _inferForElement(element, inferredTypeArgument,
+              inferredSpreadTypes, inferredConditionTypes);
+        case ForInElement():
+          return _inferForInElement(element, inferredTypeArgument,
+              inferredSpreadTypes, inferredConditionTypes);
+      }
     } else {
       ExpressionInferenceResult result =
           inferExpression(element, inferredTypeArgument, isVoidAllowed: true);
@@ -2728,48 +2733,71 @@
   }
 
   void checkElement(
-      Expression item,
+      ControlFlowElement item,
       Expression parent,
       DartType typeArgument,
       Map<TreeNode, DartType> inferredSpreadTypes,
       Map<Expression, DartType> inferredConditionTypes) {
-    if (item is SpreadElement) {
-      DartType? spreadType = inferredSpreadTypes[item.expression];
-      if (spreadType is DynamicType) {
-        Expression expression = ensureAssignable(
-            coreTypes.iterableRawType(item.isNullAware
-                ? Nullability.nullable
-                : Nullability.nonNullable),
-            spreadType,
-            item.expression);
-        item.expression = expression..parent = item;
-      }
-    } else if (item is NullAwareElement) {
-      checkElement(item.expression, item, typeArgument, inferredSpreadTypes,
-          inferredConditionTypes);
-    } else if (item is IfElement) {
-      checkElement(item.then, item, typeArgument, inferredSpreadTypes,
-          inferredConditionTypes);
-      if (item.otherwise != null) {
-        checkElement(item.otherwise!, item, typeArgument, inferredSpreadTypes,
-            inferredConditionTypes);
-      }
-    } else if (item is ForElement) {
-      if (item.condition != null) {
-        DartType conditionType = inferredConditionTypes[item.condition]!;
-        Expression condition = ensureAssignable(
-            coreTypes.boolRawType(Nullability.nonNullable),
-            conditionType,
-            item.condition!);
-        item.condition = condition..parent = item;
-      }
-      checkElement(item.body, item, typeArgument, inferredSpreadTypes,
-          inferredConditionTypes);
-    } else if (item is ForInElement) {
-      checkElement(item.body, item, typeArgument, inferredSpreadTypes,
-          inferredConditionTypes);
-    } else {
-      // Do nothing.  Assignability checks are done during type inference.
+    switch (item) {
+      case SpreadElement():
+        DartType? spreadType = inferredSpreadTypes[item.expression];
+        if (spreadType is DynamicType) {
+          Expression expression = ensureAssignable(
+              coreTypes.iterableRawType(item.isNullAware
+                  ? Nullability.nullable
+                  : Nullability.nonNullable),
+              spreadType,
+              item.expression);
+          item.expression = expression..parent = item;
+        }
+      case NullAwareElement():
+        Expression itemExpression = item.expression;
+        if (itemExpression is ControlFlowElement) {
+          checkElement(itemExpression, item, typeArgument, inferredSpreadTypes,
+              inferredConditionTypes);
+        }
+      case IfElement():
+        Expression itemThen = item.then;
+        if (itemThen is ControlFlowElement) {
+          checkElement(itemThen, item, typeArgument, inferredSpreadTypes,
+              inferredConditionTypes);
+        }
+        Expression? itemOtherwise = item.otherwise;
+        if (itemOtherwise is ControlFlowElement) {
+          checkElement(itemOtherwise, item, typeArgument, inferredSpreadTypes,
+              inferredConditionTypes);
+        }
+      case IfCaseElement():
+        Expression itemThen = item.then;
+        if (itemThen is ControlFlowElement) {
+          checkElement(itemThen, item, typeArgument, inferredSpreadTypes,
+              inferredConditionTypes);
+        }
+        Expression? itemOtherwise = item.otherwise;
+        if (itemOtherwise is ControlFlowElement) {
+          checkElement(itemOtherwise, item, typeArgument, inferredSpreadTypes,
+              inferredConditionTypes);
+        }
+      case ForElement():
+        if (item.condition != null) {
+          DartType conditionType = inferredConditionTypes[item.condition]!;
+          Expression condition = ensureAssignable(
+              coreTypes.boolRawType(Nullability.nonNullable),
+              conditionType,
+              item.condition!);
+          item.condition = condition..parent = item;
+        }
+        Expression itemBody = item.body;
+        if (itemBody is ControlFlowElement) {
+          checkElement(itemBody, item, typeArgument, inferredSpreadTypes,
+              inferredConditionTypes);
+        }
+      case ForInElement():
+        Expression itemBody = item.body;
+        if (itemBody is ControlFlowElement) {
+          checkElement(itemBody, item, typeArgument, inferredSpreadTypes,
+              inferredConditionTypes);
+        }
     }
   }
 
@@ -2838,8 +2866,11 @@
       node.typeArgument = inferredTypeArgument;
     }
     for (int i = 0; i < node.expressions.length; i++) {
-      checkElement(node.expressions[i], node, node.typeArgument,
-          inferredSpreadTypes, inferredConditionTypes);
+      Expression expression = node.expressions[i];
+      if (expression is ControlFlowElement) {
+        checkElement(expression, node, node.typeArgument, inferredSpreadTypes,
+            inferredConditionTypes);
+      }
     }
     DartType inferredType = new InterfaceType(
         listClass, Nullability.nonNullable, [inferredTypeArgument]);
@@ -2988,31 +3019,38 @@
   void _translateElement(Expression element, InterfaceType receiverType,
       DartType elementType, VariableDeclaration result, List<Statement> body,
       {required bool isSet}) {
-    if (element is SpreadElement) {
-      _translateSpreadElement(element, receiverType, elementType, result, body,
-          isSet: isSet);
-    } else if (element is NullAwareElement) {
-      _translateNullAwareElement(
-          element, receiverType, elementType, result, body,
-          isSet: isSet);
-    } else if (element is IfElement) {
-      _translateIfElement(element, receiverType, elementType, result, body,
-          isSet: isSet);
-    } else if (element is IfCaseElement) {
-      _translateIfCaseElement(element, receiverType, elementType, result, body,
-          isSet: isSet);
-    } else if (element is ForElement) {
-      if (element is PatternForElement) {
-        _translatePatternForElement(
-            element, receiverType, elementType, result, body,
-            isSet: isSet);
-      } else {
-        _translateForElement(element, receiverType, elementType, result, body,
-            isSet: isSet);
+    if (element is ControlFlowElement) {
+      switch (element) {
+        case SpreadElement():
+          _translateSpreadElement(
+              element, receiverType, elementType, result, body,
+              isSet: isSet);
+        case NullAwareElement():
+          _translateNullAwareElement(
+              element, receiverType, elementType, result, body,
+              isSet: isSet);
+        case IfElement():
+          _translateIfElement(element, receiverType, elementType, result, body,
+              isSet: isSet);
+        case IfCaseElement():
+          _translateIfCaseElement(
+              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);
+          }
+        case ForInElement():
+          _translateForInElement(
+              element, receiverType, elementType, result, body,
+              isSet: isSet);
       }
-    } else if (element is ForInElement) {
-      _translateForInElement(element, receiverType, elementType, result, body,
-          isSet: isSet);
     } else {
       _addExpressionElement(element, receiverType, result, body, isSet: isSet);
     }
@@ -3738,51 +3776,58 @@
 
     for (; i < elements.length; ++i) {
       Expression element = elements[i];
-      if (element is SpreadElement) {
-        if (currentPart != null) {
-          parts.add(makeLiteral(node.fileOffset, currentPart));
-          currentPart = null;
+      if (element is ControlFlowElement) {
+        switch (element) {
+          case SpreadElement():
+            if (currentPart != null) {
+              parts.add(makeLiteral(node.fileOffset, currentPart));
+              currentPart = null;
+            }
+            Expression spreadExpression = element.expression;
+            if (element.isNullAware) {
+              VariableDeclaration temp = _createVariable(
+                  spreadExpression,
+                  typeSchemaEnvironment.iterableType(
+                      elementType, Nullability.nullable));
+              parts.add(_createNullAwareGuard(element.fileOffset, temp,
+                  makeLiteral(element.fileOffset, []), iterableType));
+            } else {
+              parts.add(spreadExpression);
+            }
+          case NullAwareElement():
+            if (currentPart != null) {
+              parts.add(makeLiteral(node.fileOffset, currentPart));
+              currentPart = null;
+            }
+            VariableDeclaration temp = _createVariable(element.expression,
+                elementType.withDeclaredNullability(Nullability.nullable));
+            parts.add(_createNullAwareGuard(element.fileOffset, temp,
+                makeLiteral(element.fileOffset, []), iterableType,
+                nullCheckedValue: makeLiteral(element.fileOffset,
+                    [_createNullCheckedVariableGet(temp)])));
+          case IfElement():
+            // Coverage-ignore-block(suite): Not run.
+            if (currentPart != null) {
+              parts.add(makeLiteral(node.fileOffset, currentPart));
+              currentPart = null;
+            }
+            Expression condition = element.condition;
+            Expression then =
+                makeLiteral(element.then.fileOffset, [element.then]);
+            Expression otherwise = element.otherwise != null
+                ? makeLiteral(
+                    element.otherwise!.fileOffset, [element.otherwise!])
+                : makeLiteral(element.fileOffset, []);
+            parts.add(_createConditionalExpression(
+                element.fileOffset, condition, then, otherwise, iterableType));
+          case IfCaseElement():
+          case ForElement():
+          case ForInElement():
+            // Coverage-ignore-block(suite): Not run.
+            // Rejected earlier.
+            problems.unhandled("${element.runtimeType}",
+                "_translateConstListOrSet", element.fileOffset, helper.uri);
         }
-        Expression spreadExpression = element.expression;
-        if (element.isNullAware) {
-          VariableDeclaration temp = _createVariable(
-              spreadExpression,
-              typeSchemaEnvironment.iterableType(
-                  elementType, Nullability.nullable));
-          parts.add(_createNullAwareGuard(element.fileOffset, temp,
-              makeLiteral(element.fileOffset, []), iterableType));
-        } else {
-          parts.add(spreadExpression);
-        }
-      } else if (element is NullAwareElement) {
-        if (currentPart != null) {
-          parts.add(makeLiteral(node.fileOffset, currentPart));
-          currentPart = null;
-        }
-        VariableDeclaration temp = _createVariable(element.expression,
-            elementType.withDeclaredNullability(Nullability.nullable));
-        parts.add(_createNullAwareGuard(element.fileOffset, temp,
-            makeLiteral(element.fileOffset, []), iterableType,
-            nullCheckedValue: makeLiteral(
-                element.fileOffset, [_createNullCheckedVariableGet(temp)])));
-      } else if (element is IfElement) {
-        // Coverage-ignore-block(suite): Not run.
-        if (currentPart != null) {
-          parts.add(makeLiteral(node.fileOffset, currentPart));
-          currentPart = null;
-        }
-        Expression condition = element.condition;
-        Expression then = makeLiteral(element.then.fileOffset, [element.then]);
-        Expression otherwise = element.otherwise != null
-            ? makeLiteral(element.otherwise!.fileOffset, [element.otherwise!])
-            : makeLiteral(element.fileOffset, []);
-        parts.add(_createConditionalExpression(
-            element.fileOffset, condition, then, otherwise, iterableType));
-      } else if (element is ForElement || element is ForInElement) {
-        // Coverage-ignore-block(suite): Not run.
-        // Rejected earlier.
-        problems.unhandled("${element.runtimeType}", "_translateConstListOrSet",
-            element.fileOffset, helper.uri);
       } else {
         currentPart ??= <Expression>[];
         currentPart.add(element);
@@ -4999,12 +5044,11 @@
             typeArgument: inferredTypeArgument, isConst: node.isConst)
           ..fileOffset = node.fileOffset;
         for (int i = 0; i < setLiteral.expressions.length; i++) {
-          checkElement(
-              setLiteral.expressions[i],
-              setLiteral,
-              setLiteral.typeArgument,
-              inferredSpreadTypes,
-              inferredConditionTypes);
+          Expression element = setLiteral.expressions[i];
+          if (element is ControlFlowElement) {
+            checkElement(element, setLiteral, setLiteral.typeArgument,
+                inferredSpreadTypes, inferredConditionTypes);
+          }
         }
 
         Expression result = _translateSetLiteral(setLiteral);
@@ -8288,8 +8332,11 @@
       node.typeArgument = inferredTypeArgument;
     }
     for (int i = 0; i < node.expressions.length; i++) {
-      checkElement(node.expressions[i], node, node.typeArgument,
-          inferredSpreadTypes, inferredConditionTypes);
+      Expression element = node.expressions[i];
+      if (element is ControlFlowElement) {
+        checkElement(element, node, node.typeArgument, inferredSpreadTypes,
+            inferredConditionTypes);
+      }
     }
     DartType inferredType = new InterfaceType(
         setClass, Nullability.nonNullable, [inferredTypeArgument]);
diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart
index 6c2fd73..31be2a9 100644
--- a/pkg/front_end/test/coverage_suite_expected.dart
+++ b/pkg/front_end/test/coverage_suite_expected.dart
@@ -163,10 +163,10 @@
     hitCount: 25,
     missCount: 0,
   ),
-  // 93.20388349514563%.
+  // 88.07339449541286%.
   "package:front_end/src/base/local_scope.dart": (
     hitCount: 96,
-    missCount: 7,
+    missCount: 13,
   ),
   // 100.0%.
   "package:front_end/src/base/messages.dart": (
@@ -178,10 +178,10 @@
     hitCount: 29,
     missCount: 0,
   ),
-  // 96.35036496350365%.
+  // 97.87234042553192%.
   "package:front_end/src/base/name_space.dart": (
-    hitCount: 132,
-    missCount: 5,
+    hitCount: 138,
+    missCount: 3,
   ),
   // 100.0%.
   "package:front_end/src/base/operator.dart": (
@@ -198,10 +198,10 @@
     hitCount: 246,
     missCount: 0,
   ),
-  // 93.56796116504854%.
+  // 99.11504424778761%.
   "package:front_end/src/base/scope.dart": (
-    hitCount: 771,
-    missCount: 53,
+    hitCount: 672,
+    missCount: 6,
   ),
   // 100.0%.
   "package:front_end/src/base/ticker.dart": (
@@ -440,7 +440,7 @@
   ),
   // 100.0%.
   "package:front_end/src/dill/dill_library_builder.dart": (
-    hitCount: 341,
+    hitCount: 337,
     missCount: 0,
   ),
   // 100.0%.
@@ -473,20 +473,20 @@
     hitCount: 0,
     missCount: 0,
   ),
-  // 99.38483547925608%.
+  // 99.34238741958542%.
   "package:front_end/src/kernel/body_builder.dart": (
-    hitCount: 6947,
-    missCount: 43,
+    hitCount: 6949,
+    missCount: 46,
   ),
   // 100.0%.
   "package:front_end/src/kernel/body_builder_context.dart": (
     hitCount: 345,
     missCount: 0,
   ),
-  // 93.31103678929766%.
+  // 90.35087719298247%.
   "package:front_end/src/kernel/collections.dart": (
-    hitCount: 279,
-    missCount: 20,
+    hitCount: 309,
+    missCount: 33,
   ),
   // 100.0%.
   "package:front_end/src/kernel/combined_member_signature.dart": (
@@ -595,7 +595,7 @@
   ),
   // 100.0%.
   "package:front_end/src/kernel/internal_ast.dart": (
-    hitCount: 595,
+    hitCount: 569,
     missCount: 0,
   ),
   // 100.0%.
@@ -788,14 +788,14 @@
     hitCount: 158,
     missCount: 3,
   ),
-  // 99.75490196078431%.
+  // 99.7545008183306%.
   "package:front_end/src/source/source_class_builder.dart": (
-    hitCount: 1221,
+    hitCount: 1219,
     missCount: 3,
   ),
-  // 99.47089947089947%.
+  // 99.47712418300654%.
   "package:front_end/src/source/source_compilation_unit.dart": (
-    hitCount: 752,
+    hitCount: 761,
     missCount: 4,
   ),
   // 98.31460674157303%.
@@ -834,9 +834,9 @@
     hitCount: 296,
     missCount: 0,
   ),
-  // 99.85835694050992%.
+  // 99.8589562764457%.
   "package:front_end/src/source/source_library_builder.dart": (
-    hitCount: 1410,
+    hitCount: 1416,
     missCount: 2,
   ),
   // 99.89264626945786%.
@@ -866,7 +866,7 @@
   ),
   // 100.0%.
   "package:front_end/src/source/type_parameter_scope_builder.dart": (
-    hitCount: 176,
+    hitCount: 173,
     missCount: 0,
   ),
   // 100.0%.
@@ -899,10 +899,10 @@
     hitCount: 166,
     missCount: 0,
   ),
-  // 99.96187571483036%.
+  // 99.52038369304557%.
   "package:front_end/src/type_inference/inference_visitor.dart": (
-    hitCount: 7866,
-    missCount: 3,
+    hitCount: 7885,
+    missCount: 38,
   ),
   // 99.87525987525989%.
   "package:front_end/src/type_inference/inference_visitor_base.dart": (
diff --git a/pkg/front_end/test/fasta/ambiguous_export_test.dart b/pkg/front_end/test/fasta/ambiguous_export_test.dart
index 48f647e..d2f1e85 100644
--- a/pkg/front_end/test/fasta/ambiguous_export_test.dart
+++ b/pkg/front_end/test/fasta/ambiguous_export_test.dart
@@ -31,7 +31,7 @@
       target.loader.buildOutline(builder);
       builder.markAsReadyToFinalizeExports();
       var mainExport =
-          builder.exportScope.lookupLocalMember("main", setter: false);
+          builder.exportNameSpace.lookupLocalMember("main", setter: false);
       Expect.isTrue(mainExport is InvalidTypeDeclarationBuilder);
     });
   });
diff --git a/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.expect b/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.expect
index c5066cd..1d82563 100644
--- a/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.expect
@@ -32,7 +32,7 @@
     {
       final synthesized dynamic #0#0 = x;
       if(#0#0 is core::String)
-        for (final has-declared-initializer dynamic #t13 in another) {
+        for (final has-declared-initializer dynamic #t13 in another as{TypeError,ForDynamic} core::Iterable<dynamic>) {
           final dynamic #t14 = #t13 as{TypeError} dynamic;
           #t12.{core::Set::add}{Invariant}(#t14){(dynamic) → core::bool};
         }
diff --git a/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.modular.expect b/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.modular.expect
index c5066cd..1d82563 100644
--- a/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.modular.expect
+++ b/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.modular.expect
@@ -32,7 +32,7 @@
     {
       final synthesized dynamic #0#0 = x;
       if(#0#0 is core::String)
-        for (final has-declared-initializer dynamic #t13 in another) {
+        for (final has-declared-initializer dynamic #t13 in another as{TypeError,ForDynamic} core::Iterable<dynamic>) {
           final dynamic #t14 = #t13 as{TypeError} dynamic;
           #t12.{core::Set::add}{Invariant}(#t14){(dynamic) → core::bool};
         }
diff --git a/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.transformed.expect
index 3c17d6a..340cd8e 100644
--- a/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/patterns/collections_entry_to_element_conversion_in_inference.dart.strong.transformed.expect
@@ -37,9 +37,9 @@
     {
       final synthesized dynamic #0#0 = x;
       if(#0#0 is core::String) {
-        synthesized core::Iterator<invalid-type> :sync-for-iterator = another.{core::Iterable::iterator}{core::Iterator<invalid-type>};
+        synthesized core::Iterator<dynamic> :sync-for-iterator = (another as{TypeError,ForDynamic} core::Iterable<dynamic>).{core::Iterable::iterator}{core::Iterator<dynamic>};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
-          final dynamic #t13 = :sync-for-iterator.{core::Iterator::current}{invalid-type};
+          final dynamic #t13 = :sync-for-iterator.{core::Iterator::current}{dynamic};
           {
             final dynamic #t14 = #t13 as{TypeError} dynamic;
             #t12.{core::Set::add}{Invariant}(#t14){(dynamic) → core::bool};
diff --git a/pkg/front_end/tool/dart_doctest_impl.dart b/pkg/front_end/tool/dart_doctest_impl.dart
index fe3d801..a0de469 100644
--- a/pkg/front_end/tool/dart_doctest_impl.dart
+++ b/pkg/front_end/tool/dart_doctest_impl.dart
@@ -31,7 +31,6 @@
 import 'package:front_end/src/base/hybrid_file_system.dart';
 import 'package:front_end/src/base/incremental_compiler.dart';
 import 'package:front_end/src/base/processed_options.dart';
-import 'package:front_end/src/base/scope.dart';
 import 'package:front_end/src/base/uri_translator.dart';
 import 'package:front_end/src/builder/library_builder.dart';
 import 'package:front_end/src/codes/cfe_codes.dart';
@@ -821,10 +820,7 @@
       packageLanguageVersion:
           new ImplicitLanguageVersion(libraryBuilder.languageVersion),
       loader: loader,
-      // TODO(jensj): Should probably set up scopes the same was as it's done
-      // (now) for expression compilation.
-      importScope: libraryBuilder.scope
-          .createNestedScope(debugName: "dartdoctest", kind: ScopeKind.library),
+      parentScope: libraryBuilder.scope,
       nameOrigin: libraryBuilder,
       isUnsupported: false,
       isAugmentation: false,
diff --git a/tools/VERSION b/tools/VERSION
index 35eff83..31659c9 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 3
 MINOR 6
 PATCH 0
-PRERELEASE 85
+PRERELEASE 86
 PRERELEASE_PATCH 0