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