[cfe] Build extension types as their on-types if they are enabled
Change-Id: Iae52f25ffcc0517e9ec05c445ae1227af9fa3b97
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/185881
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 725ff20..c4c4e5c 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -593,7 +593,7 @@
null);
}
- // arguments.length == typeVariables.length
+ assert(arguments.length == typeVariablesCount);
List<DartType> result =
new List<DartType>.filled(arguments.length, null, growable: true);
for (int i = 0; i < result.length; ++i) {
diff --git a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
index 5c150ad..1ef8de3 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -6,20 +6,23 @@
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
+import 'package:kernel/type_algebra.dart';
-import '../fasta_codes.dart' show templateInternalProblemNotFoundIn;
+import '../fasta_codes.dart'
+ show templateInternalProblemNotFoundIn, templateTypeArgumentMismatch;
import '../scope.dart';
+import '../source/source_library_builder.dart';
import '../problems.dart';
import '../util/helpers.dart';
import 'builder.dart';
+import 'declaration_builder.dart';
import 'library_builder.dart';
import 'member_builder.dart';
import 'metadata_builder.dart';
import 'nullability_builder.dart';
import 'type_builder.dart';
import 'type_variable_builder.dart';
-import 'declaration_builder.dart';
abstract class ExtensionBuilder implements DeclarationBuilder {
List<TypeVariableBuilder> get typeParameters;
@@ -86,14 +89,82 @@
DartType buildType(LibraryBuilder library,
NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
[bool notInstanceContext]) {
- throw new UnsupportedError("ExtensionBuilder.buildType is not supported.");
+ if (library is SourceLibraryBuilder &&
+ library.enableExtensionTypesInLibrary) {
+ return buildTypesWithBuiltArguments(
+ library,
+ nullabilityBuilder.build(library),
+ buildTypeArguments(library, arguments, notInstanceContext));
+ } else {
+ throw new UnsupportedError("ExtensionBuilder.buildType is not supported"
+ "in library '${library.importUri}'.");
+ }
}
@override
DartType buildTypesWithBuiltArguments(LibraryBuilder library,
Nullability nullability, List<DartType> arguments) {
- throw new UnsupportedError("ExtensionBuilder.buildTypesWithBuiltArguments "
- "is not supported.");
+ if (library is SourceLibraryBuilder &&
+ library.enableExtensionTypesInLibrary) {
+ // TODO(dmitryas): Build the extension type rather than the on-type.
+ DartType builtOnType = onType.build(library);
+ if (typeParameters != null) {
+ List<TypeParameter> typeParameterNodes = <TypeParameter>[];
+ for (TypeVariableBuilder typeParameter in typeParameters) {
+ typeParameterNodes.add(typeParameter.parameter);
+ }
+ builtOnType = Substitution.fromPairs(typeParameterNodes, arguments)
+ .substituteType(builtOnType);
+ }
+ return builtOnType;
+ } else {
+ throw new UnsupportedError(
+ "ExtensionBuilder.buildTypesWithBuiltArguments "
+ "is not supported in library '${library.importUri}'.");
+ }
+ }
+
+ @override
+ int get typeVariablesCount => typeParameters?.length ?? 0;
+
+ List<DartType> buildTypeArguments(
+ LibraryBuilder library, List<TypeBuilder> arguments,
+ [bool notInstanceContext]) {
+ if (arguments == null && typeParameters == null) {
+ return <DartType>[];
+ }
+
+ if (arguments == null && typeParameters != null) {
+ List<DartType> result = new List<DartType>.filled(
+ typeParameters.length, null,
+ growable: true);
+ for (int i = 0; i < result.length; ++i) {
+ result[i] = typeParameters[i].defaultType.build(library);
+ }
+ if (library is SourceLibraryBuilder) {
+ library.inferredTypes.addAll(result);
+ }
+ return result;
+ }
+
+ if (arguments != null && arguments.length != typeVariablesCount) {
+ // That should be caught and reported as a compile-time error earlier.
+ return unhandled(
+ templateTypeArgumentMismatch
+ .withArguments(typeVariablesCount)
+ .message,
+ "buildTypeArguments",
+ -1,
+ null);
+ }
+
+ assert(arguments.length == typeVariablesCount);
+ List<DartType> result =
+ new List<DartType>.filled(arguments.length, null, growable: true);
+ for (int i = 0; i < result.length; ++i) {
+ result[i] = arguments[i].build(library);
+ }
+ return result;
}
@override
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 6004b66..c0e9971 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -37,6 +37,8 @@
import '../scope.dart';
+import '../source/source_library_builder.dart';
+
import 'builder.dart';
import 'builtin_type_declaration_builder.dart';
import 'class_builder.dart';
@@ -140,7 +142,9 @@
return;
} else if (member is TypeDeclarationBuilder) {
declaration = member.origin;
- if (!declaration.isExtension) {
+ if (!declaration.isExtension ||
+ library is SourceLibraryBuilder &&
+ library.enableExtensionTypesInLibrary) {
return;
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index ec1a7ec..edcd72b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -442,6 +442,11 @@
DartType get implicitTypeArgument => const ImplicitTypeArgument();
+ @override
+ bool get enableExtensionTypesInLibrary {
+ return libraryBuilder.enableExtensionTypesInLibrary;
+ }
+
void _enterLocalState({bool inLateLocalInitializer: false}) {
_localInitializerState =
_localInitializerState.prepend(inLateLocalInitializer);
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index d179e00..3208247 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -2975,7 +2975,7 @@
@override
TypeBuilder buildTypeWithResolvedArguments(
NullabilityBuilder nullabilityBuilder, List<UnresolvedType> arguments) {
- if (declaration.isExtension) {
+ if (declaration.isExtension && !_helper.enableExtensionTypesInLibrary) {
// Extension declarations cannot be used as types.
return super
.buildTypeWithResolvedArguments(nullabilityBuilder, arguments);
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index 8d03df8..128205c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -62,6 +62,8 @@
/// `true` if we are in the type of an as expression.
bool get inIsOrAsOperatorType;
+ bool get enableExtensionTypesInLibrary;
+
scopeLookup(Scope scope, String name, Token token,
{bool isQualified: false, PrefixBuilder prefix});
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index b476720..11b2502 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -299,6 +299,7 @@
bool _enableTripleShiftInLibrary;
bool _enableExtensionMethodsInLibrary;
bool _enableGenericMetadataInLibrary;
+ bool _enableExtensionTypesInLibrary;
bool get enableVarianceInLibrary =>
_enableVarianceInLibrary ??= loader.target.isExperimentEnabledInLibrary(
@@ -337,6 +338,10 @@
loader.target.isExperimentEnabledInLibrary(
ExperimentalFlag.genericMetadata, _packageUri ?? importUri);
+ bool get enableExtensionTypesInLibrary => _enableExtensionTypesInLibrary ??=
+ loader.target.isExperimentEnabledInLibrary(
+ ExperimentalFlag.extensionTypes, _packageUri ?? importUri);
+
void updateLibraryNNBDSettings() {
library.isNonNullableByDefault = isNonNullableByDefault;
if (enableNonNullableInLibrary) {
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 1b92362..185fede 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -11,7 +11,10 @@
a0x
a1x
+a2i
a2x
+a3i
+a4i
aa
aaa
abc
diff --git a/pkg/front_end/testcases/extension_types/folder.options b/pkg/front_end/testcases/extension_types/folder.options
new file mode 100644
index 0000000..f936fab
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/folder.options
@@ -0,0 +1 @@
+--enable-experiment=extension-types
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extension_types/simple.dart b/pkg/front_end/testcases/extension_types/simple.dart
new file mode 100644
index 0000000..b9a9997
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2021, 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.
+
+class Foo<X> {}
+class Bar<X, Y> {}
+
+extension A1 on dynamic {}
+A1 foo1(A1 a) => throw 42;
+
+extension A2<X> on Foo<X> {}
+A2 foo2(A2<int> a, A2 ai) => throw 42;
+
+extension A3<X, Y extends Function(X)> on Bar<X, Y> {}
+A3 foo3(A3<int, Function(num)> a, A3 ai) => throw 42;
+
+extension A4<X, Y extends Function(X)> on Foo<Y> {}
+A4 foo4(A4<int, Function(num)> a, A4 ai) => throw 42;
+
+bar() {
+ A1 a1;
+ A2<int> a2;
+ A2 a2i;
+ A3<int, Function(num)> a3;
+ A3 a3i;
+ A4<int, Function(num)> a4;
+ A4 a4i;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple.dart.strong.expect b/pkg/front_end/testcases/extension_types/simple.dart.strong.expect
new file mode 100644
index 0000000..aa31646
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple.dart.strong.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Foo<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo<self::Foo::X%>
+ : super core::Object::•()
+ ;
+}
+class Bar<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bar<self::Bar::X%, self::Bar::Y%>
+ : super core::Object::•()
+ ;
+}
+extension A1 on dynamic {
+}
+extension A2<X extends core::Object? = dynamic> on self::Foo<X%> {
+}
+extension A3<X extends core::Object? = dynamic, Y extends (X%) → dynamic = (Never) → dynamic> on self::Bar<X%, Y> {
+}
+extension A4<X extends core::Object? = dynamic, Y extends (X%) → dynamic = (Never) → dynamic> on self::Foo<Y> {
+}
+static method foo1(dynamic a) → dynamic
+ return throw 42;
+static method foo2(self::Foo<core::int> a, self::Foo<dynamic> ai) → self::Foo<dynamic>
+ return throw 42;
+static method foo3(self::Bar<core::int, (core::num) → dynamic> a, self::Bar<dynamic, (Never) → dynamic> ai) → self::Bar<dynamic, (Never) → dynamic>
+ return throw 42;
+static method foo4(self::Foo<(core::num) → dynamic> a, self::Foo<(Never) → dynamic> ai) → self::Foo<(Never) → dynamic>
+ return throw 42;
+static method bar() → dynamic {
+ dynamic a1;
+ self::Foo<core::int> a2;
+ self::Foo<dynamic> a2i;
+ self::Bar<core::int, (core::num) → dynamic> a3;
+ self::Bar<dynamic, (Never) → dynamic> a3i;
+ self::Foo<(core::num) → dynamic> a4;
+ self::Foo<(Never) → dynamic> a4i;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple.dart.strong.transformed.expect b/pkg/front_end/testcases/extension_types/simple.dart.strong.transformed.expect
new file mode 100644
index 0000000..aa31646
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple.dart.strong.transformed.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Foo<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo<self::Foo::X%>
+ : super core::Object::•()
+ ;
+}
+class Bar<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bar<self::Bar::X%, self::Bar::Y%>
+ : super core::Object::•()
+ ;
+}
+extension A1 on dynamic {
+}
+extension A2<X extends core::Object? = dynamic> on self::Foo<X%> {
+}
+extension A3<X extends core::Object? = dynamic, Y extends (X%) → dynamic = (Never) → dynamic> on self::Bar<X%, Y> {
+}
+extension A4<X extends core::Object? = dynamic, Y extends (X%) → dynamic = (Never) → dynamic> on self::Foo<Y> {
+}
+static method foo1(dynamic a) → dynamic
+ return throw 42;
+static method foo2(self::Foo<core::int> a, self::Foo<dynamic> ai) → self::Foo<dynamic>
+ return throw 42;
+static method foo3(self::Bar<core::int, (core::num) → dynamic> a, self::Bar<dynamic, (Never) → dynamic> ai) → self::Bar<dynamic, (Never) → dynamic>
+ return throw 42;
+static method foo4(self::Foo<(core::num) → dynamic> a, self::Foo<(Never) → dynamic> ai) → self::Foo<(Never) → dynamic>
+ return throw 42;
+static method bar() → dynamic {
+ dynamic a1;
+ self::Foo<core::int> a2;
+ self::Foo<dynamic> a2i;
+ self::Bar<core::int, (core::num) → dynamic> a3;
+ self::Bar<dynamic, (Never) → dynamic> a3i;
+ self::Foo<(core::num) → dynamic> a4;
+ self::Foo<(Never) → dynamic> a4i;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/simple.dart.textual_outline.expect
new file mode 100644
index 0000000..39e9531
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple.dart.textual_outline.expect
@@ -0,0 +1,21 @@
+class Foo<X> {}
+
+class Bar<X, Y> {}
+
+extension A1 on dynamic {}
+
+A1 foo1(A1 a) => throw 42;
+
+extension A2<X> on Foo<X> {}
+
+A2 foo2(A2<int> a, A2 ai) => throw 42;
+
+extension A3<X, Y extends Function(X)> on Bar<X, Y> {}
+
+A3 foo3(A3<int, Function(num)> a, A3 ai) => throw 42;
+
+extension A4<X, Y extends Function(X)> on Foo<Y> {}
+
+A4 foo4(A4<int, Function(num)> a, A4 ai) => throw 42;
+bar() {}
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extension_types/simple.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d876d2a
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+A1 foo1(A1 a) => throw 42;
+A2 foo2(A2<int> a, A2 ai) => throw 42;
+A3 foo3(A3<int, Function(num)> a, A3 ai) => throw 42;
+A4 foo4(A4<int, Function(num)> a, A4 ai) => throw 42;
+bar() {}
+
+class Bar<X, Y> {}
+
+class Foo<X> {}
+
+extension A1 on dynamic {}
+
+extension A2<X> on Foo<X> {}
+
+extension A3<X, Y extends Function(X)> on Bar<X, Y> {}
+
+extension A4<X, Y extends Function(X)> on Foo<Y> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple.dart.weak.expect b/pkg/front_end/testcases/extension_types/simple.dart.weak.expect
new file mode 100644
index 0000000..aa31646
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple.dart.weak.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Foo<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo<self::Foo::X%>
+ : super core::Object::•()
+ ;
+}
+class Bar<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bar<self::Bar::X%, self::Bar::Y%>
+ : super core::Object::•()
+ ;
+}
+extension A1 on dynamic {
+}
+extension A2<X extends core::Object? = dynamic> on self::Foo<X%> {
+}
+extension A3<X extends core::Object? = dynamic, Y extends (X%) → dynamic = (Never) → dynamic> on self::Bar<X%, Y> {
+}
+extension A4<X extends core::Object? = dynamic, Y extends (X%) → dynamic = (Never) → dynamic> on self::Foo<Y> {
+}
+static method foo1(dynamic a) → dynamic
+ return throw 42;
+static method foo2(self::Foo<core::int> a, self::Foo<dynamic> ai) → self::Foo<dynamic>
+ return throw 42;
+static method foo3(self::Bar<core::int, (core::num) → dynamic> a, self::Bar<dynamic, (Never) → dynamic> ai) → self::Bar<dynamic, (Never) → dynamic>
+ return throw 42;
+static method foo4(self::Foo<(core::num) → dynamic> a, self::Foo<(Never) → dynamic> ai) → self::Foo<(Never) → dynamic>
+ return throw 42;
+static method bar() → dynamic {
+ dynamic a1;
+ self::Foo<core::int> a2;
+ self::Foo<dynamic> a2i;
+ self::Bar<core::int, (core::num) → dynamic> a3;
+ self::Bar<dynamic, (Never) → dynamic> a3i;
+ self::Foo<(core::num) → dynamic> a4;
+ self::Foo<(Never) → dynamic> a4i;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/simple.dart.weak.outline.expect
new file mode 100644
index 0000000..3364bc3
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple.dart.weak.outline.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Foo<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo<self::Foo::X%>
+ ;
+}
+class Bar<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bar<self::Bar::X%, self::Bar::Y%>
+ ;
+}
+extension A1 on dynamic {
+}
+extension A2<X extends core::Object? = dynamic> on self::Foo<X%> {
+}
+extension A3<X extends core::Object? = dynamic, Y extends (X%) → dynamic = (Never) → dynamic> on self::Bar<X%, Y> {
+}
+extension A4<X extends core::Object? = dynamic, Y extends (X%) → dynamic = (Never) → dynamic> on self::Foo<Y> {
+}
+static method foo1(dynamic a) → dynamic
+ ;
+static method foo2(self::Foo<core::int> a, self::Foo<dynamic> ai) → self::Foo<dynamic>
+ ;
+static method foo3(self::Bar<core::int, (core::num) → dynamic> a, self::Bar<dynamic, (Never) → dynamic> ai) → self::Bar<dynamic, (Never) → dynamic>
+ ;
+static method foo4(self::Foo<(core::num) → dynamic> a, self::Foo<(Never) → dynamic> ai) → self::Foo<(Never) → dynamic>
+ ;
+static method bar() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/extension_types/simple.dart.weak.transformed.expect b/pkg/front_end/testcases/extension_types/simple.dart.weak.transformed.expect
new file mode 100644
index 0000000..aa31646
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple.dart.weak.transformed.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Foo<X extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo<self::Foo::X%>
+ : super core::Object::•()
+ ;
+}
+class Bar<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bar<self::Bar::X%, self::Bar::Y%>
+ : super core::Object::•()
+ ;
+}
+extension A1 on dynamic {
+}
+extension A2<X extends core::Object? = dynamic> on self::Foo<X%> {
+}
+extension A3<X extends core::Object? = dynamic, Y extends (X%) → dynamic = (Never) → dynamic> on self::Bar<X%, Y> {
+}
+extension A4<X extends core::Object? = dynamic, Y extends (X%) → dynamic = (Never) → dynamic> on self::Foo<Y> {
+}
+static method foo1(dynamic a) → dynamic
+ return throw 42;
+static method foo2(self::Foo<core::int> a, self::Foo<dynamic> ai) → self::Foo<dynamic>
+ return throw 42;
+static method foo3(self::Bar<core::int, (core::num) → dynamic> a, self::Bar<dynamic, (Never) → dynamic> ai) → self::Bar<dynamic, (Never) → dynamic>
+ return throw 42;
+static method foo4(self::Foo<(core::num) → dynamic> a, self::Foo<(Never) → dynamic> ai) → self::Foo<(Never) → dynamic>
+ return throw 42;
+static method bar() → dynamic {
+ dynamic a1;
+ self::Foo<core::int> a2;
+ self::Foo<dynamic> a2i;
+ self::Bar<core::int, (core::num) → dynamic> a3;
+ self::Bar<dynamic, (Never) → dynamic> a3i;
+ self::Foo<(core::num) → dynamic> a4;
+ self::Foo<(Never) → dynamic> a4i;
+}
+static method main() → dynamic {}