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