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