[fasta] Fix default argument values in noSuchMethod forwarders
Fixes #33459
Bug: http://dartbug.com/33459
Change-Id: I194535d8d8893429ee0e6870c35e7b9ec84dde5c
Reviewed-on: https://dart-review.googlesource.com/62808
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Samir Jindel <sjindel@google.com>
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index 7e81d10..dcd6413 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -126,6 +126,8 @@
int finishDeferredLoadTearoffs() => 0;
+ int finishNoSuchMethodForwarders() => 0;
+
int finishNativeMethods() => 0;
int finishPatchMethods() => 0;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index ebb64ec..e30260e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -430,6 +430,10 @@
transformProcedureToNoSuchMethodForwarder(noSuchMethod, target, cloned);
cls.procedures.add(cloned);
cloned.parent = cls;
+
+ KernelLibraryBuilder library = this.library;
+ library.noSuchMethodForwardersOrigins.add(cloned);
+ library.noSuchMethodForwardersOrigins.add(procedure);
}
void addNoSuchMethodForwarderGetterForField(Member noSuchMethod,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index cc5a316..009fd3a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -25,8 +25,11 @@
StringLiteral,
TreeNode,
Typedef,
+ VariableDeclaration,
VoidType;
+import 'package:kernel/clone.dart' show CloneVisitor;
+
import '../../scanner/token.dart' show Token;
import '../export.dart' show Export;
@@ -59,7 +62,7 @@
import '../modifier.dart'
show abstractMask, namedMixinApplicationMask, staticMask;
-import '../problems.dart' show unhandled;
+import '../problems.dart' show unexpected, unhandled;
import '../source/source_class_builder.dart' show SourceClassBuilder;
@@ -126,6 +129,12 @@
final List<KernelTypeVariableBuilder> boundlessTypeVariables =
<KernelTypeVariableBuilder>[];
+ // A list of alternating noSuchMethod forwarders and the abstract procedures
+ // they were generated for. Note that it may not include a forwarder-origin
+ // pair in cases when the former does not need to be updated after the body of
+ // the latter was built.
+ final List<Procedure> noSuchMethodForwardersOrigins = <Procedure>[];
+
/// Exports that can't be serialized.
///
/// The key is the name of the exported member.
@@ -1003,6 +1012,55 @@
return total;
}
+ int finishNoSuchMethodForwarders() {
+ int count = 0;
+ CloneVisitor cloner = new CloneVisitor();
+ for (int i = 0; i < noSuchMethodForwardersOrigins.length; i += 2) {
+ Procedure forwarder = noSuchMethodForwardersOrigins[i];
+ Procedure origin = noSuchMethodForwardersOrigins[i + 1];
+
+ int positionalCount = origin.function.positionalParameters.length;
+ if (forwarder.function.positionalParameters.length != positionalCount) {
+ return unexpected(
+ "$positionalCount",
+ "${forwarder.function.positionalParameters.length}",
+ origin.fileOffset,
+ origin.fileUri);
+ }
+ for (int j = 0; j < positionalCount; ++j) {
+ VariableDeclaration forwarderParameter =
+ forwarder.function.positionalParameters[j];
+ VariableDeclaration originParameter =
+ origin.function.positionalParameters[j];
+ if (originParameter.initializer != null) {
+ forwarderParameter.initializer =
+ cloner.clone(originParameter.initializer);
+ forwarderParameter.initializer.parent = forwarderParameter;
+ }
+ }
+
+ Map<String, VariableDeclaration> originNamedMap =
+ <String, VariableDeclaration>{};
+ for (VariableDeclaration originNamed in origin.function.namedParameters) {
+ originNamedMap[originNamed.name] = originNamed;
+ }
+ for (VariableDeclaration forwarderNamed
+ in forwarder.function.namedParameters) {
+ VariableDeclaration originNamed = originNamedMap[forwarderNamed.name];
+ if (originNamed == null) {
+ return unhandled(
+ "null", forwarder.name.name, origin.fileOffset, origin.fileUri);
+ }
+ forwarderNamed.initializer = cloner.clone(originNamed.initializer);
+ forwarderNamed.initializer.parent = forwarderNamed;
+ }
+
+ ++count;
+ }
+ noSuchMethodForwardersOrigins.clear();
+ return count;
+ }
+
void addNativeMethod(KernelFunctionBuilder method) {
nativeMethods.add(method);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index b48bef4..d83a48b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -288,6 +288,7 @@
ticker.logMs("Building component");
await loader.buildBodies();
loader.finishDeferredLoadTearoffs();
+ loader.finishNoSuchMethodForwarders();
List<SourceClassBuilder> myClasses = collectMyClasses();
finishAllConstructors(myClasses);
loader.finishNativeMethods();
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 5398291..3304efc 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -383,6 +383,16 @@
ticker.logMs("Finished deferred load tearoffs $count");
}
+ void finishNoSuchMethodForwarders() {
+ int count = 0;
+ builders.forEach((Uri uri, LibraryBuilder library) {
+ if (library.loader == this) {
+ count += library.finishNoSuchMethodForwarders();
+ }
+ });
+ ticker.logMs("Finished noSuchMethod forwarders for $count procedures");
+ }
+
void resolveConstructors() {
int count = 0;
builders.forEach((Uri uri, LibraryBuilder library) {
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart
new file mode 100644
index 0000000..a4fb653
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2018, 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.
+
+// This test checks that the default argument values of noSuchMethod forwarder
+// parameters are passed to noSuchMethod when the corresponding arguments aren't
+// specified at the call site.
+
+abstract class A {
+ noSuchMethod(Invocation i) {
+ if (i.memberName == #foo) {
+ return i.namedArguments[#bar];
+ } else if (i.memberName == #hest) {
+ return i.positionalArguments[0];
+ }
+ return null;
+ }
+
+ // These shouldn't be turned into a noSuchMethod forwarder, because the
+ // enclosing class is abstract.
+ String foo({String bar = "baz"});
+ int hest([int fisk = 42]);
+}
+
+class B extends A {
+ // [B] should receive the noSuchMethod forwarders for [A.foo] and [A.hest],
+ // and the default argument values in them should be passed into the
+ // constructor of [Invocation].
+}
+
+main() {
+ B b = new B();
+ dynamic value;
+ if ((value = b.foo()) != "baz") {
+ throw "Unexpected value: '$value'; expected 'baz'.";
+ }
+ if ((value = b.hest()) != 42) {
+ throw "Unexpected value: '$value'; expected '42'.";
+ }
+}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.direct.expect
new file mode 100644
index 0000000..2be3542
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.direct.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ if(i.memberName.==(#foo)) {
+ return i.namedArguments.[](#bar);
+ }
+ else
+ if(i.memberName.==(#hest)) {
+ return i.positionalArguments.[](0);
+ }
+ return null;
+ }
+ abstract method foo({core::String bar = "baz"}) → core::String;
+ abstract method hest([core::int fisk = 42]) → core::int;
+}
+class B extends self::A {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ no-such-method-forwarder method foo({core::String bar = "baz"}) → core::String
+ return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withoutType("foo", const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(<core::Symbol, dynamic>{#bar: bar}), false)) as{TypeError} core::String;
+ no-such-method-forwarder method hest([core::int fisk = 42]) → core::int
+ return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withoutType("hest", const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[fisk]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}), false)) as{TypeError} core::int;
+}
+static method main() → dynamic {
+ self::B b = new self::B::•();
+ dynamic value;
+ if(!(value = b.foo()).==("baz")) {
+ throw "Unexpected value: '${value}'; expected 'baz'.";
+ }
+ if(!(value = b.hest()).==(42)) {
+ throw "Unexpected value: '${value}'; expected '42'.";
+ }
+}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.direct.transformed.expect
new file mode 100644
index 0000000..2be3542
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.direct.transformed.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ if(i.memberName.==(#foo)) {
+ return i.namedArguments.[](#bar);
+ }
+ else
+ if(i.memberName.==(#hest)) {
+ return i.positionalArguments.[](0);
+ }
+ return null;
+ }
+ abstract method foo({core::String bar = "baz"}) → core::String;
+ abstract method hest([core::int fisk = 42]) → core::int;
+}
+class B extends self::A {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ no-such-method-forwarder method foo({core::String bar = "baz"}) → core::String
+ return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withoutType("foo", const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(<core::Symbol, dynamic>{#bar: bar}), false)) as{TypeError} core::String;
+ no-such-method-forwarder method hest([core::int fisk = 42]) → core::int
+ return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withoutType("hest", const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[fisk]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}), false)) as{TypeError} core::int;
+}
+static method main() → dynamic {
+ self::B b = new self::B::•();
+ dynamic value;
+ if(!(value = b.foo()).==("baz")) {
+ throw "Unexpected value: '${value}'; expected 'baz'.";
+ }
+ if(!(value = b.hest()).==(42)) {
+ throw "Unexpected value: '${value}'; expected '42'.";
+ }
+}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.outline.expect
new file mode 100644
index 0000000..ff0e80e
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.outline.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ ;
+ abstract method foo({core::String bar}) → core::String;
+ abstract method hest([core::int fisk]) → core::int;
+}
+class B extends self::A {
+ synthetic constructor •() → void
+ ;
+ no-such-method-forwarder method foo({core::String bar}) → core::String
+ return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withoutType("foo", const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(<core::Symbol, dynamic>{#bar: bar}), false)) as{TypeError} core::String;
+ no-such-method-forwarder method hest([core::int fisk]) → core::int
+ return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withoutType("hest", const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[fisk]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}), false)) as{TypeError} core::int;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.strong.expect
new file mode 100644
index 0000000..13822b5
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.strong.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ if(i.{core::Invocation::memberName}.{core::Symbol::==}(#foo)) {
+ return i.{core::Invocation::namedArguments}.{core::Map::[]}(#bar);
+ }
+ else
+ if(i.{core::Invocation::memberName}.{core::Symbol::==}(#hest)) {
+ return i.{core::Invocation::positionalArguments}.{core::List::[]}(0);
+ }
+ return null;
+ }
+ abstract method foo({core::String bar = "baz"}) → core::String;
+ abstract method hest([core::int fisk = 42]) → core::int;
+}
+class B extends self::A {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ no-such-method-forwarder method foo({core::String bar = "baz"}) → core::String
+ return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withoutType("foo", const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(<core::Symbol, dynamic>{#bar: bar}), false)) as{TypeError} core::String;
+ no-such-method-forwarder method hest([core::int fisk = 42]) → core::int
+ return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withoutType("hest", const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[fisk]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}), false)) as{TypeError} core::int;
+}
+static method main() → dynamic {
+ self::B b = new self::B::•();
+ dynamic value;
+ if(!(value = b.{self::B::foo}()).{core::String::==}("baz")) {
+ throw "Unexpected value: '${value}'; expected 'baz'.";
+ }
+ if(!(value = b.{self::B::hest}()).{core::num::==}(42)) {
+ throw "Unexpected value: '${value}'; expected '42'.";
+ }
+}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.strong.transformed.expect
new file mode 100644
index 0000000..13822b5
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.strong.transformed.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ if(i.{core::Invocation::memberName}.{core::Symbol::==}(#foo)) {
+ return i.{core::Invocation::namedArguments}.{core::Map::[]}(#bar);
+ }
+ else
+ if(i.{core::Invocation::memberName}.{core::Symbol::==}(#hest)) {
+ return i.{core::Invocation::positionalArguments}.{core::List::[]}(0);
+ }
+ return null;
+ }
+ abstract method foo({core::String bar = "baz"}) → core::String;
+ abstract method hest([core::int fisk = 42]) → core::int;
+}
+class B extends self::A {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ no-such-method-forwarder method foo({core::String bar = "baz"}) → core::String
+ return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withoutType("foo", const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(<core::Symbol, dynamic>{#bar: bar}), false)) as{TypeError} core::String;
+ no-such-method-forwarder method hest([core::int fisk = 42]) → core::int
+ return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withoutType("hest", const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[fisk]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}), false)) as{TypeError} core::int;
+}
+static method main() → dynamic {
+ self::B b = new self::B::•();
+ dynamic value;
+ if(!(value = b.{self::B::foo}()).{core::String::==}("baz")) {
+ throw "Unexpected value: '${value}'; expected 'baz'.";
+ }
+ if(!(value = b.{self::B::hest}()).{core::num::==}(42)) {
+ throw "Unexpected value: '${value}'; expected '42'.";
+ }
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
index 79d7fdc..01c1009 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
@@ -51,7 +51,7 @@
return [@vm.direct-call.metadata=#lib::B::noSuchMethod] [@vm.inferred-type.metadata=#lib::T1] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withoutType("get:bar", const <core::Type>[], const <dynamic>[], [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}), false)) as{TypeError} dynamic;
no-such-method-forwarder method foo() → dynamic
return [@vm.direct-call.metadata=#lib::B::noSuchMethod] [@vm.inferred-type.metadata=#lib::T1] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withoutType("foo", const <core::Type>[], const <dynamic>[], [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}), false)) as{TypeError} dynamic;
- no-such-method-forwarder method bazz([@vm.inferred-type.metadata=!] dynamic a1, [@vm.inferred-type.metadata=!] dynamic a2, [@vm.inferred-type.metadata=!] dynamic a3, [[@vm.inferred-type.metadata=!] dynamic a4, [@vm.inferred-type.metadata=dart.core::Null?] dynamic a5]) → dynamic
+ no-such-method-forwarder method bazz([@vm.inferred-type.metadata=!] dynamic a1, [@vm.inferred-type.metadata=!] dynamic a2, [@vm.inferred-type.metadata=!] dynamic a3, [[@vm.inferred-type.metadata=!] dynamic a4 = null, [@vm.inferred-type.metadata=dart.core::Null?] dynamic a5 = null]) → dynamic
return [@vm.direct-call.metadata=#lib::B::noSuchMethod] [@vm.inferred-type.metadata=#lib::T1] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withoutType("bazz", const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, a5]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}), false)) as{TypeError} dynamic;
}
abstract class C extends core::Object {
@@ -70,7 +70,7 @@
return [@vm.direct-call.metadata=#lib::C::noSuchMethod] [@vm.inferred-type.metadata=#lib::T2] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withoutType("get:bar", const <core::Type>[], const <dynamic>[], [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}), false)) as{TypeError} dynamic;
no-such-method-forwarder method foo() → dynamic
return [@vm.direct-call.metadata=#lib::C::noSuchMethod] [@vm.inferred-type.metadata=#lib::T2] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withoutType("foo", const <core::Type>[], const <dynamic>[], [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}), false)) as{TypeError} dynamic;
- no-such-method-forwarder method bazz([@vm.inferred-type.metadata=!] dynamic a1, [@vm.inferred-type.metadata=!] dynamic a2, [@vm.inferred-type.metadata=!] dynamic a3, [[@vm.inferred-type.metadata=!] dynamic a4, [@vm.inferred-type.metadata=dart.core::Null?] dynamic a5]) → dynamic
+ no-such-method-forwarder method bazz([@vm.inferred-type.metadata=!] dynamic a1, [@vm.inferred-type.metadata=!] dynamic a2, [@vm.inferred-type.metadata=!] dynamic a3, [[@vm.inferred-type.metadata=!] dynamic a4 = null, [@vm.inferred-type.metadata=dart.core::Null?] dynamic a5 = null]) → dynamic
return [@vm.direct-call.metadata=#lib::C::noSuchMethod] [@vm.inferred-type.metadata=#lib::T2] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withoutType("bazz", const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, a5]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView] core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}), false)) as{TypeError} dynamic;
}
class E extends core::Object implements self::A {